<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[1970] MacRuby/branches/experimental</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.macosforge.org/projects/ruby/changeset/1970">1970</a></dd>
<dt>Author</dt> <dd>lsansonetti@apple.com</dd>
<dt>Date</dt> <dd>2009-07-01 22:14:36 -0700 (Wed, 01 Jul 2009)</dd>
</dl>
<h3>Log Message</h3>
<pre>AOT compiler: ivar slots support</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#MacRubybranchesexperimentalcompilercpp">MacRuby/branches/experimental/compiler.cpp</a></li>
<li><a href="#MacRubybranchesexperimentalcompilerh">MacRuby/branches/experimental/compiler.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="MacRubybranchesexperimentalcompilercpp"></a>
<div class="modfile"><h4>Modified: MacRuby/branches/experimental/compiler.cpp (1969 => 1970)</h4>
<pre class="diff"><span>
<span class="info">--- MacRuby/branches/experimental/compiler.cpp        2009-07-02 01:31:22 UTC (rev 1969)
+++ MacRuby/branches/experimental/compiler.cpp        2009-07-02 05:14:36 UTC (rev 1970)
</span><span class="lines">@@ -136,6 +136,7 @@
</span><span class="cx"> cObject = ConstantInt::get(RubyObjTy, (long)rb_cObject);
</span><span class="cx"> PtrTy = PointerType::getUnqual(Type::Int8Ty);
</span><span class="cx"> PtrPtrTy = PointerType::getUnqual(PtrTy);
</span><ins>+ Int32PtrTy = PointerType::getUnqual(Type::Int32Ty);
</ins><span class="cx">
</span><span class="cx"> #if ROXOR_COMPILER_DEBUG
</span><span class="cx"> level = 0;
</span><span class="lines">@@ -933,23 +934,72 @@
</span><span class="cx">          "", bb);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+Instruction *
+RoxorCompiler::gen_slot_cache(ID id)
+{
+ int *slot = (int *)malloc(sizeof(int));
+ *slot = -1;
+ return compile_const_pointer(slot, Int32PtrTy, false);
+}
+
+Instruction *
+RoxorAOTCompiler::gen_slot_cache(ID id)
+{
+ GlobalVariable *gvar = new GlobalVariable(
+         Int32PtrTy,
+         false,
+         GlobalValue::InternalLinkage,
+         Constant::getNullValue(Int32PtrTy),
+         rb_id2name(id),
+         RoxorCompiler::module);
+
+ ivar_slots.push_back(gvar);
+
+ return new LoadInst(gvar, "");
+}
+
+Instruction *
+RoxorCompiler::compile_slot_cache(ID id)
+{
+ if (inside_eval || current_block || !current_instance_method
+        || current_module) {
+        return compile_const_pointer(NULL, Int32PtrTy);
+ }
+
+ std::map<ID, Instruction *>::iterator iter = ivar_slots_cache.find(id);
+ Instruction *slot;
+ if (iter == ivar_slots_cache.end()) {
+#if ROXOR_COMPILER_DEBUG
+        printf("allocating a new slot for ivar %s\n", rb_id2name(id));
+#endif
+        slot = gen_slot_cache(id);
+        ivar_slots_cache[id] = slot;
+ }
+ else {
+        slot = iter->second;
+ }
+
+ Instruction *insn = slot->clone();
+ BasicBlock::InstListType &list = bb->getInstList();
+ list.insert(list.end(), insn);
+ return insn;
+}
+
</ins><span class="cx"> Value *
</span><span class="cx"> RoxorCompiler::compile_ivar_read(ID vid)
</span><span class="cx"> {
</span><span class="cx"> if (getIvarFunc == NULL) {
</span><del>-        // VALUE rb_vm_ivar_get(VALUE obj, ID name, void *slot_cache);
</del><ins>+        // VALUE rb_vm_ivar_get(VALUE obj, ID name, int *slot_cache);
</ins><span class="cx">         getIvarFunc = cast<Function>(module->getOrInsertFunction("rb_vm_ivar_get",
</span><del>-                 RubyObjTy, RubyObjTy, IntTy, PtrTy, NULL));
</del><ins>+                 RubyObjTy, RubyObjTy, IntTy, Int32PtrTy, NULL));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> std::vector<Value *> params;
</span><span class="cx">
</span><span class="cx"> params.push_back(current_self);
</span><span class="cx"> params.push_back(compile_id(vid));
</span><ins>+ params.push_back(compile_slot_cache(vid));
</ins><span class="cx">
</span><del>- int *slot_cache = get_slot_cache(vid);
- params.push_back(compile_const_pointer(slot_cache));
-
</del><span class="cx"> return CallInst::Create(getIvarFunc, params.begin(), params.end(), "", bb);
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -960,7 +1010,7 @@
</span><span class="cx">         // void rb_vm_ivar_set(VALUE obj, ID name, VALUE val, int *slot_cache);
</span><span class="cx">         setIvarFunc =
</span><span class="cx">          cast<Function>(module->getOrInsertFunction("rb_vm_ivar_set",
</span><del>-                        Type::VoidTy, RubyObjTy, IntTy, RubyObjTy, PtrTy,
</del><ins>+                        Type::VoidTy, RubyObjTy, IntTy, RubyObjTy, Int32PtrTy,
</ins><span class="cx">                         NULL));
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -969,10 +1019,8 @@
</span><span class="cx"> params.push_back(current_self);
</span><span class="cx"> params.push_back(compile_id(vid));
</span><span class="cx"> params.push_back(val);
</span><ins>+ params.push_back(compile_slot_cache(vid));
</ins><span class="cx">
</span><del>- int *slot_cache = get_slot_cache(vid);
- params.push_back(compile_const_pointer(slot_cache));
-
</del><span class="cx"> CallInst::Create(setIvarFunc, params.begin(), params.end(), "", bb);
</span><span class="cx">
</span><span class="cx"> return val;
</span><span class="lines">@@ -2347,27 +2395,41 @@
</span><span class="cx">
</span><span class="cx"> void
</span><span class="cx"> RoxorCompiler::compile_ivar_slots(Value *klass,
</span><del>-                                 BasicBlock::InstListType &list,
-                                 BasicBlock::InstListType::iterator list_iter)
</del><ins>+        BasicBlock::InstListType &list,
+        BasicBlock::InstListType::iterator list_iter)
</ins><span class="cx"> {
</span><span class="cx"> if (ivar_slots_cache.size() > 0) {
</span><span class="cx">         if (prepareIvarSlotFunc == NULL) {
</span><del>-         // void rb_vm_prepare_class_ivar_slot(VALUE klass, ID name, int *slot_cache);
</del><ins>+         // void rb_vm_prepare_class_ivar_slot(VALUE klass, ID name,
+         //                 int *slot_cache);
</ins><span class="cx">          prepareIvarSlotFunc = cast<Function>(
</span><del>-                 module->getOrInsertFunction("rb_vm_prepare_class_ivar_slot",
-                        Type::VoidTy, RubyObjTy, IntTy, PtrTy, NULL));
</del><ins>+                 module->getOrInsertFunction(
+                        "rb_vm_prepare_class_ivar_slot",
+                        Type::VoidTy, RubyObjTy, IntTy, Int32PtrTy, NULL));
</ins><span class="cx">         }
</span><del>-        for (std::map<ID, int *>::iterator iter = ivar_slots_cache.begin();
-                iter != ivar_slots_cache.end();
-                ++iter) {
</del><ins>+        for (std::map<ID, Instruction *>::iterator iter
+                = ivar_slots_cache.begin();
+         iter != ivar_slots_cache.end();
+         ++iter) {
</ins><span class="cx">
</span><ins>+         ID ivar_name = iter->first;
+         Instruction *ivar_slot = iter->second;
</ins><span class="cx">          std::vector<Value *> params;
</span><ins>+
</ins><span class="cx">          params.push_back(klass);
</span><del>-         params.push_back(compile_id(iter->first));
-         Instruction *ptr = compile_const_pointer(iter->second, false);
-         list.insert(list_iter, ptr);
-         params.push_back(ptr);
</del><span class="cx">
</span><ins>+         Value *id_val = compile_id(ivar_name);
+         if (Instruction::classof(id_val)) {
+                Instruction *insn = cast<Instruction>(id_val);
+                insn->removeFromParent();
+                list.insert(list_iter, insn);
+         }
+         params.push_back(id_val);
+
+         Instruction *insn = ivar_slot->clone();
+         list.insert(list_iter, insn);
+         params.push_back(insn);
+
</ins><span class="cx">          CallInst *call = CallInst::Create(prepareIvarSlotFunc,
</span><span class="cx">                  params.begin(), params.end(), "");
</span><span class="cx">
</span><span class="lines">@@ -2509,7 +2571,6 @@
</span><span class="cx">
</span><span class="cx">                  if (has_vars_to_save) {
</span><span class="cx">                         current_var_uses = new AllocaInst(PtrTy, "", bb);
</span><del>-                        //current_var_uses = new MallocInst(PtrTy, "", bb);
</del><span class="cx">                         new StoreInst(compile_const_pointer(NULL), current_var_uses, bb);
</span><span class="cx">                  }
</span><span class="cx">
</span><span class="lines">@@ -2597,8 +2658,8 @@
</span><span class="cx">                          ++inst_it) {
</span><span class="cx">                          if (dyn_cast<ReturnInst>(inst_it)) {
</span><span class="cx">                                 if (params.empty()) {
</span><del>-                                 params.push_back(new LoadInst(current_var_uses, "", inst_it));
-                                 params.push_back(NULL); // filled right after.
</del><ins>+                                 params.push_back(NULL);
+                                 params.push_back(NULL);
</ins><span class="cx">                                  int vars_count = 0;
</span><span class="cx">                                  for (std::map<ID, Value *>::iterator iter = lvars.begin();
</span><span class="cx">                                          iter != lvars.end(); ++iter) {
</span><span class="lines">@@ -2617,6 +2678,8 @@
</span><span class="cx">                                  params[1] = ConstantInt::get(Type::Int32Ty, vars_count);
</span><span class="cx">                                 }
</span><span class="cx">
</span><ins>+                                params[0] = new LoadInst(current_var_uses, "", inst_it);
+
</ins><span class="cx">                                 // TODO: only call the function if current_use is not NULL
</span><span class="cx">                                 CallInst::Create(keepVarsFunc, params.begin(), params.end(), "",
</span><span class="cx">                                         inst_it);
</span><span class="lines">@@ -3206,7 +3269,8 @@
</span><span class="cx">
</span><span class="cx">                         bool old_current_module = current_module;
</span><span class="cx">
</span><del>-                        std::map<ID, int *> old_ivar_slots_cache = ivar_slots_cache;
</del><ins>+                        std::map<ID, Instruction *> old_ivar_slots_cache
+                         = ivar_slots_cache;
</ins><span class="cx">                         ivar_slots_cache.clear();
</span><span class="cx">
</span><span class="cx">                         new StoreInst(classVal, current_opened_class, bb);
</span><span class="lines">@@ -4337,10 +4401,15 @@
</span><span class="cx"> Function *
</span><span class="cx"> RoxorAOTCompiler::compile_main_function(NODE *node)
</span><span class="cx"> {
</span><del>- Function *function = RoxorCompiler::compile_main_function(node);
</del><ins>+ current_instance_method = true;
</ins><span class="cx">
</span><ins>+ Value *val = compile_node(node);
+ assert(Function::classof(val));
+ Function *function = cast<Function>(val);
+
</ins><span class="cx"> BasicBlock::InstListType &list =
</span><span class="cx">         function->getEntryBlock().getInstList();
</span><ins>+ bb = &function->getEntryBlock();
</ins><span class="cx">
</span><span class="cx"> // Compile method caches.
</span><span class="cx">
</span><span class="lines">@@ -4501,6 +4570,48 @@
</span><span class="cx">         list.insert(list.begin(), load);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+ // Compile ivar slots.
+
+ if (!ivar_slots_cache.empty()) {
+        GlobalVariable *toplevel = compile_const_global_string("TopLevel");
+
+        std::vector<Value *> idxs;
+        idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+        idxs.push_back(ConstantInt::get(Type::Int32Ty, 0));
+        Instruction *load = GetElementPtrInst::Create(toplevel,
+                idxs.begin(), idxs.end(), "");
+
+        std::vector<Value *> params;
+        params.push_back(load);
+
+        Instruction *call = CallInst::Create(objcGetClassFunc, params.begin(),
+                params.end(), "");
+
+        compile_ivar_slots(call, list, list.begin());
+        ivar_slots_cache.clear();
+
+        list.insert(list.begin(), call);
+        list.insert(list.begin(), load);
+ }
+
+ for (std::vector<GlobalVariable *>::iterator i = ivar_slots.begin();
+         i != ivar_slots.end();
+         ++i) {
+
+        GlobalVariable *gvar = *i;
+
+        Instruction *call = new MallocInst(Type::Int32Ty, "");
+        Instruction *assign1 =
+         new StoreInst(ConstantInt::get(Type::Int32Ty, -1), call, "");
+        Instruction *assign2 = new StoreInst(call, gvar, "");
+
+        list.insert(list.begin(), assign2);
+        list.insert(list.begin(), assign1);
+        list.insert(list.begin(), call);
+ }
+
+ bb = NULL;
+
</ins><span class="cx"> return function;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="MacRubybranchesexperimentalcompilerh"></a>
<div class="modfile"><h4>Modified: MacRuby/branches/experimental/compiler.h (1969 => 1970)</h4>
<pre class="diff"><span>
<span class="info">--- MacRuby/branches/experimental/compiler.h        2009-07-02 01:31:22 UTC (rev 1969)
+++ MacRuby/branches/experimental/compiler.h        2009-07-02 05:14:36 UTC (rev 1970)
</span><span class="lines">@@ -59,7 +59,7 @@
</span><span class="cx">
</span><span class="cx">         std::map<ID, Value *> lvars;
</span><span class="cx">         std::vector<ID> dvars;
</span><del>-        std::map<ID, int *> ivar_slots_cache;
</del><ins>+        std::map<ID, Instruction *> ivar_slots_cache;
</ins><span class="cx">         std::map<std::string, GlobalVariable *> static_strings;
</span><span class="cx">
</span><span class="cx"> #if ROXOR_COMPILER_DEBUG
</span><span class="lines">@@ -165,23 +165,25 @@
</span><span class="cx">         const Type *PtrTy;
</span><span class="cx">         const Type *PtrPtrTy;
</span><span class="cx">         const Type *IntTy;
</span><ins>+        const Type *Int32PtrTy;
</ins><span class="cx">
</span><span class="cx">         void compile_node_error(const char *msg, NODE *node);
</span><span class="cx">
</span><span class="cx">         virtual Instruction *
</span><del>-        compile_const_pointer(void *ptr, bool insert_to_bb=true) {
</del><ins>+        compile_const_pointer(void *ptr, const Type *type=NULL,
+                bool insert_to_bb=true) {
</ins><span class="cx">          Value *ptrint = ConstantInt::get(IntTy, (long)ptr);
</span><ins>+         if (type == NULL) {
+                type = PtrTy;
+         }
</ins><span class="cx">          return insert_to_bb
</span><del>-                ? new IntToPtrInst(ptrint, PtrTy, "", bb)
-                : new IntToPtrInst(ptrint, PtrTy, "");
</del><ins>+                ? new IntToPtrInst(ptrint, type, "", bb)
+                : new IntToPtrInst(ptrint, type, "");
</ins><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         Instruction *
</span><span class="cx"> compile_const_pointer_to_pointer(void *ptr, bool insert_to_bb=true) {
</span><del>-         Value *ptrint = ConstantInt::get(IntTy, (long)ptr);
-         return insert_to_bb
-                ? new IntToPtrInst(ptrint, PtrPtrTy, "", bb)
-                : new IntToPtrInst(ptrint, PtrPtrTy, "");
</del><ins>+         return compile_const_pointer(ptr, PtrPtrTy, insert_to_bb);
</ins><span class="cx">         }
</span><span class="cx">
</span><span class="cx">         Value *compile_protected_call(Function *func,
</span><span class="lines">@@ -227,7 +229,7 @@
</span><span class="cx">         virtual Value *compile_mcache(SEL sel, bool super);
</span><span class="cx">         virtual Value *compile_ccache(ID id);
</span><span class="cx">         virtual Instruction *compile_sel(SEL sel, bool add_to_bb=true) {
</span><del>-         return compile_const_pointer(sel, add_to_bb);
</del><ins>+         return compile_const_pointer(sel, PtrTy, add_to_bb);
</ins><span class="cx">         }
</span><span class="cx">         virtual Value *compile_id(ID id);
</span><span class="cx">         GlobalVariable *compile_const_global_string(const char *str);
</span><span class="lines">@@ -255,24 +257,8 @@
</span><span class="cx">         Value *compile_conversion_to_ruby(const char *type,
</span><span class="cx">                                          const Type *llvm_type, Value *val);
</span><span class="cx">
</span><del>-        int *get_slot_cache(ID id) {
-         if (inside_eval || current_block || !current_instance_method
-                || current_module) {
-                return NULL;
-         }
-         std::map<ID, int *>::iterator iter = ivar_slots_cache.find(id);
-         if (iter == ivar_slots_cache.end()) {
-#if ROXOR_COMPILER_DEBUG
-                printf("allocating a new slot for ivar %s\n", rb_id2name(id));
-#endif
-                int *slot = (int *)malloc(sizeof(int));
-                *slot = -1;
-                ivar_slots_cache[id] = slot;
-                return slot;
-         }
-         return iter->second;
-        }
-
</del><ins>+        Instruction *compile_slot_cache(ID id);
+        virtual Instruction *gen_slot_cache(ID id);
</ins><span class="cx">         ICmpInst *is_value_a_fixnum(Value *val);
</span><span class="cx">         void compile_ivar_slots(Value *klass, BasicBlock::InstListType &list,
</span><span class="cx">                                 BasicBlock::InstListType::iterator iter);
</span><span class="lines">@@ -296,6 +282,7 @@
</span><span class="cx">         std::map<ID, GlobalVariable *> ccaches;
</span><span class="cx">         std::map<SEL, GlobalVariable *> sels;
</span><span class="cx">         std::map<ID, GlobalVariable *> ids;
</span><ins>+        std::vector<GlobalVariable *> ivar_slots;
</ins><span class="cx">         GlobalVariable *cObject_gvar;
</span><span class="cx">
</span><span class="cx">         Value *compile_mcache(SEL sel, bool super);
</span><span class="lines">@@ -307,10 +294,14 @@
</span><span class="cx">         Value *compile_nsobject(void);
</span><span class="cx">         Value *compile_id(ID id);
</span><span class="cx">
</span><ins>+        Instruction *gen_slot_cache(ID id);
+
</ins><span class="cx">         Instruction *
</span><del>- compile_const_pointer(void *ptr, bool insert_to_bb=true) {
</del><ins>+ compile_const_pointer(void *ptr, const Type *type=NULL,
+                bool insert_to_bb=true) {
</ins><span class="cx">          if (ptr == NULL) {
</span><del>-                return RoxorCompiler::compile_const_pointer(ptr, insert_to_bb);
</del><ins>+                return RoxorCompiler::compile_const_pointer(ptr, type,
+                        insert_to_bb);
</ins><span class="cx">          }
</span><span class="cx">          printf("compile_const_pointer() called with a non-NULL pointer " \
</span><span class="cx">                  "on the AOT compiler - leaving the ship!\n");
</span></span></pre>
</div>
</div>
</body>
</html>