X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=docs%2FGarbageCollection.rst;h=49d3496748e202751ad13aa47b87c2823476f5ab;hb=daed11e66479ea4ae7eff323d70720093db6851f;hp=7765bd7d04cf5e7504e44a7a7cfd4a2f1af139d4;hpb=b64f020a30427e90a05530f8b20f1bddd1ab9e0a;p=oota-llvm.git diff --git a/docs/GarbageCollection.rst b/docs/GarbageCollection.rst index 7765bd7d04c..49d3496748e 100644 --- a/docs/GarbageCollection.rst +++ b/docs/GarbageCollection.rst @@ -5,9 +5,6 @@ Accurate Garbage Collection with LLVM .. contents:: :local: -.. sectionauthor:: Chris Lattner and - Gordon Henriksen - Introduction ============ @@ -503,8 +500,7 @@ This boilerplate collector does nothing. More specifically: * The stack map is not compiled into the executable. -Using the LLVM makefiles (like the `sample project -`__), this code +Using the LLVM makefiles, this code can be compiled as a plugin using a simple makefile: .. code-block:: make @@ -526,7 +522,7 @@ extension): $ cat sample.ll define void @f() gc "mygc" { entry: - ret void + ret void } $ llvm-as < sample.ll | llc -load=MyGC.so @@ -637,7 +633,7 @@ Threaded Denotes a multithreaded mutator; the collector must still stop the mutator ("stop the world") before beginning reachability analysis. Stopping a multithreaded mutator is a complicated problem. It generally requires highly - platform specific code in the runtime, and the production of carefully + platform-specific code in the runtime, and the production of carefully designed machine code at safe points. Concurrent @@ -767,8 +763,8 @@ The following can be used as a template: .. code-block:: c++ - #include "llvm/Module.h" - #include "llvm/IntrinsicInst.h" + #include "llvm/IR/Module.h" + #include "llvm/IR/IntrinsicInst.h" bool MyGC::initializeCustomLowering(Module &M) { return false; @@ -899,109 +895,96 @@ in the JIT, nor using the object writers. namespace { class LLVM_LIBRARY_VISIBILITY MyGCPrinter : public GCMetadataPrinter { public: - virtual void beginAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + virtual void beginAssembly(AsmPrinter &AP); - virtual void finishAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI); + virtual void finishAssembly(AsmPrinter &AP); }; GCMetadataPrinterRegistry::Add X("mygc", "My bespoke garbage collector."); } -The collector should use ``AsmPrinter`` and ``TargetAsmInfo`` to print portable -assembly code to the ``std::ostream``. The collector itself contains the stack -map for the entire module, and may access the ``GCFunctionInfo`` using its own -``begin()`` and ``end()`` methods. Here's a realistic example: +The collector should use ``AsmPrinter`` to print portable assembly code. The +collector itself contains the stack map for the entire module, and may access +the ``GCFunctionInfo`` using its own ``begin()`` and ``end()`` methods. Here's +a realistic example: .. code-block:: c++ #include "llvm/CodeGen/AsmPrinter.h" - #include "llvm/Function.h" - #include "llvm/Target/TargetMachine.h" - #include "llvm/DataLayout.h" + #include "llvm/IR/Function.h" + #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetAsmInfo.h" + #include "llvm/Target/TargetMachine.h" - void MyGCPrinter::beginAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) { + void MyGCPrinter::beginAssembly(AsmPrinter &AP) { // Nothing to do. } - void MyGCPrinter::finishAssembly(std::ostream &OS, AsmPrinter &AP, - const TargetAsmInfo &TAI) { - // Set up for emitting addresses. - const char *AddressDirective; - int AddressAlignLog; - if (AP.TM.getDataLayout()->getPointerSize() == sizeof(int32_t)) { - AddressDirective = TAI.getData32bitsDirective(); - AddressAlignLog = 2; - } else { - AddressDirective = TAI.getData64bitsDirective(); - AddressAlignLog = 3; - } + void MyGCPrinter::finishAssembly(AsmPrinter &AP) { + MCStreamer &OS = AP.OutStreamer; + unsigned IntPtrSize = AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize(); // Put this in the data section. - AP.SwitchToDataSection(TAI.getDataSection()); + OS.SwitchSection(AP.getObjFileLowering().getDataSection()); // For each function... for (iterator FI = begin(), FE = end(); FI != FE; ++FI) { GCFunctionInfo &MD = **FI; - // Emit this data structure: + // A compact GC layout. Emit this data structure: // // struct { // int32_t PointCount; - // struct { - // void *SafePointAddress; - // int32_t LiveCount; - // int32_t LiveOffsets[LiveCount]; - // } Points[PointCount]; + // void *SafePointAddress[PointCount]; + // int32_t StackFrameSize; // in words + // int32_t StackArity; + // int32_t LiveCount; + // int32_t LiveOffsets[LiveCount]; // } __gcmap_; // Align to address width. - AP.EmitAlignment(AddressAlignLog); - - // Emit the symbol by which the stack map entry can be found. - std::string Symbol; - Symbol += TAI.getGlobalPrefix(); - Symbol += "__gcmap_"; - Symbol += MD.getFunction().getName(); - if (const char *GlobalDirective = TAI.getGlobalDirective()) - OS << GlobalDirective << Symbol << "\n"; - OS << TAI.getGlobalPrefix() << Symbol << ":\n"; + AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3); // Emit PointCount. + OS.AddComment("safe point count"); AP.EmitInt32(MD.size()); - AP.EOL("safe point count"); // And each safe point... for (GCFunctionInfo::iterator PI = MD.begin(), - PE = MD.end(); PI != PE; ++PI) { - // Align to address width. - AP.EmitAlignment(AddressAlignLog); - + PE = MD.end(); PI != PE; ++PI) { // Emit the address of the safe point. - OS << AddressDirective - << TAI.getPrivateGlobalPrefix() << "label" << PI->Num; - AP.EOL("safe point address"); - - // Emit the stack frame size. - AP.EmitInt32(MD.getFrameSize()); - AP.EOL("stack frame size"); - - // Emit the number of live roots in the function. - AP.EmitInt32(MD.live_size(PI)); - AP.EOL("live root count"); - - // And for each live root... - for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI), - LE = MD.live_end(PI); - LI != LE; ++LI) { - // Print its offset within the stack frame. - AP.EmitInt32(LI->StackOffset); - AP.EOL("stack offset"); - } + OS.AddComment("safe point address"); + MCSymbol *Label = PI->Label; + AP.EmitLabelPlusOffset(Label/*Hi*/, 0/*Offset*/, 4/*Size*/); + } + + // Stack information never change in safe points! Only print info from the + // first call-site. + GCFunctionInfo::iterator PI = MD.begin(); + + // Emit the stack frame size. + OS.AddComment("stack frame size (in words)"); + AP.EmitInt32(MD.getFrameSize() / IntPtrSize); + + // Emit stack arity, i.e. the number of stacked arguments. + unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6; + unsigned StackArity = MD.getFunction().arg_size() > RegisteredArgs ? + MD.getFunction().arg_size() - RegisteredArgs : 0; + OS.AddComment("stack arity"); + AP.EmitInt32(StackArity); + + // Emit the number of live roots in the function. + OS.AddComment("live root count"); + AP.EmitInt32(MD.live_size(PI)); + + // And for each live root... + for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI), + LE = MD.live_end(PI); + LI != LE; ++LI) { + // Emit live root's offset within the stack frame. + OS.AddComment("stack index (offset / wordsize)"); + AP.EmitInt32(LI->StackOffset); } } } @@ -1029,4 +1012,3 @@ programming. [Henderson2002] `Accurate Garbage Collection in an Uncooperative Environment `__ -