Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Side by Side Diff: src/objects.cc

Issue 3472006: Prevent modification of cached normalized maps.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698