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

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: Address comments 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
« no previous file with comments | « src/transitions.h ('k') | test/cctest/test-heap.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 // 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 = 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
284 int TransitionArray::NumberOfPrototypeTransitionsForTest(Map* map) {
285 FixedArray* transitions = GetPrototypeTransitions(map);
286 CompactPrototypeTransitionArray(transitions);
287 return TransitionArray::NumberOfPrototypeTransitions(transitions);
288 }
289
290
291 // static
237 void TransitionArray::PutPrototypeTransition(Handle<Map> map, 292 void TransitionArray::PutPrototypeTransition(Handle<Map> map,
238 Handle<Object> prototype, 293 Handle<Object> prototype,
239 Handle<Map> target_map) { 294 Handle<Map> target_map) {
240 DCHECK(HeapObject::cast(*prototype)->map()->IsMap()); 295 DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
241 // Don't cache prototype transition if this map is either shared, or a map of 296 // Don't cache prototype transition if this map is either shared, or a map of
242 // a prototype. 297 // a prototype.
243 if (map->is_prototype_map()) return; 298 if (map->is_prototype_map()) return;
244 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return; 299 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return;
245 300
246 const int header = kProtoTransitionHeaderSize; 301 const int header = kProtoTransitionHeaderSize;
247 302
248 Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map); 303 Handle<WeakCell> target_cell = Map::WeakCellForMap(target_map);
249 304
250 Handle<FixedArray> cache(GetPrototypeTransitions(*map)); 305 Handle<FixedArray> cache(GetPrototypeTransitions(*map));
251 int capacity = cache->length() - header; 306 int capacity = cache->length() - header;
252 int transitions = NumberOfPrototypeTransitions(*cache) + 1; 307 int transitions = NumberOfPrototypeTransitions(*cache) + 1;
253 308
254 if (transitions > capacity) { 309 if (transitions > capacity) {
255 // Grow array by factor 2 up to MaxCachedPrototypeTransitions. 310 // Grow the array if compacting it doesn't free space.
256 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2); 311 if (!CompactPrototypeTransitionArray(*cache)) {
257 if (new_capacity == capacity) return; 312 if (capacity == kMaxCachedPrototypeTransitions) return;
258 int grow_by = new_capacity - capacity; 313 cache = GrowPrototypeTransitionArray(cache, 2 * transitions,
259 314 map->GetIsolate());
260 Isolate* isolate = map->GetIsolate(); 315 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 } 316 }
267
268 SetPrototypeTransitions(map, cache);
269 } 317 }
270 318
271 // Reload number of transitions as GC might shrink them. 319 // Reload number of transitions as they might have been compacted.
272 int last = NumberOfPrototypeTransitions(*cache); 320 int last = NumberOfPrototypeTransitions(*cache);
273 int entry = header + last; 321 int entry = header + last;
274 322
275 cache->set(entry, *target_cell); 323 cache->set(entry, *target_cell);
276 SetNumberOfPrototypeTransitions(*cache, last + 1); 324 SetNumberOfPrototypeTransitions(*cache, last + 1);
277 } 325 }
278 326
279 327
280 // static 328 // static
281 Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map, 329 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 428 // Transition arrays are not shared. When one is replaced, it should not
381 // keep referenced objects alive, so we zap it. 429 // keep referenced objects alive, so we zap it.
382 // When there is another reference to the array somewhere (e.g. a handle), 430 // 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. 431 // not zapping turns from a waste of memory into a source of crashes.
384 ZapTransitionArray(old_transitions); 432 ZapTransitionArray(old_transitions);
385 } 433 }
386 map->set_raw_transitions(new_transitions); 434 map->set_raw_transitions(new_transitions);
387 } 435 }
388 436
389 437
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( 438 void TransitionArray::SetPrototypeTransitions(
402 Handle<Map> map, Handle<FixedArray> proto_transitions) { 439 Handle<Map> map, Handle<FixedArray> proto_transitions) {
403 EnsureHasFullTransitionArray(map); 440 EnsureHasFullTransitionArray(map);
404 if (Heap::ShouldZapGarbage()) {
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()); 441 TransitionArray* transitions = TransitionArray::cast(map->raw_transitions());
410 transitions->SetPrototypeTransitions(*proto_transitions); 442 transitions->SetPrototypeTransitions(*proto_transitions);
411 } 443 }
412 444
413 445
414 void TransitionArray::EnsureHasFullTransitionArray(Handle<Map> map) { 446 void TransitionArray::EnsureHasFullTransitionArray(Handle<Map> map) {
415 Object* raw_transitions = map->raw_transitions(); 447 Object* raw_transitions = map->raw_transitions();
416 if (IsFullTransitionArray(raw_transitions)) return; 448 if (IsFullTransitionArray(raw_transitions)) return;
417 int nof = IsSimpleTransition(raw_transitions) ? 1 : 0; 449 int nof = IsSimpleTransition(raw_transitions) ? 1 : 0;
418 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); 450 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof);
(...skipping 18 matching lines...) Expand all
437 TraverseCallback callback, 469 TraverseCallback callback,
438 void* data) { 470 void* data) {
439 Object* raw_transitions = map->raw_transitions(); 471 Object* raw_transitions = map->raw_transitions();
440 if (IsFullTransitionArray(raw_transitions)) { 472 if (IsFullTransitionArray(raw_transitions)) {
441 TransitionArray* transitions = TransitionArray::cast(raw_transitions); 473 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
442 if (transitions->HasPrototypeTransitions()) { 474 if (transitions->HasPrototypeTransitions()) {
443 FixedArray* proto_trans = transitions->GetPrototypeTransitions(); 475 FixedArray* proto_trans = transitions->GetPrototypeTransitions();
444 for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) { 476 for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) {
445 int index = TransitionArray::kProtoTransitionHeaderSize + i; 477 int index = TransitionArray::kProtoTransitionHeaderSize + i;
446 WeakCell* cell = WeakCell::cast(proto_trans->get(index)); 478 WeakCell* cell = WeakCell::cast(proto_trans->get(index));
447 TraverseTransitionTreeInternal(Map::cast(cell->value()), callback, 479 if (!cell->cleared()) {
448 data); 480 TraverseTransitionTreeInternal(Map::cast(cell->value()), callback,
481 data);
482 }
449 } 483 }
450 } 484 }
451 for (int i = 0; i < transitions->number_of_transitions(); ++i) { 485 for (int i = 0; i < transitions->number_of_transitions(); ++i) {
452 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); 486 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data);
453 } 487 }
454 } else if (IsSimpleTransition(raw_transitions)) { 488 } else if (IsSimpleTransition(raw_transitions)) {
455 TraverseTransitionTreeInternal(GetSimpleTransition(raw_transitions), 489 TraverseTransitionTreeInternal(GetSimpleTransition(raw_transitions),
456 callback, data); 490 callback, data);
457 } 491 }
458 callback(map, data); 492 callback(map, data);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
516 PropertyAttributes attributes, 550 PropertyAttributes attributes,
517 int* out_insertion_index) { 551 int* out_insertion_index) {
518 int transition = SearchName(name, out_insertion_index); 552 int transition = SearchName(name, out_insertion_index);
519 if (transition == kNotFound) { 553 if (transition == kNotFound) {
520 return kNotFound; 554 return kNotFound;
521 } 555 }
522 return SearchDetails(transition, kind, attributes, out_insertion_index); 556 return SearchDetails(transition, kind, attributes, out_insertion_index);
523 } 557 }
524 } // namespace internal 558 } // namespace internal
525 } // namespace v8 559 } // namespace v8
OLDNEW
« no previous file with comments | « src/transitions.h ('k') | test/cctest/test-heap.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698