Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: src/ic.cc

Issue 8068026: Begin to handlify the stub cache. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ic.h ('k') | src/runtime.cc » ('j') | src/stub-cache.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 831 matching lines...) Expand 10 before | Expand all | Expand 10 after
842 if (FLAG_use_ic) { 842 if (FLAG_use_ic) {
843 // Use specialized code for getting the length of strings and 843 // Use specialized code for getting the length of strings and
844 // string wrapper objects. The length property of string wrapper 844 // string wrapper objects. The length property of string wrapper
845 // objects is read-only and therefore always returns the length of 845 // objects is read-only and therefore always returns the length of
846 // the underlying string value. See ECMA-262 15.5.5.1. 846 // the underlying string value. See ECMA-262 15.5.5.1.
847 if ((object->IsString() || object->IsStringWrapper()) && 847 if ((object->IsString() || object->IsStringWrapper()) &&
848 name->Equals(isolate()->heap()->length_symbol())) { 848 name->Equals(isolate()->heap()->length_symbol())) {
849 AssertNoAllocation no_allocation; 849 AssertNoAllocation no_allocation;
850 Code* stub = NULL; 850 Code* stub = NULL;
851 if (state == UNINITIALIZED) { 851 if (state == UNINITIALIZED) {
852 stub = pre_monomorphic_stub(); 852 stub = *pre_monomorphic_stub();
853 } else if (state == PREMONOMORPHIC) { 853 } else if (state == PREMONOMORPHIC) {
854 if (object->IsString()) { 854 if (object->IsString()) {
855 stub = isolate()->builtins()->builtin( 855 stub = isolate()->builtins()->builtin(
856 Builtins::kLoadIC_StringLength); 856 Builtins::kLoadIC_StringLength);
857 } else { 857 } else {
858 stub = isolate()->builtins()->builtin( 858 stub = isolate()->builtins()->builtin(
859 Builtins::kLoadIC_StringWrapperLength); 859 Builtins::kLoadIC_StringWrapperLength);
860 } 860 }
861 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { 861 } else if (state == MONOMORPHIC && object->IsStringWrapper()) {
862 stub = isolate()->builtins()->builtin( 862 stub = isolate()->builtins()->builtin(
863 Builtins::kLoadIC_StringWrapperLength); 863 Builtins::kLoadIC_StringWrapperLength);
864 } else if (state != MEGAMORPHIC) { 864 } else if (state != MEGAMORPHIC) {
865 stub = megamorphic_stub(); 865 stub = *megamorphic_stub();
866 } 866 }
867 if (stub != NULL) { 867 if (stub != NULL) {
868 set_target(stub); 868 set_target(stub);
869 #ifdef DEBUG 869 #ifdef DEBUG
870 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); 870 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n");
871 #endif 871 #endif
872 } 872 }
873 // Get the string if we have a string wrapper object. 873 // Get the string if we have a string wrapper object.
874 if (object->IsJSValue()) { 874 if (object->IsJSValue()) {
875 return Smi::FromInt( 875 return Smi::FromInt(
876 String::cast(Handle<JSValue>::cast(object)->value())->length()); 876 String::cast(Handle<JSValue>::cast(object)->value())->length());
877 } 877 }
878 return Smi::FromInt(String::cast(*object)->length()); 878 return Smi::FromInt(String::cast(*object)->length());
879 } 879 }
880 880
881 // Use specialized code for getting the length of arrays. 881 // Use specialized code for getting the length of arrays.
882 if (object->IsJSArray() && 882 if (object->IsJSArray() &&
883 name->Equals(isolate()->heap()->length_symbol())) { 883 name->Equals(isolate()->heap()->length_symbol())) {
884 AssertNoAllocation no_allocation; 884 AssertNoAllocation no_allocation;
885 Code* stub = NULL; 885 Code* stub = NULL;
886 if (state == UNINITIALIZED) { 886 if (state == UNINITIALIZED) {
887 stub = pre_monomorphic_stub(); 887 stub = *pre_monomorphic_stub();
888 } else if (state == PREMONOMORPHIC) { 888 } else if (state == PREMONOMORPHIC) {
889 stub = isolate()->builtins()->builtin( 889 stub = isolate()->builtins()->builtin(
890 Builtins::kLoadIC_ArrayLength); 890 Builtins::kLoadIC_ArrayLength);
891 } else if (state != MEGAMORPHIC) { 891 } else if (state != MEGAMORPHIC) {
892 stub = megamorphic_stub(); 892 stub = *megamorphic_stub();
893 } 893 }
894 if (stub != NULL) { 894 if (stub != NULL) {
895 set_target(stub); 895 set_target(stub);
896 #ifdef DEBUG 896 #ifdef DEBUG
897 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); 897 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n");
898 #endif 898 #endif
899 } 899 }
900 return JSArray::cast(*object)->length(); 900 return JSArray::cast(*object)->length();
901 } 901 }
902 902
903 // Use specialized code for getting prototype of functions. 903 // Use specialized code for getting prototype of functions.
904 if (object->IsJSFunction() && 904 if (object->IsJSFunction() &&
905 name->Equals(isolate()->heap()->prototype_symbol()) && 905 name->Equals(isolate()->heap()->prototype_symbol()) &&
906 JSFunction::cast(*object)->should_have_prototype()) { 906 JSFunction::cast(*object)->should_have_prototype()) {
907 { AssertNoAllocation no_allocation; 907 { AssertNoAllocation no_allocation;
908 Code* stub = NULL; 908 Code* stub = NULL;
909 if (state == UNINITIALIZED) { 909 if (state == UNINITIALIZED) {
910 stub = pre_monomorphic_stub(); 910 stub = *pre_monomorphic_stub();
911 } else if (state == PREMONOMORPHIC) { 911 } else if (state == PREMONOMORPHIC) {
912 stub = isolate()->builtins()->builtin( 912 stub = isolate()->builtins()->builtin(
913 Builtins::kLoadIC_FunctionPrototype); 913 Builtins::kLoadIC_FunctionPrototype);
914 } else if (state != MEGAMORPHIC) { 914 } else if (state != MEGAMORPHIC) {
915 stub = megamorphic_stub(); 915 stub = *megamorphic_stub();
916 } 916 }
917 if (stub != NULL) { 917 if (stub != NULL) {
918 set_target(stub); 918 set_target(stub);
919 #ifdef DEBUG 919 #ifdef DEBUG
920 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); 920 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n");
921 #endif 921 #endif
922 } 922 }
923 } 923 }
924 return Accessors::FunctionGetPrototype(*object, 0); 924 return Accessors::FunctionGetPrototype(*object, 0);
925 } 925 }
(...skipping 11 matching lines...) Expand all
937 // If we did not find a property, check if we need to throw an exception. 937 // If we did not find a property, check if we need to throw an exception.
938 if (!lookup.IsProperty()) { 938 if (!lookup.IsProperty()) {
939 if (IsContextual(object)) { 939 if (IsContextual(object)) {
940 return ReferenceError("not_defined", name); 940 return ReferenceError("not_defined", name);
941 } 941 }
942 LOG(isolate(), SuspectReadEvent(*name, *object)); 942 LOG(isolate(), SuspectReadEvent(*name, *object));
943 } 943 }
944 944
945 // Update inline cache and stub cache. 945 // Update inline cache and stub cache.
946 if (FLAG_use_ic) { 946 if (FLAG_use_ic) {
947 UpdateCaches(&lookup, state, object, name); 947 UpdateCaches(&lookup, state, object, name);
ulan 2011/10/13 17:36:10 Can lookup.holder() become stale if this call caus
fschneider 2011/10/14 07:42:11 I think you're right, because LookupResult has a r
948 } 948 }
949 949
950 PropertyAttributes attr; 950 PropertyAttributes attr;
951 if (lookup.IsProperty() && 951 if (lookup.IsProperty() &&
952 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { 952 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) {
953 // Get the property. 953 // Get the property.
954 Object* result; 954 Object* result;
955 { MaybeObject* maybe_result = 955 { MaybeObject* maybe_result =
956 object->GetProperty(*object, &lookup, *name, &attr); 956 object->GetProperty(*object, &lookup, *name, &attr);
957 if (!maybe_result->ToObject(&result)) return maybe_result; 957 if (!maybe_result->ToObject(&result)) return maybe_result;
(...skipping 19 matching lines...) Expand all
977 if (!lookup->IsCacheable()) return; 977 if (!lookup->IsCacheable()) return;
978 978
979 // Loading properties from values is not common, so don't try to 979 // Loading properties from values is not common, so don't try to
980 // deal with non-JS objects here. 980 // deal with non-JS objects here.
981 if (!object->IsJSObject()) return; 981 if (!object->IsJSObject()) return;
982 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 982 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
983 983
984 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; 984 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return;
985 985
986 // Compute the code stub for this load. 986 // Compute the code stub for this load.
987 MaybeObject* maybe_code = NULL; 987 HandleScope scope(isolate());
Kevin Millikin (Chromium) 2011/09/29 09:21:32 Before, we created this handle scope only in the c
988 Object* code; 988 Handle<Code> code;
989 if (state == UNINITIALIZED) { 989 if (state == UNINITIALIZED) {
990 // This is the first time we execute this inline cache. 990 // This is the first time we execute this inline cache.
991 // Set the target to the pre monomorphic stub to delay 991 // Set the target to the pre monomorphic stub to delay
992 // setting the monomorphic state. 992 // setting the monomorphic state.
993 maybe_code = pre_monomorphic_stub(); 993 code = pre_monomorphic_stub();
994 } else if (!lookup->IsProperty()) { 994 } else if (!lookup->IsProperty()) {
995 // Nonexistent property. The result is undefined. 995 // Nonexistent property. The result is undefined.
996 maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name, 996 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver);
997 *receiver);
998 } else { 997 } else {
999 // Compute monomorphic stub. 998 // Compute monomorphic stub.
999 Handle<JSObject> holder(lookup->holder());
1000 switch (lookup->type()) { 1000 switch (lookup->type()) {
1001 case FIELD: { 1001 case FIELD:
1002 maybe_code = isolate()->stub_cache()->ComputeLoadField( 1002 code = isolate()->stub_cache()->ComputeLoadField(
1003 *name, 1003 name, receiver, holder, lookup->GetFieldIndex());
1004 *receiver, 1004 break;
1005 lookup->holder(), 1005 case CONSTANT_FUNCTION: {
1006 lookup->GetFieldIndex()); 1006 Handle<Object> constant(lookup->GetConstantFunction());
1007 code = isolate()->stub_cache()->ComputeLoadConstant(
1008 name, receiver, holder, constant);
1007 break; 1009 break;
1008 } 1010 }
1009 case CONSTANT_FUNCTION: { 1011 case NORMAL:
1010 Object* constant = lookup->GetConstantFunction(); 1012 if (holder->IsGlobalObject()) {
1011 maybe_code = isolate()->stub_cache()->ComputeLoadConstant( 1013 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder);
1012 *name, *receiver, lookup->holder(), constant); 1014 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup));
1013 break; 1015 code = isolate()->stub_cache()->ComputeLoadGlobal(
1014 } 1016 name, receiver, global, cell, lookup->IsDontDelete());
1015 case NORMAL: {
1016 if (lookup->holder()->IsGlobalObject()) {
1017 GlobalObject* global = GlobalObject::cast(lookup->holder());
1018 JSGlobalPropertyCell* cell =
1019 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup));
1020 maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name,
1021 *receiver,
1022 global,
1023 cell,
1024 lookup->IsDontDelete());
1025 } else { 1017 } else {
1026 // There is only one shared stub for loading normalized 1018 // There is only one shared stub for loading normalized
1027 // properties. It does not traverse the prototype chain, so the 1019 // properties. It does not traverse the prototype chain, so the
1028 // property must be found in the receiver for the stub to be 1020 // property must be found in the receiver for the stub to be
1029 // applicable. 1021 // applicable.
1030 if (lookup->holder() != *receiver) return; 1022 if (!holder.is_identical_to(receiver)) return;
1031 maybe_code = isolate()->stub_cache()->ComputeLoadNormal(); 1023 code = isolate()->stub_cache()->ComputeLoadNormal();
1032 } 1024 }
1033 break; 1025 break;
1034 }
1035 case CALLBACKS: { 1026 case CALLBACKS: {
1036 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; 1027 Handle<Object> callback_object(lookup->GetCallbackObject());
1037 AccessorInfo* callback = 1028 if (!callback_object->IsAccessorInfo()) return;
1038 AccessorInfo::cast(lookup->GetCallbackObject()); 1029 Handle<AccessorInfo> callback =
1030 Handle<AccessorInfo>::cast(callback_object);
1039 if (v8::ToCData<Address>(callback->getter()) == 0) return; 1031 if (v8::ToCData<Address>(callback->getter()) == 0) return;
1040 maybe_code = isolate()->stub_cache()->ComputeLoadCallback( 1032 code = isolate()->stub_cache()->ComputeLoadCallback(
1041 *name, *receiver, lookup->holder(), callback); 1033 name, receiver, holder, callback);
1042 break; 1034 break;
1043 } 1035 }
1044 case INTERCEPTOR: { 1036 case INTERCEPTOR:
1045 ASSERT(HasInterceptorGetter(lookup->holder())); 1037 ASSERT(HasInterceptorGetter(*holder));
1046 maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor( 1038 code = isolate()->stub_cache()->ComputeLoadInterceptor(
1047 *name, *receiver, lookup->holder()); 1039 name, receiver, holder);
1048 break; 1040 break;
1049 }
1050 default: 1041 default:
1051 return; 1042 return;
1052 } 1043 }
1053 } 1044 }
1054 1045
1055 // If we're unable to compute the stub (not enough memory left), we
1056 // simply avoid updating the caches.
1057 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return;
1058
1059 // Patch the call site depending on the state of the cache. 1046 // Patch the call site depending on the state of the cache.
1060 if (state == UNINITIALIZED || state == PREMONOMORPHIC || 1047 if (state == UNINITIALIZED ||
1048 state == PREMONOMORPHIC ||
1061 state == MONOMORPHIC_PROTOTYPE_FAILURE) { 1049 state == MONOMORPHIC_PROTOTYPE_FAILURE) {
1062 set_target(Code::cast(code)); 1050 set_target(*code);
1063 } else if (state == MONOMORPHIC) { 1051 } else if (state == MONOMORPHIC) {
1064 set_target(megamorphic_stub()); 1052 set_target(*megamorphic_stub());
1065 } else if (state == MEGAMORPHIC) { 1053 } else if (state == MEGAMORPHIC) {
1066 // Cache code holding map should be consistent with 1054 // Cache code holding map should be consistent with
1067 // GenerateMonomorphicCacheProbe. 1055 // GenerateMonomorphicCacheProbe.
1068 Map* map = JSObject::cast(object->IsJSObject() ? *object : 1056 isolate()->stub_cache()->Set(*name, receiver->map(), *code);
1069 object->GetPrototype())->map();
1070
1071 isolate()->stub_cache()->Set(*name, map, Code::cast(code));
1072 } 1057 }
1073 1058
1074 #ifdef DEBUG 1059 #ifdef DEBUG
1075 TraceIC("LoadIC", name, state, target()); 1060 TraceIC("LoadIC", name, state, target());
1076 #endif 1061 #endif
1077 } 1062 }
1078 1063
1079 1064
1080 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( 1065 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck(
1081 bool is_js_array, 1066 bool is_js_array,
1082 ElementsKind elements_kind) { 1067 ElementsKind elements_kind) {
1083 return KeyedLoadElementStub(elements_kind).TryGetCode(); 1068 return KeyedLoadElementStub(elements_kind).TryGetCode();
1084 } 1069 }
1085 1070
1086 1071
1087 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub( 1072 MaybeObject* KeyedLoadIC::ConstructMegamorphicStub(
1088 MapList* receiver_maps, 1073 MapList* receiver_maps,
1089 CodeList* targets, 1074 CodeList* targets,
1090 StrictModeFlag strict_mode) { 1075 StrictModeFlag strict_mode) {
1091 Object* object; 1076 Object* object;
1092 KeyedLoadStubCompiler compiler; 1077 HandleScope scope(isolate());
1078 KeyedLoadStubCompiler compiler(isolate());
1093 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps, 1079 MaybeObject* maybe_code = compiler.CompileLoadMegamorphic(receiver_maps,
1094 targets); 1080 targets);
1095 if (!maybe_code->ToObject(&object)) return maybe_code; 1081 if (!maybe_code->ToObject(&object)) return maybe_code;
1096 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); 1082 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment();
1097 PROFILE(isolate(), CodeCreateEvent( 1083 PROFILE(isolate(), CodeCreateEvent(
1098 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, 1084 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG,
1099 Code::cast(object), 0)); 1085 Code::cast(object), 0));
1100 return object; 1086 return object;
1101 } 1087 }
1102 1088
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after
1709 ElementsKind elements_kind) { 1695 ElementsKind elements_kind) {
1710 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode(); 1696 return KeyedStoreElementStub(is_js_array, elements_kind).TryGetCode();
1711 } 1697 }
1712 1698
1713 1699
1714 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub( 1700 MaybeObject* KeyedStoreIC::ConstructMegamorphicStub(
1715 MapList* receiver_maps, 1701 MapList* receiver_maps,
1716 CodeList* targets, 1702 CodeList* targets,
1717 StrictModeFlag strict_mode) { 1703 StrictModeFlag strict_mode) {
1718 Object* object; 1704 Object* object;
1719 KeyedStoreStubCompiler compiler(strict_mode); 1705 HandleScope scope(isolate());
1706 KeyedStoreStubCompiler compiler(isolate(), strict_mode);
1720 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps, 1707 MaybeObject* maybe_code = compiler.CompileStoreMegamorphic(receiver_maps,
1721 targets); 1708 targets);
1722 if (!maybe_code->ToObject(&object)) return maybe_code; 1709 if (!maybe_code->ToObject(&object)) return maybe_code;
1723 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); 1710 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment();
1724 PROFILE(isolate(), CodeCreateEvent( 1711 PROFILE(isolate(), CodeCreateEvent(
1725 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, 1712 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG,
1726 Code::cast(object), 0)); 1713 Code::cast(object), 0));
1727 return object; 1714 return object;
1728 } 1715 }
1729 1716
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after
2508 #undef ADDR 2495 #undef ADDR
2509 }; 2496 };
2510 2497
2511 2498
2512 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2499 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2513 return IC_utilities[id]; 2500 return IC_utilities[id];
2514 } 2501 }
2515 2502
2516 2503
2517 } } // namespace v8::internal 2504 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ic.h ('k') | src/runtime.cc » ('j') | src/stub-cache.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698