Permalink
Browse files

Checkout. Add CallFrame

  • Loading branch information...
1 parent 4e76e69 commit 77c68c4b3d7d2170353ee9d5228a91a6568eec9c Evan Phoenix committed Feb 3, 2009
Showing with 916 additions and 627 deletions.
  1. +1 −0 rakelib/vm.rake
  2. +4 −6 vm/builtin/access_variable.cpp
  3. +1 −1 vm/builtin/access_variable.hpp
  4. +58 −53 vm/builtin/block_environment.cpp
  5. +11 −10 vm/builtin/block_environment.hpp
  6. +4 −5 vm/builtin/block_wrapper.cpp
  7. +2 −2 vm/builtin/block_wrapper.hpp
  8. +6 −15 vm/builtin/channel.cpp
  9. +1 −1 vm/builtin/channel.hpp
  10. +4 −4 vm/builtin/compiledmethod.cpp
  11. +2 −2 vm/builtin/compiledmethod.hpp
  12. +2 −0 vm/builtin/contexts.cpp
  13. +1 −9 vm/builtin/contexts.hpp
  14. +2 −2 vm/builtin/executable.cpp
  15. +1 −1 vm/builtin/executable.hpp
  16. +2 −2 vm/builtin/machine_method.cpp
  17. +1 −1 vm/builtin/machine_method.hpp
  18. +2 −4 vm/builtin/nativefunction.cpp
  19. +1 −1 vm/builtin/nativefunction.hpp
  20. +7 −4 vm/builtin/nativemethod.cpp
  21. +1 −1 vm/builtin/nativemethod.hpp
  22. +1 −1 vm/builtin/nativemethodcontext.cpp
  23. +5 −4 vm/builtin/object.cpp
  24. +1 −3 vm/builtin/object.hpp
  25. +10 −10 vm/builtin/sendsite.cpp
  26. +5 −5 vm/builtin/sendsite.hpp
  27. +50 −52 vm/builtin/task.cpp
  28. +12 −12 vm/builtin/task.hpp
  29. +53 −0 vm/builtin/variable_scope.cpp
  30. +82 −0 vm/builtin/variable_scope.hpp
  31. +96 −0 vm/call_frame.cpp
  32. +157 −0 vm/call_frame.hpp
  33. +9 −13 vm/codegen/field_extract.rb
  34. +1 −21 vm/codegen/instructions_gen.rb
  35. +6 −2 vm/compiled_file.cpp
  36. +3 −1 vm/executor.hpp
  37. +3 −1 vm/globals.hpp
  38. +203 −239 vm/instructions.rb
  39. +4 −0 vm/jit_state.h
  40. +29 −79 vm/llvm/instructions.cpp
  41. +0 −1 vm/message.cpp
  42. +11 −11 vm/message.hpp
  43. +2 −2 vm/primitives.cpp
  44. +1 −1 vm/primitives.hpp
  45. +14 −0 vm/unwind_info.hpp
  46. +36 −39 vm/vmmethod.cpp
  47. +8 −6 vm/vmmethod.hpp
View
@@ -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"
@@ -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. */
@@ -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;
}
}
@@ -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:
@@ -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());
@@ -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;
@@ -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;
@@ -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);
@@ -6,7 +6,8 @@
namespace rubinius {
class CompiledMethod;
- class MethodContext;
+ class VariableScope;
+ class CallFrame;
class BlockContext;
class Message;
class VMMethod;
@@ -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
@@ -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);
@@ -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);
@@ -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);
}
}
@@ -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);
View
@@ -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) {
View
@@ -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();
@@ -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) {
@@ -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));
@@ -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) {
Oops, something went wrong.

0 comments on commit 77c68c4

Please sign in to comment.