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

Side by Side Diff: src/objects.cc

Issue 10916336: Preallocate space in descriptor arrays. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: u Created 8 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 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 2202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2213 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) { 2213 if (Marking::IsBlack(Marking::MarkBitFrom(elms))) {
2214 if (trim_mode == FROM_GC) { 2214 if (trim_mode == FROM_GC) {
2215 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta); 2215 MemoryChunk::IncrementLiveBytesFromGC(elms->address(), -size_delta);
2216 } else { 2216 } else {
2217 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta); 2217 MemoryChunk::IncrementLiveBytesFromMutator(elms->address(), -size_delta);
2218 } 2218 }
2219 } 2219 }
2220 } 2220 }
2221 2221
2222 2222
2223 void Map::CopyAppendCallbackDescriptors(Handle<Map> map, 2223 void Map::EnsureDescriptorSlack(Handle<Map> map, int slack) {
2224 Handle<Object> descriptors) { 2224 Handle<DescriptorArray> descriptors(map->instance_descriptors());
2225 if (slack <= descriptors->NumberOfSlackDescriptors()) return;
2226 int number_of_descriptors = descriptors->number_of_descriptors();
2227 Isolate* isolate = map->GetIsolate();
2228 Handle<DescriptorArray> new_descriptors =
2229 isolate->factory()->NewDescriptorArray(number_of_descriptors, slack);
2230 DescriptorArray::WhitenessWitness witness(*new_descriptors);
2231
2232 for (int i = 0; i < number_of_descriptors; ++i) {
2233 new_descriptors->CopyFrom(i, *descriptors, i, witness);
2234 }
2235
2236 Map::SetDescriptors(map, new_descriptors);
2237 }
2238
2239
2240 void Map::AppendCallbackDescriptors(Handle<Map> map,
2241 Handle<Object> descriptors) {
2225 Isolate* isolate = map->GetIsolate(); 2242 Isolate* isolate = map->GetIsolate();
2226 Handle<DescriptorArray> array(map->instance_descriptors()); 2243 Handle<DescriptorArray> array(map->instance_descriptors());
2227 v8::NeanderArray callbacks(descriptors); 2244 NeanderArray callbacks(descriptors);
2228 int nof_callbacks = callbacks.length(); 2245 int nof_callbacks = callbacks.length();
2229 int descriptor_count = array->number_of_descriptors(); 2246
2230 ASSERT(descriptor_count == map->NumberOfOwnDescriptors()); 2247 ASSERT(array->NumberOfSlackDescriptors() >= nof_callbacks);
2231 2248
2232 // Ensure the keys are symbols before writing them into the instance 2249 // Ensure the keys are symbols before writing them into the instance
2233 // descriptor. Since it may cause a GC, it has to be done before we 2250 // descriptor. Since it may cause a GC, it has to be done before we
2234 // temporarily put the heap in an invalid state while appending descriptors. 2251 // temporarily put the heap in an invalid state while appending descriptors.
2235 for (int i = 0; i < nof_callbacks; ++i) { 2252 for (int i = 0; i < nof_callbacks; ++i) {
2236 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i))); 2253 Handle<AccessorInfo> entry(AccessorInfo::cast(callbacks.get(i)));
2237 Handle<String> key = 2254 Handle<String> key =
2238 isolate->factory()->SymbolFromString( 2255 isolate->factory()->SymbolFromString(
2239 Handle<String>(String::cast(entry->name()))); 2256 Handle<String>(String::cast(entry->name())));
2240 entry->set_name(*key); 2257 entry->set_name(*key);
2241 } 2258 }
2242 2259
2243 Handle<DescriptorArray> result = 2260 int nof = map->NumberOfOwnDescriptors();
2244 isolate->factory()->NewDescriptorArray(descriptor_count + nof_callbacks);
2245
2246 // Ensure that marking will not progress and change color of objects.
2247 DescriptorArray::WhitenessWitness witness(*result);
2248
2249 // Copy the descriptors from the array.
2250 for (int i = 0; i < descriptor_count; i++) {
2251 result->CopyFrom(i, *array, i, witness);
2252 }
2253
2254 // After this point the GC is not allowed to run anymore until the map is in a
2255 // consistent state again, i.e., all the descriptors are appended and the
2256 // descriptor array is trimmed to the right size.
2257 Map::SetDescriptors(map, result);
2258 2261
2259 // Fill in new callback descriptors. Process the callbacks from 2262 // Fill in new callback descriptors. Process the callbacks from
2260 // back to front so that the last callback with a given name takes 2263 // back to front so that the last callback with a given name takes
2261 // precedence over previously added callbacks with that name. 2264 // precedence over previously added callbacks with that name.
2262 int nof = descriptor_count;
2263 for (int i = nof_callbacks - 1; i >= 0; i--) { 2265 for (int i = nof_callbacks - 1; i >= 0; i--) {
2264 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i)); 2266 AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
2265 String* key = String::cast(entry->name()); 2267 String* key = String::cast(entry->name());
2266 // Check if a descriptor with this name already exists before writing. 2268 // Check if a descriptor with this name already exists before writing.
2267 if (result->Search(key, nof) == DescriptorArray::kNotFound) { 2269 if (array->Search(key, nof) == DescriptorArray::kNotFound) {
2268 CallbacksDescriptor desc(key, entry, entry->property_attributes()); 2270 CallbacksDescriptor desc(key, entry, entry->property_attributes());
2269 map->AppendDescriptor(&desc, witness); 2271 array->Append(&desc);
2270 nof += 1; 2272 nof += 1;
2271 } 2273 }
2272 } 2274 }
2273 2275
2274 ASSERT(nof == map->NumberOfOwnDescriptors()); 2276 map->SetNumberOfOwnDescriptors(nof);
2275
2276 // Reinstall the original descriptor array if no new elements were added.
2277 if (nof == descriptor_count) {
2278 Map::SetDescriptors(map, array);
2279 return;
2280 }
2281
2282 // If duplicates were detected, trim the descriptor array to the right size.
2283 int new_array_size = DescriptorArray::LengthFor(nof);
2284 if (new_array_size < result->length()) {
2285 RightTrimFixedArray<FROM_MUTATOR>(
2286 isolate->heap(), *result, result->length() - new_array_size);
2287 }
2288 } 2277 }
2289 2278
2290 2279
2291 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) { 2280 static bool ContainsMap(MapHandleList* maps, Handle<Map> map) {
2292 ASSERT(!map.is_null()); 2281 ASSERT(!map.is_null());
2293 for (int i = 0; i < maps->length(); ++i) { 2282 for (int i = 0; i < maps->length(); ++i) {
2294 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true; 2283 if (!maps->at(i).is_null() && maps->at(i).is_identical_to(map)) return true;
2295 } 2284 }
2296 return false; 2285 return false;
2297 } 2286 }
(...skipping 2715 matching lines...) Expand 10 before | Expand all | Expand 10 after
5013 String* name = descriptor->GetKey(); 5002 String* name = descriptor->GetKey();
5014 5003
5015 TransitionArray* transitions; 5004 TransitionArray* transitions;
5016 MaybeObject* maybe_transitions = AddTransition(name, result); 5005 MaybeObject* maybe_transitions = AddTransition(name, result);
5017 if (!maybe_transitions->To(&transitions)) return maybe_transitions; 5006 if (!maybe_transitions->To(&transitions)) return maybe_transitions;
5018 5007
5019 DescriptorArray* descriptors = instance_descriptors(); 5008 DescriptorArray* descriptors = instance_descriptors();
5020 int old_size = descriptors->number_of_descriptors(); 5009 int old_size = descriptors->number_of_descriptors();
5021 5010
5022 DescriptorArray* new_descriptors; 5011 DescriptorArray* new_descriptors;
5023 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1);
5024 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5025 DescriptorArray::WhitenessWitness witness(new_descriptors);
5026 5012
5027 for (int i = 0; i < old_size; ++i) { 5013 if (descriptors->NumberOfSlackDescriptors() > 0) {
5028 new_descriptors->CopyFrom(i, descriptors, i, witness); 5014 new_descriptors = descriptors;
5029 } 5015 new_descriptors->Append(descriptor);
5030 new_descriptors->Append(descriptor, witness, old_size); 5016 } else {
5017 // Descriptor arrays grow by 50%.
5018 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(
5019 old_size, old_size < 4 ? 1 : old_size / 2);
5020 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5031 5021
5032 // If the source descriptors had an enum cache we copy it. This ensures that 5022 DescriptorArray::WhitenessWitness witness(new_descriptors);
5033 // the maps to which we push the new descriptor array back can rely on a 5023
5034 // cache always being available once it is set. If the map has more 5024 // Copy the descriptors, inserting a descriptor.
5035 // enumerated descriptors than available in the original cache, the cache 5025 for (int i = 0; i < old_size; ++i) {
5036 // will be lazily replaced by the extended cache when needed. 5026 new_descriptors->CopyFrom(i, descriptors, i, witness);
5037 if (descriptors->HasEnumCache()) { 5027 }
5038 new_descriptors->CopyEnumCacheFrom(descriptors); 5028
5029 new_descriptors->Append(descriptor, witness);
5030
5031 // If the source descriptors had an enum cache we copy it. This ensures that
5032 // the maps to which we push the new descriptor array back can rely on a
5033 // cache always being available once it is set. If the map has more
5034 // enumerated descriptors than available in the original cache, the cache
5035 // will be lazily replaced by the extended cache when needed.
5036 if (descriptors->HasEnumCache()) {
5037 new_descriptors->CopyEnumCacheFrom(descriptors);
5038 }
5039 } 5039 }
5040 5040
5041 transitions->set_descriptors(new_descriptors); 5041 transitions->set_descriptors(new_descriptors);
5042
5042 set_transitions(transitions); 5043 set_transitions(transitions);
5043 result->SetBackPointer(this); 5044 result->SetBackPointer(this);
5044 set_owns_descriptors(false); 5045 set_owns_descriptors(false);
5045 5046
5046 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors()); 5047 result->SetNumberOfOwnDescriptors(new_descriptors->number_of_descriptors());
5047 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1); 5048 ASSERT(result->NumberOfOwnDescriptors() == NumberOfOwnDescriptors() + 1);
5048 5049
5049 return result; 5050 return result;
5050 } 5051 }
5051 5052
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
5207 int new_size = old_size + 1; 5208 int new_size = old_size + 1;
5208 descriptor->SetEnumerationIndex(new_size); 5209 descriptor->SetEnumerationIndex(new_size);
5209 5210
5210 if (flag == INSERT_TRANSITION && 5211 if (flag == INSERT_TRANSITION &&
5211 owns_descriptors() && 5212 owns_descriptors() &&
5212 CanHaveMoreTransitions()) { 5213 CanHaveMoreTransitions()) {
5213 return ShareDescriptor(descriptor); 5214 return ShareDescriptor(descriptor);
5214 } 5215 }
5215 5216
5216 DescriptorArray* new_descriptors; 5217 DescriptorArray* new_descriptors;
5217 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size + 1); 5218 MaybeObject* maybe_descriptors = DescriptorArray::Allocate(old_size, 1);
5218 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors; 5219 if (!maybe_descriptors->To(&new_descriptors)) return maybe_descriptors;
5219 5220
5220 DescriptorArray::WhitenessWitness witness(new_descriptors); 5221 DescriptorArray::WhitenessWitness witness(new_descriptors);
5221 5222
5222 // Copy the descriptors, inserting a descriptor. 5223 // Copy the descriptors, inserting a descriptor.
5223 for (int i = 0; i < old_size; ++i) { 5224 for (int i = 0; i < old_size; ++i) {
5224 new_descriptors->CopyFrom(i, descriptors, i, witness); 5225 new_descriptors->CopyFrom(i, descriptors, i, witness);
5225 } 5226 }
5226 5227
5227 new_descriptors->Set(old_size, descriptor, witness); 5228 if (old_size != descriptors->number_of_descriptors()) {
5228 new_descriptors->Sort(); 5229 new_descriptors->SetNumberOfDescriptors(new_size);
5230 new_descriptors->Set(old_size, descriptor, witness);
5231 new_descriptors->Sort();
5232 } else {
5233 new_descriptors->Append(descriptor, witness);
5234 }
5229 5235
5230 return CopyReplaceDescriptors(new_descriptors, descriptor->GetKey(), flag); 5236 String* key = descriptor->GetKey();
5237
5238 return CopyReplaceDescriptors(new_descriptors, key, flag);
5231 } 5239 }
5232 5240
5233 5241
5234 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor, 5242 MaybeObject* Map::CopyInsertDescriptor(Descriptor* descriptor,
5235 TransitionFlag flag) { 5243 TransitionFlag flag) {
5236 DescriptorArray* old_descriptors = instance_descriptors(); 5244 DescriptorArray* old_descriptors = instance_descriptors();
5237 5245
5238 // Ensure the key is a symbol. 5246 // Ensure the key is a symbol.
5239 MaybeObject* maybe_result = descriptor->KeyToSymbol(); 5247 MaybeObject* maybe_result = descriptor->KeyToSymbol();
5240 if (maybe_result->IsFailure()) return maybe_result; 5248 if (maybe_result->IsFailure()) return maybe_result;
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
6071 bool FixedArray::IsEqualTo(FixedArray* other) { 6079 bool FixedArray::IsEqualTo(FixedArray* other) {
6072 if (length() != other->length()) return false; 6080 if (length() != other->length()) return false;
6073 for (int i = 0 ; i < length(); ++i) { 6081 for (int i = 0 ; i < length(); ++i) {
6074 if (get(i) != other->get(i)) return false; 6082 if (get(i) != other->get(i)) return false;
6075 } 6083 }
6076 return true; 6084 return true;
6077 } 6085 }
6078 #endif 6086 #endif
6079 6087
6080 6088
6081 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors) { 6089 MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, int slack) {
6082 Heap* heap = Isolate::Current()->heap(); 6090 Heap* heap = Isolate::Current()->heap();
6083 // Do not use DescriptorArray::cast on incomplete object. 6091 // Do not use DescriptorArray::cast on incomplete object.
6092 int size = number_of_descriptors + slack;
6093 if (size == 0) return heap->empty_descriptor_array();
6084 FixedArray* result; 6094 FixedArray* result;
6085 if (number_of_descriptors == 0) return heap->empty_descriptor_array();
6086 // Allocate the array of keys. 6095 // Allocate the array of keys.
6087 MaybeObject* maybe_array = 6096 MaybeObject* maybe_array = heap->AllocateFixedArray(LengthFor(size));
6088 heap->AllocateFixedArray(LengthFor(number_of_descriptors));
6089 if (!maybe_array->To(&result)) return maybe_array; 6097 if (!maybe_array->To(&result)) return maybe_array;
6090 6098
6099 result->set(kDescriptorLengthIndex, Smi::FromInt(number_of_descriptors));
6091 result->set(kEnumCacheIndex, Smi::FromInt(0)); 6100 result->set(kEnumCacheIndex, Smi::FromInt(0));
6092 return result; 6101 return result;
6093 } 6102 }
6094 6103
6095 6104
6096 void DescriptorArray::ClearEnumCache() { 6105 void DescriptorArray::ClearEnumCache() {
6097 set(kEnumCacheIndex, Smi::FromInt(0)); 6106 set(kEnumCacheIndex, Smi::FromInt(0));
6098 } 6107 }
6099 6108
6100 6109
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after
7495 if (transition_index == t->number_of_transitions()) return; 7504 if (transition_index == t->number_of_transitions()) return;
7496 } 7505 }
7497 7506
7498 int number_of_own_descriptors = NumberOfOwnDescriptors(); 7507 int number_of_own_descriptors = NumberOfOwnDescriptors();
7499 7508
7500 if (descriptors_owner_died) { 7509 if (descriptors_owner_died) {
7501 if (number_of_own_descriptors > 0) { 7510 if (number_of_own_descriptors > 0) {
7502 int number_of_descriptors = descriptors->number_of_descriptors(); 7511 int number_of_descriptors = descriptors->number_of_descriptors();
7503 int to_trim = number_of_descriptors - number_of_own_descriptors; 7512 int to_trim = number_of_descriptors - number_of_own_descriptors;
7504 if (to_trim > 0) { 7513 if (to_trim > 0) {
7505 RightTrimFixedArray<FROM_GC>( 7514 // Maximally keep 50% of unused descriptors.
7506 heap, descriptors, to_trim * DescriptorArray::kDescriptorSize); 7515 int keep = Min(to_trim, number_of_own_descriptors / 2);
7516 for (int i = number_of_own_descriptors;
7517 i < number_of_own_descriptors + keep;
7518 ++i) {
7519 descriptors->EraseDescriptor(heap, i);
7520 }
7521 if (to_trim > keep) {
7522 RightTrimFixedArray<FROM_GC>(heap, descriptors, to_trim - keep);
7523 }
7524 descriptors->SetNumberOfDescriptors(number_of_own_descriptors);
7507 if (descriptors->HasEnumCache()) { 7525 if (descriptors->HasEnumCache()) {
7508 int live_enum = 7526 int live_enum =
7509 NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM); 7527 NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_ENUM);
7510 if (live_enum == 0) { 7528 if (live_enum == 0) {
7511 descriptors->ClearEnumCache(); 7529 descriptors->ClearEnumCache();
7512 } else { 7530 } else {
7513 FixedArray* enum_cache = 7531 FixedArray* enum_cache =
7514 FixedArray::cast(descriptors->GetEnumCache()); 7532 FixedArray::cast(descriptors->GetEnumCache());
7515 to_trim = enum_cache->length() - live_enum; 7533 to_trim = enum_cache->length() - live_enum;
7516 if (to_trim > 0) { 7534 if (to_trim > 0) {
(...skipping 5990 matching lines...) Expand 10 before | Expand all | Expand 10 after
13507 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER); 13525 set_year(Smi::FromInt(year), SKIP_WRITE_BARRIER);
13508 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER); 13526 set_month(Smi::FromInt(month), SKIP_WRITE_BARRIER);
13509 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER); 13527 set_day(Smi::FromInt(day), SKIP_WRITE_BARRIER);
13510 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER); 13528 set_weekday(Smi::FromInt(weekday), SKIP_WRITE_BARRIER);
13511 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER); 13529 set_hour(Smi::FromInt(hour), SKIP_WRITE_BARRIER);
13512 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER); 13530 set_min(Smi::FromInt(min), SKIP_WRITE_BARRIER);
13513 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER); 13531 set_sec(Smi::FromInt(sec), SKIP_WRITE_BARRIER);
13514 } 13532 }
13515 13533
13516 } } // namespace v8::internal 13534 } } // 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