OLD | NEW |
---|---|
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 353 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
364 | 364 |
365 | 365 |
366 static bool HasInterceptorGetter(JSObject* object) { | 366 static bool HasInterceptorGetter(JSObject* object) { |
367 return !object->GetNamedInterceptor()->getter()->IsUndefined(); | 367 return !object->GetNamedInterceptor()->getter()->IsUndefined(); |
368 } | 368 } |
369 | 369 |
370 | 370 |
371 static void LookupForRead(Object* object, | 371 static void LookupForRead(Object* object, |
372 String* name, | 372 String* name, |
373 LookupResult* lookup) { | 373 LookupResult* lookup) { |
374 AssertNoAllocation no_gc; // pointers must stay valid | |
Kevin Millikin (Chromium)
2011/10/18 08:46:47
Can we restore this assert scope in the raw pointe
ulan
2011/10/18 09:31:00
Done.
| |
375 | |
376 // Skip all the objects with named interceptors, but | 374 // Skip all the objects with named interceptors, but |
377 // without actual getter. | 375 // without actual getter. |
378 while (true) { | 376 while (true) { |
379 object->Lookup(name, lookup); | 377 object->Lookup(name, lookup); |
380 // Besides normal conditions (property not found or it's not | 378 // Besides normal conditions (property not found or it's not |
381 // an interceptor), bail out if lookup is not cacheable: we won't | 379 // an interceptor), bail out if lookup is not cacheable: we won't |
382 // be able to IC it anyway and regular lookup should work fine. | 380 // be able to IC it anyway and regular lookup should work fine. |
383 if (!lookup->IsFound() | 381 if (!lookup->IsFound() |
384 || (lookup->type() != INTERCEPTOR) | 382 || (lookup->type() != INTERCEPTOR) |
385 || !lookup->IsCacheable()) { | 383 || !lookup->IsCacheable()) { |
(...skipping 15 matching lines...) Expand all Loading... | |
401 if (proto->IsNull()) { | 399 if (proto->IsNull()) { |
402 lookup->NotFound(); | 400 lookup->NotFound(); |
403 return; | 401 return; |
404 } | 402 } |
405 | 403 |
406 object = proto; | 404 object = proto; |
407 } | 405 } |
408 } | 406 } |
409 | 407 |
410 | 408 |
409 static void LookupForRead(Handle<Object> object, | |
410 Handle<String> name, | |
411 LookupResult* lookup) { | |
412 // Skip all the objects with named interceptors, but | |
413 // without actual getter. | |
414 while (true) { | |
415 object->Lookup(*name, lookup); | |
416 // Besides normal conditions (property not found or it's not | |
417 // an interceptor), bail out if lookup is not cacheable: we won't | |
418 // be able to IC it anyway and regular lookup should work fine. | |
419 if (!lookup->IsFound() | |
420 || (lookup->type() != INTERCEPTOR) | |
421 || !lookup->IsCacheable()) { | |
422 return; | |
423 } | |
424 | |
425 Handle<JSObject> holder(lookup->holder()); | |
426 if (HasInterceptorGetter(*holder)) { | |
427 return; | |
428 } | |
429 | |
430 holder->LocalLookupRealNamedProperty(*name, lookup); | |
431 if (lookup->IsProperty()) { | |
432 ASSERT(lookup->type() != INTERCEPTOR); | |
433 return; | |
434 } | |
435 | |
436 Handle<Object> proto(holder->GetPrototype()); | |
437 if (proto->IsNull()) { | |
438 lookup->NotFound(); | |
439 return; | |
440 } | |
441 | |
442 object = proto; | |
443 } | |
444 } | |
445 | |
446 | |
411 Object* CallICBase::TryCallAsFunction(Object* object) { | 447 Object* CallICBase::TryCallAsFunction(Object* object) { |
412 HandleScope scope(isolate()); | 448 HandleScope scope(isolate()); |
413 Handle<Object> target(object, isolate()); | 449 Handle<Object> target(object, isolate()); |
414 Handle<Object> delegate = Execution::GetFunctionDelegate(target); | 450 Handle<Object> delegate = Execution::GetFunctionDelegate(target); |
415 | 451 |
416 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { | 452 if (delegate->IsJSFunction() && !object->IsJSFunctionProxy()) { |
417 // Patch the receiver and use the delegate as the function to | 453 // Patch the receiver and use the delegate as the function to |
418 // invoke. This is used for invoking objects as if they were | 454 // invoke. This is used for invoking objects as if they were |
419 // functions. | 455 // functions. |
420 const int argc = this->target()->arguments_count(); | 456 const int argc = this->target()->arguments_count(); |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
843 return TypeError("non_object_property_load", object, name); | 879 return TypeError("non_object_property_load", object, name); |
844 } | 880 } |
845 | 881 |
846 if (FLAG_use_ic) { | 882 if (FLAG_use_ic) { |
847 // Use specialized code for getting the length of strings and | 883 // Use specialized code for getting the length of strings and |
848 // string wrapper objects. The length property of string wrapper | 884 // string wrapper objects. The length property of string wrapper |
849 // objects is read-only and therefore always returns the length of | 885 // objects is read-only and therefore always returns the length of |
850 // the underlying string value. See ECMA-262 15.5.5.1. | 886 // the underlying string value. See ECMA-262 15.5.5.1. |
851 if ((object->IsString() || object->IsStringWrapper()) && | 887 if ((object->IsString() || object->IsStringWrapper()) && |
852 name->Equals(isolate()->heap()->length_symbol())) { | 888 name->Equals(isolate()->heap()->length_symbol())) { |
853 AssertNoAllocation no_allocation; | 889 Handle<Code> stub; |
854 Code* stub = NULL; | |
855 if (state == UNINITIALIZED) { | 890 if (state == UNINITIALIZED) { |
856 stub = pre_monomorphic_stub(); | 891 stub = pre_monomorphic_stub(); |
857 } else if (state == PREMONOMORPHIC) { | 892 } else if (state == PREMONOMORPHIC) { |
858 if (object->IsString()) { | 893 stub = object->IsString() |
859 stub = isolate()->builtins()->builtin( | 894 ? isolate()->builtins()->LoadIC_StringLength() |
860 Builtins::kLoadIC_StringLength); | 895 : isolate()->builtins()->LoadIC_StringWrapperLength(); |
861 } else { | |
862 stub = isolate()->builtins()->builtin( | |
863 Builtins::kLoadIC_StringWrapperLength); | |
864 } | |
865 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | 896 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { |
866 stub = isolate()->builtins()->builtin( | 897 stub = isolate()->builtins()->LoadIC_StringWrapperLength(); |
867 Builtins::kLoadIC_StringWrapperLength); | |
868 } else if (state != MEGAMORPHIC) { | 898 } else if (state != MEGAMORPHIC) { |
869 stub = megamorphic_stub(); | 899 stub = megamorphic_stub(); |
870 } | 900 } |
871 if (stub != NULL) { | 901 if (!stub.is_null()) { |
872 set_target(stub); | 902 set_target(*stub); |
873 #ifdef DEBUG | 903 #ifdef DEBUG |
874 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 904 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); |
875 #endif | 905 #endif |
876 } | 906 } |
877 // Get the string if we have a string wrapper object. | 907 // Get the string if we have a string wrapper object. |
878 if (object->IsJSValue()) { | 908 Handle<Object> string = object->IsJSValue() |
879 return Smi::FromInt( | 909 ? Handle<Object>(Handle<JSValue>::cast(object)->value()) |
880 String::cast(Handle<JSValue>::cast(object)->value())->length()); | 910 : object; |
881 } | 911 return Smi::FromInt(String::cast(*string)->length()); |
882 return Smi::FromInt(String::cast(*object)->length()); | |
883 } | 912 } |
884 | 913 |
885 // Use specialized code for getting the length of arrays. | 914 // Use specialized code for getting the length of arrays. |
886 if (object->IsJSArray() && | 915 if (object->IsJSArray() && |
887 name->Equals(isolate()->heap()->length_symbol())) { | 916 name->Equals(isolate()->heap()->length_symbol())) { |
888 AssertNoAllocation no_allocation; | 917 Handle<Code> stub; |
889 Code* stub = NULL; | |
890 if (state == UNINITIALIZED) { | 918 if (state == UNINITIALIZED) { |
891 stub = pre_monomorphic_stub(); | 919 stub = pre_monomorphic_stub(); |
892 } else if (state == PREMONOMORPHIC) { | 920 } else if (state == PREMONOMORPHIC) { |
893 stub = isolate()->builtins()->builtin( | 921 stub = isolate()->builtins()->LoadIC_ArrayLength(); |
894 Builtins::kLoadIC_ArrayLength); | |
895 } else if (state != MEGAMORPHIC) { | 922 } else if (state != MEGAMORPHIC) { |
896 stub = megamorphic_stub(); | 923 stub = megamorphic_stub(); |
897 } | 924 } |
898 if (stub != NULL) { | 925 if (!stub.is_null()) { |
899 set_target(stub); | 926 set_target(*stub); |
900 #ifdef DEBUG | 927 #ifdef DEBUG |
901 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); | 928 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /array]\n"); |
902 #endif | 929 #endif |
903 } | 930 } |
904 return JSArray::cast(*object)->length(); | 931 return JSArray::cast(*object)->length(); |
905 } | 932 } |
906 | 933 |
907 // Use specialized code for getting prototype of functions. | 934 // Use specialized code for getting prototype of functions. |
908 if (object->IsJSFunction() && | 935 if (object->IsJSFunction() && |
909 name->Equals(isolate()->heap()->prototype_symbol()) && | 936 name->Equals(isolate()->heap()->prototype_symbol()) && |
910 JSFunction::cast(*object)->should_have_prototype()) { | 937 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
911 { AssertNoAllocation no_allocation; | 938 Handle<Code> stub; |
Kevin Millikin (Chromium)
2011/10/18 08:46:47
Indentation of the body is wrong (too far to the r
ulan
2011/10/18 09:31:00
Done.
| |
912 Code* stub = NULL; | |
913 if (state == UNINITIALIZED) { | 939 if (state == UNINITIALIZED) { |
914 stub = pre_monomorphic_stub(); | 940 stub = pre_monomorphic_stub(); |
915 } else if (state == PREMONOMORPHIC) { | 941 } else if (state == PREMONOMORPHIC) { |
916 stub = isolate()->builtins()->builtin( | 942 stub = isolate()->builtins()->LoadIC_FunctionPrototype(); |
917 Builtins::kLoadIC_FunctionPrototype); | |
918 } else if (state != MEGAMORPHIC) { | 943 } else if (state != MEGAMORPHIC) { |
919 stub = megamorphic_stub(); | 944 stub = megamorphic_stub(); |
920 } | 945 } |
921 if (stub != NULL) { | 946 if (!stub.is_null()) { |
922 set_target(stub); | 947 set_target(*stub); |
923 #ifdef DEBUG | 948 #ifdef DEBUG |
924 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); | 949 if (FLAG_trace_ic) PrintF("[LoadIC : +#prototype /function]\n"); |
925 #endif | 950 #endif |
926 } | 951 } |
927 } | |
928 return Accessors::FunctionGetPrototype(*object, 0); | 952 return Accessors::FunctionGetPrototype(*object, 0); |
929 } | 953 } |
930 } | 954 } |
931 | 955 |
932 // Check if the name is trivially convertible to an index and get | 956 // Check if the name is trivially convertible to an index and get |
933 // the element if so. | 957 // the element if so. |
934 uint32_t index; | 958 uint32_t index; |
935 if (name->AsArrayIndex(&index)) return object->GetElement(index); | 959 if (name->AsArrayIndex(&index)) return object->GetElement(index); |
936 | 960 |
937 // Named lookup in the object. | 961 // Named lookup in the object. |
938 LookupResult lookup; | 962 LookupResult lookup; |
939 LookupForRead(*object, *name, &lookup); | 963 LookupForRead(object, name, &lookup); |
940 | 964 |
941 // If we did not find a property, check if we need to throw an exception. | 965 // If we did not find a property, check if we need to throw an exception. |
942 if (!lookup.IsProperty()) { | 966 if (!lookup.IsProperty()) { |
943 if (IsContextual(object)) { | 967 if (IsContextual(object)) { |
944 return ReferenceError("not_defined", name); | 968 return ReferenceError("not_defined", name); |
945 } | 969 } |
946 LOG(isolate(), SuspectReadEvent(*name, *object)); | 970 LOG(isolate(), SuspectReadEvent(*name, *object)); |
947 } | 971 } |
948 | 972 |
949 // Update inline cache and stub cache. | 973 // Update inline cache and stub cache. |
950 if (FLAG_use_ic) { | 974 if (FLAG_use_ic) { |
951 UpdateCaches(&lookup, state, object, name); | 975 UpdateCaches(&lookup, state, object, name); |
952 } | 976 } |
953 | 977 |
954 PropertyAttributes attr; | 978 PropertyAttributes attr; |
955 if (lookup.IsProperty() && | 979 if (lookup.IsProperty() && |
956 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { | 980 (lookup.type() == INTERCEPTOR || lookup.type() == HANDLER)) { |
957 // Get the property. | 981 // Get the property. |
958 Object* result; | 982 Handle<Object> result = |
959 { MaybeObject* maybe_result = | 983 Object::GetProperty(isolate(), object, object, &lookup, name, &attr); |
960 object->GetProperty(*object, &lookup, *name, &attr); | 984 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
961 if (!maybe_result->ToObject(&result)) return maybe_result; | |
962 } | |
963 // If the property is not present, check if we need to throw an | 985 // If the property is not present, check if we need to throw an |
964 // exception. | 986 // exception. |
965 if (attr == ABSENT && IsContextual(object)) { | 987 if (attr == ABSENT && IsContextual(object)) { |
966 return ReferenceError("not_defined", name); | 988 return ReferenceError("not_defined", name); |
967 } | 989 } |
968 return result; | 990 return *result; |
969 } | 991 } |
970 | 992 |
971 // Get the property. | 993 // Get the property. |
972 return object->GetProperty(*object, &lookup, *name, &attr); | 994 return object->GetProperty(*object, &lookup, *name, &attr); |
973 } | 995 } |
974 | 996 |
975 | 997 |
976 void LoadIC::UpdateCaches(LookupResult* lookup, | 998 void LoadIC::UpdateCaches(LookupResult* lookup, |
977 State state, | 999 State state, |
978 Handle<Object> object, | 1000 Handle<Object> object, |
979 Handle<String> name) { | 1001 Handle<String> name) { |
980 // Bail out if the result is not cacheable. | 1002 // Bail out if the result is not cacheable. |
981 if (!lookup->IsCacheable()) return; | 1003 if (!lookup->IsCacheable()) return; |
982 | 1004 |
983 // Loading properties from values is not common, so don't try to | 1005 // Loading properties from values is not common, so don't try to |
984 // deal with non-JS objects here. | 1006 // deal with non-JS objects here. |
985 if (!object->IsJSObject()) return; | 1007 if (!object->IsJSObject()) return; |
986 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1008 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
987 | 1009 |
988 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; | 1010 if (HasNormalObjectsInPrototypeChain(isolate(), lookup, *object)) return; |
989 | 1011 |
990 // Compute the code stub for this load. | 1012 // Compute the code stub for this load. |
991 MaybeObject* maybe_code = NULL; | 1013 Handle<Code> code; |
992 Object* code; | |
993 if (state == UNINITIALIZED) { | 1014 if (state == UNINITIALIZED) { |
994 // This is the first time we execute this inline cache. | 1015 // This is the first time we execute this inline cache. |
995 // Set the target to the pre monomorphic stub to delay | 1016 // Set the target to the pre monomorphic stub to delay |
996 // setting the monomorphic state. | 1017 // setting the monomorphic state. |
997 maybe_code = pre_monomorphic_stub(); | 1018 code = pre_monomorphic_stub(); |
998 } else if (!lookup->IsProperty()) { | 1019 } else if (!lookup->IsProperty()) { |
999 // Nonexistent property. The result is undefined. | 1020 // Nonexistent property. The result is undefined. |
1000 maybe_code = isolate()->stub_cache()->ComputeLoadNonexistent(*name, | 1021 code = isolate()->stub_cache()->ComputeLoadNonexistent(name, receiver); |
1001 *receiver); | |
1002 } else { | 1022 } else { |
1003 // Compute monomorphic stub. | 1023 // Compute monomorphic stub. |
1024 Handle<JSObject> holder(lookup->holder()); | |
1004 switch (lookup->type()) { | 1025 switch (lookup->type()) { |
1005 case FIELD: { | 1026 case FIELD: |
1006 maybe_code = isolate()->stub_cache()->ComputeLoadField( | 1027 code = isolate()->stub_cache()->ComputeLoadField( |
1007 *name, | 1028 name, receiver, holder, lookup->GetFieldIndex()); |
1008 *receiver, | 1029 break; |
1009 lookup->holder(), | 1030 case CONSTANT_FUNCTION: { |
1010 lookup->GetFieldIndex()); | 1031 Handle<Object> constant(lookup->GetConstantFunction()); |
1032 code = isolate()->stub_cache()->ComputeLoadConstant( | |
1033 name, receiver, holder, constant); | |
1011 break; | 1034 break; |
1012 } | 1035 } |
1013 case CONSTANT_FUNCTION: { | 1036 case NORMAL: |
1014 Object* constant = lookup->GetConstantFunction(); | 1037 if (holder->IsGlobalObject()) { |
1015 maybe_code = isolate()->stub_cache()->ComputeLoadConstant( | 1038 Handle<GlobalObject> global = Handle<GlobalObject>::cast(holder); |
1016 *name, *receiver, lookup->holder(), constant); | 1039 Handle<JSGlobalPropertyCell> cell(global->GetPropertyCell(lookup)); |
1017 break; | 1040 code = isolate()->stub_cache()->ComputeLoadGlobal( |
1018 } | 1041 name, receiver, global, cell, lookup->IsDontDelete()); |
1019 case NORMAL: { | |
1020 if (lookup->holder()->IsGlobalObject()) { | |
1021 GlobalObject* global = GlobalObject::cast(lookup->holder()); | |
1022 JSGlobalPropertyCell* cell = | |
1023 JSGlobalPropertyCell::cast(global->GetPropertyCell(lookup)); | |
1024 maybe_code = isolate()->stub_cache()->ComputeLoadGlobal(*name, | |
1025 *receiver, | |
1026 global, | |
1027 cell, | |
1028 lookup->IsDontDelete()); | |
1029 } else { | 1042 } else { |
1030 // There is only one shared stub for loading normalized | 1043 // There is only one shared stub for loading normalized |
1031 // properties. It does not traverse the prototype chain, so the | 1044 // properties. It does not traverse the prototype chain, so the |
1032 // property must be found in the receiver for the stub to be | 1045 // property must be found in the receiver for the stub to be |
1033 // applicable. | 1046 // applicable. |
1034 if (lookup->holder() != *receiver) return; | 1047 if (!holder.is_identical_to(receiver)) return; |
1035 maybe_code = isolate()->stub_cache()->ComputeLoadNormal(); | 1048 code = isolate()->stub_cache()->ComputeLoadNormal(); |
1036 } | 1049 } |
1037 break; | 1050 break; |
1038 } | |
1039 case CALLBACKS: { | 1051 case CALLBACKS: { |
1040 if (!lookup->GetCallbackObject()->IsAccessorInfo()) return; | 1052 Handle<Object> callback_object(lookup->GetCallbackObject()); |
1041 AccessorInfo* callback = | 1053 if (!callback_object->IsAccessorInfo()) return; |
1042 AccessorInfo::cast(lookup->GetCallbackObject()); | 1054 Handle<AccessorInfo> callback(AccessorInfo::cast(*callback_object)); |
1043 if (v8::ToCData<Address>(callback->getter()) == 0) return; | 1055 if (v8::ToCData<Address>(callback->getter()) == 0) return; |
1044 maybe_code = isolate()->stub_cache()->ComputeLoadCallback( | 1056 code = isolate()->stub_cache()->ComputeLoadCallback( |
1045 *name, *receiver, lookup->holder(), callback); | 1057 name, receiver, holder, callback); |
1046 break; | 1058 break; |
1047 } | 1059 } |
1048 case INTERCEPTOR: { | 1060 case INTERCEPTOR: |
1049 ASSERT(HasInterceptorGetter(lookup->holder())); | 1061 ASSERT(HasInterceptorGetter(*holder)); |
1050 maybe_code = isolate()->stub_cache()->ComputeLoadInterceptor( | 1062 code = isolate()->stub_cache()->ComputeLoadInterceptor( |
1051 *name, *receiver, lookup->holder()); | 1063 name, receiver, holder); |
1052 break; | 1064 break; |
1053 } | |
1054 default: | 1065 default: |
1055 return; | 1066 return; |
1056 } | 1067 } |
1057 } | 1068 } |
1058 | 1069 |
1059 // If we're unable to compute the stub (not enough memory left), we | |
1060 // simply avoid updating the caches. | |
1061 if (maybe_code == NULL || !maybe_code->ToObject(&code)) return; | |
1062 | |
1063 // Patch the call site depending on the state of the cache. | 1070 // Patch the call site depending on the state of the cache. |
1064 if (state == UNINITIALIZED || state == PREMONOMORPHIC || | 1071 if (state == UNINITIALIZED || |
1072 state == PREMONOMORPHIC || | |
1065 state == MONOMORPHIC_PROTOTYPE_FAILURE) { | 1073 state == MONOMORPHIC_PROTOTYPE_FAILURE) { |
1066 set_target(Code::cast(code)); | 1074 set_target(*code); |
1067 } else if (state == MONOMORPHIC) { | 1075 } else if (state == MONOMORPHIC) { |
1068 set_target(megamorphic_stub()); | 1076 set_target(*megamorphic_stub()); |
1069 } else if (state == MEGAMORPHIC) { | 1077 } else if (state == MEGAMORPHIC) { |
1070 // Cache code holding map should be consistent with | 1078 // Cache code holding map should be consistent with |
1071 // GenerateMonomorphicCacheProbe. | 1079 // GenerateMonomorphicCacheProbe. |
1072 Map* map = JSObject::cast(object->IsJSObject() ? *object : | 1080 Handle<Map> map(receiver->map()); |
1073 object->GetPrototype())->map(); | 1081 isolate()->stub_cache()->Set(*name, *map, *code); |
Kevin Millikin (Chromium)
2011/10/18 08:46:47
I guess it doesn't make much sense to create a han
ulan
2011/10/18 09:31:00
Done.
| |
1074 | |
1075 isolate()->stub_cache()->Set(*name, map, Code::cast(code)); | |
1076 } | 1082 } |
1077 | 1083 |
1078 #ifdef DEBUG | 1084 #ifdef DEBUG |
1079 TraceIC("LoadIC", name, state, target()); | 1085 TraceIC("LoadIC", name, state, target()); |
1080 #endif | 1086 #endif |
1081 } | 1087 } |
1082 | 1088 |
1083 | 1089 |
1084 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( | 1090 MaybeObject* KeyedLoadIC::GetElementStubWithoutMapCheck( |
1085 bool is_js_array, | 1091 bool is_js_array, |
1086 ElementsKind elements_kind) { | 1092 ElementsKind elements_kind) { |
1087 return KeyedLoadElementStub(elements_kind).TryGetCode(); | 1093 return KeyedLoadElementStub(elements_kind).TryGetCode(); |
1088 } | 1094 } |
1089 | 1095 |
1090 | 1096 |
1091 MaybeObject* KeyedLoadIC::ComputePolymorphicStub( | 1097 MaybeObject* KeyedLoadIC::ComputePolymorphicStub( |
1092 MapList* receiver_maps, | 1098 MapList* receiver_maps, |
1093 StrictModeFlag strict_mode) { | 1099 StrictModeFlag strict_mode) { |
1094 CodeList handler_ics(receiver_maps->length()); | 1100 CodeList handler_ics(receiver_maps->length()); |
1095 for (int i = 0; i < receiver_maps->length(); ++i) { | 1101 for (int i = 0; i < receiver_maps->length(); ++i) { |
1096 Map* receiver_map(receiver_maps->at(i)); | 1102 Map* receiver_map(receiver_maps->at(i)); |
1097 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( | 1103 MaybeObject* maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( |
1098 receiver_map, strict_mode); | 1104 receiver_map, strict_mode); |
1099 Code* cached_stub; | 1105 Code* cached_stub; |
1100 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub; | 1106 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub; |
1101 handler_ics.Add(cached_stub); | 1107 handler_ics.Add(cached_stub); |
1102 } | 1108 } |
1103 Object* object; | 1109 Object* object; |
1104 KeyedLoadStubCompiler compiler; | 1110 HandleScope scope(isolate()); |
1111 KeyedLoadStubCompiler compiler(isolate()); | |
1105 MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps, | 1112 MaybeObject* maybe_code = compiler.CompileLoadPolymorphic(receiver_maps, |
1106 &handler_ics); | 1113 &handler_ics); |
1107 if (!maybe_code->ToObject(&object)) return maybe_code; | 1114 if (!maybe_code->ToObject(&object)) return maybe_code; |
1108 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); | 1115 isolate()->counters()->keyed_load_polymorphic_stubs()->Increment(); |
1109 PROFILE(isolate(), CodeCreateEvent( | 1116 PROFILE(isolate(), CodeCreateEvent( |
1110 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, | 1117 Logger::KEYED_LOAD_MEGAMORPHIC_IC_TAG, |
1111 Code::cast(object), 0)); | 1118 Code::cast(object), 0)); |
1112 return object; | 1119 return object; |
1113 } | 1120 } |
1114 | 1121 |
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1801 } else { | 1808 } else { |
1802 maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( | 1809 maybe_cached_stub = ComputeMonomorphicStubWithoutMapCheck( |
1803 receiver_map, strict_mode); | 1810 receiver_map, strict_mode); |
1804 } | 1811 } |
1805 Code* cached_stub; | 1812 Code* cached_stub; |
1806 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub; | 1813 if (!maybe_cached_stub->To(&cached_stub)) return maybe_cached_stub; |
1807 handler_ics.Add(cached_stub); | 1814 handler_ics.Add(cached_stub); |
1808 transitioned_maps.Add(transitioned_map); | 1815 transitioned_maps.Add(transitioned_map); |
1809 } | 1816 } |
1810 Object* object; | 1817 Object* object; |
1811 KeyedStoreStubCompiler compiler(strict_mode); | 1818 HandleScope scope(isolate()); |
1819 KeyedStoreStubCompiler compiler(isolate(), strict_mode); | |
1812 MaybeObject* maybe_code = compiler.CompileStorePolymorphic( | 1820 MaybeObject* maybe_code = compiler.CompileStorePolymorphic( |
1813 receiver_maps, &handler_ics, &transitioned_maps); | 1821 receiver_maps, &handler_ics, &transitioned_maps); |
1814 if (!maybe_code->ToObject(&object)) return maybe_code; | 1822 if (!maybe_code->ToObject(&object)) return maybe_code; |
1815 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); | 1823 isolate()->counters()->keyed_store_polymorphic_stubs()->Increment(); |
1816 PROFILE(isolate(), CodeCreateEvent( | 1824 PROFILE(isolate(), CodeCreateEvent( |
1817 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, | 1825 Logger::KEYED_STORE_MEGAMORPHIC_IC_TAG, |
1818 Code::cast(object), 0)); | 1826 Code::cast(object), 0)); |
1819 return object; | 1827 return object; |
1820 } | 1828 } |
1821 | 1829 |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2045 | 2053 |
2046 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { | 2054 if (!result->IsJSFunction() || JSFunction::cast(result)->is_compiled()) { |
2047 return result; | 2055 return result; |
2048 } | 2056 } |
2049 return CompileFunction(isolate, JSFunction::cast(result)); | 2057 return CompileFunction(isolate, JSFunction::cast(result)); |
2050 } | 2058 } |
2051 | 2059 |
2052 | 2060 |
2053 // Used from ic-<arch>.cc. | 2061 // Used from ic-<arch>.cc. |
2054 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { | 2062 RUNTIME_FUNCTION(MaybeObject*, LoadIC_Miss) { |
2055 NoHandleAllocation na; | 2063 HandleScope scope(isolate); |
2056 ASSERT(args.length() == 2); | 2064 ASSERT(args.length() == 2); |
2057 LoadIC ic(isolate); | 2065 LoadIC ic(isolate); |
2058 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); | 2066 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); |
2059 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); | 2067 return ic.Load(state, args.at<Object>(0), args.at<String>(1)); |
2060 } | 2068 } |
2061 | 2069 |
2062 | 2070 |
2063 // Used from ic-<arch>.cc | 2071 // Used from ic-<arch>.cc |
2064 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { | 2072 RUNTIME_FUNCTION(MaybeObject*, KeyedLoadIC_Miss) { |
2065 NoHandleAllocation na; | 2073 NoHandleAllocation na; |
(...skipping 546 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2612 #undef ADDR | 2620 #undef ADDR |
2613 }; | 2621 }; |
2614 | 2622 |
2615 | 2623 |
2616 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 2624 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
2617 return IC_utilities[id]; | 2625 return IC_utilities[id]; |
2618 } | 2626 } |
2619 | 2627 |
2620 | 2628 |
2621 } } // namespace v8::internal | 2629 } } // namespace v8::internal |
OLD | NEW |