| OLD | NEW |
| 1 // Copyright 2006-2009 the V8 project authors. All rights reserved. | 1 // Copyright 2006-2009 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 2081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 if (HasLocalElement(index)) return NONE; | 2092 if (HasLocalElement(index)) return NONE; |
| 2093 return ABSENT; | 2093 return ABSENT; |
| 2094 } | 2094 } |
| 2095 // Named property. | 2095 // Named property. |
| 2096 LookupResult result; | 2096 LookupResult result; |
| 2097 LocalLookup(name, &result); | 2097 LocalLookup(name, &result); |
| 2098 return GetPropertyAttribute(this, &result, name, false); | 2098 return GetPropertyAttribute(this, &result, name, false); |
| 2099 } | 2099 } |
| 2100 | 2100 |
| 2101 | 2101 |
| 2102 bool NormalizedMapCache::IsCacheable(JSObject* object) { | |
| 2103 // Caching for global objects is not worth it (there are too few of them). | |
| 2104 return !object->IsGlobalObject(); | |
| 2105 } | |
| 2106 | |
| 2107 | |
| 2108 Object* NormalizedMapCache::Get(JSObject* obj, PropertyNormalizationMode mode) { | 2102 Object* NormalizedMapCache::Get(JSObject* obj, PropertyNormalizationMode mode) { |
| 2109 Object* result; | 2103 Map* fast = obj->map(); |
| 2104 int index = Hash(fast) % kEntries; |
| 2105 Object* result = get(index); |
| 2106 if (result->IsMap() && CheckHit(Map::cast(result), fast, mode)) { |
| 2107 #ifdef DEBUG |
| 2108 if (FLAG_enable_slow_asserts) { |
| 2109 // The cached map should match newly created normalized map bit-by-bit. |
| 2110 Object* fresh = fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); |
| 2111 if (!fresh->IsFailure()) { |
| 2112 ASSERT(memcmp(Map::cast(fresh)->address(), |
| 2113 Map::cast(result)->address(), |
| 2114 Map::kSize) == 0); |
| 2115 } |
| 2116 } |
| 2117 #endif |
| 2118 return result; |
| 2119 } |
| 2110 | 2120 |
| 2111 Map* fast = obj->map(); | 2121 result = fast->CopyNormalized(mode, SHARED_NORMALIZED_MAP); |
| 2112 if (!IsCacheable(obj)) { | 2122 if (result->IsFailure()) return result; |
| 2113 result = fast->CopyNormalized(mode); | 2123 set(index, result); |
| 2114 if (result->IsFailure()) return result; | |
| 2115 } else { | |
| 2116 int index = Hash(fast) % kEntries; | |
| 2117 result = get(index); | |
| 2118 | |
| 2119 if (result->IsMap() && CheckHit(Map::cast(result), fast, mode)) { | |
| 2120 #ifdef DEBUG | |
| 2121 if (FLAG_enable_slow_asserts) { | |
| 2122 // Make sure that the new slow map has exactly the same hash as the | |
| 2123 // original fast map. This way we can use hash to check if a slow map | |
| 2124 // is already in the hash (see Contains method). | |
| 2125 ASSERT(Hash(fast) == Hash(Map::cast(result))); | |
| 2126 // The cached map should match newly created normalized map bit-by-bit. | |
| 2127 Object* fresh = fast->CopyNormalized(mode); | |
| 2128 if (!fresh->IsFailure()) { | |
| 2129 ASSERT(memcmp(Map::cast(fresh)->address(), | |
| 2130 Map::cast(result)->address(), | |
| 2131 Map::kSize) == 0); | |
| 2132 } | |
| 2133 } | |
| 2134 #endif | |
| 2135 return result; | |
| 2136 } | |
| 2137 | |
| 2138 result = fast->CopyNormalized(mode); | |
| 2139 if (result->IsFailure()) return result; | |
| 2140 set(index, result); | |
| 2141 } | |
| 2142 Counters::normalized_maps.Increment(); | 2124 Counters::normalized_maps.Increment(); |
| 2143 | 2125 |
| 2144 return result; | 2126 return result; |
| 2145 } | 2127 } |
| 2146 | 2128 |
| 2147 | 2129 |
| 2148 bool NormalizedMapCache::Contains(Map* map) { | |
| 2149 // If the map is present in the cache it can only be at one place: | |
| 2150 // at the index calculated from the hash. We assume that a slow map has the | |
| 2151 // same hash as a fast map it has been generated from. | |
| 2152 int index = Hash(map) % kEntries; | |
| 2153 return get(index) == map; | |
| 2154 } | |
| 2155 | |
| 2156 | |
| 2157 void NormalizedMapCache::Clear() { | 2130 void NormalizedMapCache::Clear() { |
| 2158 int entries = length(); | 2131 int entries = length(); |
| 2159 for (int i = 0; i != entries; i++) { | 2132 for (int i = 0; i != entries; i++) { |
| 2160 set_undefined(i); | 2133 set_undefined(i); |
| 2161 } | 2134 } |
| 2162 } | 2135 } |
| 2163 | 2136 |
| 2164 | 2137 |
| 2165 int NormalizedMapCache::Hash(Map* fast) { | 2138 int NormalizedMapCache::Hash(Map* fast) { |
| 2166 // For performance reasons we only hash the 3 most variable fields of a map: | 2139 // For performance reasons we only hash the 3 most variable fields of a map: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2177 reinterpret_cast<uintptr_t>(fast->prototype())) << 2); | 2150 reinterpret_cast<uintptr_t>(fast->prototype())) << 2); |
| 2178 | 2151 |
| 2179 return hash ^ (hash >> 16) ^ fast->bit_field2(); | 2152 return hash ^ (hash >> 16) ^ fast->bit_field2(); |
| 2180 } | 2153 } |
| 2181 | 2154 |
| 2182 | 2155 |
| 2183 bool NormalizedMapCache::CheckHit(Map* slow, | 2156 bool NormalizedMapCache::CheckHit(Map* slow, |
| 2184 Map* fast, | 2157 Map* fast, |
| 2185 PropertyNormalizationMode mode) { | 2158 PropertyNormalizationMode mode) { |
| 2186 #ifdef DEBUG | 2159 #ifdef DEBUG |
| 2187 slow->NormalizedMapVerify(); | 2160 slow->SharedMapVerify(); |
| 2188 #endif | 2161 #endif |
| 2189 return | 2162 return |
| 2190 slow->constructor() == fast->constructor() && | 2163 slow->constructor() == fast->constructor() && |
| 2191 slow->prototype() == fast->prototype() && | 2164 slow->prototype() == fast->prototype() && |
| 2192 slow->inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ? | 2165 slow->inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ? |
| 2193 0 : | 2166 0 : |
| 2194 fast->inobject_properties()) && | 2167 fast->inobject_properties()) && |
| 2195 slow->instance_type() == fast->instance_type() && | 2168 slow->instance_type() == fast->instance_type() && |
| 2196 slow->bit_field() == fast->bit_field() && | 2169 slow->bit_field() == fast->bit_field() && |
| 2197 slow->bit_field2() == fast->bit_field2(); | 2170 (slow->bit_field2() & ~(1<<Map::kIsShared)) == fast->bit_field2(); |
| 2198 } | 2171 } |
| 2199 | 2172 |
| 2200 | 2173 |
| 2201 Object* JSObject::UpdateMapCodeCache(String* name, Code* code) { | 2174 Object* JSObject::UpdateMapCodeCache(String* name, Code* code) { |
| 2202 if (!HasFastProperties() && | 2175 if (map()->is_shared()) { |
| 2203 NormalizedMapCache::IsCacheable(this) && | 2176 // Fast case maps are never marked as shared. |
| 2204 Top::context()->global_context()->normalized_map_cache()-> | 2177 ASSERT(!HasFastProperties()); |
| 2205 Contains(map())) { | 2178 // Replace the map with an identical copy that can be safely modified. |
| 2206 // Replace the map with the identical copy that can be safely modified. | 2179 Object* obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES, |
| 2207 Object* obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES); | 2180 UNIQUE_NORMALIZED_MAP); |
| 2208 if (obj->IsFailure()) return obj; | 2181 if (obj->IsFailure()) return obj; |
| 2209 Counters::normalized_maps.Increment(); | 2182 Counters::normalized_maps.Increment(); |
| 2210 | 2183 |
| 2211 set_map(Map::cast(obj)); | 2184 set_map(Map::cast(obj)); |
| 2212 } | 2185 } |
| 2213 return map()->UpdateCodeCache(name, code); | 2186 return map()->UpdateCodeCache(name, code); |
| 2214 } | 2187 } |
| 2215 | 2188 |
| 2216 | 2189 |
| 2217 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, | 2190 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, |
| (...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3182 Object* descriptors = | 3155 Object* descriptors = |
| 3183 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); | 3156 ctor->initial_map()->instance_descriptors()->RemoveTransitions(); |
| 3184 if (descriptors->IsFailure()) return descriptors; | 3157 if (descriptors->IsFailure()) return descriptors; |
| 3185 Map::cast(result)->set_instance_descriptors( | 3158 Map::cast(result)->set_instance_descriptors( |
| 3186 DescriptorArray::cast(descriptors)); | 3159 DescriptorArray::cast(descriptors)); |
| 3187 Map::cast(result)->set_pre_allocated_property_fields( | 3160 Map::cast(result)->set_pre_allocated_property_fields( |
| 3188 pre_allocated_property_fields()); | 3161 pre_allocated_property_fields()); |
| 3189 } | 3162 } |
| 3190 Map::cast(result)->set_bit_field(bit_field()); | 3163 Map::cast(result)->set_bit_field(bit_field()); |
| 3191 Map::cast(result)->set_bit_field2(bit_field2()); | 3164 Map::cast(result)->set_bit_field2(bit_field2()); |
| 3165 Map::cast(result)->set_is_shared(false); |
| 3192 Map::cast(result)->ClearCodeCache(); | 3166 Map::cast(result)->ClearCodeCache(); |
| 3193 return result; | 3167 return result; |
| 3194 } | 3168 } |
| 3195 | 3169 |
| 3196 | 3170 |
| 3197 Object* Map::CopyNormalized(PropertyNormalizationMode mode) { | 3171 Object* Map::CopyNormalized(PropertyNormalizationMode mode, |
| 3172 NormalizedMapSharingMode sharing) { |
| 3198 int new_instance_size = instance_size(); | 3173 int new_instance_size = instance_size(); |
| 3199 if (mode == CLEAR_INOBJECT_PROPERTIES) { | 3174 if (mode == CLEAR_INOBJECT_PROPERTIES) { |
| 3200 new_instance_size -= inobject_properties() * kPointerSize; | 3175 new_instance_size -= inobject_properties() * kPointerSize; |
| 3201 } | 3176 } |
| 3202 | 3177 |
| 3203 Object* result = Heap::AllocateMap(instance_type(), new_instance_size); | 3178 Object* result = Heap::AllocateMap(instance_type(), new_instance_size); |
| 3204 if (result->IsFailure()) return result; | 3179 if (result->IsFailure()) return result; |
| 3205 | 3180 |
| 3206 if (mode != CLEAR_INOBJECT_PROPERTIES) { | 3181 if (mode != CLEAR_INOBJECT_PROPERTIES) { |
| 3207 Map::cast(result)->set_inobject_properties(inobject_properties()); | 3182 Map::cast(result)->set_inobject_properties(inobject_properties()); |
| 3208 } | 3183 } |
| 3209 | 3184 |
| 3210 Map::cast(result)->set_prototype(prototype()); | 3185 Map::cast(result)->set_prototype(prototype()); |
| 3211 Map::cast(result)->set_constructor(constructor()); | 3186 Map::cast(result)->set_constructor(constructor()); |
| 3212 | 3187 |
| 3213 Map::cast(result)->set_bit_field(bit_field()); | 3188 Map::cast(result)->set_bit_field(bit_field()); |
| 3214 Map::cast(result)->set_bit_field2(bit_field2()); | 3189 Map::cast(result)->set_bit_field2(bit_field2()); |
| 3215 | 3190 |
| 3191 Map::cast(result)->set_is_shared(sharing == SHARED_NORMALIZED_MAP); |
| 3192 |
| 3216 #ifdef DEBUG | 3193 #ifdef DEBUG |
| 3217 Map::cast(result)->NormalizedMapVerify(); | 3194 if (Map::cast(result)->is_shared()) { |
| 3195 Map::cast(result)->SharedMapVerify(); |
| 3196 } |
| 3218 #endif | 3197 #endif |
| 3219 | 3198 |
| 3220 return result; | 3199 return result; |
| 3221 } | 3200 } |
| 3222 | 3201 |
| 3223 | 3202 |
| 3224 Object* Map::CopyDropTransitions() { | 3203 Object* Map::CopyDropTransitions() { |
| 3225 Object* new_map = CopyDropDescriptors(); | 3204 Object* new_map = CopyDropDescriptors(); |
| 3226 if (new_map->IsFailure()) return new_map; | 3205 if (new_map->IsFailure()) return new_map; |
| 3227 Object* descriptors = instance_descriptors()->RemoveTransitions(); | 3206 Object* descriptors = instance_descriptors()->RemoveTransitions(); |
| (...skipping 5825 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9053 if (break_point_objects()->IsUndefined()) return 0; | 9032 if (break_point_objects()->IsUndefined()) return 0; |
| 9054 // Single beak point. | 9033 // Single beak point. |
| 9055 if (!break_point_objects()->IsFixedArray()) return 1; | 9034 if (!break_point_objects()->IsFixedArray()) return 1; |
| 9056 // Multiple break points. | 9035 // Multiple break points. |
| 9057 return FixedArray::cast(break_point_objects())->length(); | 9036 return FixedArray::cast(break_point_objects())->length(); |
| 9058 } | 9037 } |
| 9059 #endif | 9038 #endif |
| 9060 | 9039 |
| 9061 | 9040 |
| 9062 } } // namespace v8::internal | 9041 } } // namespace v8::internal |
| OLD | NEW |