template
inline void SemiSpace::MarkObject(
mirror::ObjectReference* obj_ptr) {
mirror::Object* obj = obj_ptr->AsMirrorPtr();
if (obj == nullptr) {
return;
}
......
if (from_space_->HasAddress(obj)) {
mirror::Object* forward_address = GetForwardingAddressInFromSpace(obj);
// If the object has already been moved, return the new forward address.
if (UNLIKELY(forward_address == nullptr)) {
forward_address = MarkNonForwardedObject(obj);
DCHECK(forward_address != nullptr);
// Make sure to only update the forwarding address AFTER you copy the object so that the
// monitor word doesn't Get stomped over.
obj->SetLockWord(
LockWord::FromForwardingAddress(reinterpret_cast(forward_address)), false);
// Push the object onto the mark stack for later processing.
MarkStackPush(forward_address);
}
obj_ptr->Assign(forward_address);
} else if (!collect_from_space_only_ && !immune_region_.ContainsObject(obj)) {
BitmapSetSlowPathVisitor visitor(this);
if (!mark_bitmap_->Set(obj, visitor)) {
// This object was not previously marked.
MarkStackPush(obj);
}
}
}
void SemiSpace::MarkReachableObjects() {
......
for (auto& space : heap_->GetContinuousSpaces()) {
// If the space is immune then we need to mark the references to other spaces.
accounting::ModUnionTable* table = heap_->FindModUnionTableFromSpace(space);
if (table != nullptr) {
......
table->UpdateAndMarkReferences(MarkHeapReferenceCallback, this);
......
}
......
}
......
}
这个函数定义在文件art/runtime/gc/collector/semi_space.cc中。
SemiSpace类的成员函数MarkReachableObjects依次遍历组成当前堆的各个Space。如果一个Space有对应的Mod Union Table,那么就调用它的成员函数UpdateAndMarkReferences来标记那些自上次GC以来被修改的对象。对于每一个这样的对象,都回调SemiSpace类的静态成员函数MarkHeapReferenceCallback进行处理。关于Mod Union Table在GC过程中的作用,可以参考前面ART运行时垃圾收集机制简要介绍和学习计划这个系列的文章。
Mod Union Table的基类是ModUnionTable,它的子类ModUnionTableReferenceCache用来描述一个具体的Mod Union Table,接下来我们就通过它的成员函数UpdateAndMarkReferences来进一步描述被堆对象引用的对象的移动过程,它的实现如下所示:
void ModUnionTableReferenceCache::UpdateAndMarkReferences(MarkHeapReferenceCallback* callback,
void* arg) {
CardTable* card_table = heap_->GetCardTable();
std::vector*> cards_references;
ModUnionReferenceVisitor add_visitor(this, &cards_references);
for (const auto& card : cleared_cards_) {
// Clear and re-compute alloc space references associated with this card.
cards_references.clear();
uintptr_t start = reinterpret_cast(card_table->AddrFromCard(card));
uintptr_t end = start + CardTable::kCardSize;
auto* space = heap_->FindContinuousSpaceFromObject(reinterpret_cast
class ModUnionReferenceVisitor {
public:
explicit ModUnionReferenceVisitor(ModUnionTableReferenceCache* const mod_union_table,
std::vector*>* references)
: mod_union_table_(mod_union_table),
references_(references) {
}
void operator()(Object* obj) const
SHARED_LOCKS_REQUIRED(Locks::heap_bitmap_lock_, Locks::mutator_lock_) {
// We don't have an early exit since we use the visitor pattern, an early
// exit should significantly speed this up.
AddToReferenceArrayVisitor visitor(mod_union_table_, references_);
obj->VisitReferences(visitor, VoidFunctor());
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
std::vector*>* const references_;
};
class AddToReferenceArrayVisitor {
public:
explicit AddToReferenceArrayVisitor(ModUnionTableReferenceCache* mod_union_table,
std::vector*>* references)
: mod_union_table_(mod_union_table), references_(references) {
}
// Extra parameters are required since we use this same visitor signature for checking objects.
void operator()(Object* obj, MemberOffset offset, bool /*is_static*/) const
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
mirror::HeapReference* ref_ptr = obj->GetFieldObjectReferenceAddr(offset);
mirror::Object* ref = ref_ptr->AsMirrorPtr();
// Only add the reference if it is non null and fits our criteria.
if (ref != nullptr && mod_union_table_->ShouldAddReference(ref)) {
// Push the adddress of the reference.
references_->push_back(ref_ptr);
}
}
private:
ModUnionTableReferenceCache* const mod_union_table_;
std::vector*>* const references_;
};
-alloc bit map:每一个已经被分配出去的slot在alloc bit map中对应的位都会被设置为1。
-bulk free bit map:每一个将要释放的slot都不会马上被回收,而是先记录起来,等到一个Run的所有slot全部都释放时,才会执行真正的内存回收操作,因此,就需要在释放slot的时候用一个bulk free bit map中的位来记录那些slot是需要释放的。这样可以避免每释放一个slot,就执行一次内存回收操作。同时,该bulk free bit map的信息也会被同步到alloc bit map中。
-thread local bit map:当一个Run是一个线程局部Run时,那么当它的slot被释放时,释放信息会从bulk free bit map同步到thread local bit map,但是不会马上同步到alloc bitmap中,而是等到从该Run分配内存出现失败时,才会将该thread local bit map的信息同步到alloc bit map中去。
POJ-1273-Drainage Ditches
http://poj.org/problem?id=1273
基本的最大流,按LRJ的白书写的
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
#define INF 0x7fffffff
int ma
开启列模式: Alt+C 鼠标选择 OR Alt+鼠标左键拖动
列模式替换或复制内容(多行):
右键-->格式-->填充所选内容-->选择相应操作
OR
Ctrl+Shift+V(复制多行数据,必须行数一致)
-------------------------------------------------------
About Health Monitor
Beginning with Release 11g, Oracle Database includes a framework called Health Monitor for running diagnostic checks on the database.
About Health Monitor Checks
Health M
实现功能的代码:
# include <stdio.h>
# include <malloc.h>
struct Student
{
int age;
float score;
char name[100];
};
int main(void)
{
int len;
struct Student * pArr;
int i,
http://wiki.sdn.sap.com/wiki/display/BOBJ/Troubleshooting+Crystal+Reports+off+BW#TroubleshootingCrystalReportsoffBW-TracingBOE
Quite useful, especially this part:
SAP BW connectivity
For t