Skip to content

Commit

Permalink
Added tooling interpreter.
Browse files Browse the repository at this point in the history
  • Loading branch information
brixen committed Sep 13, 2012
1 parent 88bd8df commit 3c5b01f
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 18 deletions.
6 changes: 6 additions & 0 deletions vm/capi/18/include/rbxti.hpp
Expand Up @@ -9,6 +9,7 @@ namespace rbxti {
class InternalSymbol : public InternalObject {};
class InternalTable : public InternalObject {};
class InternalMethod : public InternalObject {};
class InternalMachineCode : public InternalObject {};
class InternalModule : public InternalObject {};
class InternalString : public InternalObject {};
class InternalInteger : public InternalObject {};
Expand All @@ -19,6 +20,7 @@ namespace rbxti {
typedef InternalSymbol* rsymbol;
typedef InternalTable* rtable;
typedef InternalMethod* rmethod;
typedef InternalMachineCode* rmachine_code;
typedef InternalModule* rmodule;
typedef InternalString* rstring;
typedef InternalInteger* rinteger;
Expand Down Expand Up @@ -48,6 +50,8 @@ namespace rbxti {

typedef void (*at_gc_func)(Env* env);

typedef void (*at_ip_func)(Env* env, rmachine_code code, int ip);

class Env {
public:
EnvPrivate* private_;
Expand Down Expand Up @@ -132,6 +136,8 @@ namespace rbxti {
void set_tool_thread_stop(thread_stop_func func);

void set_tool_at_gc(at_gc_func func);

void set_tool_at_ip(at_ip_func func);
};
}

Expand Down
10 changes: 10 additions & 0 deletions vm/capi/19/include/rbxti.hpp
Expand Up @@ -9,6 +9,7 @@ namespace rbxti {
class InternalSymbol : public InternalObject {};
class InternalTable : public InternalObject {};
class InternalMethod : public InternalObject {};
class InternalMachineCode : public InternalObject {};
class InternalModule : public InternalObject {};
class InternalString : public InternalObject {};
class InternalInteger : public InternalObject {};
Expand All @@ -19,6 +20,7 @@ namespace rbxti {
typedef InternalSymbol* rsymbol;
typedef InternalTable* rtable;
typedef InternalMethod* rmethod;
typedef InternalMachineCode* rmachine_code;
typedef InternalModule* rmodule;
typedef InternalString* rstring;
typedef InternalInteger* rinteger;
Expand Down Expand Up @@ -46,6 +48,10 @@ namespace rbxti {
typedef void (*thread_start_func)(Env* env);
typedef void (*thread_stop_func)(Env* env);

typedef void (*at_gc_func)(Env* env);

typedef void (*at_ip_func)(Env* env, rmachine_code code, int ip);

class Env {
public:
EnvPrivate* private_;
Expand Down Expand Up @@ -128,6 +134,10 @@ namespace rbxti {

void set_tool_thread_start(thread_start_func func);
void set_tool_thread_stop(thread_stop_func func);

void set_tool_at_gc(at_gc_func func);

void set_tool_at_ip(at_ip_func func);
};
}

Expand Down
175 changes: 157 additions & 18 deletions vm/instructions.cpp
Expand Up @@ -21,6 +21,8 @@
#include "builtin/location.hpp"
#include "builtin/cache.hpp"

#include "instruments/tooling.hpp"

#include "call_frame.hpp"

#include "objectmemory.hpp"
Expand Down Expand Up @@ -74,8 +76,8 @@ using namespace rubinius;
#define CALL_FLAGS() is.call_flags

Object* MachineCode::interpreter(STATE,
MachineCode* const mcode,
InterpreterCallFrame* const call_frame)
MachineCode* const mcode,
InterpreterCallFrame* const call_frame)
{

#include "vm/gen/instruction_locations.hpp"
Expand Down Expand Up @@ -205,14 +207,14 @@ Object* MachineCode::interpreter(STATE,
}

Object* MachineCode::uncommon_interpreter(STATE,
MachineCode* const mcode,
CallFrame* const call_frame,
int32_t entry_ip,
native_int sp,
CallFrame* const method_call_frame,
jit::RuntimeDataHolder* rd,
int32_t unwind_count,
int32_t* input_unwinds)
MachineCode* const mcode,
CallFrame* const call_frame,
int32_t entry_ip,
native_int sp,
CallFrame* const method_call_frame,
jit::RuntimeDataHolder* rd,
int32_t unwind_count,
int32_t* input_unwinds)
{

MachineCode* mc = method_call_frame->compiled_code->machine_code();
Expand Down Expand Up @@ -368,8 +370,8 @@ Object* MachineCode::uncommon_interpreter(STATE,
* a breakpoint is set on compiled method.
*/
Object* MachineCode::debugger_interpreter(STATE,
MachineCode* const mcode,
InterpreterCallFrame* const call_frame)
MachineCode* const mcode,
InterpreterCallFrame* const call_frame)
{

#include "vm/gen/instruction_locations.hpp"
Expand Down Expand Up @@ -506,12 +508,12 @@ Object* MachineCode::debugger_interpreter(STATE,
}

Object* MachineCode::debugger_interpreter_continue(STATE,
MachineCode* const mcode,
CallFrame* const call_frame,
int sp,
InterpreterState& is,
int current_unwind,
UnwindInfo* unwinds)
MachineCode* const mcode,
CallFrame* const call_frame,
int sp,
InterpreterState& is,
int current_unwind,
UnwindInfo* unwinds)
{

#include "vm/gen/instruction_locations.hpp"
Expand Down Expand Up @@ -633,3 +635,140 @@ Object* MachineCode::debugger_interpreter_continue(STATE,
rubinius::bug("Control flow error in interpreter");
return NULL;
}


/* The tooling interpreter calls the registered tool for every instruction
* executed.
*/
Object* MachineCode::tooling_interpreter(STATE,
MachineCode* const mcode,
InterpreterCallFrame* const call_frame)
{

#include "vm/gen/instruction_locations.hpp"

opcode* stream = mcode->opcodes;
InterpreterState is;
GCTokenImpl gct;

int current_unwind = 0;
UnwindInfo unwinds[kMaxUnwindInfos];

Object** stack_ptr = call_frame->stk - 1;

continue_to_run:
try {

#undef DISPATCH
#define DISPATCH \
if(unlikely(state->vm()->tooling())) { \
state->shared().tool_broker()->at_ip(state, mcode, call_frame->ip()); \
} \
goto *insn_locations[stream[call_frame->inc_ip()]];

#undef next_int
#undef cache_ip
#undef flush_ip

#define next_int ((opcode)(stream[call_frame->inc_ip()]))
#define cache_ip(which)
#define flush_ip()

#include "vm/gen/instruction_implementations.hpp"

} catch(TypeError& e) {
flush_ip();
Exception* exc =
Exception::make_type_error(state, e.type, e.object, e.reason);
exc->locations(state, Location::from_call_stack(state, call_frame));

state->raise_exception(exc);
call_frame->scope->flush_to_heap(state);
return NULL;
} catch(const RubyException& exc) {
exc.exception->locations(state,
Location::from_call_stack(state, call_frame));
state->raise_exception(exc.exception);
return NULL;
}

// no reason to be here!
rubinius::bug("Control flow error in interpreter");

// If control finds it's way down here, there is an exception.
exception:
ThreadState* th = state->vm()->thread_state();
//
switch(th->raise_reason()) {
case cException:
if(current_unwind > 0) {
UnwindInfo* info = &unwinds[--current_unwind];
stack_position(info->stack_depth);
call_frame->set_ip(info->target_ip);
cache_ip(info->target_ip);
goto continue_to_run;
} else {
call_frame->scope->flush_to_heap(state);
return NULL;
}

case cBreak:
// If we're trying to break to here, we're done!
if(th->destination_scope() == call_frame->scope->on_heap()) {
stack_push(th->raise_value());
th->clear_break();
goto continue_to_run;
// Don't return here, because we want to loop back to the top
// and keep running this method.
}

// Otherwise, fall through and run the unwinds
case cReturn:
case cCatchThrow:
// Otherwise, we're doing a long return/break unwind through
// here. We need to run ensure blocks.
while(current_unwind > 0) {
UnwindInfo* info = &unwinds[--current_unwind];
stack_position(info->stack_depth);

if(info->for_ensure()) {
stack_position(info->stack_depth);
call_frame->set_ip(info->target_ip);
cache_ip(info->target_ip);

// Don't reset ep here, we're still handling the return/break.
goto continue_to_run;
}
}

// Ok, no ensures to run.
if(th->raise_reason() == cReturn) {
call_frame->scope->flush_to_heap(state);

// If we're trying to return to here, we're done!
if(th->destination_scope() == call_frame->scope->on_heap()) {
Object* val = th->raise_value();
th->clear_return();
return val;
} else {
// Give control of this exception to the caller.
return NULL;
}

} else { // It's cBreak thats not for us!
call_frame->scope->flush_to_heap(state);
// Give control of this exception to the caller.
return NULL;
}

case cExit:
call_frame->scope->flush_to_heap(state);
return NULL;
default:
break;
} // switch

rubinius::bug("Control flow error in interpreter");
return NULL;
}

5 changes: 5 additions & 0 deletions vm/instruments/rbxti-internal.hpp
Expand Up @@ -8,6 +8,7 @@ namespace rubinius {
class Module;
class Symbol;
class CompiledCode;
class MachineCode;
class String;
class Integer;
class LookupTable;
Expand Down Expand Up @@ -59,6 +60,10 @@ namespace rbxti {
return (rmethod)m;
}

static inline rmachine_code o(rubinius::MachineCode* mcode) {
return (rmachine_code)mcode;
}

static inline rstring o(rubinius::String* s) {
return (rstring)s;
}
Expand Down
4 changes: 4 additions & 0 deletions vm/instruments/rbxti.cpp
Expand Up @@ -347,6 +347,10 @@ namespace rbxti {
private_->global()->set_tool_at_gc(func);
}

void Env::set_tool_at_ip(at_ip_func func) {
private_->global()->set_tool_at_ip(func);
}

Env* create_env(VM* state) {
Env* env = new Env;
env->private_ = new EnvPrivate(state);
Expand Down
10 changes: 10 additions & 0 deletions vm/instruments/tooling.cpp
Expand Up @@ -30,6 +30,7 @@ namespace tooling {
, thread_start_func_(0)
, thread_stop_func_(0)
, at_gc_func_(0)
, at_ip_func_(0)
, shutdown_func_(0)
{}

Expand Down Expand Up @@ -145,6 +146,11 @@ namespace tooling {
at_gc_func_(state->vm()->tooling_env());
}

void ToolBroker::at_ip(STATE, MachineCode* mcode, int ip) {
if(!at_ip_func_) return;
at_ip_func_(state->vm()->tooling_env(), rbxti::o(mcode), ip);
}

void ToolBroker::set_tool_results(rbxti::results_func func) {
results_func_ = func;
}
Expand Down Expand Up @@ -206,5 +212,9 @@ namespace tooling {
void ToolBroker::set_tool_at_gc(rbxti::at_gc_func func) {
at_gc_func_ = func;
}

void ToolBroker::set_tool_at_ip(rbxti::at_ip_func func) {
at_ip_func_ = func;
}
}
}
7 changes: 7 additions & 0 deletions vm/instruments/tooling.hpp
Expand Up @@ -6,6 +6,7 @@
namespace rubinius {
class BlockEnvironment;
class VM;
class MachineCode;
namespace tooling {

const static int cTotalToolDatas = 16;
Expand Down Expand Up @@ -34,6 +35,8 @@ namespace tooling {

rbxti::at_gc_func at_gc_func_;

rbxti::at_ip_func at_ip_func_;

rbxti::shutdown_func shutdown_func_;

public:
Expand Down Expand Up @@ -71,6 +74,8 @@ namespace tooling {

void at_gc(STATE);

void at_ip(STATE, MachineCode* mcode, int ip);

void set_tool_enter_method(rbxti::enter_method func);
void set_tool_leave_method(rbxti::leave_func func);

Expand All @@ -93,6 +98,8 @@ namespace tooling {

void set_tool_at_gc(rbxti::at_gc_func func);

void set_tool_at_ip(rbxti::at_ip_func func);

Object* results(STATE);
void enable(STATE);
bool available(STATE);
Expand Down
4 changes: 4 additions & 0 deletions vm/machine_code.hpp
Expand Up @@ -192,6 +192,10 @@ namespace rubinius {
CallFrame* const method_call_frame, jit::RuntimeDataHolder* rd,
int32_t unwind_count, int32_t* unwinds);

static Object* tooling_interpreter(STATE,
MachineCode* const mcode,
InterpreterCallFrame* const call_frame);

void setup_argument_handler(CompiledCode* meth);

bool validate_ip(STATE, size_t ip);
Expand Down

0 comments on commit 3c5b01f

Please sign in to comment.