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" |
(...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 Handle<JSFunction>::cast(object)->should_have_prototype() && | 991 Handle<JSFunction>::cast(object)->should_have_prototype() && |
992 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { | 992 !Handle<JSFunction>::cast(object)->map()->has_non_instance_prototype()) { |
993 Handle<Code> stub; | 993 Handle<Code> stub; |
994 FunctionPrototypeStub function_prototype_stub(isolate()); | 994 FunctionPrototypeStub function_prototype_stub(isolate()); |
995 return function_prototype_stub.GetCode(); | 995 return function_prototype_stub.GetCode(); |
996 } | 996 } |
997 | 997 |
998 Handle<HeapType> type = receiver_type(); | 998 Handle<HeapType> type = receiver_type(); |
999 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); | 999 Handle<JSObject> holder = lookup->GetHolder<JSObject>(); |
1000 bool receiver_is_holder = object.is_identical_to(holder); | 1000 bool receiver_is_holder = object.is_identical_to(holder); |
1001 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, | |
1002 cache_holder); | |
1003 | |
1004 // -------------- Interceptors -------------- | 1001 // -------------- Interceptors -------------- |
1005 if (lookup->state() == LookupIterator::INTERCEPTOR) { | 1002 if (lookup->state() == LookupIterator::INTERCEPTOR) { |
1006 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); | 1003 DCHECK(!holder->GetNamedInterceptor()->getter()->IsUndefined()); |
| 1004 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1005 cache_holder); |
1007 return compiler.CompileLoadInterceptor(name); | 1006 return compiler.CompileLoadInterceptor(name); |
1008 } | 1007 } |
1009 DCHECK(lookup->state() == LookupIterator::PROPERTY); | 1008 DCHECK(lookup->state() == LookupIterator::PROPERTY); |
1010 | 1009 |
1011 // -------------- Accessors -------------- | 1010 // -------------- Accessors -------------- |
1012 if (lookup->property_kind() == LookupIterator::ACCESSOR) { | 1011 if (lookup->property_kind() == LookupIterator::ACCESSOR) { |
1013 // Use simple field loads for some well-known callback properties. | 1012 // Use simple field loads for some well-known callback properties. |
1014 if (receiver_is_holder) { | 1013 if (receiver_is_holder) { |
1015 DCHECK(object->IsJSObject()); | 1014 DCHECK(object->IsJSObject()); |
1016 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1015 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1017 int object_offset; | 1016 int object_offset; |
1018 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name, | 1017 if (Accessors::IsJSObjectFieldAccessor<HeapType>(type, name, |
1019 &object_offset)) { | 1018 &object_offset)) { |
1020 FieldIndex index = | 1019 FieldIndex index = |
1021 FieldIndex::ForInObjectOffset(object_offset, receiver->map()); | 1020 FieldIndex::ForInObjectOffset(object_offset, receiver->map()); |
1022 return SimpleFieldLoad(index); | 1021 return SimpleFieldLoad(index); |
1023 } | 1022 } |
1024 } | 1023 } |
1025 | 1024 |
1026 Handle<Object> accessors = lookup->GetAccessors(); | 1025 Handle<Object> accessors = lookup->GetAccessors(); |
1027 if (accessors->IsExecutableAccessorInfo()) { | 1026 if (accessors->IsExecutableAccessorInfo()) { |
1028 Handle<ExecutableAccessorInfo> info = | 1027 Handle<ExecutableAccessorInfo> info = |
1029 Handle<ExecutableAccessorInfo>::cast(accessors); | 1028 Handle<ExecutableAccessorInfo>::cast(accessors); |
1030 if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub(); | 1029 if (v8::ToCData<Address>(info->getter()) == 0) return slow_stub(); |
1031 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, | 1030 if (!ExecutableAccessorInfo::IsCompatibleReceiverType(isolate(), info, |
1032 type)) { | 1031 type)) { |
1033 return slow_stub(); | 1032 return slow_stub(); |
1034 } | 1033 } |
1035 if (!holder->HasFastProperties()) return slow_stub(); | 1034 if (!holder->HasFastProperties()) return slow_stub(); |
| 1035 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1036 cache_holder); |
1036 return compiler.CompileLoadCallback(name, info); | 1037 return compiler.CompileLoadCallback(name, info); |
1037 } | 1038 } |
1038 if (accessors->IsAccessorPair()) { | 1039 if (accessors->IsAccessorPair()) { |
1039 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), | 1040 Handle<Object> getter(Handle<AccessorPair>::cast(accessors)->getter(), |
1040 isolate()); | 1041 isolate()); |
1041 if (!getter->IsJSFunction()) return slow_stub(); | 1042 if (!getter->IsJSFunction()) return slow_stub(); |
1042 if (!holder->HasFastProperties()) return slow_stub(); | 1043 if (!holder->HasFastProperties()) return slow_stub(); |
1043 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); | 1044 Handle<JSFunction> function = Handle<JSFunction>::cast(getter); |
1044 if (!object->IsJSObject() && !function->IsBuiltin() && | 1045 if (!object->IsJSObject() && !function->IsBuiltin() && |
1045 function->shared()->strict_mode() == SLOPPY) { | 1046 function->shared()->strict_mode() == SLOPPY) { |
1046 // Calling sloppy non-builtins with a value as the receiver | 1047 // Calling sloppy non-builtins with a value as the receiver |
1047 // requires boxing. | 1048 // requires boxing. |
1048 return slow_stub(); | 1049 return slow_stub(); |
1049 } | 1050 } |
1050 CallOptimization call_optimization(function); | 1051 CallOptimization call_optimization(function); |
| 1052 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1053 cache_holder); |
1051 if (call_optimization.is_simple_api_call() && | 1054 if (call_optimization.is_simple_api_call() && |
1052 call_optimization.IsCompatibleReceiver(object, holder)) { | 1055 call_optimization.IsCompatibleReceiver(object, holder)) { |
1053 return compiler.CompileLoadCallback(name, call_optimization); | 1056 return compiler.CompileLoadCallback(name, call_optimization); |
1054 } | 1057 } |
1055 return compiler.CompileLoadViaGetter(name, function); | 1058 return compiler.CompileLoadViaGetter(name, function); |
1056 } | 1059 } |
1057 // TODO(dcarney): Handle correctly. | 1060 // TODO(dcarney): Handle correctly. |
1058 DCHECK(accessors->IsDeclaredAccessorInfo()); | 1061 DCHECK(accessors->IsDeclaredAccessorInfo()); |
1059 return slow_stub(); | 1062 return slow_stub(); |
1060 } | 1063 } |
1061 | 1064 |
1062 // -------------- Dictionary properties -------------- | 1065 // -------------- Dictionary properties -------------- |
1063 DCHECK(lookup->property_kind() == LookupIterator::DATA); | 1066 DCHECK(lookup->property_kind() == LookupIterator::DATA); |
1064 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { | 1067 if (lookup->property_encoding() == LookupIterator::DICTIONARY) { |
1065 if (kind() != Code::LOAD_IC) return slow_stub(); | 1068 if (kind() != Code::LOAD_IC) return slow_stub(); |
1066 if (holder->IsGlobalObject()) { | 1069 if (holder->IsGlobalObject()) { |
| 1070 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1071 cache_holder); |
1067 Handle<PropertyCell> cell = lookup->GetPropertyCell(); | 1072 Handle<PropertyCell> cell = lookup->GetPropertyCell(); |
1068 Handle<Code> code = | 1073 Handle<Code> code = |
1069 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable()); | 1074 compiler.CompileLoadGlobal(cell, name, lookup->IsConfigurable()); |
1070 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. | 1075 // TODO(verwaest): Move caching of these NORMAL stubs outside as well. |
1071 CacheHolderFlag flag; | 1076 CacheHolderFlag flag; |
1072 Handle<Map> stub_holder_map = | 1077 Handle<Map> stub_holder_map = |
1073 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); | 1078 GetHandlerCacheHolder(*type, receiver_is_holder, isolate(), &flag); |
1074 Map::UpdateCodeCache(stub_holder_map, name, code); | 1079 Map::UpdateCodeCache(stub_holder_map, name, code); |
1075 return code; | 1080 return code; |
1076 } | 1081 } |
1077 // There is only one shared stub for loading normalized | 1082 // There is only one shared stub for loading normalized |
1078 // properties. It does not traverse the prototype chain, so the | 1083 // properties. It does not traverse the prototype chain, so the |
1079 // property must be found in the object for the stub to be | 1084 // property must be found in the object for the stub to be |
1080 // applicable. | 1085 // applicable. |
1081 if (!receiver_is_holder) return slow_stub(); | 1086 if (!receiver_is_holder) return slow_stub(); |
1082 return isolate()->builtins()->LoadIC_Normal(); | 1087 return isolate()->builtins()->LoadIC_Normal(); |
1083 } | 1088 } |
1084 | 1089 |
1085 // -------------- Fields -------------- | 1090 // -------------- Fields -------------- |
1086 DCHECK(lookup->property_encoding() == LookupIterator::DESCRIPTOR); | 1091 DCHECK(lookup->property_encoding() == LookupIterator::DESCRIPTOR); |
1087 if (lookup->property_details().type() == FIELD) { | 1092 if (lookup->property_details().type() == FIELD) { |
1088 FieldIndex field = lookup->GetFieldIndex(); | 1093 FieldIndex field = lookup->GetFieldIndex(); |
1089 if (receiver_is_holder) { | 1094 if (receiver_is_holder) { |
1090 return SimpleFieldLoad(field); | 1095 return SimpleFieldLoad(field); |
1091 } | 1096 } |
| 1097 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1098 cache_holder); |
1092 return compiler.CompileLoadField(name, field); | 1099 return compiler.CompileLoadField(name, field); |
1093 } | 1100 } |
1094 | 1101 |
1095 // -------------- Constant properties -------------- | 1102 // -------------- Constant properties -------------- |
1096 DCHECK(lookup->property_details().type() == CONSTANT); | 1103 DCHECK(lookup->property_details().type() == CONSTANT); |
1097 if (receiver_is_holder) { | 1104 if (receiver_is_holder) { |
1098 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); | 1105 LoadConstantStub stub(isolate(), lookup->GetConstantIndex()); |
1099 return stub.GetCode(); | 1106 return stub.GetCode(); |
1100 } | 1107 } |
| 1108 NamedLoadHandlerCompiler compiler(isolate(), receiver_type(), holder, |
| 1109 cache_holder); |
1101 return compiler.CompileLoadConstant(name, lookup->GetConstantIndex()); | 1110 return compiler.CompileLoadConstant(name, lookup->GetConstantIndex()); |
1102 } | 1111 } |
1103 | 1112 |
1104 | 1113 |
1105 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { | 1114 static Handle<Object> TryConvertKey(Handle<Object> key, Isolate* isolate) { |
1106 // This helper implements a few common fast cases for converting | 1115 // This helper implements a few common fast cases for converting |
1107 // non-smi keys of keyed loads/stores to a smi or a string. | 1116 // non-smi keys of keyed loads/stores to a smi or a string. |
1108 if (key->IsHeapNumber()) { | 1117 if (key->IsHeapNumber()) { |
1109 double value = Handle<HeapNumber>::cast(key)->value(); | 1118 double value = Handle<HeapNumber>::cast(key)->value(); |
1110 if (std::isnan(value)) { | 1119 if (std::isnan(value)) { |
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1452 Handle<String> name, | 1461 Handle<String> name, |
1453 Handle<Object> value, | 1462 Handle<Object> value, |
1454 CacheHolderFlag cache_holder) { | 1463 CacheHolderFlag cache_holder) { |
1455 if (object->IsAccessCheckNeeded()) return slow_stub(); | 1464 if (object->IsAccessCheckNeeded()) return slow_stub(); |
1456 DCHECK(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || | 1465 DCHECK(cache_holder == kCacheOnReceiver || lookup->type() == CALLBACKS || |
1457 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); | 1466 (object->IsJSGlobalProxy() && lookup->holder()->IsJSGlobalObject())); |
1458 // This is currently guaranteed by checks in StoreIC::Store. | 1467 // This is currently guaranteed by checks in StoreIC::Store. |
1459 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1468 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
1460 | 1469 |
1461 Handle<JSObject> holder(lookup->holder()); | 1470 Handle<JSObject> holder(lookup->holder()); |
1462 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); | |
1463 | 1471 |
1464 if (lookup->IsTransition()) { | 1472 if (lookup->IsTransition()) { |
1465 // Explicitly pass in the receiver map since LookupForWrite may have | 1473 // Explicitly pass in the receiver map since LookupForWrite may have |
1466 // stored something else than the receiver in the holder. | 1474 // stored something else than the receiver in the holder. |
1467 Handle<Map> transition(lookup->GetTransitionTarget()); | 1475 Handle<Map> transition(lookup->GetTransitionTarget()); |
1468 PropertyDetails details = lookup->GetPropertyDetails(); | 1476 PropertyDetails details = lookup->GetPropertyDetails(); |
1469 | 1477 |
1470 if (details.type() != CALLBACKS && details.attributes() == NONE && | 1478 if (details.type() != CALLBACKS && details.attributes() == NONE && |
1471 holder->HasFastProperties()) { | 1479 holder->HasFastProperties()) { |
| 1480 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1472 return compiler.CompileStoreTransition(transition, name); | 1481 return compiler.CompileStoreTransition(transition, name); |
1473 } | 1482 } |
1474 } else { | 1483 } else { |
1475 switch (lookup->type()) { | 1484 switch (lookup->type()) { |
1476 case FIELD: { | 1485 case FIELD: { |
1477 bool use_stub = true; | 1486 bool use_stub = true; |
1478 if (lookup->representation().IsHeapObject()) { | 1487 if (lookup->representation().IsHeapObject()) { |
1479 // Only use a generic stub if no types need to be tracked. | 1488 // Only use a generic stub if no types need to be tracked. |
1480 HeapType* field_type = lookup->GetFieldType(); | 1489 HeapType* field_type = lookup->GetFieldType(); |
1481 HeapType::Iterator<Map> it = field_type->Classes(); | 1490 HeapType::Iterator<Map> it = field_type->Classes(); |
1482 use_stub = it.Done(); | 1491 use_stub = it.Done(); |
1483 } | 1492 } |
1484 if (use_stub) { | 1493 if (use_stub) { |
1485 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | 1494 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
1486 lookup->representation()); | 1495 lookup->representation()); |
1487 return stub.GetCode(); | 1496 return stub.GetCode(); |
1488 } | 1497 } |
| 1498 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1489 return compiler.CompileStoreField(lookup, name); | 1499 return compiler.CompileStoreField(lookup, name); |
1490 } | 1500 } |
1491 case NORMAL: | 1501 case NORMAL: |
1492 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { | 1502 if (receiver->IsJSGlobalProxy() || receiver->IsGlobalObject()) { |
1493 // The stub generated for the global object picks the value directly | 1503 // The stub generated for the global object picks the value directly |
1494 // from the property cell. So the property must be directly on the | 1504 // from the property cell. So the property must be directly on the |
1495 // global object. | 1505 // global object. |
1496 PrototypeIterator iter(isolate(), receiver); | 1506 PrototypeIterator iter(isolate(), receiver); |
1497 Handle<GlobalObject> global = | 1507 Handle<GlobalObject> global = |
1498 receiver->IsJSGlobalProxy() | 1508 receiver->IsJSGlobalProxy() |
(...skipping 15 matching lines...) Expand all Loading... |
1514 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); | 1524 Handle<Object> callback(lookup->GetCallbackObject(), isolate()); |
1515 if (callback->IsExecutableAccessorInfo()) { | 1525 if (callback->IsExecutableAccessorInfo()) { |
1516 Handle<ExecutableAccessorInfo> info = | 1526 Handle<ExecutableAccessorInfo> info = |
1517 Handle<ExecutableAccessorInfo>::cast(callback); | 1527 Handle<ExecutableAccessorInfo>::cast(callback); |
1518 if (v8::ToCData<Address>(info->setter()) == 0) break; | 1528 if (v8::ToCData<Address>(info->setter()) == 0) break; |
1519 if (!holder->HasFastProperties()) break; | 1529 if (!holder->HasFastProperties()) break; |
1520 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( | 1530 if (!ExecutableAccessorInfo::IsCompatibleReceiverType( |
1521 isolate(), info, receiver_type())) { | 1531 isolate(), info, receiver_type())) { |
1522 break; | 1532 break; |
1523 } | 1533 } |
| 1534 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), |
| 1535 holder); |
1524 return compiler.CompileStoreCallback(receiver, name, info); | 1536 return compiler.CompileStoreCallback(receiver, name, info); |
1525 } else if (callback->IsAccessorPair()) { | 1537 } else if (callback->IsAccessorPair()) { |
1526 Handle<Object> setter( | 1538 Handle<Object> setter( |
1527 Handle<AccessorPair>::cast(callback)->setter(), isolate()); | 1539 Handle<AccessorPair>::cast(callback)->setter(), isolate()); |
1528 if (!setter->IsJSFunction()) break; | 1540 if (!setter->IsJSFunction()) break; |
1529 if (holder->IsGlobalObject()) break; | 1541 if (holder->IsGlobalObject()) break; |
1530 if (!holder->HasFastProperties()) break; | 1542 if (!holder->HasFastProperties()) break; |
1531 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); | 1543 Handle<JSFunction> function = Handle<JSFunction>::cast(setter); |
1532 CallOptimization call_optimization(function); | 1544 CallOptimization call_optimization(function); |
| 1545 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), |
| 1546 holder); |
1533 if (call_optimization.is_simple_api_call() && | 1547 if (call_optimization.is_simple_api_call() && |
1534 call_optimization.IsCompatibleReceiver(receiver, holder)) { | 1548 call_optimization.IsCompatibleReceiver(receiver, holder)) { |
1535 return compiler.CompileStoreCallback(receiver, name, | 1549 return compiler.CompileStoreCallback(receiver, name, |
1536 call_optimization); | 1550 call_optimization); |
1537 } | 1551 } |
1538 return compiler.CompileStoreViaSetter( | 1552 return compiler.CompileStoreViaSetter( |
1539 receiver, name, Handle<JSFunction>::cast(setter)); | 1553 receiver, name, Handle<JSFunction>::cast(setter)); |
1540 } | 1554 } |
1541 // TODO(dcarney): Handle correctly. | 1555 // TODO(dcarney): Handle correctly. |
1542 DCHECK(callback->IsDeclaredAccessorInfo()); | 1556 DCHECK(callback->IsDeclaredAccessorInfo()); |
1543 break; | 1557 break; |
1544 } | 1558 } |
1545 case INTERCEPTOR: | 1559 case INTERCEPTOR: { |
1546 DCHECK(HasInterceptorSetter(*holder)); | 1560 DCHECK(HasInterceptorSetter(*holder)); |
| 1561 NamedStoreHandlerCompiler compiler(isolate(), receiver_type(), holder); |
1547 return compiler.CompileStoreInterceptor(name); | 1562 return compiler.CompileStoreInterceptor(name); |
| 1563 } |
1548 case CONSTANT: | 1564 case CONSTANT: |
1549 break; | 1565 break; |
1550 case NONEXISTENT: | 1566 case NONEXISTENT: |
1551 case HANDLER: | 1567 case HANDLER: |
1552 UNREACHABLE(); | 1568 UNREACHABLE(); |
1553 break; | 1569 break; |
1554 } | 1570 } |
1555 } | 1571 } |
1556 return slow_stub(); | 1572 return slow_stub(); |
1557 } | 1573 } |
(...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3105 #undef ADDR | 3121 #undef ADDR |
3106 }; | 3122 }; |
3107 | 3123 |
3108 | 3124 |
3109 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3125 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
3110 return IC_utilities[id]; | 3126 return IC_utilities[id]; |
3111 } | 3127 } |
3112 | 3128 |
3113 | 3129 |
3114 } } // namespace v8::internal | 3130 } } // namespace v8::internal |
OLD | NEW |