| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 int index = frame->ComputeExpressionsCount() - (argc + 1); | 542 int index = frame->ComputeExpressionsCount() - (argc + 1); |
| 543 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); | 543 frame->SetExpression(index, *isolate()->factory()->ToObject(object)); |
| 544 } | 544 } |
| 545 } | 545 } |
| 546 | 546 |
| 547 | 547 |
| 548 MaybeObject* CallICBase::LoadFunction(State state, | 548 MaybeObject* CallICBase::LoadFunction(State state, |
| 549 Code::ExtraICState extra_ic_state, | 549 Code::ExtraICState extra_ic_state, |
| 550 Handle<Object> object, | 550 Handle<Object> object, |
| 551 Handle<String> name) { | 551 Handle<String> name) { |
| 552 bool use_ic = FLAG_use_ic; |
| 552 if (object->IsJSObject()) { | 553 if (object->IsJSObject()) { |
| 553 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 554 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 554 if (receiver->map()->is_deprecated()) { | 555 if (receiver->map()->is_deprecated()) { |
| 556 use_ic = false; |
| 555 JSObject::MigrateInstance(receiver); | 557 JSObject::MigrateInstance(receiver); |
| 556 } | 558 } |
| 557 } | 559 } |
| 558 | 560 |
| 559 // If the object is undefined or null it's illegal to try to get any | 561 // If the object is undefined or null it's illegal to try to get any |
| 560 // of its properties; throw a TypeError in that case. | 562 // of its properties; throw a TypeError in that case. |
| 561 if (object->IsUndefined() || object->IsNull()) { | 563 if (object->IsUndefined() || object->IsNull()) { |
| 562 return TypeError("non_object_property_call", object, name); | 564 return TypeError("non_object_property_call", object, name); |
| 563 } | 565 } |
| 564 | 566 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 583 | 585 |
| 584 if (!lookup.IsFound()) { | 586 if (!lookup.IsFound()) { |
| 585 // If the object does not have the requested property, check which | 587 // If the object does not have the requested property, check which |
| 586 // exception we need to throw. | 588 // exception we need to throw. |
| 587 return IsUndeclaredGlobal(object) | 589 return IsUndeclaredGlobal(object) |
| 588 ? ReferenceError("not_defined", name) | 590 ? ReferenceError("not_defined", name) |
| 589 : TypeError("undefined_method", object, name); | 591 : TypeError("undefined_method", object, name); |
| 590 } | 592 } |
| 591 | 593 |
| 592 // Lookup is valid: Update inline cache and stub cache. | 594 // Lookup is valid: Update inline cache and stub cache. |
| 593 if (FLAG_use_ic) { | 595 if (use_ic) UpdateCaches(&lookup, state, extra_ic_state, object, name); |
| 594 UpdateCaches(&lookup, state, extra_ic_state, object, name); | |
| 595 } | |
| 596 | 596 |
| 597 // Get the property. | 597 // Get the property. |
| 598 PropertyAttributes attr; | 598 PropertyAttributes attr; |
| 599 Handle<Object> result = | 599 Handle<Object> result = |
| 600 Object::GetProperty(object, object, &lookup, name, &attr); | 600 Object::GetProperty(object, object, &lookup, name, &attr); |
| 601 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 601 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 602 | 602 |
| 603 if (lookup.IsInterceptor() && attr == ABSENT) { | 603 if (lookup.IsInterceptor() && attr == ABSENT) { |
| 604 // If the object does not have the requested property, check which | 604 // If the object does not have the requested property, check which |
| 605 // exception we need to throw. | 605 // exception we need to throw. |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 MaybeObject* KeyedCallIC::LoadFunction(State state, | 812 MaybeObject* KeyedCallIC::LoadFunction(State state, |
| 813 Handle<Object> object, | 813 Handle<Object> object, |
| 814 Handle<Object> key) { | 814 Handle<Object> key) { |
| 815 if (key->IsInternalizedString()) { | 815 if (key->IsInternalizedString()) { |
| 816 return CallICBase::LoadFunction(state, | 816 return CallICBase::LoadFunction(state, |
| 817 Code::kNoExtraICState, | 817 Code::kNoExtraICState, |
| 818 object, | 818 object, |
| 819 Handle<String>::cast(key)); | 819 Handle<String>::cast(key)); |
| 820 } | 820 } |
| 821 | 821 |
| 822 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); |
| 822 if (object->IsJSObject()) { | 823 if (object->IsJSObject()) { |
| 823 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 824 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 824 if (receiver->map()->is_deprecated()) { | 825 if (receiver->map()->is_deprecated()) { |
| 826 use_ic = false; |
| 825 JSObject::MigrateInstance(receiver); | 827 JSObject::MigrateInstance(receiver); |
| 826 } | 828 } |
| 827 } | 829 } |
| 828 | 830 |
| 829 if (object->IsUndefined() || object->IsNull()) { | 831 if (object->IsUndefined() || object->IsNull()) { |
| 830 return TypeError("non_object_property_call", object, key); | 832 return TypeError("non_object_property_call", object, key); |
| 831 } | 833 } |
| 832 | 834 |
| 833 bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded(); | |
| 834 ASSERT(!(use_ic && object->IsJSGlobalProxy())); | 835 ASSERT(!(use_ic && object->IsJSGlobalProxy())); |
| 835 | 836 |
| 836 if (use_ic && state != MEGAMORPHIC) { | 837 if (use_ic && state != MEGAMORPHIC) { |
| 837 int argc = target()->arguments_count(); | 838 int argc = target()->arguments_count(); |
| 838 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( | 839 Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic( |
| 839 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); | 840 argc, Code::KEYED_CALL_IC, Code::kNoExtraICState); |
| 840 if (object->IsJSObject()) { | 841 if (object->IsJSObject()) { |
| 841 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 842 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 842 if (receiver->elements()->map() == | 843 if (receiver->elements()->map() == |
| 843 isolate()->heap()->non_strict_arguments_elements_map()) { | 844 isolate()->heap()->non_strict_arguments_elements_map()) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 867 | 868 |
| 868 MaybeObject* LoadIC::Load(State state, | 869 MaybeObject* LoadIC::Load(State state, |
| 869 Handle<Object> object, | 870 Handle<Object> object, |
| 870 Handle<String> name) { | 871 Handle<String> name) { |
| 871 // If the object is undefined or null it's illegal to try to get any | 872 // If the object is undefined or null it's illegal to try to get any |
| 872 // of its properties; throw a TypeError in that case. | 873 // of its properties; throw a TypeError in that case. |
| 873 if (object->IsUndefined() || object->IsNull()) { | 874 if (object->IsUndefined() || object->IsNull()) { |
| 874 return TypeError("non_object_property_load", object, name); | 875 return TypeError("non_object_property_load", object, name); |
| 875 } | 876 } |
| 876 | 877 |
| 877 if (FLAG_use_ic) { | 878 bool use_ic = FLAG_use_ic; |
| 879 |
| 880 if (use_ic) { |
| 878 // Use specialized code for getting the length of strings and | 881 // Use specialized code for getting the length of strings and |
| 879 // string wrapper objects. The length property of string wrapper | 882 // string wrapper objects. The length property of string wrapper |
| 880 // objects is read-only and therefore always returns the length of | 883 // objects is read-only and therefore always returns the length of |
| 881 // the underlying string value. See ECMA-262 15.5.5.1. | 884 // the underlying string value. See ECMA-262 15.5.5.1. |
| 882 if ((object->IsString() || object->IsStringWrapper()) && | 885 if (object->IsStringWrapper() && |
| 883 name->Equals(isolate()->heap()->length_string())) { | 886 name->Equals(isolate()->heap()->length_string())) { |
| 884 Handle<Code> stub; | 887 Handle<Code> stub; |
| 885 if (state == UNINITIALIZED) { | 888 if (state == UNINITIALIZED) { |
| 886 stub = pre_monomorphic_stub(); | 889 stub = pre_monomorphic_stub(); |
| 887 } else if (state == PREMONOMORPHIC) { | 890 } else if (state == PREMONOMORPHIC || state == MONOMORPHIC) { |
| 888 StringLengthStub string_length_stub(kind(), !object->IsString()); | 891 StringLengthStub string_length_stub(kind()); |
| 889 stub = string_length_stub.GetCode(isolate()); | |
| 890 } else if (state == MONOMORPHIC && object->IsStringWrapper()) { | |
| 891 StringLengthStub string_length_stub(kind(), true); | |
| 892 stub = string_length_stub.GetCode(isolate()); | 892 stub = string_length_stub.GetCode(isolate()); |
| 893 } else if (state != MEGAMORPHIC) { | 893 } else if (state != MEGAMORPHIC) { |
| 894 ASSERT(state != GENERIC); | 894 ASSERT(state != GENERIC); |
| 895 stub = megamorphic_stub(); | 895 stub = megamorphic_stub(); |
| 896 } | 896 } |
| 897 if (!stub.is_null()) { | 897 if (!stub.is_null()) { |
| 898 set_target(*stub); | 898 set_target(*stub); |
| 899 #ifdef DEBUG | 899 #ifdef DEBUG |
| 900 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /string]\n"); | 900 if (FLAG_trace_ic) PrintF("[LoadIC : +#length /stringwrapper]\n"); |
| 901 #endif | 901 #endif |
| 902 } | 902 } |
| 903 // Get the string if we have a string wrapper object. | 903 // Get the string if we have a string wrapper object. |
| 904 Handle<Object> string = object->IsJSValue() | 904 String* string = String::cast(JSValue::cast(*object)->value()); |
| 905 ? Handle<Object>(Handle<JSValue>::cast(object)->value(), isolate()) | 905 return Smi::FromInt(string->length()); |
| 906 : object; | |
| 907 return Smi::FromInt(String::cast(*string)->length()); | |
| 908 } | 906 } |
| 909 | 907 |
| 910 // Use specialized code for getting prototype of functions. | 908 // Use specialized code for getting prototype of functions. |
| 911 if (object->IsJSFunction() && | 909 if (object->IsJSFunction() && |
| 912 name->Equals(isolate()->heap()->prototype_string()) && | 910 name->Equals(isolate()->heap()->prototype_string()) && |
| 913 Handle<JSFunction>::cast(object)->should_have_prototype()) { | 911 Handle<JSFunction>::cast(object)->should_have_prototype()) { |
| 914 Handle<Code> stub; | 912 Handle<Code> stub; |
| 915 if (state == UNINITIALIZED) { | 913 if (state == UNINITIALIZED) { |
| 916 stub = pre_monomorphic_stub(); | 914 stub = pre_monomorphic_stub(); |
| 917 } else if (state == PREMONOMORPHIC) { | 915 } else if (state == PREMONOMORPHIC) { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 929 } | 927 } |
| 930 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); | 928 return *Accessors::FunctionGetPrototype(Handle<JSFunction>::cast(object)); |
| 931 } | 929 } |
| 932 } | 930 } |
| 933 | 931 |
| 934 // Check if the name is trivially convertible to an index and get | 932 // Check if the name is trivially convertible to an index and get |
| 935 // the element or char if so. | 933 // the element or char if so. |
| 936 uint32_t index; | 934 uint32_t index; |
| 937 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 935 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 938 // Rewrite to the generic keyed load stub. | 936 // Rewrite to the generic keyed load stub. |
| 939 if (FLAG_use_ic) set_target(*generic_stub()); | 937 if (use_ic) set_target(*generic_stub()); |
| 940 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); | 938 return Runtime::GetElementOrCharAtOrFail(isolate(), object, index); |
| 941 } | 939 } |
| 942 | 940 |
| 943 if (object->IsJSObject()) { | 941 if (object->IsJSObject()) { |
| 944 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 942 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 945 if (receiver->map()->is_deprecated()) { | 943 if (receiver->map()->is_deprecated()) { |
| 944 use_ic = false; |
| 946 JSObject::MigrateInstance(receiver); | 945 JSObject::MigrateInstance(receiver); |
| 947 } | 946 } |
| 948 } | 947 } |
| 949 | 948 |
| 950 // Named lookup in the object. | 949 // Named lookup in the object. |
| 951 LookupResult lookup(isolate()); | 950 LookupResult lookup(isolate()); |
| 952 LookupForRead(object, name, &lookup); | 951 LookupForRead(object, name, &lookup); |
| 953 | 952 |
| 954 // If we did not find a property, check if we need to throw an exception. | 953 // If we did not find a property, check if we need to throw an exception. |
| 955 if (!lookup.IsFound()) { | 954 if (!lookup.IsFound()) { |
| 956 if (IsUndeclaredGlobal(object)) { | 955 if (IsUndeclaredGlobal(object)) { |
| 957 return ReferenceError("not_defined", name); | 956 return ReferenceError("not_defined", name); |
| 958 } | 957 } |
| 959 LOG(isolate(), SuspectReadEvent(*name, *object)); | 958 LOG(isolate(), SuspectReadEvent(*name, *object)); |
| 960 } | 959 } |
| 961 | 960 |
| 962 // Update inline cache and stub cache. | 961 // Update inline cache and stub cache. |
| 963 if (FLAG_use_ic) UpdateCaches(&lookup, state, object, name); | 962 if (use_ic) UpdateCaches(&lookup, state, object, name); |
| 964 | 963 |
| 965 PropertyAttributes attr; | 964 PropertyAttributes attr; |
| 966 if (lookup.IsInterceptor() || lookup.IsHandler()) { | 965 if (lookup.IsInterceptor() || lookup.IsHandler()) { |
| 967 // Get the property. | 966 // Get the property. |
| 968 Handle<Object> result = | 967 Handle<Object> result = |
| 969 Object::GetProperty(object, object, &lookup, name, &attr); | 968 Object::GetProperty(object, object, &lookup, name, &attr); |
| 970 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 969 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 971 // If the property is not present, check if we need to throw an | 970 // If the property is not present, check if we need to throw an |
| 972 // exception. | 971 // exception. |
| 973 if (attr == ABSENT && IsUndeclaredGlobal(object)) { | 972 if (attr == ABSENT && IsUndeclaredGlobal(object)) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 989 receiver_maps->at(current).is_identical_to(new_receiver_map)) { | 988 receiver_maps->at(current).is_identical_to(new_receiver_map)) { |
| 990 return false; | 989 return false; |
| 991 } | 990 } |
| 992 } | 991 } |
| 993 receiver_maps->Add(new_receiver_map); | 992 receiver_maps->Add(new_receiver_map); |
| 994 return true; | 993 return true; |
| 995 } | 994 } |
| 996 | 995 |
| 997 | 996 |
| 998 bool IC::UpdatePolymorphicIC(State state, | 997 bool IC::UpdatePolymorphicIC(State state, |
| 999 Handle<JSObject> receiver, | 998 Handle<HeapObject> receiver, |
| 1000 Handle<String> name, | 999 Handle<String> name, |
| 1001 Handle<Code> code, | 1000 Handle<Code> code, |
| 1002 StrictModeFlag strict_mode) { | 1001 StrictModeFlag strict_mode) { |
| 1003 if (code->type() == Code::NORMAL) return false; | 1002 if (code->type() == Code::NORMAL) return false; |
| 1004 if (target()->ic_state() == MONOMORPHIC && | 1003 if (target()->ic_state() == MONOMORPHIC && |
| 1005 target()->type() == Code::NORMAL) { | 1004 target()->type() == Code::NORMAL) { |
| 1006 return false; | 1005 return false; |
| 1007 } | 1006 } |
| 1008 | 1007 |
| 1009 MapHandleList receiver_maps; | 1008 MapHandleList receiver_maps; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1070 Handle<Code> StoreIC::ComputePolymorphicIC(MapHandleList* receiver_maps, | 1069 Handle<Code> StoreIC::ComputePolymorphicIC(MapHandleList* receiver_maps, |
| 1071 CodeHandleList* handlers, | 1070 CodeHandleList* handlers, |
| 1072 int number_of_valid_maps, | 1071 int number_of_valid_maps, |
| 1073 Handle<Name> name, | 1072 Handle<Name> name, |
| 1074 StrictModeFlag strict_mode) { | 1073 StrictModeFlag strict_mode) { |
| 1075 return isolate()->stub_cache()->ComputePolymorphicStoreIC( | 1074 return isolate()->stub_cache()->ComputePolymorphicStoreIC( |
| 1076 receiver_maps, handlers, number_of_valid_maps, name, strict_mode); | 1075 receiver_maps, handlers, number_of_valid_maps, name, strict_mode); |
| 1077 } | 1076 } |
| 1078 | 1077 |
| 1079 | 1078 |
| 1080 void LoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1079 void LoadIC::UpdateMonomorphicIC(Handle<HeapObject> receiver, |
| 1081 Handle<Code> handler, | 1080 Handle<Code> handler, |
| 1082 Handle<String> name, | 1081 Handle<String> name, |
| 1083 StrictModeFlag strict_mode) { | 1082 StrictModeFlag strict_mode) { |
| 1084 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1083 if (handler->is_load_stub()) return set_target(*handler); |
| 1085 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicLoadIC( | 1084 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicLoadIC( |
| 1086 receiver, handler, name); | 1085 receiver, handler, name); |
| 1087 set_target(*ic); | 1086 set_target(*ic); |
| 1088 } | 1087 } |
| 1089 | 1088 |
| 1090 | 1089 |
| 1091 void KeyedLoadIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1090 void KeyedLoadIC::UpdateMonomorphicIC(Handle<HeapObject> receiver, |
| 1092 Handle<Code> handler, | 1091 Handle<Code> handler, |
| 1093 Handle<String> name, | 1092 Handle<String> name, |
| 1094 StrictModeFlag strict_mode) { | 1093 StrictModeFlag strict_mode) { |
| 1095 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1094 if (handler->is_keyed_load_stub()) return set_target(*handler); |
| 1096 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedLoadIC( | 1095 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedLoadIC( |
| 1097 receiver, handler, name); | 1096 receiver, handler, name); |
| 1098 set_target(*ic); | 1097 set_target(*ic); |
| 1099 } | 1098 } |
| 1100 | 1099 |
| 1101 | 1100 |
| 1102 void StoreIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1101 void StoreIC::UpdateMonomorphicIC(Handle<HeapObject> receiver, |
| 1103 Handle<Code> handler, | 1102 Handle<Code> handler, |
| 1104 Handle<String> name, | 1103 Handle<String> name, |
| 1105 StrictModeFlag strict_mode) { | 1104 StrictModeFlag strict_mode) { |
| 1106 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1105 if (handler->is_store_stub()) return set_target(*handler); |
| 1107 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicStoreIC( | 1106 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicStoreIC( |
| 1108 receiver, handler, name, strict_mode); | 1107 receiver, handler, name, strict_mode); |
| 1109 set_target(*ic); | 1108 set_target(*ic); |
| 1110 } | 1109 } |
| 1111 | 1110 |
| 1112 | 1111 |
| 1113 void KeyedStoreIC::UpdateMonomorphicIC(Handle<JSObject> receiver, | 1112 void KeyedStoreIC::UpdateMonomorphicIC(Handle<HeapObject> receiver, |
| 1114 Handle<Code> handler, | 1113 Handle<Code> handler, |
| 1115 Handle<String> name, | 1114 Handle<String> name, |
| 1116 StrictModeFlag strict_mode) { | 1115 StrictModeFlag strict_mode) { |
| 1117 if (handler->type() == Code::NORMAL) return set_target(*handler); | 1116 if (handler->is_keyed_store_stub()) return set_target(*handler); |
| 1118 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedStoreIC( | 1117 Handle<Code> ic = isolate()->stub_cache()->ComputeMonomorphicKeyedStoreIC( |
| 1119 receiver, handler, name, strict_mode); | 1118 receiver, handler, name, strict_mode); |
| 1120 set_target(*ic); | 1119 set_target(*ic); |
| 1121 } | 1120 } |
| 1122 | 1121 |
| 1123 | 1122 |
| 1124 void IC::CopyICToMegamorphicCache(Handle<String> name) { | 1123 void IC::CopyICToMegamorphicCache(Handle<String> name) { |
| 1125 MapHandleList receiver_maps; | 1124 MapHandleList receiver_maps; |
| 1126 CodeHandleList handlers; | 1125 CodeHandleList handlers; |
| 1127 { | 1126 { |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1148 : NULL; | 1147 : NULL; |
| 1149 | 1148 |
| 1150 return transitioned_map == receiver_map; | 1149 return transitioned_map == receiver_map; |
| 1151 } | 1150 } |
| 1152 | 1151 |
| 1153 | 1152 |
| 1154 // Since GC may have been invoked, by the time PatchCache is called, |state| is | 1153 // Since GC may have been invoked, by the time PatchCache is called, |state| is |
| 1155 // not necessarily equal to target()->state(). | 1154 // not necessarily equal to target()->state(). |
| 1156 void IC::PatchCache(State state, | 1155 void IC::PatchCache(State state, |
| 1157 StrictModeFlag strict_mode, | 1156 StrictModeFlag strict_mode, |
| 1158 Handle<JSObject> receiver, | 1157 Handle<HeapObject> receiver, |
| 1159 Handle<String> name, | 1158 Handle<String> name, |
| 1160 Handle<Code> code) { | 1159 Handle<Code> code) { |
| 1161 switch (state) { | 1160 switch (state) { |
| 1162 case UNINITIALIZED: | 1161 case UNINITIALIZED: |
| 1163 case PREMONOMORPHIC: | 1162 case PREMONOMORPHIC: |
| 1164 case MONOMORPHIC_PROTOTYPE_FAILURE: | 1163 case MONOMORPHIC_PROTOTYPE_FAILURE: |
| 1165 UpdateMonomorphicIC(receiver, code, name, strict_mode); | 1164 UpdateMonomorphicIC(receiver, code, name, strict_mode); |
| 1166 break; | 1165 break; |
| 1167 case MONOMORPHIC: | 1166 case MONOMORPHIC: |
| 1168 // Only move to megamorphic if the target changes. | 1167 // Only move to megamorphic if the target changes. |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 UNREACHABLE(); | 1257 UNREACHABLE(); |
| 1259 break; | 1258 break; |
| 1260 } | 1259 } |
| 1261 } | 1260 } |
| 1262 | 1261 |
| 1263 | 1262 |
| 1264 void LoadIC::UpdateCaches(LookupResult* lookup, | 1263 void LoadIC::UpdateCaches(LookupResult* lookup, |
| 1265 State state, | 1264 State state, |
| 1266 Handle<Object> object, | 1265 Handle<Object> object, |
| 1267 Handle<String> name) { | 1266 Handle<String> name) { |
| 1268 // Bail out if the result is not cacheable. | 1267 // TODO(verwaest): It would be nice to support loading fields from smis as |
| 1269 if (!lookup->IsCacheable()) { | 1268 // well. For now just fail to update the cache. |
| 1270 set_target(*generic_stub()); | 1269 if (!object->IsHeapObject()) return; |
| 1271 return; | |
| 1272 } | |
| 1273 | 1270 |
| 1274 // TODO(jkummerow): It would be nice to support non-JSObjects in | 1271 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
| 1275 // UpdateCaches, then we wouldn't need to go generic here. | |
| 1276 if (!object->IsJSObject()) { | |
| 1277 set_target(*generic_stub()); | |
| 1278 return; | |
| 1279 } | |
| 1280 | 1272 |
| 1281 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | |
| 1282 Handle<Code> code; | 1273 Handle<Code> code; |
| 1283 if (state == UNINITIALIZED) { | 1274 if (state == UNINITIALIZED) { |
| 1284 // This is the first time we execute this inline cache. | 1275 // This is the first time we execute this inline cache. |
| 1285 // Set the target to the pre monomorphic stub to delay | 1276 // Set the target to the pre monomorphic stub to delay |
| 1286 // setting the monomorphic state. | 1277 // setting the monomorphic state. |
| 1287 code = pre_monomorphic_stub(); | 1278 code = pre_monomorphic_stub(); |
| 1279 } else if (!lookup->IsCacheable()) { |
| 1280 // Bail out if the result is not cacheable. |
| 1281 code = slow_stub(); |
| 1282 } else if (object->IsString() && |
| 1283 name->Equals(isolate()->heap()->length_string())) { |
| 1284 int length_index = String::kLengthOffset / kPointerSize; |
| 1285 if (target()->is_load_stub()) { |
| 1286 LoadFieldStub stub(true, length_index, Representation::Tagged()); |
| 1287 code = stub.GetCode(isolate()); |
| 1288 } else { |
| 1289 KeyedLoadFieldStub stub(true, length_index, Representation::Tagged()); |
| 1290 code = stub.GetCode(isolate()); |
| 1291 } |
| 1292 } else if (!object->IsJSObject()) { |
| 1293 // TODO(jkummerow): It would be nice to support non-JSObjects in |
| 1294 // ComputeLoadHandler, then we wouldn't need to go generic here. |
| 1295 code = slow_stub(); |
| 1288 } else { | 1296 } else { |
| 1289 code = ComputeLoadHandler(lookup, receiver, name); | 1297 code = ComputeLoadHandler(lookup, Handle<JSObject>::cast(receiver), name); |
| 1290 if (code.is_null()) { | 1298 if (code.is_null()) code = slow_stub(); |
| 1291 set_target(*generic_stub()); | |
| 1292 return; | |
| 1293 } | |
| 1294 } | 1299 } |
| 1295 | 1300 |
| 1296 PatchCache(state, kNonStrictMode, receiver, name, code); | 1301 PatchCache(state, kNonStrictMode, receiver, name, code); |
| 1297 TRACE_IC("LoadIC", name, state, target()); | 1302 TRACE_IC("LoadIC", name, state, target()); |
| 1298 } | 1303 } |
| 1299 | 1304 |
| 1300 | 1305 |
| 1301 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { | 1306 void IC::UpdateMegamorphicCache(Map* map, Name* name, Code* code) { |
| 1302 // Cache code holding map should be consistent with | 1307 // Cache code holding map should be consistent with |
| 1303 // GenerateMonomorphicCacheProbe. | 1308 // GenerateMonomorphicCacheProbe. |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1361 CallOptimization call_optimization(function); | 1366 CallOptimization call_optimization(function); |
| 1362 if (call_optimization.is_simple_api_call() && | 1367 if (call_optimization.is_simple_api_call() && |
| 1363 call_optimization.IsCompatibleReceiver(*receiver) && | 1368 call_optimization.IsCompatibleReceiver(*receiver) && |
| 1364 FLAG_js_accessor_ics) { | 1369 FLAG_js_accessor_ics) { |
| 1365 return isolate()->stub_cache()->ComputeLoadCallback( | 1370 return isolate()->stub_cache()->ComputeLoadCallback( |
| 1366 name, receiver, holder, call_optimization); | 1371 name, receiver, holder, call_optimization); |
| 1367 } | 1372 } |
| 1368 return isolate()->stub_cache()->ComputeLoadViaGetter( | 1373 return isolate()->stub_cache()->ComputeLoadViaGetter( |
| 1369 name, receiver, holder, function); | 1374 name, receiver, holder, function); |
| 1370 } else if (receiver->IsJSArray() && | 1375 } else if (receiver->IsJSArray() && |
| 1371 name->Equals(isolate()->heap()->length_string())) { | 1376 name->Equals(isolate()->heap()->length_string())) { |
| 1372 PropertyIndex lengthIndex = | 1377 PropertyIndex lengthIndex = PropertyIndex::NewHeaderIndex( |
| 1373 PropertyIndex::NewHeaderIndex(JSArray::kLengthOffset / kPointerSize); | 1378 JSArray::kLengthOffset / kPointerSize); |
| 1374 return isolate()->stub_cache()->ComputeLoadField( | 1379 return isolate()->stub_cache()->ComputeLoadField( |
| 1375 name, receiver, holder, lengthIndex, Representation::Tagged()); | 1380 name, receiver, holder, lengthIndex, Representation::Tagged()); |
| 1376 } | 1381 } |
| 1377 // TODO(dcarney): Handle correctly. | 1382 // TODO(dcarney): Handle correctly. |
| 1378 if (callback->IsDeclaredAccessorInfo()) break; | 1383 if (callback->IsDeclaredAccessorInfo()) break; |
| 1379 ASSERT(callback->IsForeign()); | 1384 ASSERT(callback->IsForeign()); |
| 1380 // No IC support for old-style native accessors. | 1385 // No IC support for old-style native accessors. |
| 1381 break; | 1386 break; |
| 1382 } | 1387 } |
| 1383 case INTERCEPTOR: | 1388 case INTERCEPTOR: |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1495 if (use_ic) { | 1500 if (use_ic) { |
| 1496 Handle<Code> stub = generic_stub(); | 1501 Handle<Code> stub = generic_stub(); |
| 1497 if (miss_mode != MISS_FORCE_GENERIC) { | 1502 if (miss_mode != MISS_FORCE_GENERIC) { |
| 1498 if (object->IsString() && key->IsNumber()) { | 1503 if (object->IsString() && key->IsNumber()) { |
| 1499 if (state == UNINITIALIZED) { | 1504 if (state == UNINITIALIZED) { |
| 1500 stub = string_stub(); | 1505 stub = string_stub(); |
| 1501 } | 1506 } |
| 1502 } else if (object->IsJSObject()) { | 1507 } else if (object->IsJSObject()) { |
| 1503 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1508 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1504 if (receiver->map()->is_deprecated()) { | 1509 if (receiver->map()->is_deprecated()) { |
| 1510 use_ic = false; |
| 1505 JSObject::MigrateInstance(receiver); | 1511 JSObject::MigrateInstance(receiver); |
| 1506 } | 1512 } |
| 1507 | 1513 |
| 1508 if (receiver->elements()->map() == | 1514 if (receiver->elements()->map() == |
| 1509 isolate()->heap()->non_strict_arguments_elements_map()) { | 1515 isolate()->heap()->non_strict_arguments_elements_map()) { |
| 1510 stub = non_strict_arguments_stub(); | 1516 stub = non_strict_arguments_stub(); |
| 1511 } else if (receiver->HasIndexedInterceptor()) { | 1517 } else if (receiver->HasIndexedInterceptor()) { |
| 1512 stub = indexed_interceptor_stub(); | 1518 stub = indexed_interceptor_stub(); |
| 1513 } else if (!key->ToSmi()->IsFailure() && | 1519 } else if (!key->ToSmi()->IsFailure() && |
| 1514 (target() != *non_strict_arguments_stub())) { | 1520 (target() != *non_strict_arguments_stub())) { |
| 1515 stub = LoadElementStub(receiver); | 1521 stub = LoadElementStub(receiver); |
| 1516 } | 1522 } |
| 1517 } | 1523 } |
| 1518 } else { | 1524 } else { |
| 1519 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); | 1525 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); |
| 1520 } | 1526 } |
| 1521 ASSERT(!stub.is_null()); | 1527 if (use_ic) { |
| 1522 set_target(*stub); | 1528 ASSERT(!stub.is_null()); |
| 1523 TRACE_IC("KeyedLoadIC", key, state, target()); | 1529 set_target(*stub); |
| 1530 TRACE_IC("KeyedLoadIC", key, state, target()); |
| 1531 } |
| 1524 } | 1532 } |
| 1525 | 1533 |
| 1526 | 1534 |
| 1527 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); | 1535 return Runtime::GetObjectPropertyOrFail(isolate(), object, key); |
| 1528 } | 1536 } |
| 1529 | 1537 |
| 1530 | 1538 |
| 1531 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, | 1539 Handle<Code> KeyedLoadIC::ComputeLoadHandler(LookupResult* lookup, |
| 1532 Handle<JSObject> receiver, | 1540 Handle<JSObject> receiver, |
| 1533 Handle<String> name) { | 1541 Handle<String> name) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1677 name->Equals(isolate()->heap()->length_string())) { | 1685 name->Equals(isolate()->heap()->length_string())) { |
| 1678 return TypeError("strict_read_only_property", object, name); | 1686 return TypeError("strict_read_only_property", object, name); |
| 1679 } | 1687 } |
| 1680 | 1688 |
| 1681 // Ignore other stores where the receiver is not a JSObject. | 1689 // Ignore other stores where the receiver is not a JSObject. |
| 1682 // TODO(1475): Must check prototype chains of object wrappers. | 1690 // TODO(1475): Must check prototype chains of object wrappers. |
| 1683 if (!object->IsJSObject()) return *value; | 1691 if (!object->IsJSObject()) return *value; |
| 1684 | 1692 |
| 1685 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 1693 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 1686 | 1694 |
| 1695 bool use_ic = FLAG_use_ic; |
| 1687 if (receiver->map()->is_deprecated()) { | 1696 if (receiver->map()->is_deprecated()) { |
| 1697 use_ic = false; |
| 1688 JSObject::MigrateInstance(receiver); | 1698 JSObject::MigrateInstance(receiver); |
| 1689 } | 1699 } |
| 1690 | 1700 |
| 1691 // Check if the given name is an array index. | 1701 // Check if the given name is an array index. |
| 1692 uint32_t index; | 1702 uint32_t index; |
| 1693 if (name->AsArrayIndex(&index)) { | 1703 if (name->AsArrayIndex(&index)) { |
| 1694 Handle<Object> result = | 1704 Handle<Object> result = |
| 1695 JSObject::SetElement(receiver, index, value, NONE, strict_mode); | 1705 JSObject::SetElement(receiver, index, value, NONE, strict_mode); |
| 1696 RETURN_IF_EMPTY_HANDLE(isolate(), result); | 1706 RETURN_IF_EMPTY_HANDLE(isolate(), result); |
| 1697 return *value; | 1707 return *value; |
| 1698 } | 1708 } |
| 1699 | 1709 |
| 1700 // Observed objects are always modified through the runtime. | 1710 // Observed objects are always modified through the runtime. |
| 1701 if (FLAG_harmony_observation && receiver->map()->is_observed()) { | 1711 if (FLAG_harmony_observation && receiver->map()->is_observed()) { |
| 1702 return JSReceiver::SetPropertyOrFail( | 1712 return JSReceiver::SetPropertyOrFail( |
| 1703 receiver, name, value, NONE, strict_mode, store_mode); | 1713 receiver, name, value, NONE, strict_mode, store_mode); |
| 1704 } | 1714 } |
| 1705 | 1715 |
| 1706 // Use specialized code for setting the length of arrays with fast | 1716 // Use specialized code for setting the length of arrays with fast |
| 1707 // properties. Slow properties might indicate redefinition of the length | 1717 // properties. Slow properties might indicate redefinition of the length |
| 1708 // property. Note that when redefined using Object.freeze, it's possible | 1718 // property. Note that when redefined using Object.freeze, it's possible |
| 1709 // to have fast properties but a read-only length. | 1719 // to have fast properties but a read-only length. |
| 1710 if (FLAG_use_ic && | 1720 if (use_ic && |
| 1711 receiver->IsJSArray() && | 1721 receiver->IsJSArray() && |
| 1712 name->Equals(isolate()->heap()->length_string()) && | 1722 name->Equals(isolate()->heap()->length_string()) && |
| 1713 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && | 1723 Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() && |
| 1714 receiver->HasFastProperties() && | 1724 receiver->HasFastProperties() && |
| 1715 !receiver->map()->is_frozen()) { | 1725 !receiver->map()->is_frozen()) { |
| 1716 Handle<Code> stub = | 1726 Handle<Code> stub = |
| 1717 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); | 1727 StoreArrayLengthStub(kind(), strict_mode).GetCode(isolate()); |
| 1718 set_target(*stub); | 1728 set_target(*stub); |
| 1719 TRACE_IC("StoreIC", name, state, *stub); | 1729 TRACE_IC("StoreIC", name, state, *stub); |
| 1720 return JSReceiver::SetPropertyOrFail( | 1730 return JSReceiver::SetPropertyOrFail( |
| 1721 receiver, name, value, NONE, strict_mode, store_mode); | 1731 receiver, name, value, NONE, strict_mode, store_mode); |
| 1722 } | 1732 } |
| 1723 | 1733 |
| 1724 if (receiver->IsJSGlobalProxy()) { | 1734 if (receiver->IsJSGlobalProxy()) { |
| 1725 if (FLAG_use_ic && kind() != Code::KEYED_STORE_IC) { | 1735 if (use_ic && kind() != Code::KEYED_STORE_IC) { |
| 1726 // Generate a generic stub that goes to the runtime when we see a global | 1736 // Generate a generic stub that goes to the runtime when we see a global |
| 1727 // proxy as receiver. | 1737 // proxy as receiver. |
| 1728 Handle<Code> stub = (strict_mode == kStrictMode) | 1738 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1729 ? global_proxy_stub_strict() | 1739 ? global_proxy_stub_strict() |
| 1730 : global_proxy_stub(); | 1740 : global_proxy_stub(); |
| 1731 set_target(*stub); | 1741 set_target(*stub); |
| 1732 TRACE_IC("StoreIC", name, state, *stub); | 1742 TRACE_IC("StoreIC", name, state, *stub); |
| 1733 } | 1743 } |
| 1734 return JSReceiver::SetPropertyOrFail( | 1744 return JSReceiver::SetPropertyOrFail( |
| 1735 receiver, name, value, NONE, strict_mode, store_mode); | 1745 receiver, name, value, NONE, strict_mode, store_mode); |
| 1736 } | 1746 } |
| 1737 | 1747 |
| 1738 LookupResult lookup(isolate()); | 1748 LookupResult lookup(isolate()); |
| 1739 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); | 1749 bool can_store = LookupForWrite(receiver, name, value, &lookup, &state); |
| 1740 if (!can_store && | 1750 if (!can_store && |
| 1741 strict_mode == kStrictMode && | 1751 strict_mode == kStrictMode && |
| 1742 !(lookup.IsProperty() && lookup.IsReadOnly()) && | 1752 !(lookup.IsProperty() && lookup.IsReadOnly()) && |
| 1743 IsUndeclaredGlobal(object)) { | 1753 IsUndeclaredGlobal(object)) { |
| 1744 // Strict mode doesn't allow setting non-existent global property. | 1754 // Strict mode doesn't allow setting non-existent global property. |
| 1745 return ReferenceError("not_defined", name); | 1755 return ReferenceError("not_defined", name); |
| 1746 } | 1756 } |
| 1747 if (FLAG_use_ic) { | 1757 if (use_ic) { |
| 1748 if (state == UNINITIALIZED) { | 1758 if (state == UNINITIALIZED) { |
| 1749 Handle<Code> stub = (strict_mode == kStrictMode) | 1759 Handle<Code> stub = (strict_mode == kStrictMode) |
| 1750 ? pre_monomorphic_stub_strict() | 1760 ? pre_monomorphic_stub_strict() |
| 1751 : pre_monomorphic_stub(); | 1761 : pre_monomorphic_stub(); |
| 1752 set_target(*stub); | 1762 set_target(*stub); |
| 1753 TRACE_IC("StoreIC", name, state, *stub); | 1763 TRACE_IC("StoreIC", name, state, *stub); |
| 1754 } else if (can_store) { | 1764 } else if (can_store) { |
| 1755 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); | 1765 UpdateCaches(&lookup, state, strict_mode, receiver, name, value); |
| 1756 } else if (!name->IsCacheable(isolate()) || | 1766 } else if (!name->IsCacheable(isolate()) || |
| 1757 lookup.IsNormal() || | 1767 lookup.IsNormal() || |
| (...skipping 1381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3139 #undef ADDR | 3149 #undef ADDR |
| 3140 }; | 3150 }; |
| 3141 | 3151 |
| 3142 | 3152 |
| 3143 Address IC::AddressFromUtilityId(IC::UtilityId id) { | 3153 Address IC::AddressFromUtilityId(IC::UtilityId id) { |
| 3144 return IC_utilities[id]; | 3154 return IC_utilities[id]; |
| 3145 } | 3155 } |
| 3146 | 3156 |
| 3147 | 3157 |
| 3148 } } // namespace v8::internal | 3158 } } // namespace v8::internal |
| OLD | NEW |