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