OLD | NEW |
---|---|
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 2292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2303 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; | 2303 if (map->instance_type() < FIRST_JS_OBJECT_TYPE) continue; |
2304 | 2304 |
2305 if (map_mark.Get() && | 2305 if (map_mark.Get() && |
2306 map->attached_to_shared_function_info()) { | 2306 map->attached_to_shared_function_info()) { |
2307 // This map is used for inobject slack tracking and has been detached | 2307 // This map is used for inobject slack tracking and has been detached |
2308 // from SharedFunctionInfo during the mark phase. | 2308 // from SharedFunctionInfo during the mark phase. |
2309 // Since it survived the GC, reattach it now. | 2309 // Since it survived the GC, reattach it now. |
2310 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); | 2310 map->unchecked_constructor()->unchecked_shared()->AttachInitialMap(map); |
2311 } | 2311 } |
2312 | 2312 |
2313 // Clear dead prototype transitions. | 2313 ClearNonLivePrototypeTransitions(map); |
2314 int number_of_transitions = map->NumberOfProtoTransitions(); | 2314 ClearNonLiveMapTransitions(map, map_mark.Get()); |
2315 FixedArray* prototype_transitions = map->prototype_transitions(); | |
2316 | |
2317 int new_number_of_transitions = 0; | |
2318 const int header = Map::kProtoTransitionHeaderSize; | |
2319 const int proto_offset = | |
2320 header + Map::kProtoTransitionPrototypeOffset; | |
2321 const int map_offset = header + Map::kProtoTransitionMapOffset; | |
2322 const int step = Map::kProtoTransitionElementsPerEntry; | |
2323 for (int i = 0; i < number_of_transitions; i++) { | |
2324 Object* prototype = prototype_transitions->get(proto_offset + i * step); | |
2325 Object* cached_map = prototype_transitions->get(map_offset + i * step); | |
2326 if (IsMarked(prototype) && IsMarked(cached_map)) { | |
2327 int proto_index = proto_offset + new_number_of_transitions * step; | |
2328 int map_index = map_offset + new_number_of_transitions * step; | |
2329 if (new_number_of_transitions != i) { | |
2330 prototype_transitions->set_unchecked( | |
2331 heap_, | |
2332 proto_index, | |
2333 prototype, | |
2334 UPDATE_WRITE_BARRIER); | |
2335 prototype_transitions->set_unchecked( | |
2336 heap_, | |
2337 map_index, | |
2338 cached_map, | |
2339 SKIP_WRITE_BARRIER); | |
2340 } | |
2341 Object** slot = | |
2342 HeapObject::RawField(prototype_transitions, | |
2343 FixedArray::OffsetOfElementAt(proto_index)); | |
2344 RecordSlot(slot, slot, prototype); | |
2345 new_number_of_transitions++; | |
2346 } | |
2347 } | |
2348 | |
2349 if (new_number_of_transitions != number_of_transitions) { | |
2350 map->SetNumberOfProtoTransitions(new_number_of_transitions); | |
2351 } | |
2352 | |
2353 // Fill slots that became free with undefined value. | |
2354 for (int i = new_number_of_transitions * step; | |
2355 i < number_of_transitions * step; | |
2356 i++) { | |
2357 prototype_transitions->set_undefined(heap_, header + i); | |
2358 } | |
2359 | |
2360 // Follow the chain of back pointers to find the prototype. | |
2361 Map* current = map; | |
2362 while (current->IsMap()) { | |
2363 current = reinterpret_cast<Map*>(current->prototype()); | |
2364 ASSERT(current->IsHeapObject()); | |
2365 } | |
2366 Object* real_prototype = current; | |
2367 | |
2368 // Follow back pointers, setting them to prototype, | |
2369 // clearing map transitions when necessary. | |
2370 current = map; | |
2371 bool on_dead_path = !map_mark.Get(); | |
2372 Object* next; | |
2373 while (current->IsMap()) { | |
2374 next = current->prototype(); | |
2375 // There should never be a dead map above a live map. | |
2376 MarkBit current_mark = Marking::MarkBitFrom(current); | |
2377 bool is_alive = current_mark.Get(); | |
2378 ASSERT(on_dead_path || is_alive); | |
2379 | |
2380 // A live map above a dead map indicates a dead transition. | |
2381 // This test will always be false on the first iteration. | |
2382 if (on_dead_path && is_alive) { | |
2383 on_dead_path = false; | |
2384 current->ClearNonLiveTransitions(heap(), real_prototype); | |
2385 } | |
2386 *HeapObject::RawField(current, Map::kPrototypeOffset) = | |
2387 real_prototype; | |
2388 | |
2389 if (is_alive) { | |
2390 Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset); | |
2391 RecordSlot(slot, slot, real_prototype); | |
2392 } | |
2393 current = reinterpret_cast<Map*>(next); | |
2394 } | |
2395 } | 2315 } |
2396 } | 2316 } |
2397 | 2317 |
2318 | |
2319 void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) { | |
2320 int number_of_transitions = map->NumberOfProtoTransitions(); | |
2321 FixedArray* prototype_transitions = map->prototype_transitions(); | |
2322 | |
2323 int new_number_of_transitions = 0; | |
2324 const int header = Map::kProtoTransitionHeaderSize; | |
2325 const int proto_offset = header + Map::kProtoTransitionPrototypeOffset; | |
2326 const int map_offset = header + Map::kProtoTransitionMapOffset; | |
2327 const int step = Map::kProtoTransitionElementsPerEntry; | |
2328 for (int i = 0; i < number_of_transitions; i++) { | |
2329 Object* prototype = prototype_transitions->get(proto_offset + i * step); | |
2330 Object* cached_map = prototype_transitions->get(map_offset + i * step); | |
2331 if (IsMarked(prototype) && IsMarked(cached_map)) { | |
2332 int proto_index = proto_offset + new_number_of_transitions * step; | |
2333 int map_index = map_offset + new_number_of_transitions * step; | |
2334 if (new_number_of_transitions != i) { | |
2335 prototype_transitions->set_unchecked( | |
2336 heap_, | |
2337 proto_index, | |
2338 prototype, | |
2339 UPDATE_WRITE_BARRIER); | |
2340 prototype_transitions->set_unchecked( | |
2341 heap_, | |
2342 map_index, | |
2343 cached_map, | |
2344 SKIP_WRITE_BARRIER); | |
2345 } | |
2346 Object** slot = | |
2347 HeapObject::RawField(prototype_transitions, | |
2348 FixedArray::OffsetOfElementAt(proto_index)); | |
2349 RecordSlot(slot, slot, prototype); | |
2350 new_number_of_transitions++; | |
2351 } | |
2352 } | |
2353 | |
2354 if (new_number_of_transitions != number_of_transitions) { | |
2355 map->SetNumberOfProtoTransitions(new_number_of_transitions); | |
2356 } | |
2357 | |
2358 // Fill slots that became free with undefined value. | |
2359 for (int i = new_number_of_transitions * step; | |
2360 i < number_of_transitions * step; | |
2361 i++) { | |
2362 prototype_transitions->set_undefined(heap_, header + i); | |
2363 } | |
2364 } | |
2365 | |
2366 | |
2367 void MarkCompactCollector::ClearNonLiveMapTransitions(Map* map, bool marked) { | |
Michael Starzinger
2012/01/25 13:15:47
I don't like boolean flags, they are very confusin
| |
2368 // Follow the chain of back pointers to find the prototype. | |
2369 Map* real_prototype = map; | |
2370 while (real_prototype->IsMap()) { | |
2371 real_prototype = reinterpret_cast<Map*>(real_prototype->prototype()); | |
2372 ASSERT(real_prototype->IsHeapObject()); | |
2373 } | |
2374 | |
2375 // Follow back pointers, setting them to prototype, clearing map transitions | |
2376 // when necessary. | |
2377 Map* current = map; | |
2378 bool on_dead_path = !marked; | |
2379 while (current->IsMap()) { | |
2380 Object* next = current->prototype(); | |
2381 // There should never be a dead map above a live map. | |
2382 MarkBit current_mark = Marking::MarkBitFrom(current); | |
Michael Starzinger
2012/01/25 13:15:47
Like the above comment said: Initialize outside of
| |
2383 bool is_alive = current_mark.Get(); | |
2384 ASSERT(on_dead_path || is_alive); | |
2385 | |
2386 // A live map above a dead map indicates a dead transition. | |
2387 // This test will always be false on the first iteration. | |
2388 if (on_dead_path && is_alive) { | |
2389 on_dead_path = false; | |
2390 current->ClearNonLiveTransitions(heap(), real_prototype); | |
2391 } | |
2392 *HeapObject::RawField(current, Map::kPrototypeOffset) = real_prototype; | |
2393 | |
2394 if (is_alive) { | |
2395 Object** slot = HeapObject::RawField(current, Map::kPrototypeOffset); | |
2396 RecordSlot(slot, slot, real_prototype); | |
2397 } | |
2398 current = reinterpret_cast<Map*>(next); | |
2399 } | |
2400 } | |
2401 | |
2398 | 2402 |
2399 void MarkCompactCollector::ProcessWeakMaps() { | 2403 void MarkCompactCollector::ProcessWeakMaps() { |
2400 Object* weak_map_obj = encountered_weak_maps(); | 2404 Object* weak_map_obj = encountered_weak_maps(); |
2401 while (weak_map_obj != Smi::FromInt(0)) { | 2405 while (weak_map_obj != Smi::FromInt(0)) { |
2402 ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj))); | 2406 ASSERT(MarkCompactCollector::IsMarked(HeapObject::cast(weak_map_obj))); |
2403 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); | 2407 JSWeakMap* weak_map = reinterpret_cast<JSWeakMap*>(weak_map_obj); |
2404 ObjectHashTable* table = ObjectHashTable::cast(weak_map->table()); | 2408 ObjectHashTable* table = ObjectHashTable::cast(weak_map->table()); |
2405 for (int i = 0; i < table->Capacity(); i++) { | 2409 for (int i = 0; i < table->Capacity(); i++) { |
2406 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { | 2410 if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) { |
2407 Object* value = table->get(table->EntryToValueIndex(i)); | 2411 Object* value = table->get(table->EntryToValueIndex(i)); |
(...skipping 1525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3933 while (buffer != NULL) { | 3937 while (buffer != NULL) { |
3934 SlotsBuffer* next_buffer = buffer->next(); | 3938 SlotsBuffer* next_buffer = buffer->next(); |
3935 DeallocateBuffer(buffer); | 3939 DeallocateBuffer(buffer); |
3936 buffer = next_buffer; | 3940 buffer = next_buffer; |
3937 } | 3941 } |
3938 *buffer_address = NULL; | 3942 *buffer_address = NULL; |
3939 } | 3943 } |
3940 | 3944 |
3941 | 3945 |
3942 } } // namespace v8::internal | 3946 } } // namespace v8::internal |
OLD | NEW |