Permalink
Browse files

Update C++ Argument objects with the GC. Fixes NASTY GC bug.

  • Loading branch information...
1 parent ea60df2 commit 50a4b8c6c80ef2a39eb34f479f16e78c18bd2182 Evan Phoenix committed Mar 30, 2010
View
@@ -66,9 +66,25 @@ namespace rubinius {
}
Object* Arguments::shift(STATE) {
- total_--;
Object* first = arguments_[0];
- arguments_++;
+
+ if(argument_container_) {
+ Tuple* tup = Tuple::create(state, total() - 1);
+ for(uint32_t i = 1; i < total_; i++) {
+ tup->put(state, i - 1, get_argument(i));
+ }
+
+ use_tuple(tup, total_ - 1);
+ } else {
+ total_--;
+ arguments_++;
+ }
+
return first;
}
+
+ void Arguments::update_argument_container(Tuple* tup) {
+ arguments_ = tup->field;
+ argument_container_ = tup;
+ }
}
View
@@ -8,38 +8,45 @@
namespace rubinius {
class Array;
+ class GarbageCollector;
+
class Arguments {
Object* recv_;
Object* block_;
uint32_t total_;
Object** arguments_;
+ Tuple* argument_container_;
public:
Arguments(Object* recv, Object* block, uint32_t total, Object** buffer)
: recv_(recv)
, block_(block)
, total_(total)
, arguments_(buffer)
+ , argument_container_(0)
{}
Arguments(Object* recv, uint32_t total, Object** buffer)
: recv_(recv)
, block_(Qnil)
, total_(total)
, arguments_(buffer)
+ , argument_container_(0)
{}
Arguments(uint32_t total, Object** buffer)
: recv_(0)
, block_(Qnil)
, total_(total)
, arguments_(buffer)
+ , argument_container_(0)
{}
Arguments()
: total_(0)
, arguments_(0)
+ , argument_container_(0)
{}
Arguments(Array* ary) {
@@ -66,18 +73,28 @@ namespace rubinius {
return arguments_[which];
}
+ Object** arguments() {
+ return arguments_;
+ }
+
+ Tuple* argument_container() {
+ return argument_container_;
+ }
+
+ void update_argument_container(Tuple* obj);
+
uint32_t total() {
return total_;
}
void use_array(Array* ary) {
- total_ = ary->size();
- arguments_ = ary->tuple()->field + ary->start()->to_native();
+ use_tuple(ary->tuple(), ary->size());
}
void use_tuple(Tuple* tup, int size) {
total_ = size;
arguments_ = tup->field;
+ argument_container_ = tup;
}
Array* as_array(STATE);
@@ -114,6 +114,7 @@ namespace rubinius {
frame->previous = previous;
frame->static_scope_ = invocation.static_scope;
+ frame->arguments = &args;
frame->dispatch_data = NULL;
frame->cm = env->method_;
frame->scope = scope;
@@ -133,12 +134,12 @@ namespace rubinius {
profiler::MethodEntry method(state,
env->top_scope_->method()->name(), mod, env->method_);
- return (*vmm->run)(state, vmm, frame, args);
+ return (*vmm->run)(state, vmm, frame);
} else {
- return (*vmm->run)(state, vmm, frame, args);
+ return (*vmm->run)(state, vmm, frame);
}
#else
- return (*vmm->run)(state, vmm, frame, args);
+ return (*vmm->run)(state, vmm, frame);
#endif
}
View
@@ -49,6 +49,8 @@ namespace rubinius {
VariableScope* top_scope_;
StackVariables* scope;
+ Arguments* arguments;
+
// Stack
Object* stk[];
View
@@ -1,5 +1,6 @@
#include "builtin/object.hpp"
#include "util/thread.hpp"
+#include "objectmemory.hpp"
#include "capi/capi.hpp"
#include "capi/ruby.h"
@@ -30,7 +31,14 @@ extern "C" {
}
void rb_gc() {
- // Ignore this. It's almost always a hack.
+ NativeMethodEnvironment* env = NativeMethodEnvironment::get();
+
+ // Normally ignore this. It's almost always a hack.
+ if(getenv("RBX_RESPECT_RB_GC")) {
+ env->state()->om->collect_young_now = true;
+ env->state()->om->collect_mature_now = true;
+ env->state()->interrupts.set_perform_gc();
+ }
}
void rb_gc_mark(VALUE ptr) {
View
@@ -17,6 +17,8 @@
#include "builtin/staticscope.hpp"
#include "capi/handle.hpp"
+#include "arguments.hpp"
+
#include "object_watch.hpp"
namespace rubinius {
@@ -153,6 +155,21 @@ namespace rubinius {
msg->method = (Executable*)mark_object(msg->method);
}
+ Arguments* args = call_frame->arguments;
+ if(!call_frame->inline_method_p() && args) {
+ args->set_recv(mark_object(args->recv()));
+ args->set_block(mark_object(args->block()));
+
+ if(Tuple* tup = args->argument_container()) {
+ args->update_argument_container((Tuple*)mark_object(tup));
+ } else {
+ Object** ary = args->arguments();
+ for(uint32_t i = 0; i < args->total(); i++) {
+ ary[i] = mark_object(ary[i]);
+ }
+ }
+ }
+
#ifdef ENABLE_LLVM
if(jit::RuntimeDataHolder* jd = call_frame->jit_data()) {
jd->set_mark();
@@ -231,6 +248,22 @@ namespace rubinius {
call_frame->top_scope_ = (VariableScope*)visit.call(call_frame->top_scope_);
}
+ if(Dispatch* msg = call_frame->dispatch()) {
+ msg->module = (Module*)visit.call(msg->module);
+ msg->method = (Executable*)visit.call(msg->method);
+ }
+
+ Arguments* args = call_frame->arguments;
+ if(!call_frame->inline_method_p() && args) {
+ args->set_recv(visit.call(args->recv()));
+ args->set_block(visit.call(args->block()));
+
+ Object** ary = args->arguments();
+ for(uint32_t i = 0; i < args->total(); i++) {
+ ary[i] = visit.call(ary[i]);
+ }
+ }
+
visit_variable_scope(call_frame, call_frame->scope, visit);
#ifdef ENABLE_LLVM
View
@@ -89,8 +89,7 @@ extern "C" {
Object* VMMethod::interpreter(STATE,
VMMethod* const vmm,
- InterpreterCallFrame* const call_frame,
- Arguments& args)
+ InterpreterCallFrame* const call_frame)
{
#include "vm/gen/instruction_locations.hpp"
@@ -236,7 +235,6 @@ Object* VMMethod::interpreter(STATE,
Object* VMMethod::uncommon_interpreter(STATE,
VMMethod* const vmm,
CallFrame* const call_frame,
- Arguments& args,
int32_t entry_ip,
native_int sp)
{
@@ -379,8 +377,7 @@ Object* VMMethod::uncommon_interpreter(STATE,
*/
Object* VMMethod::debugger_interpreter(STATE,
VMMethod* const vmm,
- InterpreterCallFrame* const call_frame,
- Arguments& args)
+ InterpreterCallFrame* const call_frame)
{
#include "vm/gen/instruction_locations.hpp"
View
@@ -554,7 +554,7 @@ end
# test onto the stack.
instruction passed_arg(index) [ -- boolean ]
- if(index < (int)args.total()) {
+ if(index < (int)call_frame->arguments->total()) {
stack_push(Qtrue);
} else {
stack_push(Qfalse);
@@ -1444,7 +1444,7 @@ end
# test onto the stack.
instruction passed_blockarg(count) [ -- boolean ]
- if(count == (int)args.total()) {
+ if(count == (int)call_frame->arguments->total()) {
stack_push(Qtrue);
} else {
stack_push(Qfalse);
@@ -1501,15 +1501,15 @@ end
# The result is then pushed onto the stack.
instruction cast_for_single_block_arg() [ -- argument ]
- int k = args.total();
+ int k = call_frame->arguments->total();
if(k == 0) {
stack_push(Qnil);
} else if(k == 1) {
- stack_push(args.get_argument(0));
+ stack_push(call_frame->arguments->get_argument(0));
} else {
Array* ary = Array::create(state, k);
for(int i = 0; i < k; i++) {
- ary->set(state, i, args.get_argument(i));
+ ary->set(state, i, call_frame->arguments->get_argument(i));
}
stack_push(ary);
}
@@ -1539,12 +1539,13 @@ end
instruction cast_for_multi_block_arg() [ -- array ]
/* If there is only one argument and that thing is an array... */
- if(args.total() == 1 && kind_of<Array>(args.get_argument(0))) {
- stack_push(args.get_argument(0));
+ if(call_frame->arguments->total() == 1 &&
+ kind_of<Array>(call_frame->arguments->get_argument(0))) {
+ stack_push(call_frame->arguments->get_argument(0));
} else {
- Array* ary = Array::create(state, args.total());
- for(size_t i = 0; i < args.total(); i++) {
- ary->set(state, i, args.get_argument(i));
+ Array* ary = Array::create(state, call_frame->arguments->total());
+ for(size_t i = 0; i < call_frame->arguments->total(); i++) {
+ ary->set(state, i, call_frame->arguments->get_argument(i));
}
stack_push(ary);
}
@@ -1578,9 +1579,9 @@ end
# The resulting array is then pushed back onto the stack.
instruction cast_for_splat_block_arg() [ -- arguments ]
- Array* ary = Array::create(state, args.total());
- for(size_t i = 0; i < args.total(); i++) {
- ary->set(state, i, args.get_argument(i));
+ Array* ary = Array::create(state, call_frame->arguments->total());
+ for(size_t i = 0; i < call_frame->arguments->total(); i++) {
+ ary->set(state, i, call_frame->arguments->get_argument(i));
}
stack_push(ary);
@@ -2397,7 +2398,7 @@ instruction zsuper(literal) [ block -- value ]
end
instruction push_block_arg() [ -- block ]
- stack_push(args.block());
+ stack_push(call_frame->arguments->block());
end
instruction push_undef() [ -- value ]
View
@@ -148,6 +148,9 @@ namespace jit {
b().CreateStore(ss, get_field(call_frame, offset::cf_static_scope));
+ // arguments
+ b().CreateStore(args, get_field(call_frame, offset::cf_arguments));
+
// msg
b().CreateStore(Constant::getNullValue(ls_->Int8PtrTy),
get_field(call_frame, offset::cf_msg));
View
@@ -373,6 +373,9 @@ namespace jit {
// previous
b().CreateStore(prev, get_field(call_frame, offset::cf_previous));
+ // arguments
+ b().CreateStore(args, get_field(call_frame, offset::cf_arguments));
+
// msg
b().CreateStore(
b().CreatePointerCast(msg, ls_->Int8PtrTy),
View
@@ -867,7 +867,7 @@ extern "C" {
self->set_table_ivar(state, name, val);
}
- Object* rbx_continue_uncommon(STATE, CallFrame* call_frame, Arguments& args,
+ Object* rbx_continue_uncommon(STATE, CallFrame* call_frame,
int32_t entry_ip, native_int sp)
{
LLVMState::get(state)->add_uncommons_taken();
@@ -906,7 +906,7 @@ extern "C" {
}
}
- return VMMethod::uncommon_interpreter(state, vmm, call_frame, args, entry_ip, sp);
+ return VMMethod::uncommon_interpreter(state, vmm, call_frame, entry_ip, sp);
}
Object* rbx_restart_interp(STATE, CallFrame* call_frame, Dispatch& msg, Arguments& args) {
Oops, something went wrong.

0 comments on commit 50a4b8c

Please sign in to comment.