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 2799 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2810 void HLoadNamedField::PrintDataTo(StringStream* stream) { | 2810 void HLoadNamedField::PrintDataTo(StringStream* stream) { |
2811 object()->PrintNameTo(stream); | 2811 object()->PrintNameTo(stream); |
2812 access_.PrintTo(stream); | 2812 access_.PrintTo(stream); |
2813 if (HasTypeCheck()) { | 2813 if (HasTypeCheck()) { |
2814 stream->Add(" "); | 2814 stream->Add(" "); |
2815 typecheck()->PrintNameTo(stream); | 2815 typecheck()->PrintNameTo(stream); |
2816 } | 2816 } |
2817 } | 2817 } |
2818 | 2818 |
2819 | 2819 |
2820 // Returns true if an instance of this map can never find a property with this | |
2821 // name in its prototype chain. This means all prototypes up to the top are | |
2822 // fast and don't have the name in them. It would be good if we could optimize | |
2823 // polymorphic loads where the property is sometimes found in the prototype | |
2824 // chain. | |
2825 static bool PrototypeChainCanNeverResolve( | |
2826 Handle<Map> map, Handle<String> name) { | |
2827 Isolate* isolate = map->GetIsolate(); | |
2828 Object* current = map->prototype(); | |
2829 while (current != isolate->heap()->null_value()) { | |
2830 if (current->IsJSGlobalProxy() || | |
2831 current->IsGlobalObject() || | |
2832 !current->IsJSObject() || | |
2833 JSObject::cast(current)->map()->has_named_interceptor() || | |
2834 JSObject::cast(current)->IsAccessCheckNeeded() || | |
2835 !JSObject::cast(current)->HasFastProperties()) { | |
2836 return false; | |
2837 } | |
2838 | |
2839 LookupResult lookup(isolate); | |
2840 Map* map = JSObject::cast(current)->map(); | |
2841 map->LookupDescriptor(NULL, *name, &lookup); | |
2842 if (lookup.IsFound()) return false; | |
2843 if (!lookup.IsCacheable()) return false; | |
2844 current = JSObject::cast(current)->GetPrototype(); | |
2845 } | |
2846 return true; | |
2847 } | |
2848 | |
2849 | |
2850 HLoadNamedFieldPolymorphic::HLoadNamedFieldPolymorphic(HValue* context, | |
2851 HValue* object, | |
2852 SmallMapList* types, | |
2853 Handle<String> name, | |
2854 Zone* zone) | |
2855 : types_(Min(types->length(), kMaxLoadPolymorphism), zone), | |
2856 name_(name), | |
2857 types_unique_ids_(0, zone), | |
2858 name_unique_id_(), | |
2859 need_generic_(false) { | |
2860 SetOperandAt(0, context); | |
2861 SetOperandAt(1, object); | |
2862 set_representation(Representation::Tagged()); | |
2863 SetGVNFlag(kDependsOnMaps); | |
2864 SmallMapList negative_lookups; | |
2865 for (int i = 0; | |
2866 i < types->length() && types_.length() < kMaxLoadPolymorphism; | |
2867 ++i) { | |
2868 Handle<Map> map = types->at(i); | |
2869 // Deprecated maps are updated to the current map in the type oracle. | |
2870 ASSERT(!map->is_deprecated()); | |
2871 LookupResult lookup(map->GetIsolate()); | |
2872 map->LookupDescriptor(NULL, *name, &lookup); | |
2873 if (lookup.IsFound()) { | |
2874 switch (lookup.type()) { | |
2875 case FIELD: { | |
2876 int index = lookup.GetLocalFieldIndexFromMap(*map); | |
2877 if (index < 0) { | |
2878 SetGVNFlag(kDependsOnInobjectFields); | |
2879 } else { | |
2880 SetGVNFlag(kDependsOnBackingStoreFields); | |
2881 } | |
2882 if (FLAG_track_double_fields && | |
2883 lookup.representation().IsDouble()) { | |
2884 // Since the value needs to be boxed, use a generic handler for | |
2885 // loading doubles. | |
2886 continue; | |
2887 } | |
2888 types_.Add(types->at(i), zone); | |
2889 break; | |
2890 } | |
2891 case CONSTANT: | |
2892 types_.Add(types->at(i), zone); | |
2893 break; | |
2894 case CALLBACKS: | |
2895 break; | |
2896 case TRANSITION: | |
2897 case INTERCEPTOR: | |
2898 case NONEXISTENT: | |
2899 case NORMAL: | |
2900 case HANDLER: | |
2901 UNREACHABLE(); | |
2902 break; | |
2903 } | |
2904 } else if (lookup.IsCacheable() && | |
2905 // For dicts the lookup on the map will fail, but the object may | |
2906 // contain the property so we cannot generate a negative lookup | |
2907 // (which would just be a map check and return undefined). | |
2908 !map->is_dictionary_map() && | |
2909 !map->has_named_interceptor() && | |
2910 PrototypeChainCanNeverResolve(map, name)) { | |
2911 negative_lookups.Add(types->at(i), zone); | |
2912 } | |
2913 } | |
2914 | |
2915 bool need_generic = | |
2916 (types->length() != negative_lookups.length() + types_.length()); | |
2917 if (!need_generic && FLAG_deoptimize_uncommon_cases) { | |
2918 SetFlag(kUseGVN); | |
2919 for (int i = 0; i < negative_lookups.length(); i++) { | |
2920 types_.Add(negative_lookups.at(i), zone); | |
2921 } | |
2922 } else { | |
2923 // We don't have an easy way to handle both a call (to the generic stub) and | |
2924 // a deopt in the same hydrogen instruction, so in this case we don't add | |
2925 // the negative lookups which can deopt - just let the generic stub handle | |
2926 // them. | |
2927 SetAllSideEffects(); | |
2928 need_generic_ = true; | |
2929 } | |
2930 } | |
2931 | |
2932 | |
2933 HCheckMaps* HCheckMaps::New(Zone* zone, | 2820 HCheckMaps* HCheckMaps::New(Zone* zone, |
2934 HValue* context, | 2821 HValue* context, |
2935 HValue* value, | 2822 HValue* value, |
2936 Handle<Map> map, | 2823 Handle<Map> map, |
2937 CompilationInfo* info, | 2824 CompilationInfo* info, |
2938 HValue* typecheck) { | 2825 HValue* typecheck) { |
2939 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); | 2826 HCheckMaps* check_map = new(zone) HCheckMaps(value, zone, typecheck); |
2940 check_map->map_set_.Add(map, zone); | 2827 check_map->map_set_.Add(map, zone); |
2941 check_map->has_migration_target_ = map->is_migration_target(); | 2828 check_map->has_migration_target_ = map->is_migration_target(); |
2942 if (map->CanOmitMapChecks() && | 2829 if (map->CanOmitMapChecks() && |
2943 value->IsConstant() && | 2830 value->IsConstant() && |
2944 HConstant::cast(value)->InstanceOf(map)) { | 2831 HConstant::cast(value)->InstanceOf(map)) { |
2945 check_map->omit(info); | 2832 check_map->omit(info); |
2946 } | 2833 } |
2947 return check_map; | 2834 return check_map; |
2948 } | 2835 } |
2949 | 2836 |
2950 | 2837 |
2951 void HCheckMaps::FinalizeUniqueValueId() { | 2838 void HCheckMaps::FinalizeUniqueValueId() { |
2952 if (!map_unique_ids_.is_empty()) return; | 2839 if (!map_unique_ids_.is_empty()) return; |
2953 Zone* zone = block()->zone(); | 2840 Zone* zone = block()->zone(); |
2954 map_unique_ids_.Initialize(map_set_.length(), zone); | 2841 map_unique_ids_.Initialize(map_set_.length(), zone); |
2955 for (int i = 0; i < map_set_.length(); i++) { | 2842 for (int i = 0; i < map_set_.length(); i++) { |
2956 map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone); | 2843 map_unique_ids_.Add(UniqueValueId(map_set_.at(i)), zone); |
2957 } | 2844 } |
2958 } | 2845 } |
2959 | 2846 |
2960 | 2847 |
2961 void HLoadNamedFieldPolymorphic::FinalizeUniqueValueId() { | |
2962 if (!types_unique_ids_.is_empty()) return; | |
2963 Zone* zone = block()->zone(); | |
2964 types_unique_ids_.Initialize(types_.length(), zone); | |
2965 for (int i = 0; i < types_.length(); i++) { | |
2966 types_unique_ids_.Add(UniqueValueId(types_.at(i)), zone); | |
2967 } | |
2968 name_unique_id_ = UniqueValueId(name_); | |
2969 } | |
2970 | |
2971 | |
2972 bool HLoadNamedFieldPolymorphic::DataEquals(HValue* value) { | |
2973 ASSERT_EQ(types_.length(), types_unique_ids_.length()); | |
2974 HLoadNamedFieldPolymorphic* other = HLoadNamedFieldPolymorphic::cast(value); | |
2975 if (name_unique_id_ != other->name_unique_id_) return false; | |
2976 if (types_unique_ids_.length() != other->types_unique_ids_.length()) { | |
2977 return false; | |
2978 } | |
2979 if (need_generic_ != other->need_generic_) return false; | |
2980 for (int i = 0; i < types_unique_ids_.length(); i++) { | |
2981 bool found = false; | |
2982 for (int j = 0; j < types_unique_ids_.length(); j++) { | |
2983 if (types_unique_ids_.at(j) == other->types_unique_ids_.at(i)) { | |
2984 found = true; | |
2985 break; | |
2986 } | |
2987 } | |
2988 if (!found) return false; | |
2989 } | |
2990 return true; | |
2991 } | |
2992 | |
2993 | |
2994 void HLoadNamedFieldPolymorphic::PrintDataTo(StringStream* stream) { | |
2995 object()->PrintNameTo(stream); | |
2996 stream->Add("."); | |
2997 stream->Add(*String::cast(*name())->ToCString()); | |
2998 } | |
2999 | |
3000 | |
3001 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) { | 2848 void HLoadNamedGeneric::PrintDataTo(StringStream* stream) { |
3002 object()->PrintNameTo(stream); | 2849 object()->PrintNameTo(stream); |
3003 stream->Add("."); | 2850 stream->Add("."); |
3004 stream->Add(*String::cast(*name())->ToCString()); | 2851 stream->Add(*String::cast(*name())->ToCString()); |
3005 } | 2852 } |
3006 | 2853 |
3007 | 2854 |
3008 void HLoadKeyed::PrintDataTo(StringStream* stream) { | 2855 void HLoadKeyed::PrintDataTo(StringStream* stream) { |
3009 if (!is_external()) { | 2856 if (!is_external()) { |
3010 elements()->PrintNameTo(stream); | 2857 elements()->PrintNameTo(stream); |
(...skipping 1109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4120 break; | 3967 break; |
4121 case kExternalMemory: | 3968 case kExternalMemory: |
4122 stream->Add("[external-memory]"); | 3969 stream->Add("[external-memory]"); |
4123 break; | 3970 break; |
4124 } | 3971 } |
4125 | 3972 |
4126 stream->Add("@%d", offset()); | 3973 stream->Add("@%d", offset()); |
4127 } | 3974 } |
4128 | 3975 |
4129 } } // namespace v8::internal | 3976 } } // namespace v8::internal |
OLD | NEW |