[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