[macruby-changes] [4272] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Jun 24 17:57:40 PDT 2010


Revision: 4272
          http://trac.macosforge.org/projects/ruby/changeset/4272
Author:   lsansonetti at apple.com
Date:     2010-06-24 17:57:38 -0700 (Thu, 24 Jun 2010)
Log Message:
-----------
aot: precompiling BridgeSupport metadata (work in progress)

Modified Paths:
--------------
    MacRuby/trunk/bin/rubyc
    MacRuby/trunk/compiler.cpp
    MacRuby/trunk/compiler.h
    MacRuby/trunk/include/ruby/ruby.h
    MacRuby/trunk/objc.h
    MacRuby/trunk/objc.m
    MacRuby/trunk/ruby.c
    MacRuby/trunk/vm.cpp

Modified: MacRuby/trunk/bin/rubyc
===================================================================
--- MacRuby/trunk/bin/rubyc	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/bin/rubyc	2010-06-25 00:57:38 UTC (rev 4272)
@@ -13,17 +13,17 @@
   VALID_ARCHS = ['i386', 'x86_64']
 
   def initialize(argv)
-    @mode = :normal
     @archs = []
     @internal = argv.delete('--internal')
+    @frameworks = %w{Foundation}
 
     # Parse arguments.
     OptionParser.new do |opts|
       opts.banner = "Usage: #{NAME} [options] file..."
       opts.on('-c', 'Compile and assemble, but do not link') { @dont_link = true }
       opts.on('-o <file>', 'Place the output into <file>') { |output| @output = output }
-      #opts.on('--mode [MODE]', "Select compilation mode (normal or full)") { |mode| @mode = mode.intern }
       opts.on('--static', "Create a standalone static executable") { @static = true }
+      opts.on('--framework <name>', "Link standalone static executable with given framework") { |p| @frameworks << p }
       opts.on('--dylib', "Create a dynamic library") { @dylib = true }
       opts.on('-C', 'Compile, assemble and link a loadable object file') { @bundle = true }
       opts.on('-a', '--arch <ARCH>', 'Compile for specified CPU architecture') { |arch| @archs << arch }
@@ -37,9 +37,6 @@
       end
       die opts if argv.empty?
       @files = argv
-      if @mode != :normal and @mode != :full
-        die "Invalid mode `#{@mode}'. Possible choices are: normal, full"
-      end
       @archs.uniq!
       @archs << RUBY_ARCH if @archs.empty?
       @archs.each do |arch|
@@ -47,6 +44,7 @@
           die "Invalid CPU architecture `#{arch}'. Possible values are: " + VALID_ARCHS.join(", ")
         end
       end
+      @frameworks.uniq!
     end
 
     # Locate necessary programs.
@@ -76,8 +74,19 @@
   end
 
   def run
-    if @mode == :full
-      die "Full compilation mode is not implemented yet!"
+    @uses_bs_flags = ''
+    @frameworks.each do |f|
+      p =
+        if File.exist?(f)
+	  "#{f}/Resources/BridgeSupport/#{File.basename(f)}Full.bridgesupport"
+        else
+          "/System/Library/Frameworks/#{f}.framework/Resources/BridgeSupport/#{f}Full.bridgesupport"
+        end
+      if File.exist?(p)
+        @uses_bs_flags << "--uses-bs #{p} "
+      else
+        die "Couldn't locate the Full BridgeSupport file for framework: `%{f}'"
+      end
     end
     if @dont_link or @bundle
       die "Cannot specify --static when not building an executable" if @static
@@ -138,7 +147,7 @@
     @archs.each do |arch|
       # Compile the file into LLVM bitcode.
       bc = gen_tmpfile(base + arch, 'bc')
-      execute("arch -#{arch} #{@macruby} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\"")
+      execute("arch -#{arch} #{@macruby} #{@uses_bs_flags} --emit-llvm \"#{bc}\" #{init_func} \"#{path}\"")
 
       # Compile the bitcode as assembly.
       asm = gen_tmpfile(base + arch, 's')
@@ -239,7 +248,8 @@
     main_txt << <<EOS
 }
 
-int main(int argc, char **argv)
+int
+main(int argc, char **argv)
 {
     const char *progname = argv[0];
     ruby_sysinit(&argc, &argv);
@@ -284,9 +294,11 @@
 
     # Link all objects into executable.
     path = @internal ? "-L." : "-L#{RbConfig::CONFIG['libdir']}"
-    linkf = @static ? 
+    linkf = "-lobjc -licucore -lauto "
+    @frameworks.each { |f| linkf << "-framework #{f} " }
+    linkf << (@static ?
       "#{path} #{RbConfig::CONFIG['LIBRUBYARG_STATIC_REALLY']}" :
-      "#{path} -lmacruby -framework Foundation -lobjc -lauto"
+      "#{path} -lmacruby")
     line = "#{@gcxx} -o \"#{output}\" #{arch_flags} #{linkf} "
     objs.each { |o| line << " \"#{o}\"" }
     execute(line)

Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/compiler.cpp	2010-06-25 00:57:38 UTC (rev 4272)
@@ -538,7 +538,7 @@
     return compile_protected_call(whenSplatFunc, args, args + 3);
 }
 
-GlobalVariable *
+Instruction *
 RoxorCompiler::compile_const_global_ustring(const UniChar *str,
 	const size_t len)
 {
@@ -568,10 +568,14 @@
 	gvar = iter->second;
     }
 
-    return gvar;
+    Value *idxs[] = {
+	ConstantInt::get(Int32Ty, 0),
+	ConstantInt::get(Int32Ty, 0)
+    };
+    return GetElementPtrInst::Create(gvar, idxs, idxs + 2, "", bb);
 }
 
-GlobalVariable *
+Instruction *
 RoxorCompiler::compile_const_global_string(const char *str,
 	const size_t len)
 {
@@ -601,7 +605,11 @@
 	gvar = iter->second;
     }
 
-    return gvar;
+    Value *idxs[] = {
+	ConstantInt::get(Int32Ty, 0),
+	ConstantInt::get(Int32Ty, 0)
+    };
+    return GetElementPtrInst::Create(gvar, idxs, idxs + 2, "", bb);
 }
 
 Value *
@@ -630,6 +638,24 @@
     return new LoadInst(gvar, "", bb);
 }
 
+static void
+discover_stubs(std::map<SEL, std::vector<std::string> *> &map,
+	std::vector<std::string> &dest, SEL sel)
+{
+    std::map<SEL, std::vector<std::string> *>::iterator iter;
+    iter = map.find(sel);
+    if (iter != map.end()) {
+	std::vector<std::string> *v = iter->second;
+	for (std::vector<std::string>::iterator i = v->begin();
+		i != v->end(); ++i) {
+	    std::string s = *i;
+	    if (std::find(dest.begin(), dest.end(), s) == dest.end()) {
+		dest.push_back(s);
+	    }		
+	}
+    }
+}
+
 Value *
 RoxorAOTCompiler::compile_sel(SEL sel, bool add_to_bb)
 {
@@ -641,6 +667,9 @@
 		"");
 	assert(gvar != NULL);
 	sels[sel] = gvar;
+
+	discover_stubs(bs_c_stubs_types, c_stubs, sel);
+	discover_stubs(bs_objc_stubs_types, objc_stubs, sel);
     }
     else {
 	gvar = iter->second;
@@ -773,12 +802,7 @@
 	types[3 + i] = '@';
     }
     types[arity.real + 3] = '\0';
-    GlobalVariable *gvar = compile_const_global_string(types);
-    Value *idxs[] = {
-	ConstantInt::get(Int32Ty, 0),
-	ConstantInt::get(Int32Ty, 0)
-    };
-    params.push_back(GetElementPtrInst::Create(gvar, idxs, idxs + 2, "", bb));
+    params.push_back(compile_const_global_string(types));
     Function *stub = compile_objc_stub(func, NULL, arity, types);
     params.push_back(new BitCastInst(stub, PtrTy, "", bb));
     params.push_back(compile_const_pointer(NULL));
@@ -2278,7 +2302,7 @@
 
 Instruction *
 RoxorCompiler::compile_range(Value *beg, Value *end, bool exclude_end,
-	bool retain, bool add_to_bb)
+	bool retain)
 {
     if (newRangeFunc == NULL) {
 	// VALUE rb_range_new2(VALUE beg, VALUE end, int exclude_end,
@@ -2295,10 +2319,7 @@
 	ConstantInt::get(Int32Ty, exclude_end ? 1 : 0),
 	ConstantInt::get(Int32Ty, retain ? 1 : 0)
     };
-    if (add_to_bb) {
-	return compile_protected_call(newRangeFunc, args, args + 4);
-    }
-    return CallInst::Create(newRangeFunc, args, args + 4, "");
+    return compile_protected_call(newRangeFunc, args, args + 4);
 }
 
 Value *
@@ -2325,16 +2346,6 @@
 
 	    assert(cstr_len > 0);
 
-	    GlobalVariable *str_gvar = compile_const_global_string(cstr,
-		    cstr_len);
-
-	    Value *idxs[] = {
-		ConstantInt::get(Int32Ty, 0),
-		ConstantInt::get(Int32Ty, 0)
-	    };
-	    Instruction *load = GetElementPtrInst::Create(str_gvar,
-		    idxs, idxs + 2, "", bb);
-
 	    if (newString2Func == NULL) {	
 		newString2Func = cast<Function>(
 			module->getOrInsertFunction(
@@ -2343,7 +2354,7 @@
 	    }
 
 	    Value *args[] = {
-		load,
+		compile_const_global_string(cstr, cstr_len),
 		ConstantInt::get(Int32Ty, cstr_len)
 	    };
 	    return CallInst::Create(newString2Func, args, args + 2, "", bb);
@@ -4689,13 +4700,27 @@
 {
     Value *val = compile_node(node);
     assert(Function::classof(val));
-    Function *function = cast<Function>(val);
-    function->setLinkage(GlobalValue::ExternalLinkage);
+    Function *func = cast<Function>(val);
+    func->setLinkage(GlobalValue::ExternalLinkage);
 
-    BasicBlock::InstListType &list = 
-	function->getEntryBlock().getInstList();
-    bb = &function->getEntryBlock();
+    Function *init_func = compile_init_function(); 
+    BasicBlock::InstListType &list = func->getEntryBlock().getInstList();
+    list.insert(list.begin(), CallInst::Create(init_func, ""));
 
+    return func;
+}
+
+Function *
+RoxorAOTCompiler::compile_init_function(void)
+{
+    reset_compiler_state();
+
+    FunctionType *ft = FunctionType::get(VoidTy, false);
+    Function *f = Function::Create(ft, GlobalValue::InternalLinkage,
+	    "init_func", module);
+
+    bb = BasicBlock::Create(context, "MainBlock", f);
+
     // Compile constant caches.
 
     Function *getConstCacheFunc = cast<Function>(module->getOrInsertFunction(
@@ -4703,29 +4728,15 @@
 		PtrTy, PtrTy, NULL));
 
     for (std::map<ID, GlobalVariable *>::iterator i = ccaches.begin();
-	 i != ccaches.end();
-	 ++i) {
+	    i != ccaches.end();
+	    ++i) {
 
 	ID name = i->first;
 	GlobalVariable *gvar = i->second;
 
-	GlobalVariable *const_gvar =
-	    compile_const_global_string(rb_id2name(name));
-
-	Value *idxs[] = {
-	    ConstantInt::get(Int32Ty, 0),
-	    ConstantInt::get(Int32Ty, 0)
-	};
-	Instruction *load = GetElementPtrInst::Create(const_gvar, idxs,
-		idxs + 2, "");
-
-	Instruction *call = CallInst::Create(getConstCacheFunc, load, "");
-
-	Instruction *assign = new StoreInst(call, gvar, "");
- 
-	list.insert(list.begin(), assign);
-	list.insert(list.begin(), call);
-	list.insert(list.begin(), load);
+	Value *val = CallInst::Create(getConstCacheFunc,
+		compile_const_global_string(rb_id2name(name)), "", bb);
+	new StoreInst(val, gvar, "", bb);
     }
 
     // Compile selectors.
@@ -4733,32 +4744,16 @@
     Function *registerSelFunc = get_function("sel_registerName");
 
     for (std::map<SEL, GlobalVariable *>::iterator i = sels.begin();
-	 i != sels.end();
-	 ++i) {
+	    i != sels.end();
+	    ++i) {
 
 	SEL sel = i->first;
 	GlobalVariable *gvar = i->second;
 
-	GlobalVariable *sel_gvar =
-	    compile_const_global_string(sel_getName(sel));
-
-	Value *idxs[] = {
-	    ConstantInt::get(Int32Ty, 0),
-	    ConstantInt::get(Int32Ty, 0)
-	};
-	Instruction *load = GetElementPtrInst::Create(sel_gvar, idxs, idxs + 2,
-		"");
-
-	Instruction *call = CallInst::Create(registerSelFunc, load, "");
-
-	Instruction *cast = new BitCastInst(call, PtrTy, "");
-
-	Instruction *assign = new StoreInst(cast, gvar, "");
- 
-	list.insert(list.begin(), assign);
-	list.insert(list.begin(), cast);
-	list.insert(list.begin(), call);
-	list.insert(list.begin(), load);
+	Value *val = CallInst::Create(registerSelFunc,
+		compile_const_global_string(sel_getName(sel)), "", bb);
+	val = new BitCastInst(val, PtrTy, "", bb);
+	new StoreInst(val, gvar, "", bb);
     }
 
     // Compile literals.
@@ -4787,30 +4782,16 @@
 
 	VALUE val = i->first;
 	GlobalVariable *gvar = i->second;
+	Value *lit_val = NULL;
 
 	switch (TYPE(val)) {
 	    case T_CLASS:
 		{
 		    // This strange literal seems to be only emitted for 
 		    // `for' loops.
-		    GlobalVariable *kname_gvar =
-			compile_const_global_string(class_getName((Class)val));
-
-		    Value *idxs[] = {
-			ConstantInt::get(Int32Ty, 0),
-			ConstantInt::get(Int32Ty, 0)
-		    };
-		    Instruction *load = GetElementPtrInst::Create(kname_gvar,
-			    idxs, idxs + 2, "");
-
-		    Instruction *call = CallInst::Create(getClassFunc,
-			    load, "");
-
-		    Instruction *assign = new StoreInst(call, gvar, "");
-
-		    list.insert(list.begin(), assign);
-		    list.insert(list.begin(), call);
-		    list.insert(list.begin(), load);
+		    const char *cname = class_getName((Class)val);
+		    lit_val = CallInst::Create(getClassFunc,
+			    compile_const_global_string(cname), "", bb);
 		}
 		break;
 
@@ -4827,15 +4808,8 @@
 				PointerType::getUnqual(Int16Ty));
 		    }
 		    else {
-			GlobalVariable *re_name_gvar =
-			    compile_const_global_ustring(chars, chars_len);
-
-			Value *idxs[] = {
-			    ConstantInt::get(Int32Ty, 0),
-			    ConstantInt::get(Int32Ty, 0)
-			};
-			re_str = GetElementPtrInst::Create(re_name_gvar,
-				idxs, idxs + 2, "");
+			re_str = compile_const_global_ustring(chars,
+				chars_len);
 		    }
 
 		    Value *args[] = {
@@ -4843,67 +4817,24 @@
 			ConstantInt::get(Int32Ty, chars_len),
 			ConstantInt::get(Int32Ty, rb_reg_options(val))
 		    };
-		    Instruction *call = CallInst::Create(newRegexp2Func,
-			    args, args + 3, "");
-
-		    Instruction *assign = new StoreInst(call, gvar, "");
-
-		    list.insert(list.begin(), assign);
-		    list.insert(list.begin(), call);
-		    Instruction *re_str_insn = dyn_cast<Instruction>(re_str);
-		    if (re_str_insn != NULL) {
-			list.insert(list.begin(), re_str_insn);
-		    }
+		    lit_val = CallInst::Create(newRegexp2Func, args, args + 3,
+			    "", bb);
 		}
 		break;
 
 	    case T_SYMBOL:
 		{
 		    const char *symname = rb_id2name(SYM2ID(val));
-
-		    GlobalVariable *symname_gvar =
-			compile_const_global_string(symname);
-
-		    Value *idxs[] = {
-			ConstantInt::get(Int32Ty, 0),
-			ConstantInt::get(Int32Ty, 0)
-		    };
-		    Instruction *load = GetElementPtrInst::Create(symname_gvar,
-			    idxs, idxs + 2, "");
-
-		    Instruction *call = CallInst::Create(name2symFunc,
-			    load, "");
-
-		    Instruction *assign = new StoreInst(call, gvar, "");
-
-		    list.insert(list.begin(), assign);
-		    list.insert(list.begin(), call);
-		    list.insert(list.begin(), load);
+		    lit_val = CallInst::Create(name2symFunc,
+			    compile_const_global_string(symname), "", bb);
 		}
 		break;
 
 	    case T_BIGNUM:
 		{
 		    const char *bigstr = RSTRING_PTR(rb_big2str(val, 10));
-
-		    GlobalVariable *bigstr_gvar =
-			compile_const_global_string(bigstr);
-
-		    Value *idxs[] = {
-			ConstantInt::get(Int32Ty, 0),
-			ConstantInt::get(Int32Ty, 0)
-		    };
-		    Instruction *load = GetElementPtrInst::Create(bigstr_gvar,
-			    idxs, idxs + 2, "");
-
-		    Instruction *call = CallInst::Create(newBignumFunc,
-			    load, "");
-
-		    Instruction *assign = new StoreInst(call, gvar, "");
-
-		    list.insert(list.begin(), assign);
-		    list.insert(list.begin(), call);
-		    list.insert(list.begin(), load);
+		    lit_val = CallInst::Create(newBignumFunc,
+			    compile_const_global_string(bigstr), "", bb);
 		}
 		break;
 
@@ -4913,15 +4844,9 @@
 		    bool exclude_end = false;
 		    rb_range_extract(val, &beg, &end, &exclude_end);
 
-		    Instruction *call = compile_range(
-			    ConstantInt::get(RubyObjTy, beg),
+		    lit_val = compile_range(ConstantInt::get(RubyObjTy, beg),
 			    ConstantInt::get(RubyObjTy, end),
-			    exclude_end, true, false);	
-
-		    Instruction *assign = new StoreInst(call, gvar, "");
-
-		    list.insert(list.begin(), assign);
-		    list.insert(list.begin(), call);
+			    exclude_end, true);	
 		}
 		else {
 		    printf("unrecognized literal `%s' (class `%s' type %d)\n",
@@ -4932,33 +4857,9 @@
 		}
 		break;
 	}
-    }
 
-    // Compile global entries.
-
-    Function *globalEntryFunc = cast<Function>(module->getOrInsertFunction(
-		"rb_global_entry",
-		PtrTy, IntTy, NULL));
-
-    for (std::map<ID, GlobalVariable *>::iterator i = global_entries.begin();
-	 i != global_entries.end();
-	 ++i) {
-
-	ID name_id = i->first;
-	GlobalVariable *gvar = i->second;
-
-	Value *name_val = compile_id(name_id);
-	assert(Instruction::classof(name_val));
-	Instruction *name = cast<Instruction>(name_val);
-	name->removeFromParent();	
-
-	Instruction *call = CallInst::Create(globalEntryFunc, name, "");
-
-	Instruction *assign = new StoreInst(call, gvar, "");
-	
-	list.insert(list.begin(), assign);
-	list.insert(list.begin(), call);
-	list.insert(list.begin(), name);
+	assert(lit_val != NULL);
+	new StoreInst(lit_val, gvar, "", bb);
     }
 
     // Compile IDs.
@@ -4968,55 +4869,47 @@
 		IntTy, PtrTy, NULL));
 
     for (std::map<ID, GlobalVariable *>::iterator i = ids.begin();
-	 i != ids.end();
-	 ++i) {
+	    i != ids.end();
+	    ++i) {
 
 	ID name = i->first;
 	GlobalVariable *gvar = i->second;
 
-	GlobalVariable *name_gvar =
-	    compile_const_global_string(rb_id2name(name));
+	Value *val = CallInst::Create(rbInternFunc,
+		compile_const_global_string(rb_id2name(name)), "", bb);
+	new StoreInst(val, gvar, "", bb);
+    }
 
-	Value *idxs[] = {
-	    ConstantInt::get(Int32Ty, 0),
-	    ConstantInt::get(Int32Ty, 0)
-	};
-	Instruction *load = GetElementPtrInst::Create(name_gvar, idxs,
-		idxs + 2, "");
+    // Compile global entries.
 
-	Instruction *call = CallInst::Create(rbInternFunc, load, "");
+    Function *globalEntryFunc = cast<Function>(module->getOrInsertFunction(
+		"rb_global_entry",
+		PtrTy, IntTy, NULL));
 
-	Instruction *assign = new StoreInst(call, gvar, "");
- 
-	list.insert(list.begin(), assign);
-	list.insert(list.begin(), call);
-	list.insert(list.begin(), load);
+    for (std::map<ID, GlobalVariable *>::iterator i = global_entries.begin();
+	    i != global_entries.end();
+	    ++i) {
+
+	ID name = i->first;
+	GlobalVariable *gvar = i->second;
+
+	Value *val = CallInst::Create(rbInternFunc,
+		compile_const_global_string(rb_id2name(name)), "", bb);
+	val = CallInst::Create(globalEntryFunc, val, "", bb);
+	new StoreInst(val, gvar, "", bb);
     }
 
     // Compile constant class references.
 
     for (std::vector<GlobalVariable *>::iterator i = class_gvars.begin();
-	 i != class_gvars.end();
-	 ++i) {
+	    i != class_gvars.end();
+	    ++i) {
 
 	GlobalVariable *gvar = *i;
-
-	GlobalVariable *str = compile_const_global_string(
-		gvar->getName().str().c_str());
-
-	Value *idxs[] = {
-	    ConstantInt::get(Int32Ty, 0),
-	    ConstantInt::get(Int32Ty, 0)
-	};
-	Instruction *load = GetElementPtrInst::Create(str, idxs, idxs + 2, "");
-
-	Instruction *call = CallInst::Create(getClassFunc, load, "");
-
-	Instruction *assign = new StoreInst(call, gvar, "");
-
-	list.insert(list.begin(), assign);
-	list.insert(list.begin(), call);
-	list.insert(list.begin(), load);
+	Value *val = CallInst::Create(getClassFunc,
+		compile_const_global_string(gvar->getName().str().c_str()),
+		"",bb);
+	new StoreInst(val, gvar, "", bb);
     }
 
     // Instance variable slots.
@@ -5026,21 +4919,56 @@
 		PtrTy, NULL));
 
     for (std::vector<GlobalVariable *>::iterator i = ivar_slots.begin();
-	 i != ivar_slots.end();
-	 ++i) {
+	    i != ivar_slots.end();
+	    ++i) {
 
 	GlobalVariable *gvar = *i;
+	Value *val = CallInst::Create(ivarSlotAlloc, "", bb);
+	new StoreInst(val, gvar, "", bb);
+    }
 
-	Instruction *call = CallInst::Create(ivarSlotAlloc, "");
-	Instruction *assign = new StoreInst(call, gvar, "");
+    // Stubs.
 
-	list.insert(list.begin(), assign);
-	list.insert(list.begin(), call);
+    Function *addStub = cast<Function>(module->getOrInsertFunction(
+		"rb_vm_add_stub", VoidTy, PtrTy, PtrTy, Int8Ty, NULL));
+
+    for (std::vector<std::string>::iterator i = c_stubs.begin();
+	    i != c_stubs.end();
+	    ++i) {
+
+	const char *types = i->c_str();
+	try {
+	    Value *args[] = {
+		compile_const_global_string(types),
+		new BitCastInst(compile_stub(types, false, TypeArity(types),
+			    false), PtrTy, "", bb),
+		ConstantInt::get(Int8Ty, 0)
+	    };
+	    CallInst::Create(addStub, args, args + 3, "", bb);
+	}
+	catch (...) {}
     }
 
-    bb = NULL;
+    for (std::vector<std::string>::iterator i = objc_stubs.begin();
+	    i != objc_stubs.end();
+	    ++i) {
 
-    return function;
+	const char *types = i->c_str();
+	try {
+	    Value *args[] = {
+		compile_const_global_string(types),
+		new BitCastInst(compile_stub(types, false,
+			    TypeArity(types) - 2, true), PtrTy, "", bb),
+		ConstantInt::get(Int8Ty, 1)
+	    };
+	    CallInst::Create(addStub, args, args + 3, "", bb);
+	}
+	catch (...) {}
+    }
+
+    ReturnInst::Create(context, bb);
+
+    return f;
 }
 
 Function *
@@ -5520,16 +5448,8 @@
 		    "rb_vm_new_pointer", RubyObjTy, PtrTy, PtrTy, NULL));
     }
 
-    GlobalVariable *gvar = compile_const_global_string(type);
-    Value *idxs[] = {
-	ConstantInt::get(Int32Ty, 0),
-	ConstantInt::get(Int32Ty, 0)
-    };
-    Instruction *load = GetElementPtrInst::Create(gvar, idxs, idxs + 2,
-	    "", bb);
-
     Value *args[] = {
-	load,
+	compile_const_global_string(type),
 	val
     };
     return CallInst::Create(newPointerFunc, args, args + 2, "", bb);
@@ -5804,8 +5724,12 @@
 RoxorCompiler::compile_stub(const char *types, bool variadic, int min_argc,
 	bool is_objc)
 {
-    Function *f;
+    save_compiler_state();
+    reset_compiler_state();
 
+    Function *f = NULL;
+    try {
+
     if (is_objc) {
 	// VALUE stub(IMP imp, VALUE self, SEL sel, int argc, VALUE *argv)
 	// {
@@ -5947,6 +5871,16 @@
 
     free(buf);
 
+    } // try
+    catch (...) {
+	if (f != NULL) {
+	    f->eraseFromParent();
+	}
+	restore_compiler_state();
+	throw;
+    }
+
+    restore_compiler_state();
     return f;
 }
 
@@ -6695,4 +6629,36 @@
     return pn;
 }
 
+static void
+add_stub_types_cb(SEL sel, const char *types, bool is_objc, void *ctx)
+{
+    RoxorAOTCompiler *compiler = (RoxorAOTCompiler *)ctx;
+
+    std::map<SEL, std::vector<std::string> *> &map =
+	is_objc ? compiler->bs_objc_stubs_types : compiler->bs_c_stubs_types;
+
+    std::map<SEL, std::vector<std::string> *>::iterator iter = map.find(sel);
+    std::vector<std::string> *v;
+    if (iter == map.end()) {
+	v = new std::vector<std::string>();
+	map[sel] = v;
+    }
+    else {
+	v = iter->second;
+    }
+    v->push_back(types);
+}
+
+extern "C"
+void
+rb_vm_parse_bs_full_file(const char *path,
+	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
+	void *ctx);
+
+void
+RoxorAOTCompiler::load_bs_full_file(const char *path)
+{
+    rb_vm_parse_bs_full_file(path, add_stub_types_cb, (void *)this);
+}
+
 #endif // !MACRUBY_STATIC

Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/compiler.h	2010-06-25 00:57:38 UTC (rev 4272)
@@ -377,17 +377,17 @@
 	    return compile_const_pointer(sel, PtrTy);
 	}
 	virtual Value *compile_id(ID id);
-	GlobalVariable *compile_const_global_string(const char *str,
+	Instruction *compile_const_global_string(const char *str,
 		const size_t str_len);
-	GlobalVariable *compile_const_global_string(const char *str) {
+	Instruction *compile_const_global_string(const char *str) {
 	    return compile_const_global_string(str, strlen(str));
 	}
-	GlobalVariable *compile_const_global_ustring(const UniChar *str,
+	Instruction *compile_const_global_ustring(const UniChar *str,
 		const size_t str_len);
 
 	Value *compile_arity(rb_vm_arity_t &arity);
 	Instruction *compile_range(Value *beg, Value *end, bool exclude_end,
-		bool retain=false, bool add_to_bb=true);
+		bool retain=false);
 	Value *compile_literal(VALUE val);
 	virtual Value *compile_immutable_literal(VALUE val);
 	virtual Value *compile_global_entry(NODE *node);
@@ -442,6 +442,12 @@
 
 	Function *compile_main_function(NODE *node, bool *can_be_interpreted);
 
+	// BridgeSupport metadata needed for AOT compilation.
+	std::map<SEL, std::vector<std::string> *> bs_c_stubs_types,
+	    bs_objc_stubs_types;
+
+	void load_bs_full_file(const char *path);
+
     private:
 	std::map<ID, GlobalVariable *> ccaches;
 	std::map<SEL, GlobalVariable *> sels;
@@ -449,11 +455,13 @@
 	std::map<ID, GlobalVariable *> global_entries;
 	std::vector<GlobalVariable *> ivar_slots;
 	std::map<VALUE, GlobalVariable *> literals;
+	std::vector<std::string> c_stubs, objc_stubs;
 
 	GlobalVariable *cObject_gvar;
 	GlobalVariable *cStandardError_gvar;
 	std::vector<GlobalVariable *> class_gvars;
 
+	Function *compile_init_function(void);
 	Value *compile_ccache(ID id);
 	Value *compile_sel(SEL sel, bool add_to_bb=true);
 	void compile_prepare_method(Value *classVal, Value *sel,

Modified: MacRuby/trunk/include/ruby/ruby.h
===================================================================
--- MacRuby/trunk/include/ruby/ruby.h	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/include/ruby/ruby.h	2010-06-25 00:57:38 UTC (rev 4272)
@@ -814,7 +814,7 @@
 RUBY_EXTERN VALUE ruby_verbose, ruby_debug;
 
 // AOT compiler.
-RUBY_EXTERN VALUE ruby_aot_compile, ruby_aot_init_func;
+RUBY_EXTERN VALUE ruby_aot_compile, ruby_aot_init_func, ruby_aot_bs_files;
 
 // Debugger.
 RUBY_EXTERN VALUE ruby_debug_socket_path;

Modified: MacRuby/trunk/objc.h
===================================================================
--- MacRuby/trunk/objc.h	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/objc.h	2010-06-25 00:57:38 UTC (rev 4272)
@@ -223,6 +223,12 @@
 
 extern bool rb_objc_enable_ivar_set_kvo_notifications;
 
+#if !defined(MACRUBY_STATIC)
+void rb_vm_parse_bs_full_file(const char *path,
+	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
+	void *ctx);
+#endif
+
 #if defined(__cplusplus)
 }
 #endif

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/objc.m	2010-06-25 00:57:38 UTC (rev 4272)
@@ -814,3 +814,73 @@
     return (id)objc_getProtocol([name UTF8String]);
 } 
 @end
+
+#if !defined(MACRUBY_STATIC)
+static NSString *
+get_type(NSXMLElement *elem)
+{
+   NSXMLNode *node = nil;
+#if __LP64__
+   node = [elem attributeForName:@"type64"];
+#endif
+   if (node == nil) {
+       node = [elem attributeForName:@"type"];
+       assert(node != nil);
+   }
+   return [node stringValue];
+}
+
+static void
+add_stub_types(NSXMLElement *elem,
+	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
+	void *ctx,
+	bool is_objc)
+{
+    NSXMLNode *name = [elem attributeForName:is_objc
+	? @"selector" : @"name"];
+    NSArray *ary = [elem elementsForName:@"retval"];
+    assert([ary count] == 1);
+    NSXMLElement *retval = [ary objectAtIndex:0];
+    NSMutableString *types = [NSMutableString new];
+    [types appendString:get_type(retval)];
+    if (is_objc) {
+	[types appendString:@"@:"]; // self, sel
+    }
+    ary = [elem elementsForName:@"arg"];
+    for (NSXMLElement *a in ary) {
+	[types appendString:get_type(a)];
+    }
+    NSString *sel_str = [name stringValue];
+    if (!is_objc && [ary count] > 0) {
+	sel_str = [sel_str stringByAppendingString:@":"];
+    }
+    SEL sel = sel_registerName([sel_str UTF8String]);
+    add_stub_types_cb(sel, [types UTF8String], is_objc, ctx);
+}
+
+void
+rb_vm_parse_bs_full_file(const char *path,
+	void (*add_stub_types_cb)(SEL, const char *, bool, void *),
+	void *ctx)
+{
+    NSURL *url = [NSURL fileURLWithPath:[NSString stringWithUTF8String:path]];
+    NSError *err = nil;
+    NSXMLDocument *doc = [[NSXMLDocument alloc] initWithContentsOfURL: url
+	options: 0 error: &err];
+    if (doc == nil) {
+	NSLog(@"can't open BridgeSupport full file at path `%s': %@",
+		path, err);
+	exit(1);
+    }
+    NSXMLElement *root = [doc rootElement];
+
+    for (NSXMLElement *k in [root elementsForName:@"class"]) {
+	for (NSXMLElement *m in [k elementsForName:@"method"]) {
+	    add_stub_types(m, add_stub_types_cb, ctx, true);
+	}
+    }
+    for (NSXMLElement *f in [root elementsForName:@"function"]) {
+	add_stub_types(f, add_stub_types_cb, ctx, false);
+    }
+}
+#endif

Modified: MacRuby/trunk/ruby.c
===================================================================
--- MacRuby/trunk/ruby.c	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/ruby.c	2010-06-25 00:57:38 UTC (rev 4272)
@@ -36,6 +36,7 @@
 VALUE ruby_debug_socket_path = Qfalse;
 VALUE ruby_aot_compile = Qfalse;
 VALUE ruby_aot_init_func = Qfalse;
+VALUE ruby_aot_bs_files = Qnil;
 VALUE rb_progname = Qnil;
 
 static int uid, euid, gid, egid;
@@ -715,6 +716,21 @@
 		argc--; argv++;
 		argc--; argv++;
 	    }
+	    else if (strcmp("uses-bs", s) == 0) {
+		// This option is not documented and only used by macrubyc.
+		// Users should use macrubyc and never call this option
+		// directly.
+		if (argc < 2) {
+		    rb_raise(rb_eRuntimeError,
+			    "expected 1 argument (complete BridgeSupport file ) for --uses-bs");
+		}
+		if (ruby_aot_bs_files == Qnil) {
+		    ruby_aot_bs_files = rb_ary_new();
+		    GC_RETAIN(ruby_aot_bs_files);
+		}
+		rb_ary_push(ruby_aot_bs_files, rb_str_new2(argv[1]));
+		argc--; argv++;
+	    }
 	    else if (strcmp("debug-mode", s) == 0) {
 		// This option is not documented and only used by macrubyd.
 		// Users should use macrubyd and never call this option

Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp	2010-06-24 23:16:45 UTC (rev 4271)
+++ MacRuby/trunk/vm.cpp	2010-06-25 00:57:38 UTC (rev 4272)
@@ -2823,7 +2823,8 @@
     void *stub;
     if (iter == stubs.end()) {
 #if MACRUBY_STATIC
-	printf("uncached stub %s\n", types.c_str());
+	printf("uncached %s stub `%s'\n", is_objc ? "ObjC" : "C",
+		types.c_str());
 	abort();
 #else
 	Function *f = RoxorCompiler::shared->compile_stub(types.c_str(),
@@ -3848,6 +3849,7 @@
 }
 
 extern VALUE rb_progname;
+extern "C" void rb_vm_aot_load_bs_files(VALUE);
 
 extern "C"
 void
@@ -3859,6 +3861,15 @@
     assert(ruby_aot_compile);
     assert(ruby_aot_init_func);
 
+    // Load the BridgeSupport files.
+    if (ruby_aot_bs_files != Qnil) {
+	for (int i = 0, count = RARRAY_LEN(ruby_aot_bs_files); i < count;
+		i++) {
+	    ((RoxorAOTCompiler *)RoxorCompiler::shared)->load_bs_full_file(
+		RSTRING_PTR(RARRAY_AT(ruby_aot_bs_files, i)));
+	}
+    }
+
     // Compile the program as IR.
     RoxorCompiler::shared->set_fname(RSTRING_PTR(rb_progname));
     Function *f = RoxorCompiler::shared->compile_main_function(node, NULL);
@@ -4640,6 +4651,13 @@
     GET_CORE()->insert_stub("#@:", (void *)builtin_ostub1, true);
 }
 
+extern "C"
+void
+rb_vm_add_stub(const char *types, void *func, unsigned char is_objc)
+{
+    GET_CORE()->insert_stub(types, func, is_objc);
+}
+
 #if !defined(MACRUBY_STATIC)
 static IMP old_resolveClassMethod_imp = NULL;
 static IMP old_resolveInstanceMethod_imp = NULL;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100624/b29f21a6/attachment-0001.html>


More information about the macruby-changes mailing list