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

Side by Side Diff: src/objects.cc

Issue 3134027: Reapplying r5147 (caching maps for slow case objects).... (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 2080 matching lines...) Expand 10 before | Expand all | Expand 10 after
2091 if (HasLocalElement(index)) return NONE; 2091 if (HasLocalElement(index)) return NONE;
2092 return ABSENT; 2092 return ABSENT;
2093 } 2093 }
2094 // Named property. 2094 // Named property.
2095 LookupResult result; 2095 LookupResult result;
2096 LocalLookup(name, &result); 2096 LocalLookup(name, &result);
2097 return GetPropertyAttribute(this, &result, name, false); 2097 return GetPropertyAttribute(this, &result, name, false);
2098 } 2098 }
2099 2099
2100 2100
2101 bool NormalizedMapCache::IsCacheable(JSObject* object) {
2102 // Caching for global objects is not worth it (there are too few of them).
2103 return !object->IsGlobalObject();
2104 }
2105
2106
2107 Object* NormalizedMapCache::Get(JSObject* obj, PropertyNormalizationMode mode) {
2108 Object* result;
2109
2110 Map* fast = obj->map();
2111 if (!IsCacheable(obj)) {
2112 result = fast->CopyNormalized(mode);
2113 if (result->IsFailure()) return result;
2114 } else {
2115 int index = Hash(fast) % kEntries;
2116 result = get(index);
2117
2118 if (result->IsMap() && CheckHit(Map::cast(result), fast, mode)) {
2119 #ifdef DEBUG
2120 if (FLAG_enable_slow_asserts) {
2121 // Make sure that the new slow map has exactly the same hash as the
2122 // original fast map. This way we can use hash to check if a slow map
2123 // is already in the hash (see Contains method).
2124 ASSERT(Hash(fast) == Hash(Map::cast(result)));
2125 // The cached map should match newly created normalized map bit-by-bit.
2126 Object* fresh = fast->CopyNormalized(mode);
2127 if (!fresh->IsFailure()) {
2128 // Copy the unused byte so that the assertion below works.
2129 Map::cast(fresh)->address()[Map::kUnusedOffset] =
2130 Map::cast(result)->address()[Map::kUnusedOffset];
2131 ASSERT(memcmp(Map::cast(fresh)->address(),
2132 Map::cast(result)->address(),
2133 Map::kSize) == 0);
2134 }
2135 }
2136 #endif
2137 return result;
2138 }
2139
2140 result = fast->CopyNormalized(mode);
2141 if (result->IsFailure()) return result;
2142 set(index, result);
2143 }
2144 Counters::normalized_maps.Increment();
2145
2146 return result;
2147 }
2148
2149
2150 bool NormalizedMapCache::Contains(Map* map) {
2151 // If the map is present in the cache it can only be at one place:
2152 // at the index calculated from the hash. We assume that a slow map has the
2153 // same hash as a fast map it has been generated from.
2154 int index = Hash(map) % kEntries;
2155 return get(index) == map;
2156 }
2157
2158
2159 void NormalizedMapCache::Clear() {
2160 int entries = length();
2161 for (int i = 0; i != entries; i++) {
2162 set_undefined(i);
2163 }
2164 }
2165
2166
2167 int NormalizedMapCache::Hash(Map* fast) {
2168 // For performance reasons we only hash the 3 most variable fields of a map:
2169 // constructor, prototype and bit_field2.
2170
2171 // Shift away the tag.
2172 int hash = (static_cast<uint32_t>(
2173 reinterpret_cast<uintptr_t>(fast->constructor())) >> 2);
2174
2175 // XOR-ing the prototype and constructor directly yields too many zero bits
2176 // when the two pointers are close (which is fairly common).
2177 // To avoid this we shift the prototype 4 bits relatively to the constructor.
2178 hash ^= (static_cast<uint32_t>(
2179 reinterpret_cast<uintptr_t>(fast->prototype())) << 2);
2180
2181 return hash ^ (hash >> 16) ^ fast->bit_field2();
2182 }
2183
2184
2185 bool NormalizedMapCache::CheckHit(Map* slow,
2186 Map* fast,
2187 PropertyNormalizationMode mode) {
2188 #ifdef DEBUG
2189 slow->NormalizedMapVerify();
2190 #endif
2191 return
2192 slow->constructor() == fast->constructor() &&
2193 slow->prototype() == fast->prototype() &&
2194 slow->inobject_properties() == ((mode == CLEAR_INOBJECT_PROPERTIES) ?
2195 0 :
2196 fast->inobject_properties()) &&
2197 slow->instance_type() == fast->instance_type() &&
2198 slow->bit_field() == fast->bit_field() &&
2199 slow->bit_field2() == fast->bit_field2();
2200 }
2201
2202
2203 Object* JSObject::UpdateMapCodeCache(String* name, Code* code) {
2204 if (!HasFastProperties() &&
2205 NormalizedMapCache::IsCacheable(this) &&
2206 Top::context()->global_context()->normalized_map_cache()->
2207 Contains(map())) {
2208 // Replace the map with the identical copy that can be safely modified.
2209 Object* obj = map()->CopyNormalized(KEEP_INOBJECT_PROPERTIES);
2210 if (obj->IsFailure()) return obj;
2211 Counters::normalized_maps.Increment();
2212
2213 set_map(Map::cast(obj));
2214 }
2215 return map()->UpdateCodeCache(name, code);
2216 }
2217
2218
2101 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode, 2219 Object* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
2102 int expected_additional_properties) { 2220 int expected_additional_properties) {
2103 if (!HasFastProperties()) return this; 2221 if (!HasFastProperties()) return this;
2104 2222
2105 // The global object is always normalized. 2223 // The global object is always normalized.
2106 ASSERT(!IsGlobalObject()); 2224 ASSERT(!IsGlobalObject());
2107 2225
2108 // Allocate new content. 2226 // Allocate new content.
2109 int property_count = map()->NumberOfDescribedProperties(); 2227 int property_count = map()->NumberOfDescribedProperties();
2110 if (expected_additional_properties > 0) { 2228 if (expected_additional_properties > 0) {
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
2155 break; 2273 break;
2156 default: 2274 default:
2157 UNREACHABLE(); 2275 UNREACHABLE();
2158 } 2276 }
2159 } 2277 }
2160 2278
2161 // Copy the next enumeration index from instance descriptor. 2279 // Copy the next enumeration index from instance descriptor.
2162 int index = map()->instance_descriptors()->NextEnumerationIndex(); 2280 int index = map()->instance_descriptors()->NextEnumerationIndex();
2163 dictionary->SetNextEnumerationIndex(index); 2281 dictionary->SetNextEnumerationIndex(index);
2164 2282
2165 // Allocate new map. 2283 obj = Top::context()->global_context()->
2166 obj = map()->CopyDropDescriptors(); 2284 normalized_map_cache()->Get(this, mode);
2167 if (obj->IsFailure()) return obj; 2285 if (obj->IsFailure()) return obj;
2168 Map* new_map = Map::cast(obj); 2286 Map* new_map = Map::cast(obj);
2169 2287
2170 // Clear inobject properties if needed by adjusting the instance size and
2171 // putting in a filler object instead of the inobject properties.
2172 if (mode == CLEAR_INOBJECT_PROPERTIES && map()->inobject_properties() > 0) {
2173 int instance_size_delta = map()->inobject_properties() * kPointerSize;
2174 int new_instance_size = map()->instance_size() - instance_size_delta;
2175 new_map->set_inobject_properties(0);
2176 new_map->set_instance_size(new_instance_size);
2177 new_map->set_visitor_id(StaticVisitorBase::GetVisitorId(new_map));
2178 Heap::CreateFillerObjectAt(this->address() + new_instance_size,
2179 instance_size_delta);
2180 }
2181 new_map->set_unused_property_fields(0);
2182
2183 // We have now successfully allocated all the necessary objects. 2288 // We have now successfully allocated all the necessary objects.
2184 // Changes can now be made with the guarantee that all of them take effect. 2289 // Changes can now be made with the guarantee that all of them take effect.
2290
2291 // Resize the object in the heap if necessary.
2292 int new_instance_size = new_map->instance_size();
2293 int instance_size_delta = map()->instance_size() - new_instance_size;
2294 ASSERT(instance_size_delta >= 0);
2295 Heap::CreateFillerObjectAt(this->address() + new_instance_size,
2296 instance_size_delta);
2297
2185 set_map(new_map); 2298 set_map(new_map);
2186 map()->set_instance_descriptors(Heap::empty_descriptor_array());
2187 2299
2188 set_properties(dictionary); 2300 set_properties(dictionary);
2189 2301
2190 Counters::props_to_dictionary.Increment(); 2302 Counters::props_to_dictionary.Increment();
2191 2303
2192 #ifdef DEBUG 2304 #ifdef DEBUG
2193 if (FLAG_trace_normalization) { 2305 if (FLAG_trace_normalization) {
2194 PrintF("Object properties have been normalized:\n"); 2306 PrintF("Object properties have been normalized:\n");
2195 Print(); 2307 Print();
2196 } 2308 }
(...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after
3076 Map::cast(result)->set_pre_allocated_property_fields( 3188 Map::cast(result)->set_pre_allocated_property_fields(
3077 pre_allocated_property_fields()); 3189 pre_allocated_property_fields());
3078 } 3190 }
3079 Map::cast(result)->set_bit_field(bit_field()); 3191 Map::cast(result)->set_bit_field(bit_field());
3080 Map::cast(result)->set_bit_field2(bit_field2()); 3192 Map::cast(result)->set_bit_field2(bit_field2());
3081 Map::cast(result)->ClearCodeCache(); 3193 Map::cast(result)->ClearCodeCache();
3082 return result; 3194 return result;
3083 } 3195 }
3084 3196
3085 3197
3198 Object* Map::CopyNormalized(PropertyNormalizationMode mode) {
3199 int new_instance_size = instance_size();
3200 if (mode == CLEAR_INOBJECT_PROPERTIES) {
3201 new_instance_size -= inobject_properties() * kPointerSize;
3202 }
3203
3204 Object* result = Heap::AllocateMap(instance_type(), new_instance_size);
3205 if (result->IsFailure()) return result;
3206
3207 if (mode != CLEAR_INOBJECT_PROPERTIES) {
3208 Map::cast(result)->set_inobject_properties(inobject_properties());
3209 }
3210
3211 Map::cast(result)->set_prototype(prototype());
3212 Map::cast(result)->set_constructor(constructor());
3213
3214 Map::cast(result)->set_bit_field(bit_field());
3215 Map::cast(result)->set_bit_field2(bit_field2());
3216
3217 #ifdef DEBUG
3218 Map::cast(result)->NormalizedMapVerify();
3219 #endif
3220
3221 return result;
3222 }
3223
3224
3086 Object* Map::CopyDropTransitions() { 3225 Object* Map::CopyDropTransitions() {
3087 Object* new_map = CopyDropDescriptors(); 3226 Object* new_map = CopyDropDescriptors();
3088 if (new_map->IsFailure()) return new_map; 3227 if (new_map->IsFailure()) return new_map;
3089 Object* descriptors = instance_descriptors()->RemoveTransitions(); 3228 Object* descriptors = instance_descriptors()->RemoveTransitions();
3090 if (descriptors->IsFailure()) return descriptors; 3229 if (descriptors->IsFailure()) return descriptors;
3091 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors)); 3230 cast(new_map)->set_instance_descriptors(DescriptorArray::cast(descriptors));
3092 return new_map; 3231 return new_map;
3093 } 3232 }
3094 3233
3095 3234
(...skipping 5661 matching lines...) Expand 10 before | Expand all | Expand 10 after
8757 if (break_point_objects()->IsUndefined()) return 0; 8896 if (break_point_objects()->IsUndefined()) return 0;
8758 // Single beak point. 8897 // Single beak point.
8759 if (!break_point_objects()->IsFixedArray()) return 1; 8898 if (!break_point_objects()->IsFixedArray()) return 1;
8760 // Multiple break points. 8899 // Multiple break points.
8761 return FixedArray::cast(break_point_objects())->length(); 8900 return FixedArray::cast(break_point_objects())->length();
8762 } 8901 }
8763 #endif 8902 #endif
8764 8903
8765 8904
8766 } } // namespace v8::internal 8905 } } // 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