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 945 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
956 ->map() | 956 ->map() |
957 ->has_non_instance_prototype()) { | 957 ->has_non_instance_prototype()) { |
958 Handle<Code> stub; | 958 Handle<Code> stub; |
959 FunctionPrototypeStub function_prototype_stub(isolate()); | 959 FunctionPrototypeStub function_prototype_stub(isolate()); |
960 return function_prototype_stub.GetCode(); | 960 return function_prototype_stub.GetCode(); |
961 } | 961 } |
962 | 962 |
963 Handle<HeapType> type = receiver_type(); | 963 Handle<HeapType> type = receiver_type(); |
964 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 964 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
965 bool receiver_is_holder = receiver.is_identical_to(holder); | 965 bool receiver_is_holder = receiver.is_identical_to(holder); |
966 // -------------- Interceptors -------------- | 966 switch (lookup->state()) { |
967 if (lookup->state() == LookupIterator::INTERCEPTOR) { | 967 case LookupIterator::INTERCEPTOR: { |
968 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 968 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
969 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | 969 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
970 cache_holder); | 970 cache_holder); |
971 // Perform a lookup behind the interceptor. Copy the LookupIterator since | 971 // Perform a lookup behind the interceptor. Copy the LookupIterator since |
972 // the original iterator will be used to fetch the value. | 972 // the original iterator will be used to fetch the value. |
973 LookupIterator it = *lookup; | 973 LookupIterator it = *lookup; |
974 it.Next(); | 974 it.Next(); |
975 LookupForRead(&it); | 975 LookupForRead(&it); |
976 return compiler.CompileLoadInterceptor(&it); | 976 return compiler.CompileLoadInterceptor(&it); |
| 977 } |
| 978 |
| 979 case LookupIterator::ACCESSOR: { |
| 980 // Use simple field loads for some well-known callback properties. |
| 981 if (receiver_is_holder) { |
| 982 DCHECK(receiver->IsJSObject()); |
| 983 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); |
| 984 int object_offset; |
| 985 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(), |
| 986 &object_offset)) { |
| 987 FieldIndex index = |
| 988 FieldIndex::ForInObjectOffset(object_offset, js_receiver->map()); |
| 989 return SimpleFieldLoad(index); |
| 990 } |
| 991 } |
| 992 |
| 993 Handle<Object> accessors = lookup->GetAccessors(); |
| 994 if (accessors->IsExecutableAccessorInfo()) { |
| 995 Handle<ExecutableAccessorInfo> info = |
| 996 Handle<ExecutableAccessorInfo>::cast(accessors); |
| 997 if (v8::ToCData<Address>(info->getter()) == 0) break; |
| 998 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, |
| 999 type)) { |
| 1000 break; |
| 1001 } |
| 1002 if (!holder->HasFastProperties()) break; |
| 1003 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1004 cache_holder); |
| 1005 return compiler.CompileLoadCallback(lookup->name(), info); |
| 1006 } |
| 1007 if (accessors->IsAccessorPair()) { |
| 1008 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
| 1009 isolate()); |
| 1010 if (!getter->IsJSFunction()) break; |
| 1011 if (!holder->HasFastProperties()) break; |
| 1012 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
| 1013 if (!receiver->IsJSObject() && !function->IsBuiltin() && |
| 1014 function->shared()->strict_mode() == SLOPPY) { |
| 1015 // Calling sloppy non-builtins with a value as the receiver |
| 1016 // requires boxing. |
| 1017 break; |
| 1018 } |
| 1019 CallOptimization call_optimization(function); |
| 1020 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1021 cache_holder); |
| 1022 if (call_optimization.is_simple_api_call() && |
| 1023 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
| 1024 return compiler.CompileLoadCallback(lookup->name(), |
| 1025 call_optimization); |
| 1026 } |
| 1027 return compiler.CompileLoadViaGetter(lookup->name(), function); |
| 1028 } |
| 1029 // TODO(dcarney): Handle correctly. |
| 1030 DCHECK(accessors->IsDeclaredAccessorInfo()); |
| 1031 break; |
| 1032 } |
| 1033 |
| 1034 case LookupIterator::DATA: { |
| 1035 if (lookup->is_dictionary_holder()) { |
| 1036 if (kind() != Code::LOAD_IC) break; |
| 1037 if (holder->IsGlobalObject()) { |
| 1038 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1039 cache_holder); |
| 1040 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1041 Handle<Code> code = compiler.CompileLoadGlobal( |
| 1042 cell, lookup->name(), lookup->IsConfigurable()); |
| 1043 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1044 CacheHolderFlag flag; |
| 1045 Handle<Map> stub_holder_map = GetHandlerCacheHolder( |
| 1046 *type, receiver_is_holder, isolate(), &flag); |
| 1047 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); |
| 1048 return code; |
| 1049 } |
| 1050 // There is only one shared stub for loading normalized |
| 1051 // properties. It does not traverse the prototype chain, so the |
| 1052 // property must be found in the object for the stub to be |
| 1053 // applicable. |
| 1054 if (!receiver_is_holder) break; |
| 1055 return isolate()->builtins()->LoadIC_Normal(); |
| 1056 } |
| 1057 |
| 1058 // -------------- Fields -------------- |
| 1059 if (lookup->property_details().type() == FIELD) { |
| 1060 FieldIndex field = lookup->GetFieldIndex(); |
| 1061 if (receiver_is_holder) { |
| 1062 return SimpleFieldLoad(field); |
| 1063 } |
| 1064 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1065 cache_holder); |
| 1066 return compiler.CompileLoadField(lookup->name(), field); |
| 1067 } |
| 1068 |
| 1069 // -------------- Constant properties -------------- |
| 1070 DCHECK(lookup->property_details().type() == CONSTANT); |
| 1071 if (receiver_is_holder) { |
| 1072 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
| 1073 return stub.GetCode(); |
| 1074 } |
| 1075 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1076 cache_holder); |
| 1077 return compiler.CompileLoadConstant(lookup->name(), |
| 1078 lookup->GetConstantIndex()); |
| 1079 } |
| 1080 |
| 1081 case LookupIterator::ACCESS_CHECK: |
| 1082 case LookupIterator::JSPROXY: |
| 1083 case LookupIterator::NOT_FOUND: |
| 1084 case LookupIterator::TRANSITION: |
| 1085 case LookupIterator::UNKNOWN: |
| 1086 UNREACHABLE(); |
977 } | 1087 } |
978 | 1088 |
979 // -------------- Accessors -------------- | 1089 return slow_stub(); |
980 if (lookup->state() == LookupIterator::ACCESSOR) { | |
981 // Use simple field loads for some well-known callback properties. | |
982 if (receiver_is_holder) { | |
983 DCHECK(receiver->IsJSObject()); | |
984 Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver); | |
985 int object_offset; | |
986 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, lookup->name(), | |
987 &object_offset)) { | |
988 FieldIndex index = | |
989 FieldIndex::ForInObjectOffset(object_offset, js_receiver->map()); | |
990 return SimpleFieldLoad(index); | |
991 } | |
992 } | |
993 | |
994 Handle<Object> accessors = lookup->GetAccessors(); | |
995 if (accessors->IsExecutableAccessorInfo()) { | |
996 Handle<ExecutableAccessorInfo> info = | |
997 Handle<ExecutableAccessorInfo>::cast(accessors); | |
998 if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub(); | |
999 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, | |
1000 type)) { | |
1001 return slow_stub(); | |
1002 } | |
1003 if (!holder->HasFastProperties()) return slow_stub(); | |
1004 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | |
1005 cache_holder); | |
1006 return compiler.CompileLoadCallback(lookup->name(), info); | |
1007 } | |
1008 if (accessors->IsAccessorPair()) { | |
1009 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | |
1010 isolate()); | |
1011 if (!getter->IsJSFunction()) return slow_stub(); | |
1012 if (!holder->HasFastProperties()) return slow_stub(); | |
1013 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | |
1014 if (!receiver->IsJSObject() && !function->IsBuiltin() && | |
1015 function->shared()->strict_mode() == SLOPPY) { | |
1016 // Calling sloppy non-builtins with a value as the receiver | |
1017 // requires boxing. | |
1018 return slow_stub(); | |
1019 } | |
1020 CallOptimization call_optimization(function); | |
1021 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | |
1022 cache_holder); | |
1023 if (call_optimization.is_simple_api_call() && | |
1024 call_optimization.IsCompatibleReceiver(receiver, holder)) { | |
1025 return compiler.CompileLoadCallback(lookup->name(), call_optimization); | |
1026 } | |
1027 return compiler.CompileLoadViaGetter(lookup->name(), function); | |
1028 } | |
1029 // TODO(dcarney): Handle correctly. | |
1030 DCHECK(accessors->IsDeclaredAccessorInfo()); | |
1031 return slow_stub(); | |
1032 } | |
1033 | |
1034 // -------------- Dictionary properties -------------- | |
1035 DCHECK(lookup->state() == LookupIterator::DATA); | |
1036 if (lookup->is_dictionary_holder()) { | |
1037 if (kind() != Code::LOAD_IC) return slow_stub(); | |
1038 if (holder->IsGlobalObject()) { | |
1039 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | |
1040 cache_holder); | |
1041 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | |
1042 Handle<Code> code = compiler.CompileLoadGlobal(cell, lookup->name(), | |
1043 lookup->IsConfigurable()); | |
1044 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | |
1045 CacheHolderFlag flag; | |
1046 Handle<Map> stub_holder_map = | |
1047 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); | |
1048 Map::UpdateCodeCache(stub_holder_map, lookup->name(), code); | |
1049 return code; | |
1050 } | |
1051 // There is only one shared stub for loading normalized | |
1052 // properties. It does not traverse the prototype chain, so the | |
1053 // property must be found in the object for the stub to be | |
1054 // applicable. | |
1055 if (!receiver_is_holder) return slow_stub(); | |
1056 return isolate()->builtins()->LoadIC_Normal(); | |
1057 } | |
1058 | |
1059 // -------------- Fields -------------- | |
1060 if (lookup->property_details().type() == FIELD) { | |
1061 FieldIndex field = lookup->GetFieldIndex(); | |
1062 if (receiver_is_holder) { | |
1063 return SimpleFieldLoad(field); | |
1064 } | |
1065 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | |
1066 cache_holder); | |
1067 return compiler.CompileLoadField(lookup->name(), field); | |
1068 } | |
1069 | |
1070 // -------------- Constant properties -------------- | |
1071 DCHECK(lookup->property_details().type() == CONSTANT); | |
1072 if (receiver_is_holder) { | |
1073 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | |
1074 return stub.GetCode(); | |
1075 } | |
1076 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | |
1077 cache_holder); | |
1078 return compiler.CompileLoadConstant(lookup->name(), | |
1079 lookup->GetConstantIndex()); | |
1080 } | 1090 } |
1081 | 1091 |
1082 | 1092 |
1083 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1093 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1084 // This helper implements a few common fast cases for converting | 1094 // This helper implements a few common fast cases for converting |
1085 // non-smi keys of keyed loads/stores to a smi or a string. | 1095 // non-smi keys of keyed loads/stores to a smi or a string. |
1086 if (key->IsHeapNumber()) { | 1096 if (key->IsHeapNumber()) { |
1087 double value = Handle<HeapNumber>::cast(key)->value(); | 1097 double value = Handle<HeapNumber>::cast(key)->value(); |
1088 if (std::isnan(value)) { | 1098 if (std::isnan(value)) { |
1089 key = isolate->factory()->nan_string(); | 1099 key = isolate->factory()->nan_string(); |
(...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1393 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, | 1403 Handle<Code> StoreIC::CompileHandler(LookupIterator* lookup, |
1394 Handle<Object> value, | 1404 Handle<Object> value, |
1395 CacheHolderFlag cache_holder) { | 1405 CacheHolderFlag cache_holder) { |
1396 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); | 1406 DCHECK_NE(LookupIterator::JSPROXY, lookup->state()); |
1397 | 1407 |
1398 // This is currently guaranteed by checks in StoreIC::Store. | 1408 // This is currently guaranteed by checks in StoreIC::Store. |
1399 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); | 1409 Handle<JSObject> receiver = Handle<JSObject>::cast(lookup->GetReceiver()); |
1400 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 1410 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1401 DCHECK(!receiver->IsAccessCheckNeeded()); | 1411 DCHECK(!receiver->IsAccessCheckNeeded()); |
1402 | 1412 |
1403 // -------------- Transition -------------- | 1413 switch (lookup->state()) { |
1404 if (lookup->state() == LookupIterator::TRANSITION) { | 1414 case LookupIterator::TRANSITION: { |
1405 Handle<Map> transition = lookup->transition_map(); | 1415 Handle<Map> transition = lookup->transition_map(); |
1406 // Currently not handled by CompileStoreTransition. | 1416 // Currently not handled by CompileStoreTransition. |
1407 if (!holder->HasFastProperties()) return slow_stub(); | 1417 if (!holder->HasFastProperties()) break; |
1408 | 1418 |
1409 DCHECK(lookup->IsCacheableTransition()); | 1419 DCHECK(lookup->IsCacheableTransition()); |
1410 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | 1420 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1411 return compiler.CompileStoreTransition(transition, lookup->name()); | 1421 return compiler.CompileStoreTransition(transition, lookup->name()); |
| 1422 } |
| 1423 |
| 1424 case LookupIterator::INTERCEPTOR: { |
| 1425 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); |
| 1426 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
| 1427 return compiler.CompileStoreInterceptor(lookup->name()); |
| 1428 } |
| 1429 |
| 1430 case LookupIterator::ACCESSOR: { |
| 1431 if (!holder->HasFastProperties()) break; |
| 1432 Handle<Object> accessors = lookup->GetAccessors(); |
| 1433 if (accessors->IsExecutableAccessorInfo()) { |
| 1434 Handle<ExecutableAccessorInfo> info = |
| 1435 Handle<ExecutableAccessorInfo>::cast(accessors); |
| 1436 if (v8::ToCData<Address>(info->setter()) == 0) break; |
| 1437 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( |
| 1438 isolate(), info, receiver_type())) { |
| 1439 break; |
| 1440 } |
| 1441 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
| 1442 return compiler.CompileStoreCallback(receiver, lookup->name(), info); |
| 1443 } else if (accessors->IsAccessorPair()) { |
| 1444 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), |
| 1445 isolate()); |
| 1446 if (!setter->IsJSFunction()) break; |
| 1447 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
| 1448 CallOptimization call_optimization(function); |
| 1449 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
| 1450 if (call_optimization.is_simple_api_call() && |
| 1451 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
| 1452 return compiler.CompileStoreCallback(receiver, lookup->name(), |
| 1453 call_optimization); |
| 1454 } |
| 1455 return compiler.CompileStoreViaSetter(receiver, lookup->name(), |
| 1456 Handle<JSFunction>::cast(setter)); |
| 1457 } |
| 1458 // TODO(dcarney): Handle correctly. |
| 1459 DCHECK(accessors->IsDeclaredAccessorInfo()); |
| 1460 break; |
| 1461 } |
| 1462 |
| 1463 case LookupIterator::DATA: { |
| 1464 if (lookup->is_dictionary_holder()) { |
| 1465 if (holder->IsGlobalObject()) { |
| 1466 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
| 1467 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); |
| 1468 StoreGlobalStub stub(isolate(), union_type->IsConstant(), |
| 1469 receiver->IsJSGlobalProxy()); |
| 1470 Handle<Code> code = stub.GetCodeCopyFromTemplate( |
| 1471 Handle<GlobalObject>::cast(holder), cell); |
| 1472 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
| 1473 HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code); |
| 1474 return code; |
| 1475 } |
| 1476 DCHECK(holder.is_identical_to(receiver)); |
| 1477 return isolate()->builtins()->StoreIC_Normal(); |
| 1478 } |
| 1479 |
| 1480 // -------------- Fields -------------- |
| 1481 if (lookup->property_details().type() == FIELD) { |
| 1482 bool use_stub = true; |
| 1483 if (lookup->representation().IsHeapObject()) { |
| 1484 // Only use a generic stub if no types need to be tracked. |
| 1485 Handle<HeapType> field_type = lookup->GetFieldType(); |
| 1486 HeapType::Iterator<Map> it = field_type->Classes(); |
| 1487 use_stub = it.Done(); |
| 1488 } |
| 1489 if (use_stub) { |
| 1490 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
| 1491 lookup->representation()); |
| 1492 return stub.GetCode(); |
| 1493 } |
| 1494 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
| 1495 return compiler.CompileStoreField(lookup); |
| 1496 } |
| 1497 |
| 1498 // -------------- Constant properties -------------- |
| 1499 DCHECK(lookup->property_details().type() == CONSTANT); |
| 1500 break; |
| 1501 } |
| 1502 |
| 1503 case LookupIterator::ACCESS_CHECK: |
| 1504 case LookupIterator::JSPROXY: |
| 1505 case LookupIterator::NOT_FOUND: |
| 1506 case LookupIterator::UNKNOWN: |
| 1507 UNREACHABLE(); |
1412 } | 1508 } |
1413 | |
1414 // -------------- Interceptors -------------- | |
1415 if (lookup->state() == LookupIterator::INTERCEPTOR) { | |
1416 DCHECK(!holder->GetNamedInterceptor()->setter()->IsUndefined()); | |
1417 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | |
1418 return compiler.CompileStoreInterceptor(lookup->name()); | |
1419 } | |
1420 | |
1421 // -------------- Accessors -------------- | |
1422 if (lookup->state() == LookupIterator::ACCESSOR) { | |
1423 if (!holder->HasFastProperties()) return slow_stub(); | |
1424 Handle<Object> accessors = lookup->GetAccessors(); | |
1425 if (accessors->IsExecutableAccessorInfo()) { | |
1426 Handle<ExecutableAccessorInfo> info = | |
1427 Handle<ExecutableAccessorInfo>::cast(accessors); | |
1428 if (v8::ToCData<Address>(info->setter()) == 0) return slow_stub(); | |
1429 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, | |
1430 receiver_type())) { | |
1431 return slow_stub(); | |
1432 } | |
1433 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | |
1434 return compiler.CompileStoreCallback(receiver, lookup->name(), info); | |
1435 } else if (accessors->IsAccessorPair()) { | |
1436 Handle<Object> setter(Handle<AccessorPair>::cast(accessors)->setter(), | |
1437 isolate()); | |
1438 if (!setter->IsJSFunction()) return slow_stub(); | |
1439 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | |
1440 CallOptimization call_optimization(function); | |
1441 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | |
1442 if (call_optimization.is_simple_api_call() && | |
1443 call_optimization.IsCompatibleReceiver(receiver, holder)) { | |
1444 return compiler.CompileStoreCallback(receiver, lookup->name(), | |
1445 call_optimization); | |
1446 } | |
1447 return compiler.CompileStoreViaSetter(receiver, lookup->name(), | |
1448 Handle<JSFunction>::cast(setter)); | |
1449 } | |
1450 // TODO(dcarney): Handle correctly. | |
1451 DCHECK(accessors->IsDeclaredAccessorInfo()); | |
1452 return slow_stub(); | |
1453 } | |
1454 | |
1455 // -------------- Dictionary properties -------------- | |
1456 DCHECK(lookup->state() == LookupIterator::DATA); | |
1457 if (lookup->is_dictionary_holder()) { | |
1458 if (holder->IsGlobalObject()) { | |
1459 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | |
1460 Handle<HeapType> union_type = PropertyCell::UpdatedType(cell, value); | |
1461 StoreGlobalStub stub(isolate(), union_type->IsConstant(), | |
1462 receiver->IsJSGlobalProxy()); | |
1463 Handle<Code> code = stub.GetCodeCopyFromTemplate( | |
1464 Handle<GlobalObject>::cast(holder), cell); | |
1465 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | |
1466 HeapObject::UpdateMapCodeCache(receiver, lookup->name(), code); | |
1467 return code; | |
1468 } | |
1469 DCHECK(holder.is_identical_to(receiver)); | |
1470 return isolate()->builtins()->StoreIC_Normal(); | |
1471 } | |
1472 | |
1473 // -------------- Fields -------------- | |
1474 if (lookup->property_details().type() == FIELD) { | |
1475 bool use_stub = true; | |
1476 if (lookup->representation().IsHeapObject()) { | |
1477 // Only use a generic stub if no types need to be tracked. | |
1478 Handle<HeapType> field_type = lookup->GetFieldType(); | |
1479 HeapType::Iterator<Map> it = field_type->Classes(); | |
1480 use_stub = it.Done(); | |
1481 } | |
1482 if (use_stub) { | |
1483 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | |
1484 lookup->representation()); | |
1485 return stub.GetCode(); | |
1486 } | |
1487 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | |
1488 return compiler.CompileStoreField(lookup); | |
1489 } | |
1490 | |
1491 // -------------- Constant properties -------------- | |
1492 DCHECK(lookup->property_details().type() == CONSTANT); | |
1493 return slow_stub(); | 1509 return slow_stub(); |
1494 } | 1510 } |
1495 | 1511 |
1496 | 1512 |
1497 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, | 1513 Handle<Code> KeyedStoreIC::StoreElementStub(Handle<JSObject> receiver, |
1498 KeyedAccessStoreMode store_mode) { | 1514 KeyedAccessStoreMode store_mode) { |
1499 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS | 1515 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS |
1500 // via megamorphic stubs, since they don't have a map in their relocation info | 1516 // via megamorphic stubs, since they don't have a map in their relocation info |
1501 // and so the stubs can't be harvested for the object needed for a map check. | 1517 // and so the stubs can't be harvested for the object needed for a map check. |
1502 if (target()->type() != Code::NORMAL) { | 1518 if (target()->type() != Code::NORMAL) { |
(...skipping 1696 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3199 static const Address IC_utilities[] = { | 3215 static const Address IC_utilities[] = { |
3200 #define ADDR(name) FUNCTION_ADDR(name), | 3216 #define ADDR(name) FUNCTION_ADDR(name), |
3201 IC_UTIL_LIST(ADDR) NULL | 3217 IC_UTIL_LIST(ADDR) NULL |
3202 #undef ADDR | 3218 #undef ADDR |
3203 }; | 3219 }; |
3204 | 3220 |
3205 | 3221 |
3206 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 3222 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
3207 } | 3223 } |
3208 } // namespace v8::internal | 3224 } // namespace v8::internal |
OLD | NEW |