Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

355 lines (263 sloc) 7.984 kb
#ifndef RBX_VM_H
#define RBX_VM_H
#include "globals.hpp"
#include "gc/object_mark.hpp"
#include "thread_state.hpp"
#include "util/refcount.hpp"
#include "global_lock.hpp"
#include "maps.hpp"
#include "call_frame_list.hpp"
#include "async_message.hpp"
#include "gc/variable_buffer.hpp"
#include "shared_state.hpp"
#include <vector>
#include <pthread.h>
#include <setjmp.h>
namespace llvm {
class Module;
namespace rubinius {
class Exception;
class LLVMState;
namespace event {
class Loop;
namespace profiler {
class Profiler;
class GlobalCache;
class TaskProbe;
class Primitives;
class ObjectMemory;
class TypeInfo;
class MethodContext;
class String;
class Symbol;
class ConfigParser;
class TypeError;
class Assertion;
class CallFrame;
class Object;
class Configuration;
class Interrupts;
class VMManager;
class Waiter;
class LookupTable;
class SymbolTable;
class SharedState;
struct Stats {
// How much time is spent running the JIT
uint64_t jit_timing;
// How many methods have been compiled by the JIT
uint64_t jitted_methods;
// How much time is spent in the GC
uint64_t time_in_gc;
: jit_timing(0)
, jitted_methods(0)
, time_in_gc(0)
class VM {
CallFrame* saved_call_frame_;
ASyncMessageMailbox mailbox_;
void* stack_start_;
bool alive_;
profiler::Profiler* profiler_;
bool run_signals_;
/* Data members */
SharedState& shared;
thread::Mutex local_lock_;
Waiter* waiter_;
Globals& globals;
ObjectMemory* om;
event::Loop* events;
event::Loop* signal_events;
GlobalCache* global_cache;
TypedRoot<TaskProbe*> probe;
Interrupts& interrupts;
SymbolTable& symbols;
bool check_local_interrupts;
ThreadState thread_state_;
// The Thread object for this VM state
TypedRoot<Thread*> thread;
Stats stats;
// Temporary holder for rb_gc_mark() in subtend
ObjectMark* current_mark;
bool reuse_llvm;
// The thread used to trigger preemptive thread switching
pthread_t preemption_thread;
// The safe position on the stack used to handle rare
// events.
sigjmp_buf safe_position;
// Indicates if safe_position should be used, or if the error
// should be thrown as a C++ exception.
bool use_safe_position;
// Data used with safe_position.
union {
Exception* exc;
TypeError* type_error;
Assertion* assertion;
} safe_position_data;
static const int cReasonException = 1;
static const int cReasonTypeError = 2;
static const int cReasonAssertion = 3;
static int cStackDepthMax;
public: /* Inline methods */
bool run_signals_p() {
return run_signals_;
void set_run_signals(bool val) {
run_signals_ = val;
bool alive_p() {
return alive_;
ThreadState* thread_state() {
return &thread_state_;
GlobalLock& global_lock() {
return shared.global_lock();
thread::Mutex& local_lock() {
return local_lock_;
CallFrame** call_frame_location() {
return &saved_call_frame_;
void set_call_frame(CallFrame* frame) {
saved_call_frame_ = frame;
CallFrame* saved_call_frame() {
return saved_call_frame_;
// NOTE this will need to be VM local, ie Thread local, once the GIL
// is removed.
VariableRootBuffers* variable_buffers() {
return shared.variable_buffers();
void* stack_start() {
return stack_start_;
void set_stack_start(void* s) {
stack_start_ = s;
bool check_stack(CallFrame* call_frame, void* end) {
// @TODO assumes stack growth direction
if(reinterpret_cast<intptr_t>(stack_start_) -
reinterpret_cast<intptr_t>(end) > cStackDepthMax) {
return false;
return true;
/* Prototypes */
VM(SharedState& shared);
void check_exception(CallFrame* call_frame);
void initialize();
// Initialize the basic objects and the execution machinery
void boot();
// Returns the current VM state object.
static VM* current_state();
// Registers a VM* object as the current state.
static void register_state(VM*);
static void discard(VM*);
void bootstrap_class();
void bootstrap_ontology();
void bootstrap_symbol();
void bootstrap_exceptions();
void initialize_fundamental_constants();
void initialize_builtin_classes();
void initialize_platform_data();
void boot_threads();
void raise_exception_safely(Exception* exc);
void raise_typeerror_safely(TypeError* exc);
void raise_assertion_safely(Assertion* exc);
void raise_stack_error(CallFrame* call_frame);
void init_stack_size();
Object* new_object_typed(Class* cls, size_t bytes, object_type type);
Object* new_object_typed_mature(Class* cls, size_t bytes, object_type type);
Object* new_object_from_type(Class* cls, TypeInfo* ti);
template <class T>
T* new_object(Class *cls) {
return reinterpret_cast<T*>(new_object_typed(cls, sizeof(T), T::type));
template <class T>
T* new_struct(Class* cls, size_t bytes = 0) {
T* obj = reinterpret_cast<T*>(new_object_typed(cls, sizeof(T) + bytes, T::type));
return obj;
template <class T>
T* new_object_mature(Class *cls) {
return reinterpret_cast<T*>(new_object_typed_mature(cls, sizeof(T), T::type));
// Create an uninitialized Class object
Class* new_basic_class(Class* sup);
// Create a Class of name +name+ as an Object subclass
Class* new_class(const char* name);
// Create a Class of name +name+ as a subclass of +super_class+
Class* new_class(const char* name, Class* super_class);
// Create a Class of name +name+ as a subclass of +sup+
// under Module +under+
Class* new_class(const char* name, Class* sup, Module* under);
// Create a Class of name +name+ under +under+
Class* new_class_under(const char* name, Module* under);
Module* new_module(const char* name, Module* under = NULL);
Symbol* symbol(const char* str);
Symbol* symbol(String* str);
TypeInfo* find_type(int type);
void init_ffi();
void init_native_libraries();
Thread* current_thread();
void collect(CallFrame* call_frame);
// Check the flags in ObjectMemory and collect if we need to.
void collect_maybe(CallFrame* call_frame);
void raise_from_errno(const char* reason);
void raise_exception(Exception* exc);
Exception* new_exception(Class* cls, const char* msg);
Object* current_block();
void set_const(const char* name, Object* val);
void set_const(Module* mod, const char* name, Object* val);
llvm::Module* llvm_module();
void llvm_cleanup();
void print_backtrace();
void setup_preemption();
// Run in a seperate thread to provide preemptive thread
// scheduling.
void scheduler_loop();
// Run the garbage collectors as soon as you can
void run_gc_soon();
void install_waiter(Waiter& waiter);
void clear_waiter();
bool wakeup();
void register_raise(Exception* exc);
// Called when a thread should be delivered to this thread
void send_async_signal(int sig);
bool process_async(CallFrame* call_frame);
bool check_async(CallFrame* call_frame) {
if(check_local_interrupts) {
return process_async(call_frame);
return true;
profiler::Profiler* profiler();
void remove_profiler();
class StopTheWorld {
VM* vm_;
StopTheWorld(STATE) :
~StopTheWorld() {
Jump to Line
Something went wrong with that request. Please try again.