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

Side by Side Diff: src/mark-compact.cc

Issue 3135026: Merge flush code phase into marking phase. (Closed)
Patch Set: returned checked casts Created 10 years, 4 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
« no previous file with comments | « src/mark-compact.h ('k') | src/objects.h » ('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-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
28 #include "v8.h" 28 #include "v8.h"
29 29
30 #include "compilation-cache.h"
30 #include "execution.h" 31 #include "execution.h"
31 #include "heap-profiler.h" 32 #include "heap-profiler.h"
32 #include "global-handles.h" 33 #include "global-handles.h"
33 #include "ic-inl.h" 34 #include "ic-inl.h"
34 #include "mark-compact.h" 35 #include "mark-compact.h"
35 #include "objects-visiting.h" 36 #include "objects-visiting.h"
36 #include "stub-cache.h" 37 #include "stub-cache.h"
37 38
38 namespace v8 { 39 namespace v8 {
39 namespace internal { 40 namespace internal {
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 return HeapObject::cast(first); 246 return HeapObject::cast(first);
246 } 247 }
247 248
248 249
249 class StaticMarkingVisitor : public StaticVisitorBase { 250 class StaticMarkingVisitor : public StaticVisitorBase {
250 public: 251 public:
251 static inline void IterateBody(Map* map, HeapObject* obj) { 252 static inline void IterateBody(Map* map, HeapObject* obj) {
252 table_.GetVisitor(map)(map, obj); 253 table_.GetVisitor(map)(map, obj);
253 } 254 }
254 255
256 static void EnableCodeFlushing(bool enabled) {
257 if (enabled) {
258 table_.Register(kVisitJSFunction, &VisitJSFunction);
259 } else {
260 table_.Register(kVisitJSFunction,
261 &JSObjectVisitor::VisitSpecialized<JSFunction::kSize>);
262 }
263 }
264
255 static void Initialize() { 265 static void Initialize() {
256 table_.Register(kVisitShortcutCandidate, 266 table_.Register(kVisitShortcutCandidate,
257 &FixedBodyVisitor<StaticMarkingVisitor, 267 &FixedBodyVisitor<StaticMarkingVisitor,
258 ConsString::BodyDescriptor, 268 ConsString::BodyDescriptor,
259 void>::Visit); 269 void>::Visit);
260 270
261 table_.Register(kVisitConsString, 271 table_.Register(kVisitConsString,
262 &FixedBodyVisitor<StaticMarkingVisitor, 272 &FixedBodyVisitor<StaticMarkingVisitor,
263 ConsString::BodyDescriptor, 273 ConsString::BodyDescriptor,
264 void>::Visit); 274 void>::Visit);
(...skipping 17 matching lines...) Expand all
282 &FixedBodyVisitor<StaticMarkingVisitor, 292 &FixedBodyVisitor<StaticMarkingVisitor,
283 Oddball::BodyDescriptor, 293 Oddball::BodyDescriptor,
284 void>::Visit); 294 void>::Visit);
285 table_.Register(kVisitMap, 295 table_.Register(kVisitMap,
286 &FixedBodyVisitor<StaticMarkingVisitor, 296 &FixedBodyVisitor<StaticMarkingVisitor,
287 Map::BodyDescriptor, 297 Map::BodyDescriptor,
288 void>::Visit); 298 void>::Visit);
289 299
290 table_.Register(kVisitCode, &VisitCode); 300 table_.Register(kVisitCode, &VisitCode);
291 301
302 table_.Register(kVisitJSFunction, &VisitJSFunction);
303
292 table_.Register(kVisitPropertyCell, 304 table_.Register(kVisitPropertyCell,
293 &FixedBodyVisitor<StaticMarkingVisitor, 305 &FixedBodyVisitor<StaticMarkingVisitor,
294 JSGlobalPropertyCell::BodyDescriptor, 306 JSGlobalPropertyCell::BodyDescriptor,
295 void>::Visit); 307 void>::Visit);
296 308
297 table_.RegisterSpecializations<DataObjectVisitor, 309 table_.RegisterSpecializations<DataObjectVisitor,
298 kVisitDataObject, 310 kVisitDataObject,
299 kVisitDataObjectGeneric>(); 311 kVisitDataObjectGeneric>();
300 312
301 table_.RegisterSpecializations<JSObjectVisitor, 313 table_.RegisterSpecializations<JSObjectVisitor,
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 void> JSObjectVisitor; 410 void> JSObjectVisitor;
399 411
400 typedef FlexibleBodyVisitor<StaticMarkingVisitor, 412 typedef FlexibleBodyVisitor<StaticMarkingVisitor,
401 StructBodyDescriptor, 413 StructBodyDescriptor,
402 void> StructObjectVisitor; 414 void> StructObjectVisitor;
403 415
404 static void VisitCode(Map* map, HeapObject* object) { 416 static void VisitCode(Map* map, HeapObject* object) {
405 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>(); 417 reinterpret_cast<Code*>(object)->CodeIterateBody<StaticMarkingVisitor>();
406 } 418 }
407 419
420 // Code flushing support.
421
422 // How many collections newly compiled code object will survive before being
423 // flushed.
424 static const int kCodeAgeThreshold = 5;
425
426 inline static bool HasSourceCode(SharedFunctionInfo* info) {
427 Object* undefined = Heap::raw_unchecked_undefined_value();
428 return (info->script() != undefined) &&
429 (reinterpret_cast<Script*>(info->script())->source() != undefined);
430 }
431
432
433 inline static bool IsCompiled(JSFunction* function) {
434 return
435 function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile);
436 }
437
438
439 inline static bool IsCompiled(SharedFunctionInfo* function) {
440 return
441 function->unchecked_code() != Builtins::builtin(Builtins::LazyCompile);
442 }
443
444
445 static void FlushCodeForFunction(JSFunction* function) {
446 SharedFunctionInfo* shared_info = function->unchecked_shared();
447
448 if (shared_info->IsMarked()) return;
449
450 // Special handling if the function and shared info objects
451 // have different code objects.
452 if (function->unchecked_code() != shared_info->unchecked_code()) {
453 // If the shared function has been flushed but the function has not,
454 // we flush the function if possible.
455 if (!IsCompiled(shared_info) &&
456 IsCompiled(function) &&
457 !function->unchecked_code()->IsMarked()) {
458 function->set_code(shared_info->unchecked_code());
459 }
460 return;
461 }
462
463 // Code is either on stack or in compilation cache.
464 if (shared_info->unchecked_code()->IsMarked()) {
465 shared_info->set_code_age(0);
466 return;
467 }
468
469 // The function must be compiled and have the source code available,
470 // to be able to recompile it in case we need the function again.
471 if (!(shared_info->is_compiled() && HasSourceCode(shared_info))) return;
472
473 // We never flush code for Api functions.
474 Object* function_data = shared_info->function_data();
475 if (function_data->IsHeapObject() &&
476 (SafeMap(function_data)->instance_type() ==
477 FUNCTION_TEMPLATE_INFO_TYPE)) {
478 return;
479 }
480
481 // Only flush code for functions.
482 if (shared_info->code()->kind() != Code::FUNCTION) return;
483
484 // Function must be lazy compilable.
485 if (!shared_info->allows_lazy_compilation()) return;
486
487 // If this is a full script wrapped in a function we do no flush the code.
488 if (shared_info->is_toplevel()) return;
489
490 // Age this shared function info.
491 if (shared_info->code_age() < kCodeAgeThreshold) {
492 shared_info->set_code_age(shared_info->code_age() + 1);
493 return;
494 }
495
496 // Compute the lazy compilable version of the code.
497 Code* code = Builtins::builtin(Builtins::LazyCompile);
498 shared_info->set_code(code);
499 function->set_code(code);
500 }
501
502
503 static inline Map* SafeMap(Object* obj) {
504 MapWord map_word = HeapObject::cast(obj)->map_word();
505 map_word.ClearMark();
506 map_word.ClearOverflow();
507 return map_word.ToMap();
508 }
509
510
511 static inline bool IsJSBuiltinsObject(Object* obj) {
512 return obj->IsHeapObject() &&
513 (SafeMap(obj)->instance_type() == JS_BUILTINS_OBJECT_TYPE);
514 }
515
516
517 static inline bool IsValidNotBuiltinContext(Object* ctx) {
518 if (!ctx->IsHeapObject()) return false;
519
520 Map* map = SafeMap(ctx);
521 if(!(map == Heap::raw_unchecked_context_map() ||
522 map == Heap::raw_unchecked_catch_context_map() ||
523 map == Heap::raw_unchecked_global_context_map())) {
524 return false;
525 }
526
527 Context* context = reinterpret_cast<Context*>(ctx);
528
529 if(IsJSBuiltinsObject(context->global())) {
530 return false;
531 }
532
533 return true;
534 }
535
536
537 static void VisitJSFunction(Map* map, HeapObject* object) {
538 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
539
540 // The function must have a valid context and not be a builtin.
541 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
542 FlushCodeForFunction(jsfunction);
543 }
544
545 JSObjectVisitor::VisitSpecialized<JSFunction::kSize>(map, object);
546 }
547
408 typedef void (*Callback)(Map* map, HeapObject* object); 548 typedef void (*Callback)(Map* map, HeapObject* object);
409 549
410 static VisitorDispatchTable<Callback> table_; 550 static VisitorDispatchTable<Callback> table_;
411 }; 551 };
412 552
413 553
414 VisitorDispatchTable<StaticMarkingVisitor::Callback> 554 VisitorDispatchTable<StaticMarkingVisitor::Callback>
415 StaticMarkingVisitor::table_; 555 StaticMarkingVisitor::table_;
416 556
417 557
(...skipping 10 matching lines...) Expand all
428 void VisitCodeTarget(RelocInfo* rinfo) { 568 void VisitCodeTarget(RelocInfo* rinfo) {
429 StaticMarkingVisitor::VisitCodeTarget(rinfo); 569 StaticMarkingVisitor::VisitCodeTarget(rinfo);
430 } 570 }
431 571
432 void VisitDebugTarget(RelocInfo* rinfo) { 572 void VisitDebugTarget(RelocInfo* rinfo) {
433 StaticMarkingVisitor::VisitDebugTarget(rinfo); 573 StaticMarkingVisitor::VisitDebugTarget(rinfo);
434 } 574 }
435 }; 575 };
436 576
437 577
578 class CodeMarkingVisitor : public ThreadVisitor {
579 public:
580 void VisitThread(ThreadLocalTop* top) {
581 for (StackFrameIterator it(top); !it.done(); it.Advance()) {
582 MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
583 }
584 }
585 };
586
587
588 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor {
589 public:
590 void VisitPointers(Object** start, Object** end) {
591 for (Object** p = start; p < end; p++) VisitPointer(p);
592 }
593
594 void VisitPointer(Object** slot) {
595 Object* obj = *slot;
596 if (obj->IsHeapObject()) {
597 MarkCompactCollector::MarkObject(HeapObject::cast(obj));
598 }
599 }
600 };
601
602
603 void MarkCompactCollector::PrepareForCodeFlushing() {
604 if (!FLAG_flush_code) {
605 StaticMarkingVisitor::EnableCodeFlushing(false);
606 return;
607 }
608
609 #ifdef ENABLE_DEBUGGER_SUPPORT
610 if (Debug::IsLoaded() || Debug::has_break_points()) {
611 StaticMarkingVisitor::EnableCodeFlushing(false);
612 return;
613 }
614 #endif
615 StaticMarkingVisitor::EnableCodeFlushing(true);
616
617 // Make sure we are not referencing the code from the stack.
618 for (StackFrameIterator it; !it.done(); it.Advance()) {
619 MarkCompactCollector::MarkObject(it.frame()->unchecked_code());
620 }
621
622 // Iterate the archived stacks in all threads to check if
623 // the code is referenced.
624 CodeMarkingVisitor code_marking_visitor;
625 ThreadManager::IterateArchivedThreads(&code_marking_visitor);
626
627 SharedFunctionInfoMarkingVisitor visitor;
628 CompilationCache::IterateFunctions(&visitor);
629
630 MarkCompactCollector::ProcessMarkingStack();
631 }
632
633
438 // Visitor class for marking heap roots. 634 // Visitor class for marking heap roots.
439 class RootMarkingVisitor : public ObjectVisitor { 635 class RootMarkingVisitor : public ObjectVisitor {
440 public: 636 public:
441 void VisitPointer(Object** p) { 637 void VisitPointer(Object** p) {
442 MarkObjectByPointer(p); 638 MarkObjectByPointer(p);
443 } 639 }
444 640
445 void VisitPointers(Object** start, Object** end) { 641 void VisitPointers(Object** start, Object** end) {
446 for (Object** p = start; p < end; p++) MarkObjectByPointer(p); 642 for (Object** p = start; p < end; p++) MarkObjectByPointer(p);
447 } 643 }
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after
786 ASSERT(state_ == PREPARE_GC); 982 ASSERT(state_ == PREPARE_GC);
787 state_ = MARK_LIVE_OBJECTS; 983 state_ = MARK_LIVE_OBJECTS;
788 #endif 984 #endif
789 // The to space contains live objects, the from space is used as a marking 985 // The to space contains live objects, the from space is used as a marking
790 // stack. 986 // stack.
791 marking_stack.Initialize(Heap::new_space()->FromSpaceLow(), 987 marking_stack.Initialize(Heap::new_space()->FromSpaceLow(),
792 Heap::new_space()->FromSpaceHigh()); 988 Heap::new_space()->FromSpaceHigh());
793 989
794 ASSERT(!marking_stack.overflowed()); 990 ASSERT(!marking_stack.overflowed());
795 991
992 PrepareForCodeFlushing();
993
796 RootMarkingVisitor root_visitor; 994 RootMarkingVisitor root_visitor;
797 MarkRoots(&root_visitor); 995 MarkRoots(&root_visitor);
798 996
799 // The objects reachable from the roots are marked, yet unreachable 997 // The objects reachable from the roots are marked, yet unreachable
800 // objects are unmarked. Mark objects reachable from object groups 998 // objects are unmarked. Mark objects reachable from object groups
801 // containing at least one marked object, and continue until no new 999 // containing at least one marked object, and continue until no new
802 // objects are reachable from the object groups. 1000 // objects are reachable from the object groups.
803 ProcessObjectGroups(); 1001 ProcessObjectGroups();
804 1002
805 // The objects reachable from the roots or object groups are marked, 1003 // The objects reachable from the roots or object groups are marked,
(...skipping 1635 matching lines...) Expand 10 before | Expand all | Expand 10 after
2441 } 2639 }
2442 2640
2443 2641
2444 void MarkCompactCollector::Initialize() { 2642 void MarkCompactCollector::Initialize() {
2445 StaticPointersToNewGenUpdatingVisitor::Initialize(); 2643 StaticPointersToNewGenUpdatingVisitor::Initialize();
2446 StaticMarkingVisitor::Initialize(); 2644 StaticMarkingVisitor::Initialize();
2447 } 2645 }
2448 2646
2449 2647
2450 } } // namespace v8::internal 2648 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/mark-compact.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698