| //===--------- VirtualMachine.h - Registering a VM ------------------------===// |
| // |
| // The VMKit project |
| // |
| // This file is distributed under the University of Pierre et Marie Curie |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef VMKIT_VIRTUALMACHINE_H |
| #define VMKIT_VIRTUALMACHINE_H |
| |
| #include "vmkit/config.h" |
| |
| #include "llvm/ADT/DenseMap.h" |
| |
| #include "vmkit/Allocator.h" |
| #include "vmkit/CollectionRV.h" |
| #include "vmkit/Locks.h" |
| #include "vmkit/GC.h" |
| |
| #include <cassert> |
| #include <map> |
| |
| namespace vmkit { |
| |
| class CompiledFrames; |
| class FrameInfo; |
| class Frames; |
| |
| class FunctionMap { |
| public: |
| /// Functions - Map of applicative methods to function pointers. This map is |
| /// used when walking the stack so that VMKit knows which applicative method |
| /// is executing on the stack. |
| /// |
| llvm::DenseMap<word_t, FrameInfo*> Functions; |
| |
| /// FunctionMapLock - Spin lock to protect the Functions map. |
| /// |
| vmkit::SpinLock FunctionMapLock; |
| |
| /// IPToFrameInfo - Map a code start instruction instruction to the FrameInfo. |
| /// |
| FrameInfo* IPToFrameInfo(word_t ip); |
| |
| /// addFrameInfo - A new instruction pointer in the function map. |
| /// |
| void addFrameInfo(word_t ip, FrameInfo* meth); |
| void addFrameInfoNoLock(word_t ip, FrameInfo* meth) { |
| Functions[ip] = meth; |
| } |
| /// removeFrameInfos - Remove all FrameInfo owned by the given owner. |
| void removeFrameInfos(void* owner) {} /* TODO */ |
| |
| FunctionMap(BumpPtrAllocator& allocator, CompiledFrames** frames); |
| }; |
| |
| /// VirtualMachine - This class is the root of virtual machine classes. It |
| /// defines what a VM should be. |
| /// |
| class VirtualMachine : public vmkit::PermanentObject { |
| protected: |
| VirtualMachine(BumpPtrAllocator &Alloc, CompiledFrames** frames) : |
| allocator(Alloc), FunctionsCache(Alloc, frames) { |
| mainThread = NULL; |
| numberOfThreads = 0; |
| doExit = false; |
| exitingThread = NULL; |
| } |
| |
| virtual ~VirtualMachine() { |
| } |
| |
| public: |
| |
| /// allocator - Bump pointer allocator to allocate permanent memory |
| /// related to this VM. |
| /// |
| vmkit::BumpPtrAllocator& allocator; |
| |
| //===----------------------------------------------------------------------===// |
| // (1) Thread-related methods. |
| //===----------------------------------------------------------------------===// |
| |
| /// mainThread - The main thread of this VM. |
| /// |
| vmkit::Thread* mainThread; |
| |
| /// NumberOfThreads - The number of threads that currently run under this VM. |
| /// |
| uint32_t numberOfThreads; |
| |
| /// ThreadLock - Lock to create or destroy a new thread. |
| /// |
| vmkit::LockNormal threadLock; |
| |
| /// ThreadVar - Condition variable to wake up the thread manager. |
| vmkit::Cond threadVar; |
| |
| /// exitingThread - Thread that is currently exiting. Used by the thread |
| /// manager to free the resources (stack) used by a thread. |
| vmkit::Thread* exitingThread; |
| |
| /// doExit - Should the VM exit now? |
| bool doExit; |
| |
| /// setMainThread - Set the main thread of this VM. |
| /// |
| void setMainThread(vmkit::Thread* th) { mainThread = th; } |
| |
| /// getMainThread - Get the main thread of this VM. |
| /// |
| vmkit::Thread* getMainThread() const { return mainThread; } |
| |
| /// addThread - Add a new thread to the list of threads. |
| /// |
| void addThread(vmkit::Thread* th) { |
| threadLock.lock(); |
| numberOfThreads++; |
| if (th != mainThread) { |
| if (mainThread) th->append(mainThread); |
| else mainThread = th; |
| } |
| threadLock.unlock(); |
| } |
| |
| /// removeThread - Remove the thread from the list of threads. |
| /// |
| void removeThread(vmkit::Thread* th) { |
| threadLock.lock(); |
| while (exitingThread != NULL) { |
| // Make sure the thread manager had a chance to consume the previous |
| // dead thread. |
| threadLock.unlock(); |
| Thread::yield(); |
| threadLock.lock(); |
| } |
| numberOfThreads--; |
| if (mainThread == th) mainThread = (Thread*)th->next(); |
| th->remove(); |
| if (numberOfThreads == 0) mainThread = NULL; |
| exitingThread = th; |
| threadVar.signal(); |
| threadLock.unlock(); |
| } |
| |
| /// exit - Exit this virtual machine. |
| void exit(); |
| |
| /// waitForExit - Wait until the virtual machine stops its execution. |
| void waitForExit(); |
| |
| //===----------------------------------------------------------------------===// |
| // (2) GC-related methods. |
| //===----------------------------------------------------------------------===// |
| |
| /// startCollection - Preliminary code before starting a GC. |
| /// |
| virtual void startCollection() {} |
| |
| /// endCollection - Code after running a GC. |
| /// |
| virtual void endCollection() {} |
| |
| /// scanWeakReferencesQueue - Scan all weak references. Called by the GC |
| /// before scanning the finalization queue. |
| /// |
| virtual void scanWeakReferencesQueue(word_t closure) {} |
| |
| /// scanSoftReferencesQueue - Scan all soft references. Called by the GC |
| /// before scanning the finalization queue. |
| /// |
| virtual void scanSoftReferencesQueue(word_t closure) {} |
| |
| /// scanPhantomReferencesQueue - Scan all phantom references. Called by the GC |
| /// after the finalization queue. |
| /// |
| virtual void scanPhantomReferencesQueue(word_t closure) {} |
| |
| /// scanFinalizationQueue - Scan objets with a finalized method and schedule |
| /// them for finalization if they are not live. |
| /// |
| virtual void scanFinalizationQueue(word_t closure) {} |
| |
| /// addFinalizationCandidate - Add an object to the queue of objects with |
| /// a finalization method. |
| /// |
| virtual void addFinalizationCandidate(gc* object) {} |
| |
| /// finalizeObject - Called by the finalizer thread for objects finalization. |
| /// |
| virtual void finalizeObject(gc* res) {} |
| |
| /// tracer - Trace this virtual machine's GC-objects. |
| /// |
| virtual void tracer(word_t closure) {} |
| |
| /// traceObject - Method called during GC to trace live objects graph. |
| /// |
| virtual void traceObject(gc* object, word_t closure) = 0; |
| |
| /// setType - Method called when allocating an object. The VirtualMachine has to |
| /// set the identity of the object (identity is determined by user). |
| /// |
| virtual void setType(gc* header, void* type) = 0; |
| // virtual void setType(void* header, void* type) = 0; |
| |
| /// getType - Gets the type of given object. |
| /// |
| virtual void* getType(gc* header) = 0; |
| |
| /// getObjectSize - Get the size of this object. Used by copying collectors. |
| /// |
| virtual size_t getObjectSize(gc* object) = 0; |
| |
| /// getObjectTypeName - Get the type of this object. Used by the GC for |
| /// debugging purposes. |
| /// |
| virtual const char* getObjectTypeName(gc* object) { return "An object"; } |
| |
| /// rendezvous - The rendezvous implementation for garbage collection. |
| /// |
| CooperativeCollectionRV rendezvous; |
| |
| //===----------------------------------------------------------------------===// |
| // (2.5) GC-DEBUG-related methods. |
| //===----------------------------------------------------------------------===// |
| |
| /// isCorruptedType - Return true if object is corrupted. |
| /// |
| virtual bool isCorruptedType(gc* header) { return false; } |
| |
| |
| //===----------------------------------------------------------------------===// |
| // (3) Backtrace-related methods. |
| //===----------------------------------------------------------------------===// |
| |
| FunctionMap FunctionsCache; |
| FrameInfo* IPToFrameInfo(word_t ip) { |
| return FunctionsCache.IPToFrameInfo(ip); |
| } |
| void removeFrameInfos(void* owner) { |
| FunctionsCache.removeFrameInfos(owner); |
| } |
| |
| virtual void printMethod(FrameInfo* FI, word_t ip, word_t addr) = 0; |
| |
| //===----------------------------------------------------------------------===// |
| // (4) Launch-related methods. |
| //===----------------------------------------------------------------------===// |
| |
| /// runApplication - Run an application. The application name is in |
| /// the arguments, hence it is the virtual machine's job to parse them. |
| virtual void runApplication(int argc, char** argv) = 0; |
| |
| //===----------------------------------------------------------------------===// |
| // (5) Exception-related methods. |
| //===----------------------------------------------------------------------===// |
| |
| virtual void nullPointerException() = 0; |
| virtual void stackOverflowError() = 0; |
| |
| //===----------------------------------------------------------------------===// |
| // (6) ReferenceQueue-related methods (if used). |
| // You have to create a class which inherits from specialized ReferenceThread class. |
| // e.g: class MyReferenceThread : public ReferenceThread<YourThread> (see ReferenceQueue.h) |
| // |
| // Then once thread has been started you can enqueue references and the reference thread |
| // delegates enqueuing process to the virtual machine threw the following methods. |
| //===----------------------------------------------------------------------===// |
| |
| /// invokeEnqueueReference - This method is called whenever an object is enqueued in |
| /// Soft, Weak or Phantom reference queues. |
| /// |
| virtual void invokeEnqueueReference(gc* ref) {} |
| |
| /// clearObjectReferent - Clears object's referent |
| /// |
| virtual void clearObjectReferent(gc* ref) {} |
| |
| /// getObjectReferentPtr - returns object referent's pointer |
| /// |
| virtual gc** getObjectReferentPtr(gc* _obj) { abort(); return NULL; } |
| |
| /// setObjectReferent - set the referent of an object |
| /// |
| virtual void setObjectReferent(gc* _obj, gc* val) {} |
| }; |
| |
| |
| } // end namespace vmkit |
| #endif // VMKIT_VIRTUALMACHINE_H |