[macruby-changes] [1508] MacRuby/branches/experimental
source_changes at macosforge.org
source_changes at macosforge.org
Fri May 1 20:49:05 PDT 2009
Revision: 1508
http://trac.macosforge.org/projects/ruby/changeset/1508
Author: vincent.isambart at gmail.com
Date: 2009-05-01 20:49:04 -0700 (Fri, 01 May 2009)
Log Message:
-----------
First version of code that save local variables in the heap if they can be used later.
It's far from being finished, but it's still a good start.
Modified Paths:
--------------
MacRuby/branches/experimental/gc.c
MacRuby/branches/experimental/proc.c
MacRuby/branches/experimental/roxor.cpp
MacRuby/branches/experimental/roxor.h
MacRuby/branches/experimental/vm_eval.c
Modified: MacRuby/branches/experimental/gc.c
===================================================================
--- MacRuby/branches/experimental/gc.c 2009-04-30 23:06:00 UTC (rev 1507)
+++ MacRuby/branches/experimental/gc.c 2009-05-02 03:49:04 UTC (rev 1508)
@@ -239,6 +239,19 @@
VALUE rb_mGC;
void
+rb_gc_assign_weak_ref(const void *value, void *const*location)
+{
+ auto_assign_weak_reference(__auto_zone, value, location, NULL);
+}
+
+void*
+rb_gc_read_weak_ref(void **referrer)
+{
+ return auto_read_weak_reference(__auto_zone, referrer);
+}
+
+
+void
rb_objc_wb(void *dst, void *newval)
{
if (!SPECIAL_CONST_P(newval)) {
Modified: MacRuby/branches/experimental/proc.c
===================================================================
--- MacRuby/branches/experimental/proc.c 2009-04-30 23:06:00 UTC (rev 1507)
+++ MacRuby/branches/experimental/proc.c 2009-05-02 03:49:04 UTC (rev 1508)
@@ -34,12 +34,28 @@
return obj;
}
+void rb_gc_assign_weak_ref(const void *value, void *const*location);
+
VALUE
rb_proc_alloc_with_block(VALUE klass, rb_vm_block_t *proc)
{
VALUE obj;
obj = Data_Wrap_Struct(klass, NULL, NULL, proc);
- proc->flags |= VM_BLOCK_PROC;
+ if (!(proc->flags & VM_BLOCK_PROC)) {
+ proc->flags |= VM_BLOCK_PROC;
+ if (proc->parent_lvar_uses != NULL) {
+ rb_vm_lvar_uses_t** parent_lvar_uses = proc->parent_lvar_uses;
+ if ((*parent_lvar_uses == NULL) || ((*parent_lvar_uses)->uses_count == VM_LVAR_USES_SIZE)) {
+ rb_vm_lvar_uses_t* new_uses = malloc(sizeof(rb_vm_lvar_uses_t));
+ new_uses->next = *parent_lvar_uses;
+ new_uses->uses_count = 0;
+ *parent_lvar_uses = new_uses;
+ }
+ int current_index = (*parent_lvar_uses)->uses_count;
+ rb_gc_assign_weak_ref(proc, &(*parent_lvar_uses)->uses[current_index]);
+ ++(*parent_lvar_uses)->uses_count;
+ }
+ }
return obj;
}
Modified: MacRuby/branches/experimental/roxor.cpp
===================================================================
--- MacRuby/branches/experimental/roxor.cpp 2009-04-30 23:06:00 UTC (rev 1507)
+++ MacRuby/branches/experimental/roxor.cpp 2009-05-02 03:49:04 UTC (rev 1508)
@@ -231,6 +231,7 @@
ID self_id;
Value *current_self;
bool current_block;
+ Value *current_lvar_uses;
BasicBlock *begin_bb;
BasicBlock *rescue_bb;
BasicBlock *ensure_bb;
@@ -279,6 +280,7 @@
Function *newRangeFunc;
Function *newRegexpFunc;
Function *strInternFunc;
+ Function *keepVarsFunc;
Function *masgnGetElemBeforeSplatFunc;
Function *masgnGetElemAfterSplatFunc;
Function *masgnGetSplatFunc;
@@ -324,6 +326,13 @@
: new IntToPtrInst(ptrint, PtrTy, "");
}
+ Instruction *compile_const_pointer_to_pointer(void *ptr, bool insert_to_bb=true) {
+ Value *ptrint = ConstantInt::get(IntTy, (long)ptr);
+ return insert_to_bb
+ ? new IntToPtrInst(ptrint, PtrPtrTy, "", bb)
+ : new IntToPtrInst(ptrint, PtrPtrTy, "");
+ }
+
Value *compile_protected_call(Function *func, std::vector<Value *> ¶ms);
void compile_dispatch_arguments(NODE *args, std::vector<Value *> &arguments, int *pargc);
Function::ArgumentListType::iterator
@@ -660,6 +669,7 @@
current_instance_method = false;
self_id = rb_intern("self");
current_self = NULL;
+ current_lvar_uses = NULL;
current_block = false;
current_block_node = NULL;
current_block_func = NULL;
@@ -706,6 +716,7 @@
newRangeFunc = NULL;
newRegexpFunc = NULL;
strInternFunc = NULL;
+ keepVarsFunc = NULL;
masgnGetElemBeforeSplatFunc = NULL;
masgnGetElemAfterSplatFunc = NULL;
masgnGetSplatFunc = NULL;
@@ -1226,11 +1237,13 @@
if (prepareBlockFunc == NULL) {
// void *rb_vm_prepare_block(Function *func, NODE *node, VALUE self,
+ // rb_vm_lvar_uses_t **parent_lvar_uses,
// int dvars_size, ...);
std::vector<const Type *> types;
types.push_back(PtrTy);
types.push_back(PtrTy);
types.push_back(RubyObjTy);
+ types.push_back(PtrPtrTy);
types.push_back(Type::Int32Ty);
FunctionType *ft = FunctionType::get(PtrTy, types, true);
prepareBlockFunc = cast<Function>
@@ -1241,6 +1254,12 @@
params.push_back(compile_const_pointer(current_block_func));
params.push_back(compile_const_pointer(current_block_node));
params.push_back(current_self);
+ if (current_lvar_uses == NULL) {
+ params.push_back(compile_const_pointer_to_pointer(NULL));
+ }
+ else {
+ params.push_back(current_lvar_uses);
+ }
// Dvars.
params.push_back(ConstantInt::get(Type::Int32Ty, (int)dvars.size()));
@@ -2984,7 +3003,15 @@
dvars_arg->setName("dvars");
}
- if (node->nd_tbl != NULL) {
+ Value *old_current_lvar_uses = current_lvar_uses;
+
+ if (node->nd_tbl == NULL) {
+ current_lvar_uses = NULL;
+ }
+ else {
+ current_lvar_uses = new AllocaInst(PtrTy, "", bb);
+ new StoreInst(compile_const_pointer(NULL), current_lvar_uses, bb);
+
int i, args_count = (int)node->nd_tbl[0];
assert(args_count == nargs
|| args_count == nargs + 1 /* optional block */
@@ -3087,6 +3114,39 @@
if (val == NULL) {
val = nilVal;
}
+
+ // current_lvar_uses has 2 uses or more if it is really used
+ // (there is always a StoreInst in which we assign it NULL)
+ if (current_lvar_uses != NULL && current_lvar_uses->hasNUsesOrMore(2)) {
+ // TODO: only call the function is current_use is not NULL
+ if (keepVarsFunc == NULL) {
+ // void rb_vm_keep_vars(rb_vm_lvar_uses_t *uses, int lvars_size, ...);
+ std::vector<const Type *> types;
+ types.push_back(PtrTy);
+ types.push_back(Type::Int32Ty);
+ FunctionType *ft = FunctionType::get(Type::VoidTy, types, true);
+ keepVarsFunc = cast<Function>
+ (module->getOrInsertFunction("rb_vm_keep_vars", ft));
+ }
+
+ std::vector<Value *> params;
+
+ params.push_back(new LoadInst(current_lvar_uses, "", bb));
+
+ params.push_back(ConstantInt::get(Type::Int32Ty, (int)lvars.size()));
+ for (std::map<ID, Value *>::iterator iter = lvars.begin();
+ iter != lvars.end(); ++iter) {
+ ID name = iter->first;
+ Value *slot = iter->second;
+ if (std::find(dvars.begin(), dvars.end(), name) == dvars.end()) {
+ params.push_back(ConstantInt::get(IntTy, (long)name));
+ params.push_back(slot);
+ }
+ }
+
+ CallInst::Create(keepVarsFunc, params.begin(), params.end(), "", bb);
+ }
+
ReturnInst::Create(val, bb);
bb = old_bb;
@@ -3094,6 +3154,7 @@
lvars = old_lvars;
current_self = old_self;
rescue_bb = old_rescue_bb;
+ current_lvar_uses = old_current_lvar_uses;
return cast<Value>(f);
}
@@ -7681,7 +7742,7 @@
extern "C"
rb_vm_block_t *
-rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self,
+rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self, rb_vm_lvar_uses_t **parent_lvar_uses,
int dvars_size, ...)
{
NODE *cache_key;
@@ -7716,6 +7777,7 @@
}
b->flags = 0;
b->dvars_size = dvars_size;
+ b->parent_lvar_uses = NULL;
rb_objc_retain(b);
GET_VM()->blocks[cache_key] = b;
@@ -7728,6 +7790,7 @@
b->self = self;
b->node = node;
+ b->parent_lvar_uses = parent_lvar_uses;
va_list ar;
va_start(ar, dvars_size);
@@ -7757,7 +7820,72 @@
}
extern "C"
+void*
+rb_gc_read_weak_ref(void **referrer);
+
+struct rb_vm_kept_local {
+ ID name;
+ VALUE *stack_address;
+ VALUE *new_address;
+};
+
+extern "C"
void
+rb_vm_keep_vars(rb_vm_lvar_uses_t *uses, int lvars_size, ...)
+{
+ rb_vm_lvar_uses_t *current = uses;
+ int use_index;
+
+ while (current != NULL) {
+ for (use_index = 0; use_index < current->uses_count; ++use_index) {
+ if (rb_gc_read_weak_ref(¤t->uses[use_index]) != NULL) {
+ goto use_found;
+ }
+ }
+
+ void *old_current = current;
+ current = current->next;
+ free(old_current);
+ }
+ // no use still alive so nothing to do
+ return;
+
+use_found:
+ rb_vm_kept_local *locals = (rb_vm_kept_local *)alloca(sizeof(rb_vm_kept_local)*lvars_size);
+
+ va_list ar;
+ va_start(ar, lvars_size);
+ for (int i = 0; i < lvars_size; ++i) {
+ locals[i].name = va_arg(ar, ID);
+ locals[i].stack_address = va_arg(ar, VALUE *);
+ locals[i].new_address = (VALUE *)xmalloc(sizeof(VALUE));
+ GC_WB(locals[i].new_address, *locals[i].stack_address);
+ }
+ va_end(ar);
+
+ while (current != NULL) {
+ for (; use_index < current->uses_count; ++use_index) {
+ rb_vm_block_t *block = (rb_vm_block_t *)rb_gc_read_weak_ref(¤t->uses[use_index]);
+ if (block != NULL) {
+ for (int dvar_index=0; dvar_index<block->dvars_size; ++dvar_index) {
+ for (int lvar_index=0; lvar_index<lvars_size; ++lvar_index) {
+ if (block->dvars[dvar_index] == locals[lvar_index].stack_address) {
+ GC_WB(&block->dvars[dvar_index], locals[lvar_index].new_address);
+ break;
+ }
+ }
+ }
+ }
+ }
+ void *old_current = current;
+ current = current->next;
+ use_index = 0;
+ free(old_current);
+ }
+}
+
+extern "C"
+void
rb_vm_push_binding(VALUE self, int lvars_size, ...)
{
rb_vm_binding_t *b = (rb_vm_binding_t *)xmalloc(sizeof(rb_vm_binding_t));
Modified: MacRuby/branches/experimental/roxor.h
===================================================================
--- MacRuby/branches/experimental/roxor.h 2009-04-30 23:06:00 UTC (rev 1507)
+++ MacRuby/branches/experimental/roxor.h 2009-05-02 03:49:04 UTC (rev 1508)
@@ -19,6 +19,13 @@
};
typedef struct rb_vm_local rb_vm_local_t;
+#define VM_LVAR_USES_SIZE 128
+typedef struct rb_vm_lvar_uses {
+ int uses_count;
+ void *uses[VM_LVAR_USES_SIZE];
+ struct rb_vm_lvar_uses *next;
+} rb_vm_lvar_uses_t;
+
#define VM_BLOCK_PROC 0x0001 // block is a Proc object
#define VM_BLOCK_LAMBDA 0x0002 // block is a lambda
#define VM_BLOCK_ACTIVE 0x0004 // block is active (being executed)
@@ -30,6 +37,7 @@
IMP imp;
int flags;
rb_vm_local_t *locals;
+ rb_vm_lvar_uses_t **parent_lvar_uses;
int dvars_size;
VALUE *dvars[1];
} rb_vm_block_t;
@@ -139,7 +147,8 @@
return (rb_vm_block_t *)DATA_PTR(proc);
}
-rb_vm_block_t *rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self, int dvars_size, ...);
+rb_vm_block_t *rb_vm_prepare_block(void *llvm_function, NODE *node, VALUE self,
+ rb_vm_lvar_uses_t **parent_lvar_uses, int dvars_size, ...);
rb_vm_block_t *rb_vm_current_block(void);
bool rb_vm_block_saved(void);
void rb_vm_change_current_block(rb_vm_block_t *block);
Modified: MacRuby/branches/experimental/vm_eval.c
===================================================================
--- MacRuby/branches/experimental/vm_eval.c 2009-04-30 23:06:00 UTC (rev 1507)
+++ MacRuby/branches/experimental/vm_eval.c 2009-05-02 03:49:04 UTC (rev 1508)
@@ -277,7 +277,7 @@
VALUE (*bl_proc) (ANYARGS), VALUE data2)
{
NODE *node = NEW_IFUNC(bl_proc, data2);
- rb_vm_block_t *b = rb_vm_prepare_block(NULL, node, obj, 0, 0);
+ rb_vm_block_t *b = rb_vm_prepare_block(NULL, node, obj, NULL, 0, 0);
rb_vm_change_current_block(b);
if (cache == NULL) {
cache = rb_vm_get_call_cache(sel);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20090501/bc4523f0/attachment-0001.html>
More information about the macruby-changes
mailing list