OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 : isolate_(isolate), | 612 : isolate_(isolate), |
613 jsfunction_candidates_head_(NULL), | 613 jsfunction_candidates_head_(NULL), |
614 shared_function_info_candidates_head_(NULL) {} | 614 shared_function_info_candidates_head_(NULL) {} |
615 | 615 |
616 void AddCandidate(SharedFunctionInfo* shared_info) { | 616 void AddCandidate(SharedFunctionInfo* shared_info) { |
617 SetNextCandidate(shared_info, shared_function_info_candidates_head_); | 617 SetNextCandidate(shared_info, shared_function_info_candidates_head_); |
618 shared_function_info_candidates_head_ = shared_info; | 618 shared_function_info_candidates_head_ = shared_info; |
619 } | 619 } |
620 | 620 |
621 void AddCandidate(JSFunction* function) { | 621 void AddCandidate(JSFunction* function) { |
622 ASSERT(function->unchecked_code() == | 622 ASSERT(function->code() == function->shared()->code()); |
623 function->unchecked_shared()->unchecked_code()); | |
624 | 623 |
625 SetNextCandidate(function, jsfunction_candidates_head_); | 624 SetNextCandidate(function, jsfunction_candidates_head_); |
626 jsfunction_candidates_head_ = function; | 625 jsfunction_candidates_head_ = function; |
627 } | 626 } |
628 | 627 |
629 void ProcessCandidates() { | 628 void ProcessCandidates() { |
630 ProcessSharedFunctionInfoCandidates(); | 629 ProcessSharedFunctionInfoCandidates(); |
631 ProcessJSFunctionCandidates(); | 630 ProcessJSFunctionCandidates(); |
632 } | 631 } |
633 | 632 |
634 private: | 633 private: |
635 void ProcessJSFunctionCandidates() { | 634 void ProcessJSFunctionCandidates() { |
636 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile); | 635 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile); |
637 | 636 |
638 JSFunction* candidate = jsfunction_candidates_head_; | 637 JSFunction* candidate = jsfunction_candidates_head_; |
639 JSFunction* next_candidate; | 638 JSFunction* next_candidate; |
640 while (candidate != NULL) { | 639 while (candidate != NULL) { |
641 next_candidate = GetNextCandidate(candidate); | 640 next_candidate = GetNextCandidate(candidate); |
642 | 641 |
643 SharedFunctionInfo* shared = candidate->unchecked_shared(); | 642 SharedFunctionInfo* shared = candidate->shared(); |
644 | 643 |
645 Code* code = shared->unchecked_code(); | 644 Code* code = shared->code(); |
646 MarkBit code_mark = Marking::MarkBitFrom(code); | 645 MarkBit code_mark = Marking::MarkBitFrom(code); |
647 if (!code_mark.Get()) { | 646 if (!code_mark.Get()) { |
648 shared->set_code(lazy_compile); | 647 shared->set_code(lazy_compile); |
649 candidate->set_code(lazy_compile); | 648 candidate->set_code(lazy_compile); |
650 } else { | 649 } else { |
651 candidate->set_code(shared->unchecked_code()); | 650 candidate->set_code(shared->code()); |
652 } | 651 } |
653 | 652 |
654 // We are in the middle of a GC cycle so the write barrier in the code | 653 // We are in the middle of a GC cycle so the write barrier in the code |
655 // setter did not record the slot update and we have to do that manually. | 654 // setter did not record the slot update and we have to do that manually. |
656 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; | 655 Address slot = candidate->address() + JSFunction::kCodeEntryOffset; |
657 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); | 656 Code* target = Code::cast(Code::GetObjectFromEntryAddress(slot)); |
658 isolate_->heap()->mark_compact_collector()-> | 657 isolate_->heap()->mark_compact_collector()-> |
659 RecordCodeEntrySlot(slot, target); | 658 RecordCodeEntrySlot(slot, target); |
660 | 659 |
661 candidate = next_candidate; | 660 candidate = next_candidate; |
662 } | 661 } |
663 | 662 |
664 jsfunction_candidates_head_ = NULL; | 663 jsfunction_candidates_head_ = NULL; |
665 } | 664 } |
666 | 665 |
667 | 666 |
668 void ProcessSharedFunctionInfoCandidates() { | 667 void ProcessSharedFunctionInfoCandidates() { |
669 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile); | 668 Code* lazy_compile = isolate_->builtins()->builtin(Builtins::kLazyCompile); |
670 | 669 |
671 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; | 670 SharedFunctionInfo* candidate = shared_function_info_candidates_head_; |
672 SharedFunctionInfo* next_candidate; | 671 SharedFunctionInfo* next_candidate; |
673 while (candidate != NULL) { | 672 while (candidate != NULL) { |
674 next_candidate = GetNextCandidate(candidate); | 673 next_candidate = GetNextCandidate(candidate); |
675 SetNextCandidate(candidate, NULL); | 674 SetNextCandidate(candidate, NULL); |
676 | 675 |
677 Code* code = candidate->unchecked_code(); | 676 Code* code = candidate->code(); |
678 MarkBit code_mark = Marking::MarkBitFrom(code); | 677 MarkBit code_mark = Marking::MarkBitFrom(code); |
679 if (!code_mark.Get()) { | 678 if (!code_mark.Get()) { |
680 candidate->set_code(lazy_compile); | 679 candidate->set_code(lazy_compile); |
681 } | 680 } |
682 | 681 |
683 candidate = next_candidate; | 682 candidate = next_candidate; |
684 } | 683 } |
685 | 684 |
686 shared_function_info_candidates_head_ = NULL; | 685 shared_function_info_candidates_head_ = NULL; |
687 } | 686 } |
688 | 687 |
689 static JSFunction** GetNextCandidateField(JSFunction* candidate) { | 688 static JSFunction** GetNextCandidateField(JSFunction* candidate) { |
690 return reinterpret_cast<JSFunction**>( | 689 return reinterpret_cast<JSFunction**>( |
691 candidate->address() + JSFunction::kCodeEntryOffset); | 690 candidate->address() + JSFunction::kCodeEntryOffset); |
692 } | 691 } |
693 | 692 |
694 static JSFunction* GetNextCandidate(JSFunction* candidate) { | 693 static JSFunction* GetNextCandidate(JSFunction* candidate) { |
695 return *GetNextCandidateField(candidate); | 694 return *GetNextCandidateField(candidate); |
696 } | 695 } |
697 | 696 |
698 static void SetNextCandidate(JSFunction* candidate, | 697 static void SetNextCandidate(JSFunction* candidate, |
699 JSFunction* next_candidate) { | 698 JSFunction* next_candidate) { |
700 *GetNextCandidateField(candidate) = next_candidate; | 699 *GetNextCandidateField(candidate) = next_candidate; |
701 } | 700 } |
702 | 701 |
703 static SharedFunctionInfo** GetNextCandidateField( | 702 static SharedFunctionInfo** GetNextCandidateField( |
704 SharedFunctionInfo* candidate) { | 703 SharedFunctionInfo* candidate) { |
705 Code* code = candidate->unchecked_code(); | 704 Code* code = candidate->code(); |
706 return reinterpret_cast<SharedFunctionInfo**>( | 705 return reinterpret_cast<SharedFunctionInfo**>( |
707 code->address() + Code::kNextCodeFlushingCandidateOffset); | 706 code->address() + Code::kNextCodeFlushingCandidateOffset); |
708 } | 707 } |
709 | 708 |
710 static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) { | 709 static SharedFunctionInfo* GetNextCandidate(SharedFunctionInfo* candidate) { |
711 return *GetNextCandidateField(candidate); | 710 return *GetNextCandidateField(candidate); |
712 } | 711 } |
713 | 712 |
714 static void SetNextCandidate(SharedFunctionInfo* candidate, | 713 static void SetNextCandidate(SharedFunctionInfo* candidate, |
715 SharedFunctionInfo* next_candidate) { | 714 SharedFunctionInfo* next_candidate) { |
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1030 static const int kRegExpCodeThreshold = 5; | 1029 static const int kRegExpCodeThreshold = 5; |
1031 | 1030 |
1032 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { | 1031 inline static bool HasSourceCode(Heap* heap, SharedFunctionInfo* info) { |
1033 Object* undefined = heap->undefined_value(); | 1032 Object* undefined = heap->undefined_value(); |
1034 return (info->script() != undefined) && | 1033 return (info->script() != undefined) && |
1035 (reinterpret_cast<Script*>(info->script())->source() != undefined); | 1034 (reinterpret_cast<Script*>(info->script())->source() != undefined); |
1036 } | 1035 } |
1037 | 1036 |
1038 | 1037 |
1039 inline static bool IsCompiled(JSFunction* function) { | 1038 inline static bool IsCompiled(JSFunction* function) { |
1040 return function->unchecked_code() != | 1039 return function->code() != |
1041 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); | 1040 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); |
1042 } | 1041 } |
1043 | 1042 |
1044 inline static bool IsCompiled(SharedFunctionInfo* function) { | 1043 inline static bool IsCompiled(SharedFunctionInfo* function) { |
1045 return function->unchecked_code() != | 1044 return function->code() != |
1046 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); | 1045 function->GetIsolate()->builtins()->builtin(Builtins::kLazyCompile); |
1047 } | 1046 } |
1048 | 1047 |
1049 inline static bool IsFlushable(Heap* heap, JSFunction* function) { | 1048 inline static bool IsFlushable(Heap* heap, JSFunction* function) { |
1050 SharedFunctionInfo* shared_info = function->unchecked_shared(); | 1049 SharedFunctionInfo* shared_info = function->unchecked_shared(); |
1051 | 1050 |
1052 // Code is either on stack, in compilation cache or referenced | 1051 // Code is either on stack, in compilation cache or referenced |
1053 // by optimized version of function. | 1052 // by optimized version of function. |
1054 MarkBit code_mark = | 1053 MarkBit code_mark = Marking::MarkBitFrom(function->code()); |
1055 Marking::MarkBitFrom(function->unchecked_code()); | |
1056 if (code_mark.Get()) { | 1054 if (code_mark.Get()) { |
1057 if (!Marking::MarkBitFrom(shared_info).Get()) { | 1055 if (!Marking::MarkBitFrom(shared_info).Get()) { |
1058 shared_info->set_code_age(0); | 1056 shared_info->set_code_age(0); |
1059 } | 1057 } |
1060 return false; | 1058 return false; |
1061 } | 1059 } |
1062 | 1060 |
1063 // We do not flush code for optimized functions. | 1061 // We do not flush code for optimized functions. |
1064 if (function->code() != shared_info->unchecked_code()) { | 1062 if (function->code() != shared_info->code()) { |
1065 return false; | 1063 return false; |
1066 } | 1064 } |
1067 | 1065 |
1068 return IsFlushable(heap, shared_info); | 1066 return IsFlushable(heap, shared_info); |
1069 } | 1067 } |
1070 | 1068 |
1071 inline static bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info) { | 1069 inline static bool IsFlushable(Heap* heap, SharedFunctionInfo* shared_info) { |
1072 // Code is either on stack, in compilation cache or referenced | 1070 // Code is either on stack, in compilation cache or referenced |
1073 // by optimized version of function. | 1071 // by optimized version of function. |
1074 MarkBit code_mark = | 1072 MarkBit code_mark = |
1075 Marking::MarkBitFrom(shared_info->unchecked_code()); | 1073 Marking::MarkBitFrom(shared_info->code()); |
1076 if (code_mark.Get()) { | 1074 if (code_mark.Get()) { |
1077 return false; | 1075 return false; |
1078 } | 1076 } |
1079 | 1077 |
1080 // The function must be compiled and have the source code available, | 1078 // The function must be compiled and have the source code available, |
1081 // to be able to recompile it in case we need the function again. | 1079 // to be able to recompile it in case we need the function again. |
1082 if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) { | 1080 if (!(shared_info->is_compiled() && HasSourceCode(heap, shared_info))) { |
1083 return false; | 1081 return false; |
1084 } | 1082 } |
1085 | 1083 |
1086 // We never flush code for Api functions. | 1084 // We never flush code for Api functions. |
1087 Object* function_data = shared_info->function_data(); | 1085 Object* function_data = shared_info->function_data(); |
1088 if (function_data->IsFunctionTemplateInfo()) return false; | 1086 if (function_data->IsFunctionTemplateInfo()) { |
| 1087 return false; |
| 1088 } |
1089 | 1089 |
1090 // Only flush code for functions. | 1090 // Only flush code for functions. |
1091 if (shared_info->code()->kind() != Code::FUNCTION) return false; | 1091 if (shared_info->code()->kind() != Code::FUNCTION) { |
| 1092 return false; |
| 1093 } |
1092 | 1094 |
1093 // Function must be lazy compilable. | 1095 // Function must be lazy compilable. |
1094 if (!shared_info->allows_lazy_compilation()) return false; | 1096 if (!shared_info->allows_lazy_compilation()) { |
| 1097 return false; |
| 1098 } |
1095 | 1099 |
1096 // If this is a full script wrapped in a function we do no flush the code. | 1100 // If this is a full script wrapped in a function we do no flush the code. |
1097 if (shared_info->is_toplevel()) return false; | 1101 if (shared_info->is_toplevel()) { |
| 1102 return false; |
| 1103 } |
1098 | 1104 |
1099 // Age this shared function info. | 1105 // Age this shared function info. |
1100 if (shared_info->code_age() < kCodeAgeThreshold) { | 1106 if (shared_info->code_age() < kCodeAgeThreshold) { |
1101 shared_info->set_code_age(shared_info->code_age() + 1); | 1107 shared_info->set_code_age(shared_info->code_age() + 1); |
1102 return false; | 1108 return false; |
1103 } | 1109 } |
1104 | 1110 |
1105 return true; | 1111 return true; |
1106 } | 1112 } |
1107 | 1113 |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1260 } | 1266 } |
1261 | 1267 |
1262 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); | 1268 JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object); |
1263 // The function must have a valid context and not be a builtin. | 1269 // The function must have a valid context and not be a builtin. |
1264 bool flush_code_candidate = false; | 1270 bool flush_code_candidate = false; |
1265 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) { | 1271 if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) { |
1266 flush_code_candidate = FlushCodeForFunction(heap, jsfunction); | 1272 flush_code_candidate = FlushCodeForFunction(heap, jsfunction); |
1267 } | 1273 } |
1268 | 1274 |
1269 if (!flush_code_candidate) { | 1275 if (!flush_code_candidate) { |
1270 Code* code = jsfunction->unchecked_shared()->unchecked_code(); | 1276 Code* code = jsfunction->shared()->code(); |
1271 MarkBit code_mark = Marking::MarkBitFrom(code); | 1277 MarkBit code_mark = Marking::MarkBitFrom(code); |
1272 heap->mark_compact_collector()->MarkObject(code, code_mark); | 1278 collector->MarkObject(code, code_mark); |
1273 | 1279 |
1274 if (jsfunction->unchecked_code()->kind() == Code::OPTIMIZED_FUNCTION) { | 1280 if (jsfunction->code()->kind() == Code::OPTIMIZED_FUNCTION) { |
1275 // For optimized functions we should retain both non-optimized version | 1281 collector->MarkInlinedFunctionsCode(jsfunction->code()); |
1276 // of it's code and non-optimized version of all inlined functions. | |
1277 // This is required to support bailing out from inlined code. | |
1278 DeoptimizationInputData* data = | |
1279 reinterpret_cast<DeoptimizationInputData*>( | |
1280 jsfunction->unchecked_code()->unchecked_deoptimization_data()); | |
1281 | |
1282 FixedArray* literals = data->UncheckedLiteralArray(); | |
1283 | |
1284 for (int i = 0, count = data->InlinedFunctionCount()->value(); | |
1285 i < count; | |
1286 i++) { | |
1287 JSFunction* inlined = reinterpret_cast<JSFunction*>(literals->get(i)); | |
1288 Code* inlined_code = inlined->unchecked_shared()->unchecked_code(); | |
1289 MarkBit inlined_code_mark = | |
1290 Marking::MarkBitFrom(inlined_code); | |
1291 heap->mark_compact_collector()->MarkObject( | |
1292 inlined_code, inlined_code_mark); | |
1293 } | |
1294 } | 1282 } |
1295 } | 1283 } |
1296 | 1284 |
1297 VisitJSFunctionFields(map, | 1285 VisitJSFunctionFields(map, |
1298 reinterpret_cast<JSFunction*>(object), | 1286 reinterpret_cast<JSFunction*>(object), |
1299 flush_code_candidate); | 1287 flush_code_candidate); |
1300 } | 1288 } |
1301 | 1289 |
1302 | 1290 |
1303 static void VisitJSFunction(Map* map, HeapObject* object) { | 1291 static void VisitJSFunction(Map* map, HeapObject* object) { |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1408 Heap* heap_; | 1396 Heap* heap_; |
1409 }; | 1397 }; |
1410 | 1398 |
1411 | 1399 |
1412 class CodeMarkingVisitor : public ThreadVisitor { | 1400 class CodeMarkingVisitor : public ThreadVisitor { |
1413 public: | 1401 public: |
1414 explicit CodeMarkingVisitor(MarkCompactCollector* collector) | 1402 explicit CodeMarkingVisitor(MarkCompactCollector* collector) |
1415 : collector_(collector) {} | 1403 : collector_(collector) {} |
1416 | 1404 |
1417 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1405 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
1418 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 1406 collector_->PrepareThreadForCodeFlushing(isolate, top); |
1419 Code* code = it.frame()->unchecked_code(); | |
1420 MarkBit code_bit = Marking::MarkBitFrom(code); | |
1421 collector_->MarkObject(it.frame()->unchecked_code(), code_bit); | |
1422 } | |
1423 } | 1407 } |
1424 | 1408 |
1425 private: | 1409 private: |
1426 MarkCompactCollector* collector_; | 1410 MarkCompactCollector* collector_; |
1427 }; | 1411 }; |
1428 | 1412 |
1429 | 1413 |
1430 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { | 1414 class SharedFunctionInfoMarkingVisitor : public ObjectVisitor { |
1431 public: | 1415 public: |
1432 explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector) | 1416 explicit SharedFunctionInfoMarkingVisitor(MarkCompactCollector* collector) |
1433 : collector_(collector) {} | 1417 : collector_(collector) {} |
1434 | 1418 |
1435 void VisitPointers(Object** start, Object** end) { | 1419 void VisitPointers(Object** start, Object** end) { |
1436 for (Object** p = start; p < end; p++) VisitPointer(p); | 1420 for (Object** p = start; p < end; p++) VisitPointer(p); |
1437 } | 1421 } |
1438 | 1422 |
1439 void VisitPointer(Object** slot) { | 1423 void VisitPointer(Object** slot) { |
1440 Object* obj = *slot; | 1424 Object* obj = *slot; |
1441 if (obj->IsSharedFunctionInfo()) { | 1425 if (obj->IsSharedFunctionInfo()) { |
1442 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj); | 1426 SharedFunctionInfo* shared = reinterpret_cast<SharedFunctionInfo*>(obj); |
1443 MarkBit shared_mark = Marking::MarkBitFrom(shared); | 1427 MarkBit shared_mark = Marking::MarkBitFrom(shared); |
1444 MarkBit code_mark = Marking::MarkBitFrom(shared->unchecked_code()); | 1428 MarkBit code_mark = Marking::MarkBitFrom(shared->code()); |
1445 collector_->MarkObject(shared->unchecked_code(), code_mark); | 1429 collector_->MarkObject(shared->code(), code_mark); |
1446 collector_->MarkObject(shared, shared_mark); | 1430 collector_->MarkObject(shared, shared_mark); |
1447 } | 1431 } |
1448 } | 1432 } |
1449 | 1433 |
1450 private: | 1434 private: |
1451 MarkCompactCollector* collector_; | 1435 MarkCompactCollector* collector_; |
1452 }; | 1436 }; |
1453 | 1437 |
1454 | 1438 |
| 1439 void MarkCompactCollector::MarkInlinedFunctionsCode(Code* code) { |
| 1440 // For optimized functions we should retain both non-optimized version |
| 1441 // of it's code and non-optimized version of all inlined functions. |
| 1442 // This is required to support bailing out from inlined code. |
| 1443 DeoptimizationInputData* data = |
| 1444 DeoptimizationInputData::cast(code->deoptimization_data()); |
| 1445 |
| 1446 FixedArray* literals = data->LiteralArray(); |
| 1447 |
| 1448 for (int i = 0, count = data->InlinedFunctionCount()->value(); |
| 1449 i < count; |
| 1450 i++) { |
| 1451 JSFunction* inlined = JSFunction::cast(literals->get(i)); |
| 1452 Code* inlined_code = inlined->shared()->code(); |
| 1453 MarkBit inlined_code_mark = Marking::MarkBitFrom(inlined_code); |
| 1454 MarkObject(inlined_code, inlined_code_mark); |
| 1455 } |
| 1456 } |
| 1457 |
| 1458 |
| 1459 void MarkCompactCollector::PrepareThreadForCodeFlushing(Isolate* isolate, |
| 1460 ThreadLocalTop* top) { |
| 1461 for (StackFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
| 1462 // Note: for the frame that has a pending lazy deoptimization |
| 1463 // StackFrame::unchecked_code will return a non-optimized code object for |
| 1464 // the outermost function and StackFrame::LookupCode will return |
| 1465 // actual optimized code object. |
| 1466 StackFrame* frame = it.frame(); |
| 1467 Code* code = frame->unchecked_code(); |
| 1468 MarkBit code_mark = Marking::MarkBitFrom(code); |
| 1469 MarkObject(code, code_mark); |
| 1470 if (frame->is_optimized()) { |
| 1471 MarkInlinedFunctionsCode(frame->LookupCode()); |
| 1472 } |
| 1473 } |
| 1474 } |
| 1475 |
| 1476 |
1455 void MarkCompactCollector::PrepareForCodeFlushing() { | 1477 void MarkCompactCollector::PrepareForCodeFlushing() { |
1456 ASSERT(heap() == Isolate::Current()->heap()); | 1478 ASSERT(heap() == Isolate::Current()->heap()); |
1457 | 1479 |
1458 // TODO(1609) Currently incremental marker does not support code flushing. | 1480 // TODO(1609) Currently incremental marker does not support code flushing. |
1459 if (!FLAG_flush_code || was_marked_incrementally_) { | 1481 if (!FLAG_flush_code || was_marked_incrementally_) { |
1460 EnableCodeFlushing(false); | 1482 EnableCodeFlushing(false); |
1461 return; | 1483 return; |
1462 } | 1484 } |
1463 | 1485 |
1464 #ifdef ENABLE_DEBUGGER_SUPPORT | 1486 #ifdef ENABLE_DEBUGGER_SUPPORT |
1465 if (heap()->isolate()->debug()->IsLoaded() || | 1487 if (heap()->isolate()->debug()->IsLoaded() || |
1466 heap()->isolate()->debug()->has_break_points()) { | 1488 heap()->isolate()->debug()->has_break_points()) { |
1467 EnableCodeFlushing(false); | 1489 EnableCodeFlushing(false); |
1468 return; | 1490 return; |
1469 } | 1491 } |
1470 #endif | 1492 #endif |
1471 | 1493 |
1472 EnableCodeFlushing(true); | 1494 EnableCodeFlushing(true); |
1473 | 1495 |
1474 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray | 1496 // Ensure that empty descriptor array is marked. Method MarkDescriptorArray |
1475 // relies on it being marked before any other descriptor array. | 1497 // relies on it being marked before any other descriptor array. |
1476 HeapObject* descriptor_array = heap()->empty_descriptor_array(); | 1498 HeapObject* descriptor_array = heap()->empty_descriptor_array(); |
1477 MarkBit descriptor_array_mark = Marking::MarkBitFrom(descriptor_array); | 1499 MarkBit descriptor_array_mark = Marking::MarkBitFrom(descriptor_array); |
1478 MarkObject(descriptor_array, descriptor_array_mark); | 1500 MarkObject(descriptor_array, descriptor_array_mark); |
1479 | 1501 |
1480 // Make sure we are not referencing the code from the stack. | 1502 // Make sure we are not referencing the code from the stack. |
1481 ASSERT(this == heap()->mark_compact_collector()); | 1503 ASSERT(this == heap()->mark_compact_collector()); |
1482 for (StackFrameIterator it; !it.done(); it.Advance()) { | 1504 PrepareThreadForCodeFlushing(heap()->isolate(), |
1483 Code* code = it.frame()->unchecked_code(); | 1505 heap()->isolate()->thread_local_top()); |
1484 MarkBit code_mark = Marking::MarkBitFrom(code); | |
1485 MarkObject(code, code_mark); | |
1486 } | |
1487 | 1506 |
1488 // Iterate the archived stacks in all threads to check if | 1507 // Iterate the archived stacks in all threads to check if |
1489 // the code is referenced. | 1508 // the code is referenced. |
1490 CodeMarkingVisitor code_marking_visitor(this); | 1509 CodeMarkingVisitor code_marking_visitor(this); |
1491 heap()->isolate()->thread_manager()->IterateArchivedThreads( | 1510 heap()->isolate()->thread_manager()->IterateArchivedThreads( |
1492 &code_marking_visitor); | 1511 &code_marking_visitor); |
1493 | 1512 |
1494 SharedFunctionInfoMarkingVisitor visitor(this); | 1513 SharedFunctionInfoMarkingVisitor visitor(this); |
1495 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); | 1514 heap()->isolate()->compilation_cache()->IterateFunctions(&visitor); |
1496 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); | 1515 heap()->isolate()->handle_scope_implementer()->Iterate(&visitor); |
(...skipping 2388 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3885 while (buffer != NULL) { | 3904 while (buffer != NULL) { |
3886 SlotsBuffer* next_buffer = buffer->next(); | 3905 SlotsBuffer* next_buffer = buffer->next(); |
3887 DeallocateBuffer(buffer); | 3906 DeallocateBuffer(buffer); |
3888 buffer = next_buffer; | 3907 buffer = next_buffer; |
3889 } | 3908 } |
3890 *buffer_address = NULL; | 3909 *buffer_address = NULL; |
3891 } | 3910 } |
3892 | 3911 |
3893 | 3912 |
3894 } } // namespace v8::internal | 3913 } } // namespace v8::internal |
OLD | NEW |