Skip to content

Commit

Permalink
Lazy loading works but only in the interpreter.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Ford committed Apr 26, 2011
1 parent 16647d6 commit 050b38f
Show file tree
Hide file tree
Showing 13 changed files with 231 additions and 129 deletions.
2 changes: 2 additions & 0 deletions kernel/bootstrap/lazy_executable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module Rubinius
class LazyExecutable
attr_accessor :path
attr_accessor :name
attr_accessor :scope
attr_accessor :serial

def self.new(path, name, index)
Ruby.primitive :lazy_executable_create
Expand Down
6 changes: 5 additions & 1 deletion lib/compiler/stages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ def run
end

@processor.dump @input, @name
@input
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx'
Rubinius.invoke_primitive :compiledfile_load, @name, Rubinius::Signature
else
@input
end
end
end

Expand Down
1 change: 1 addition & 0 deletions vm/builtin/access_variable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "builtin/access_variable.hpp"
#include "builtin/class.hpp"
#include "builtin/executable.hpp"
#include "builtin/lazy_executable.hpp"
#include "builtin/symbol.hpp"
#include "builtin/exception.hpp"
#include "builtin/packed_object.hpp"
Expand Down
11 changes: 10 additions & 1 deletion vm/builtin/lazy_executable.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
#include "builtin/lazy_executable.hpp"
#include "builtin/class.hpp"
#include "builtin/lookuptable.hpp"
#include "builtin/staticscope.hpp"
#include "builtin/symbol.hpp"
#include "builtin/system.hpp"
#include "builtin/fixnum.hpp"

#include "compiled_file.hpp"
Expand Down Expand Up @@ -45,6 +47,8 @@ namespace rubinius {
state, state->symbol("Index")));
tbl->store(state, path, index);
}

close(fd);
}
}

Expand All @@ -60,7 +64,9 @@ namespace rubinius {
Object* LazyExecutable::lazy_executor(STATE, CallFrame* call_frame, Executable* exec,
Module* mod, Arguments& args)
{
// Should we raise an exception or load?
std::string msg = "attempting to execute a LazyExecutable directly";
throw std::runtime_error(msg);

return Qnil;
}

Expand All @@ -81,7 +87,10 @@ namespace rubinius {
stream.seekg(base + offset, std::ios::beg);

CompiledMethod* method = CompiledFile::load_method(state, stream, path_);
Module* mod = scope_->for_method_definition();
System::vm_prepare_method(state, method, mod);
method->scope(state, scope_);
method->serial(state, serial());

return method;
}
Expand Down
4 changes: 4 additions & 0 deletions vm/builtin/methodtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "builtin/array.hpp"
#include "builtin/class.hpp"
#include "builtin/fixnum.hpp"
#include "builtin/lazy_executable.hpp"
#include "builtin/symbol.hpp"
#include "builtin/tuple.hpp"
#include "builtin/string.hpp"
Expand Down Expand Up @@ -208,6 +209,9 @@ namespace rubinius {

while(entry) {
if(entry->name() == name) {
if(LazyExecutable* lazy = try_as<LazyExecutable>(entry->method())) {
entry->method(state, lazy->load(state));
}
return entry;
}
entry = try_as<MethodTableBucket>(entry->next());
Expand Down
81 changes: 43 additions & 38 deletions vm/builtin/system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -792,53 +792,58 @@ namespace rubinius {
return Tuple::from(state, 2, dis.method, dis.module);
}

Object* System::vm_add_defn_method(STATE, Symbol* name, Executable* method,
StaticScope* scope, Object* vis)
{
Module* mod = scope->for_method_definition();
mod->add_method(state, name, method);

if(CompiledMethod* m = try_as<CompiledMethod>(method)) {
m->scope(state, scope);
m->serial(state, Fixnum::from(0));

if(Class* cls = try_as<Class>(mod)) {
if(!m->internalize(state)) {
Exception::argument_error(state, "invalid bytecode method");
return 0;
}
Object* System::vm_prepare_method(STATE, CompiledMethod* method, Module* mod) {
if(Class* cls = try_as<Class>(mod)) {
if(!method->internalize(state)) {
Exception::argument_error(state, "invalid bytecode method");
return 0;
}

object_type type = (object_type)cls->instance_type()->to_native();
TypeInfo* ti = state->om->type_info[type];
if(ti) {
m->specialize(state, ti);
}
object_type type = (object_type)cls->instance_type()->to_native();
TypeInfo* ti = state->om->type_info[type];
if(ti) {
method->specialize(state, ti);
}
}

bool add_ivars = false;
bool add_ivars = false;

if(Class* cls = try_as<Class>(mod)) {
add_ivars = !kind_of<SingletonClass>(cls) && cls->type_info()->type == Object::type;
} else {
add_ivars = true;
}
if(Class* cls = try_as<Class>(mod)) {
add_ivars = !kind_of<SingletonClass>(cls) && cls->type_info()->type == Object::type;
} else {
add_ivars = true;
}

if(add_ivars) {
Array* ary = mod->seen_ivars();
if(ary->nil_p()) {
ary = Array::create(state, 5);
mod->seen_ivars(state, ary);
}
if(add_ivars) {
Array* ary = mod->seen_ivars();
if(ary->nil_p()) {
ary = Array::create(state, 5);
mod->seen_ivars(state, ary);
}

Tuple* lits = m->literals();
for(native_int i = 0; i < lits->num_fields(); i++) {
if(Symbol* sym = try_as<Symbol>(lits->at(state, i))) {
if(RTEST(sym->is_ivar_p(state))) {
if(!ary->includes_p(state, sym)) ary->append(state, sym);
}
Tuple* lits = method->literals();
for(native_int i = 0; i < lits->num_fields(); i++) {
if(Symbol* sym = try_as<Symbol>(lits->at(state, i))) {
if(RTEST(sym->is_ivar_p(state))) {
if(!ary->includes_p(state, sym)) ary->append(state, sym);
}
}
}
}

return method;
}

Object* System::vm_add_defn_method(STATE, Symbol* name, Executable* method,
StaticScope* scope, Object* vis)
{
Module* mod = scope->for_method_definition();
mod->add_method(state, name, method);

if(CompiledMethod* m = try_as<CompiledMethod>(method)) {
m->scope(state, scope);
m->serial(state, Fixnum::from(0));
System::vm_prepare_method(state, m, mod);
} else if(LazyExecutable* m = try_as<LazyExecutable>(method)) {
m->scope(state, scope);
}
Expand Down
2 changes: 2 additions & 0 deletions vm/builtin/system.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@ namespace rubinius {
// Ruby.primitive :vm_find_method
static Tuple* vm_find_method(STATE, Object* recv, Symbol* name);

static Object* vm_prepare_method(STATE, CompiledMethod* method, Module* mod);

// Ruby.primitive :vm_add_defn_method
static Object* vm_add_defn_method(STATE, Symbol* name, Executable* meth, StaticScope* scope, Object* vis);

Expand Down
14 changes: 12 additions & 2 deletions vm/global_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "vm/objectmemory.hpp"
#include "vm/builtin/module.hpp"
#include "vm/builtin/object.hpp"
#include "vm/builtin/lazy_executable.hpp"
#include "vm/builtin/methodtable.hpp"
#include "builtin/alias.hpp"

Expand Down Expand Up @@ -39,7 +40,11 @@ namespace rubinius {
msg.method = alias->original_exec();
msg.module = alias->original_module();
} else {
msg.method = entry->method();
if(LazyExecutable* lazy = try_as<LazyExecutable>(entry->method())) {
msg.method = lazy->load(state);
} else {
msg.method = entry->method();
}
msg.module = module;
}
break;
Expand Down Expand Up @@ -67,7 +72,11 @@ namespace rubinius {
msg.method = alias->original_exec();
msg.module = alias->original_module();
} else {
msg.method = entry->method();
if(LazyExecutable* lazy = try_as<LazyExecutable>(entry->method())) {
msg.method = lazy->load(state);
} else {
msg.method = entry->method();
}
msg.module = module;
}
break;
Expand Down Expand Up @@ -102,6 +111,7 @@ namespace rubinius {
if(hierarchy_resolve(state, name, msg, lookup, &was_private)) {
state->global_cache()->retain(state, lookup.from, name,
msg.module, msg.method, msg.method_missing, was_private);

return true;
}

Expand Down
11 changes: 5 additions & 6 deletions vm/inline_cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,16 +99,15 @@ namespace rubinius {
use_module = alias->original_module();
}
} else {
if(LazyExecutable* lazy = try_as<LazyExecutable>(entry->method())) {
use_exec = lazy->load(state);
} else {
use_exec = entry->method();
}

use_exec = entry->method();
use_module = module;
}

if(use_exec) {
if(LazyExecutable* lazy = try_as<LazyExecutable>(use_exec)) {
use_exec = lazy->load(state);
}

mce = MethodCacheEntry::create(state, klass, use_module, use_exec);

if(!vis_entry) vis_entry = entry;
Expand Down
1 change: 1 addition & 0 deletions vm/instructions.def
Original file line number Diff line number Diff line change
Expand Up @@ -1175,6 +1175,7 @@ instruction create_block(literal) [ -- block ]

CompiledMethod* cm;
if(LazyExecutable* lazy = try_as<LazyExecutable>(_lit)) {
lazy->scope(state, call_frame->static_scope());
cm = as<CompiledMethod>(lazy->load(state));
call_frame->cm->literals()->put(state, literal, cm);
} else {
Expand Down
Loading

0 comments on commit 050b38f

Please sign in to comment.