| 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 2365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3862 while (buffer != NULL) { | 3881 while (buffer != NULL) { |
| 3863 SlotsBuffer* next_buffer = buffer->next(); | 3882 SlotsBuffer* next_buffer = buffer->next(); |
| 3864 DeallocateBuffer(buffer); | 3883 DeallocateBuffer(buffer); |
| 3865 buffer = next_buffer; | 3884 buffer = next_buffer; |
| 3866 } | 3885 } |
| 3867 *buffer_address = NULL; | 3886 *buffer_address = NULL; |
| 3868 } | 3887 } |
| 3869 | 3888 |
| 3870 | 3889 |
| 3871 } } // namespace v8::internal | 3890 } } // namespace v8::internal |
| OLD | NEW |