Skip to content

Commit

Permalink
Checkout. Add CallFrame
Browse files Browse the repository at this point in the history
  • Loading branch information
Evan Phoenix committed Feb 3, 2009
1 parent 4e76e69 commit 77c68c4
Show file tree
Hide file tree
Showing 47 changed files with 916 additions and 627 deletions.
1 change: 1 addition & 0 deletions rakelib/vm.rake
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ field_extract_headers = %w[
vm/builtin/autoload.hpp
vm/builtin/machine_method.hpp
vm/builtin/block_wrapper.hpp
vm/builtin/variable_scope.hpp
]

BC = "vm/instructions.bc"
Expand Down
10 changes: 4 additions & 6 deletions vm/builtin/access_variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace rubinius {

/* Run when an AccessVariable is executed. Uses the details in msg.method
* to access instance variables of msg.recv */
ExecuteStatus AccessVariable::access_execute(STATE, Task* task, Message& msg) {
Object* AccessVariable::access_execute(STATE, CallFrame* call_frame, Task* task, Message& msg) {
AccessVariable* access = as<AccessVariable>(msg.method);

/* The writer case. */
Expand All @@ -38,17 +38,15 @@ namespace rubinius {

/* Fall through, handle it as a normal ivar. */
msg.recv->set_ivar(state, access->name(), msg.get_argument(0));
task->primitive_return(msg.get_argument(0), msg);
return cExecuteContinue;
return msg.get_argument(0);
}

/* The read case. */
if(msg.args() != 0) {
Exception::argument_error(state, 0, msg.args());
return Qnil;
} else {
task->primitive_return(msg.recv->get_ivar(state, access->name()), msg);
return msg.recv->get_ivar(state, access->name());
}

return cExecuteContinue;
}
}
2 changes: 1 addition & 1 deletion vm/builtin/access_variable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace rubinius {
static void init(STATE);
// Ruby.primitive :accessvariable_allocate
static AccessVariable* allocate(STATE);
static ExecuteStatus access_execute(STATE, Task* task, Message& msg);
static Object* access_execute(STATE, CallFrame* call_frame, Task* task, Message& msg);

class Info : public TypeInfo {
public:
Expand Down
111 changes: 58 additions & 53 deletions vm/builtin/block_environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,29 +34,45 @@ namespace rubinius {
return env;
}

void BlockEnvironment::call(STATE, Task* task, size_t args) {
Object* BlockEnvironment::call(STATE, Task* task, CallFrame* call_frame, size_t args) {
Object* val;
if(args > 0) {
Tuple* tup = Tuple::create(state, args);
int sp = 0;
for(int i = args - 1; i >= 0; i--) {
tup->put(state, i, task->pop());
tup->put(state, i, call_frame->stack_back(sp++));
}

val = tup;
} else {
val = Qnil;
}
task->pop(); // Remove this from the stack.
BlockContext* ctx = create_context(state, task->active());

if(unlikely(task->profiler)) task->profiler->enter_block(state, home_, method_);
VariableScope* scope = (VariableScope*)alloca(sizeof(VariableScope) +
(vmm->number_of_locals * sizeof(Object*)));

task->make_active(ctx);
task->push(val);
ctx->run(ctx->vmm, task, ctx);
scope->setup_as_block(top_scope_, scope_, vmm->number_of_locals);

CallFrame* cf = (CallFrame*)alloca(sizeof(CallFrame) + (vmm->stack_size * sizeof(Object*)));
cf->setup(vmm->stack_size);

cf->is_block = true;
cf->previous = call_frame;
cf->name = (Symbol*)Qnil;
cf->cm = method_;
cf->args = args;
cf->scope = scope;
cf->top_scope = top_scope_;
cf->run = vmm->run;
cf->vmm = vmm;

// if(unlikely(task->profiler)) task->profiler->enter_block(state, home_, method_);

cf->push(val);
return cf->run(vmm, task, cf);
}

void BlockEnvironment::call(STATE, Task* task, Message& msg) {
Object* BlockEnvironment::call(STATE, Task* task, CallFrame* call_frame, Message& msg) {
Object* val;
if(msg.args() > 0) {
Tuple* tup = Tuple::create(state, msg.args());
Expand All @@ -68,62 +84,51 @@ namespace rubinius {
} else {
val = Qnil;
}
BlockContext* ctx = create_context(state, task->active());

if(unlikely(task->profiler)) task->profiler->enter_block(state, home_, method_);
VariableScope* scope = (VariableScope*)alloca(sizeof(VariableScope) +
(vmm->number_of_locals * sizeof(Object*)));

// HACK: manually clear the stack used as args.
task->active()->clear_stack(msg.stack);
scope->setup_as_block(top_scope_, scope_, vmm->number_of_locals);

task->make_active(ctx);
task->push(val);
ctx->run(ctx->vmm, task, ctx);
}
CallFrame* cf = (CallFrame*)alloca(sizeof(CallFrame) + (vmm->stack_size * sizeof(Object*)));
cf->setup(vmm->stack_size);

cf->is_block = true;
cf->previous = call_frame;
cf->name = (Symbol*)Qnil;
cf->cm = method_;
cf->args = msg.args();
cf->scope = scope;
cf->top_scope = top_scope_;
cf->run = vmm->run;
cf->vmm = vmm;

// TODO - Untested!!!!!!!!!!
ExecuteStatus BlockEnvironment::call_prim(STATE, Executable* exec, Task* task, Message& msg) {
call(state, task, msg);
return cExecuteRestart;
// if(unlikely(task->profiler)) task->profiler->enter_block(state, home_, method_);

cf->push(val);
return cf->run(vmm, task, cf);
}

/*
* Allocates a context, adjusting the initial stack pointer by the number of
* locals the method requires.
*/
BlockContext* BlockEnvironment::create_context(STATE, MethodContext* sender) {
BlockContext* ctx = BlockContext::create(state, method_->stack_size()->to_native());
ctx->sender(state, sender);
ctx->block(state, this);
ctx->cm(state, method_);
ctx->home(state, home_);

ctx->vmm = vmm ? vmm : method_->backend_method_;
ctx->run = ctx->vmm->run;

ctx->ip = 0;
// HACK dup'd from MethodContext
ctx->position_stack(method_->number_of_locals() - 1);

return ctx;
Object* BlockEnvironment::call_prim(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg) {
return call(state, task, call_frame, msg);
}

BlockEnvironment* BlockEnvironment::under_context(STATE, CompiledMethod* cm,
MethodContext* parent, MethodContext* active, size_t index) {
BlockEnvironment* BlockEnvironment::under_call_frame(STATE, CompiledMethod* cm,
CallFrame* call_frame, size_t index) {

BlockEnvironment* be = state->new_object<BlockEnvironment>(G(blokenv));


VMMethod* vmm;
if((vmm = active->vmm->blocks[index]) == NULL) {
if((vmm = call_frame->vmm->blocks[index]) == NULL) {
vmm = new VMMethod(state, cm);
if(active->vmm->type) {
vmm->specialize(state, active->vmm->type);
if(call_frame->vmm->type) {
vmm->specialize(state, call_frame->vmm->type);
}
active->vmm->blocks[index] = vmm;
call_frame->vmm->blocks[index] = vmm;
}

be->home(state, parent);
be->home_block(state, active);
be->scope(state, call_frame->scope);
be->top_scope(state, call_frame->top_scope);
be->method(state, cm);
be->local_count(state, cm->local_count());
be->vmm = vmm;
Expand All @@ -134,8 +139,8 @@ namespace rubinius {
BlockEnvironment* BlockEnvironment::dup(STATE) {
BlockEnvironment* be = state->new_object<BlockEnvironment>(G(blokenv));

be->home(state, home_);
be->home_block(state, home_block_);
be->scope(state, scope_);
be->top_scope(state, top_scope_);
be->method(state, method_);
be->local_count(state, local_count_);
be->vmm = this->vmm;
Expand All @@ -148,8 +153,8 @@ namespace rubinius {
BlockEnvironment* be = as<BlockEnvironment>(self);

class_header(state, self);
indent_attribute(++level, "home"); be->home()->show(state, level);
indent_attribute(level, "home_block"); be->home_block()->show(state, level);
//indent_attribute(++level, "scope"); be->scope()->show(state, level);
// indent_attribute(level, "top_scope"); be->top_scope()->show(state, level);
indent_attribute(level, "local_count"); be->local_count()->show(state, level);
indent_attribute(level, "method"); be->method()->show(state, level);
close_body(level);
Expand Down
21 changes: 11 additions & 10 deletions vm/builtin/block_environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

namespace rubinius {
class CompiledMethod;
class MethodContext;
class VariableScope;
class CallFrame;
class BlockContext;
class Message;
class VMMethod;
Expand All @@ -18,8 +19,8 @@ namespace rubinius {
const static object_type type = BlockEnvironmentType;

private:
MethodContext* home_; // slot
MethodContext* home_block_; // slot
VariableScope* scope_; // slot
VariableScope* top_scope_; // slot
Object* local_count_; // slot
CompiledMethod* method_; // slot

Expand All @@ -29,8 +30,8 @@ namespace rubinius {

public:
/* accessors */
attr_accessor(home, MethodContext);
attr_accessor(home_block, MethodContext);
attr_accessor(scope, VariableScope);
attr_accessor(top_scope, VariableScope);
attr_accessor(local_count, Object);
attr_accessor(method, CompiledMethod);

Expand All @@ -41,15 +42,15 @@ namespace rubinius {
// Ruby.primitive :blockenvironment_allocate
static BlockEnvironment* allocate(STATE);

static BlockEnvironment* under_context(STATE, CompiledMethod* cm,
MethodContext* parent, MethodContext* active, size_t index);
static BlockEnvironment* BlockEnvironment::under_call_frame(STATE, CompiledMethod* cm,
CallFrame* call_frame, size_t index);

void call(STATE, Task* task, size_t args);
void call(STATE, Task* task, Message& msg);
Object* call(STATE, Task* task, CallFrame* call_frame, size_t args);
Object* call(STATE, Task* task, CallFrame* call_frame, Message& msg);
BlockContext* create_context(STATE, MethodContext* sender);

// Ruby.primitive? :block_call
ExecuteStatus call_prim(STATE, Executable* exec, Task* task, Message& msg);
Object* call_prim(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg);

BlockEnvironment* dup(STATE);

Expand Down
9 changes: 4 additions & 5 deletions vm/builtin/block_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ namespace rubinius {
return wrapper;
}

void BlockWrapper::call(STATE, Task* task, size_t args) {
block_->call(state, task, args);
Object* BlockWrapper::call(STATE, Task* task, CallFrame* call_frame, size_t args) {
return block_->call(state, task, call_frame, args);
}

ExecuteStatus BlockWrapper::call_prim(STATE, Executable* exec, Task* task, Message& msg) {
block_->call(state, task, msg);
return cExecuteRestart;
Object* BlockWrapper::call_prim(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg) {
return block_->call(state, task, call_frame, msg);
}
}
4 changes: 2 additions & 2 deletions vm/builtin/block_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ namespace rubinius {
// Ruby.primitive :block_wrapper_allocate
static BlockWrapper* create(STATE, Object* self);

void call(STATE, Task* task, size_t args);
Object* call(STATE, Task* task, CallFrame* call_frame, size_t args);

// Ruby.primitive? :block_wrapper_call
ExecuteStatus call_prim(STATE, Executable* exec, Task* task, Message& msg);
Object* call_prim(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg);

// Ruby.primitive :block_wrapper_from_env
static BlockWrapper* from_env(STATE, BlockEnvironment* env);
Expand Down
21 changes: 6 additions & 15 deletions vm/builtin/channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,39 +53,30 @@ namespace rubinius {
* @todo The list management is iffy. Should probably just
* always assume it is a list. --rue
*/
ExecuteStatus Channel::receive_prim(STATE, Executable* exec, Task* task, Message& msg) {
Object* Channel::receive_prim(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg) {
Thread* current = state->globals.current_thread.get();

task->active()->clear_stack(msg.stack);

top:
// @todo check arity
if(!value_->nil_p()) {
List* list = as<List>(value_);

task->push(list->shift(state));
Object* ret = list->shift(state);

if(list->size() == 0) {
value(state, Qnil);
}

return cExecuteContinue;
return ret;
}

/* Saves space plus if thread woken forcibly, it gets the Qfalse. */
task->push(Qfalse);

current->sleep_for(state, this);
waiting_->append(state, current);

// Blocks?
state->check_events();

/* This sets the Task to continue from the next
* opcode when it eventually reactivates. Its
* stack will then have either the real received
* value or the default Qfalse if the thread
* was forced to stop waiting for us.
*/
return cExecuteRestart;
goto top;
}

Object* Channel::receive(STATE) {
Expand Down
2 changes: 1 addition & 1 deletion vm/builtin/channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ namespace rubinius {
Object* send(STATE, Object*);

// Ruby.primitive? :channel_receive
ExecuteStatus receive_prim(STATE, Executable* exec, Task* task, Message& msg);
Object* receive_prim(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg);

Object* receive(STATE);
bool has_readers_p();
Expand Down
8 changes: 4 additions & 4 deletions vm/builtin/compiledmethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ namespace rubinius {
return this;
}

ExecuteStatus CompiledMethod::default_executor(STATE, Task* task, Message& msg) {
Object* CompiledMethod::default_executor(STATE, CallFrame* call_frame, Task* task, Message& msg) {
CompiledMethod* cm = as<CompiledMethod>(msg.method);
cm->formalize(state, false);
return cm->execute(state, task, msg);
return cm->execute(state, call_frame, task, msg);
}

void CompiledMethod::post_marshal(STATE) {
Expand All @@ -121,7 +121,7 @@ namespace rubinius {
return local_count_->to_native();
}

ExecuteStatus CompiledMethod::activate(STATE, Executable* exec, Task* task, Message& msg) {
Object* CompiledMethod::activate(STATE, Executable* exec, CallFrame* call_frame, Task* task, Message& msg) {
CompiledMethod* meth = as<CompiledMethod>(msg.recv);
Object* recv = msg.get_argument(0);
Module* mod = as<Module>(msg.get_argument(1));
Expand All @@ -140,7 +140,7 @@ namespace rubinius {
// push the name given, because there really isn't one. So if
// this is used to call a method_missing, you have to supply all
// the args.
return meth->execute(state, task, msg);
return meth->execute(state, call_frame, task, msg);
}

MachineMethod* CompiledMethod::make_machine_method(STATE) {
Expand Down
Loading

0 comments on commit 77c68c4

Please sign in to comment.