Skip to content

Commit

Permalink
Showing 9 changed files with 274 additions and 284 deletions.
3 changes: 3 additions & 0 deletions library/rubinius/configuration.rb
Original file line number Diff line number Diff line change
@@ -103,6 +103,9 @@

cs.vm_variable "limit", 3,
"Maximum number of caches at call sites"

cs.vm_variable "evictions", 10,
"Maximum number of cache evictions before disabling caching at the call site"
end

m.section "jit" do |j|
96 changes: 3 additions & 93 deletions machine/builtin/call_site.cpp
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@

namespace rubinius {
int CallSite::max_caches = 0;
int CallSite::max_evictions = 0;
CallSite::Executor CallSite::default_execute = CallSite::lookup_invoke_cache;

void CallSite::bootstrap(STATE) {
@@ -26,105 +27,14 @@ namespace rubinius {
}

max_caches = state->shared().config.machine_call_site_limit.value;
max_evictions = state->shared().config.machine_call_site_evictions.value;
}

void CallSite::Info::mark(Object* obj, memory::ObjectMark& mark) {
auto_mark(obj, mark);

CallSite* call_site = as<CallSite>(obj);

if(!call_site->caches()) return;

// 1. Check if individual caches should be evicted.
bool evict_p[call_site->depth()];

for(int i = 0; i < call_site->depth(); i++) {
evict_p[i] = call_site->caches()->cache[i].inefficient_p();
}

int evict_count = 0;
for(int i = 0; i < call_site->depth(); i++) {
if(evict_p[i]) evict_count++;
}

if(evict_count) {
VM::current()->metrics().machine.inline_cache_evicted += evict_count;

int new_size = call_site->depth() - evict_count;

if(new_size == 0) {
call_site->depth(0);
free(call_site->caches());
call_site->caches(NULL);

call_site->execute(CallSite::default_execute);
call_site->cache_miss(CallSite::default_execute);

return;
}

for(int i = 0, j = 0; i < call_site->depth() && j < new_size; i++) {
if(!evict_p[i]) {
call_site->caches()->cache[j++] = call_site->caches()->cache[i];
}
}

call_site->caches()->depth(new_size);
}

// 2. Attempt to re-order the caches by bubbling most hit forward.
bool reorder_p = false;
int indexes[call_site->depth()];

for(int i = 0; i < call_site->depth(); i++) {
indexes[i] = i;
}

InlineCaches* caches = call_site->caches();

for(int i = 0; i < call_site->depth() - 1; i++) {
if(caches->cache[i].hits() < caches->cache[i + 1].hits()) {
int tmp = indexes[i];
indexes[i] = indexes[i + 1];
indexes[i + 1] = tmp;
reorder_p = true;

// TODO: pass State through the GC!
VM::current()->metrics().machine.inline_cache_reordered++;
}
}

if(reorder_p) {
InlineCache* inline_caches = static_cast<InlineCache*>(
alloca(sizeof(CallSite) * call_site->depth()));

for(int i = 0; i < call_site->depth(); i++) {
inline_caches[i] = caches->cache[i];
}

for(int i = 0; i < call_site->depth(); i++) {
caches->cache[i] = inline_caches[indexes[i]];
}
}

// 3. Mark remaining caches.
for(int i = 0; i < call_site->depth(); i++) {
InlineCache* cache = &caches->cache[i];

if(Object* ref = mark.call(cache->receiver_class())) {
cache->receiver_class(as<Class>(ref));
mark.just_set(call_site, ref);
}

if(Object* ref = mark.call(cache->stored_module())) {
cache->stored_module(as<Module>(ref));
mark.just_set(call_site, ref);
}

if(Object* ref = mark.call(cache->executable())) {
cache->executable(as<Executable>(ref));
mark.just_set(call_site, ref);
}
}
call_site->evict_and_mark(mark);
}
}
403 changes: 231 additions & 172 deletions machine/builtin/call_site.hpp

Large diffs are not rendered by default.

38 changes: 21 additions & 17 deletions machine/builtin/compiled_code.hpp
Original file line number Diff line number Diff line change
@@ -42,6 +42,8 @@ namespace rubinius {
attr_accessor(keywords, Tuple);
attr_accessor(arity, Fixnum);
attr_accessor(breakpoints, LookupTable);
attr_accessor(iregisters, Fixnum);
attr_accessor(dregisters, Fixnum);

private:
attr_field(machine_code, MachineCode*);
@@ -60,23 +62,25 @@ namespace rubinius {
static void initialize(STATE, CompiledCode* obj) {
Executable::initialize(state, obj, CompiledCode::default_executor);

obj-> metadata(nil<Object>());
obj-> name(nil<Symbol>());
obj-> iseq(nil<InstructionSequence>());
obj-> stack_size(nil<Fixnum>());
obj-> local_count(Fixnum::from(0));
obj-> required_args(nil<Fixnum>());
obj-> post_args(nil<Fixnum>());
obj-> total_args(nil<Fixnum>());
obj-> splat(nil<Fixnum>());
obj-> lines(nil<Tuple>());
obj-> local_names(nil<Tuple>());
obj-> file(nil<Symbol>());
obj-> scope(nil<ConstantScope>());
obj-> keywords(nil<Tuple>());
obj-> arity(nil<Fixnum>());
obj-> breakpoints(nil<LookupTable>());
obj-> machine_code(NULL);
obj->metadata(nil<Object>());
obj->name(nil<Symbol>());
obj->iseq(nil<InstructionSequence>());
obj->stack_size(nil<Fixnum>());
obj->local_count(Fixnum::from(0));
obj->required_args(nil<Fixnum>());
obj->post_args(nil<Fixnum>());
obj->total_args(nil<Fixnum>());
obj->splat(nil<Fixnum>());
obj->lines(nil<Tuple>());
obj->local_names(nil<Tuple>());
obj->file(nil<Symbol>());
obj->scope(nil<ConstantScope>());
obj->keywords(nil<Tuple>());
obj->arity(nil<Fixnum>());
obj->breakpoints(nil<LookupTable>());
obj->iregisters(Fixnum::from(0));
obj->dregisters(Fixnum::from(0));
obj->machine_code(NULL);

obj->literals(nil<Tuple>());
}
2 changes: 2 additions & 0 deletions machine/machine_code.cpp
Original file line number Diff line number Diff line change
@@ -58,6 +58,8 @@ namespace rubinius {
, splat_position(-1)
, stack_size(code->stack_size()->to_native())
, number_of_locals(code->number_of_locals())
, iregisters(0)
, dregisters(0)
, sample_count(0)
, call_count(0)
, uncommon_count(0)
3 changes: 3 additions & 0 deletions machine/machine_code.hpp
Original file line number Diff line number Diff line change
@@ -69,6 +69,9 @@ namespace rubinius {
native_int stack_size;
native_int number_of_locals;

native_int iregisters;
native_int dregisters;

native_int sample_count;
native_int call_count;
native_int uncommon_count;
9 changes: 9 additions & 0 deletions machine/memory.hpp
Original file line number Diff line number Diff line change
@@ -381,6 +381,15 @@ namespace rubinius {
return static_cast<T*>(new_object(state, klass, bytes, T::type));
}

template <class T>
T* new_variable_object(STATE, Class *klass) {
T* obj = static_cast<T*>(new_object(
state, klass, TypeInfo::instance_sizes[T::type], T::type));
T::initialize(state, obj);

return obj;
}

template <class T>
T* new_bytes(STATE, Class* klass, native_int bytes) {
bytes = ObjectHeader::align(sizeof(T) + bytes);
2 changes: 1 addition & 1 deletion machine/memory/finalizer.cpp
Original file line number Diff line number Diff line change
@@ -188,7 +188,7 @@ namespace rubinius {
void FinalizerThread::wakeup(STATE) {
MachineThread::wakeup(state);

while(thread_running_) {
while(thread_running_p()) {
UnmanagedPhase unmanaged(state);
std::lock_guard<std::mutex> guard(list_mutex());

2 changes: 1 addition & 1 deletion machine/spinlock.hpp
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@ namespace rubinius {
}

bool try_lock() {
return flag.test_and_set(std::memory_order_seq_cst);
return !flag.test_and_set(std::memory_order_seq_cst);
}

void unlock() {

0 comments on commit 5c6a613

Please sign in to comment.