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

Side by Side Diff: src/transitions.cc

Issue 1470773003: Optimize ClearNonLiveReferences: do not compact prototype transitions in GC. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 5 years 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
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/transitions.h" 5 #include "src/transitions.h"
6 6
7 #include "src/objects-inl.h" 7 #include "src/objects-inl.h"
8 #include "src/transitions-inl.h" 8 #include "src/transitions-inl.h"
9 #include "src/utils.h" 9 #include "src/utils.h"
10 10
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 Object* raw_transitions = map->raw_transitions(); 227 Object* raw_transitions = map->raw_transitions();
228 if (IsFullTransitionArray(raw_transitions)) { 228 if (IsFullTransitionArray(raw_transitions)) {
229 TransitionArray* transitions = TransitionArray::cast(raw_transitions); 229 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
230 return transitions->number_of_transitions() < kMaxNumberOfTransitions; 230 return transitions->number_of_transitions() < kMaxNumberOfTransitions;
231 } 231 }
232 return true; 232 return true;
233 } 233 }
234 234
235 235
236 // static 236 // static
237 bool TransitionArray::CompactPrototypeTransitionArray(FixedArray* array) {
238 const int header = TransitionArray::kProtoTransitionHeaderSize;
239 int number_of_transitions = NumberOfPrototypeTransitions(array);
240 if (number_of_transitions == 0) {
241 // Empty array cannot be compacted.
242 return false;
243 }
244 int new_number_of_transitions = 0;
245 for (int i = 0; i < number_of_transitions; i++) {
246 Object* cell = array->get(header + i);
247 if (!WeakCell::cast(cell)->cleared()) {
248 if (new_number_of_transitions != i) {
249 array->set(header + new_number_of_transitions, cell);
250 }
251 new_number_of_transitions++;
252 }
253 }
254 // Fill slots that became free with undefined value.
255 for (int i = new_number_of_transitions; i < number_of_transitions; i++) {
256 array->set_undefined(header + i);
257 }
258 if (number_of_transitions != new_number_of_transitions) {
259 SetNumberOfPrototypeTransitions(array, new_number_of_transitions);
260 }
261 return new_number_of_transitions < number_of_transitions;
262 }
263
264
265 // static
266 Handle<FixedArray> TransitionArray::GrowPrototypeTransitionArray(
267 Handle<FixedArray> array, int new_capacity, Isolate* isolate) {
268 // Grow array by factor 2 up to MaxCachedPrototypeTransitions.
269 int capacity = array->length() - kProtoTransitionHeaderSize;
270 new_capacity = Min(kMaxCachedPrototypeTransitions, new_capacity);
271 DCHECK_GT(new_capacity, capacity);
272 int grow_by = new_capacity - capacity;
273 array = isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
274 if (capacity < 0) {
275 // There was no prototype transitions array before, so the size
276 // couldn't be copied. Initialize it explicitly.
277 SetNumberOfPrototypeTransitions(*array, 0);
278 }
279 return array;
280 }
281
282
283 // static
237 void TransitionArray::PutPrototypeTransition(Handle<Map> map, 284 void TransitionArray::PutPrototypeTransition(Handle<Map> map,
238 Handle<Object> prototype, 285 Handle<Object> prototype,
239 Handle<Map> target_map) { 286 Handle<Map> target_map) {
240 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); 287 DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
241 // Don't cache prototype transition if this map is either shared, or a map of 288 // Don't cache prototype transition if this map is either shared, or a map of
242 // a prototype. 289 // a prototype.
243 if (map->is_prototype_map()) return; 290 if (map->is_prototype_map()) return;
244 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return; 291 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return;
245 292
246 const int header = kProtoTransitionHeaderSize; 293 const int header = kProtoTransitionHeaderSize;
247 294
248 Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map); 295 Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map);
249 296
250 Handle<FixedArray> cache(GetPrototypeTransitions(*map)); 297 Handle<FixedArray> cache(GetPrototypeTransitions(*map));
251 int capacity = cache->length() - header; 298 int capacity = cache->length() - header;
252 int transitions = NumberOfPrototypeTransitions(*cache) + 1; 299 int transitions = NumberOfPrototypeTransitions(*cache) + 1;
253 300
254 if (transitions > capacity) { 301 if (transitions > capacity) {
255 // Grow array by factor 2 up to MaxCachedPrototypeTransitions. 302 // Grow the array if compacting it doesn't free space.
256 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); 303 if (!CompactPrototypeTransitionArray(*cache)) {
257 if (new_capacity == capacity) return; 304 if (capacity == kMaxCachedPrototypeTransitions) return;
258 int grow_by = new_capacity - capacity; 305 cache = GrowPrototypeTransitionArray(cache, 2 * transitions,
259 306 map->GetIsolate());
260 Isolate* isolate = map->GetIsolate(); 307 SetPrototypeTransitions(map, cache);
261 cache = isolate->factory()->CopyFixedArrayAndGrow(cache, grow_by);
262 if (capacity < 0) {
263 // There was no prototype transitions array before, so the size
264 // couldn't be copied. Initialize it explicitly.
265 SetNumberOfPrototypeTransitions(*cache, 0);
266 } 308 }
267
268 SetPrototypeTransitions(map, cache);
269 } 309 }
270 310
271 // Reload number of transitions as GC might shrink them. 311 // Reload number of transitions as they might have been compacted.
272 int last = NumberOfPrototypeTransitions(*cache); 312 int last = NumberOfPrototypeTransitions(*cache);
273 int entry = header + last; 313 int entry = header + last;
274 314
275 cache->set(entry, *target_cell); 315 cache->set(entry, *target_cell);
276 SetNumberOfPrototypeTransitions(*cache, last + 1); 316 SetNumberOfPrototypeTransitions(*cache, last + 1);
277 } 317 }
278 318
279 319
280 // static 320 // static
281 Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map, 321 Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map,
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 // Transition arrays are not shared. When one is replaced, it should not 420 // Transition arrays are not shared. When one is replaced, it should not
381 // keep referenced objects alive, so we zap it. 421 // keep referenced objects alive, so we zap it.
382 // When there is another reference to the array somewhere (e.g. a handle), 422 // When there is another reference to the array somewhere (e.g. a handle),
383 // not zapping turns from a waste of memory into a source of crashes. 423 // not zapping turns from a waste of memory into a source of crashes.
384 ZapTransitionArray(old_transitions); 424 ZapTransitionArray(old_transitions);
385 } 425 }
386 map->set_raw_transitions(new_transitions); 426 map->set_raw_transitions(new_transitions);
387 } 427 }
388 428
389 429
390 static void ZapPrototypeTransitions(Object* raw_transitions) {
391 DCHECK(TransitionArray::IsFullTransitionArray(raw_transitions));
392 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
393 if (!transitions->HasPrototypeTransitions()) return;
394 FixedArray* proto_transitions = transitions->GetPrototypeTransitions();
395 MemsetPointer(proto_transitions->data_start(),
396 proto_transitions->GetHeap()->the_hole_value(),
397 proto_transitions->length());
398 }
399
400
401 void TransitionArray::SetPrototypeTransitions( 430 void TransitionArray::SetPrototypeTransitions(
402 Handle<Map> map, Handle<FixedArray> proto_transitions) { 431 Handle<Map> map, Handle<FixedArray> proto_transitions) {
403 EnsureHasFullTransitionArray(map); 432 EnsureHasFullTransitionArray(map);
404 if (Heap::ShouldZapGarbage()) {
ulan 2015/11/24 15:47:04 We do not need to zap prototype transition array b
405 Object* raw_transitions = map->raw_transitions();
406 DCHECK(raw_transitions != *proto_transitions);
407 ZapPrototypeTransitions(raw_transitions);
408 }
409 TransitionArray* transitions = TransitionArray::cast(map->raw_transitions()); 433 TransitionArray* transitions = TransitionArray::cast(map->raw_transitions());
410 transitions->SetPrototypeTransitions(*proto_transitions); 434 transitions->SetPrototypeTransitions(*proto_transitions);
411 } 435 }
412 436
413 437
414 void TransitionArray::EnsureHasFullTransitionArray(Handle<Map> map) { 438 void TransitionArray::EnsureHasFullTransitionArray(Handle<Map> map) {
415 Object* raw_transitions = map->raw_transitions(); 439 Object* raw_transitions = map->raw_transitions();
416 if (IsFullTransitionArray(raw_transitions)) return; 440 if (IsFullTransitionArray(raw_transitions)) return;
417 int nof = IsSimpleTransition(raw_transitions) ? 1 : 0; 441 int nof = IsSimpleTransition(raw_transitions) ? 1 : 0;
418 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); 442 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 PropertyAttributes attributes, 540 PropertyAttributes attributes,
517 int* out_insertion_index) { 541 int* out_insertion_index) {
518 int transition = SearchName(name, out_insertion_index); 542 int transition = SearchName(name, out_insertion_index);
519 if (transition == kNotFound) { 543 if (transition == kNotFound) {
520 return kNotFound; 544 return kNotFound;
521 } 545 }
522 return SearchDetails(transition, kind, attributes, out_insertion_index); 546 return SearchDetails(transition, kind, attributes, out_insertion_index);
523 } 547 }
524 } // namespace internal 548 } // namespace internal
525 } // namespace v8 549 } // namespace v8
OLDNEW
« src/heap/mark-compact.cc ('K') | « src/transitions.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698