Skip to content

Commit

Permalink
Showing 66 changed files with 1,084 additions and 2,023 deletions.
28 changes: 20 additions & 8 deletions core/call_site.rb
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
module Rubinius
class CallSite
attr_reader :name
attr_reader :executable

def hits
0
end
attr_reader :cache

def ip
Rubinius.primitive :call_site_ip
raise PrimitiveFailure, "CallSite#ip primitive failed"
end

def location
"#{@executable.file}:#{@executable.line_from_ip(ip)}"
def depth
Rubinius.primitive :call_site_depth
raise PrimitiveFailure, "CallSite#depth primitive failed"
end

def invokes
Rubinius.primitive :call_site_invokes
raise PrimitiveFailure, "CallSite#invokes primitive failed"
end

def hits
Rubinius.primitive :call_site_hits
raise PrimitiveFailure, "CallSite#hits primitive failed"
end

def misses
Rubinius.primitive :call_site_misses
raise PrimitiveFailure, "CallSite#misses primitive failed"
end

def inspect
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} #{location}##{@name}(#{hits})>"
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} name=#{@name} ip=#{ip} depth=#{depth} invokes=#{invokes} hits=#{hits} misses=#{misses}>"
end
end
end
2 changes: 0 additions & 2 deletions core/load_order.txt
Original file line number Diff line number Diff line change
@@ -77,7 +77,6 @@ metrics.rb
mirror.rb
missing_method.rb
module.rb
mono_inline_cache.rb
mutex.rb
native_method.rb
nil.rb
@@ -88,7 +87,6 @@ options.rb
pack.rb
pointer.rb
pointer_accessors.rb
poly_inline_cache.rb
proc.rb
proc_mirror.rb
process.rb
25 changes: 0 additions & 25 deletions core/mono_inline_cache.rb

This file was deleted.

52 changes: 0 additions & 52 deletions core/poly_inline_cache.rb

This file was deleted.

10 changes: 10 additions & 0 deletions library/rubinius/configuration.rb
Original file line number Diff line number Diff line change
@@ -168,6 +168,16 @@
c.vm_variable "profiler.threshold", 1000000,
"The minimum number of nanoseconds a profiler node must have to be reported"

c.section "machine" do |s|
s.section "call_site" do |cs|
cs.vm_variable "cache", true,
"Cache executables at call sites"

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

c.section "system" do |s|
s.vm_variable "tmp", "$TMPDIR",
"Default temp/fallback directory for the process"
278 changes: 73 additions & 205 deletions machine/builtin/call_site.cpp
Original file line number Diff line number Diff line change
@@ -1,262 +1,130 @@
#include "arguments.hpp"
#include "call_frame.hpp"
#include "global_cache.hpp"
#include "lookup_data.hpp"
#include "object_utils.hpp"
#include "memory.hpp"

#include "builtin/class.hpp"
#include "builtin/call_site.hpp"
#include "builtin/exception.hpp"
#include "builtin/executable.hpp"
#include "builtin/mono_inline_cache.hpp"
#include "builtin/object.hpp"
#include "builtin/poly_inline_cache.hpp"

#include <stdlib.h>
#include <sstream>

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

void CallSite::bootstrap(STATE) {
GO(call_site).set(state->memory()->new_class<Class, CallSite>(
state, G(rubinius), "CallSite"));
}

CallSite* CallSite::empty(STATE, Symbol* name, Executable* executable, int ip) {
CallSite* cache = state->memory()->new_object<CallSite>(state, G(call_site));

cache->name(name);
cache->executable(state, executable);
cache->ip(ip);

state->vm()->metrics().machine.call_site_count++;

return cache;
}

Integer* CallSite::ip_prim(STATE) {
return Integer::from(state, ip());
}

Object* CallSite::empty_cache(STATE, CallSite* call_site, Arguments& args) {
Object* const self = state->vm()->call_frame()->self();
Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);

LookupData lookup(self, recv->lookup_begin(state), G(sym_public));
Dispatch dispatch(call_site->name());

if(!dispatch.resolve(state, call_site->name(), lookup)) {
if(!lookup_method_missing(state, args,
dispatch, self, recv->lookup_begin(state))) {
return NULL;
}
}

state->vm()->metrics().machine.methods_invoked++;

call_site->update(state, recv_class, dispatch);

Executable* meth = dispatch.method;
Module* mod = dispatch.module;

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
if(state->shared().config.machine_call_site_cache.value) {
default_execute = lookup_invoke_cache;
} else {
return meth->execute(state, meth, mod, args);
}
}

Object* CallSite::empty_cache_private(STATE, CallSite* call_site,
Arguments& args)
{
Object* const self = state->vm()->call_frame()->self();
Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);

LookupData lookup(self, recv->lookup_begin(state), G(sym_private));
Dispatch dispatch(call_site->name());

if(!dispatch.resolve(state, dispatch.name, lookup)) {
if(!lookup_method_missing(state, args,
dispatch, self, recv->lookup_begin(state))) {
return NULL;
}
default_execute = dispatch;
}

state->vm()->metrics().machine.methods_invoked++;

call_site->update(state, recv_class, dispatch);

Executable* meth = dispatch.method;
Module* mod = dispatch.module;

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
} else {
return meth->execute(state, meth, mod, args);
}
max_caches = state->shared().config.machine_call_site_limit.value;
}

Object* CallSite::empty_cache_vcall(STATE, CallSite* call_site, Arguments& args) {
Object* const self = state->vm()->call_frame()->self();
Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);

LookupData lookup(self, recv->lookup_begin(state), G(sym_private));
Dispatch dispatch(call_site->name());

if(!dispatch.resolve(state, call_site->name(), lookup)) {
dispatch.method_missing = eVCall;
if(!lookup_method_missing(state, args,
dispatch, self, recv->lookup_begin(state))) {
return NULL;
}
}
void CallSite::Info::mark(Object* obj, memory::ObjectMark& mark) {
auto_mark(obj, mark);

state->vm()->metrics().machine.methods_invoked++;
CallSite* call_site = as<CallSite>(obj);

call_site->update(state, recv_class, dispatch);
if(!call_site->caches()) return;

Executable* meth = dispatch.method;
Module* mod = dispatch.module;
// 1. Check if individual caches should be evicted.
bool evict_p[call_site->depth()];

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
} else {
return meth->execute(state, meth, mod, args);
for(int i = 0; i < call_site->depth(); i++) {
evict_p[i] = call_site->caches()->cache[i].inefficient_p();
}
}

Object* CallSite::empty_cache_super(STATE, CallSite* call_site,
Arguments& args)
{
CallFrame* call_frame = state->vm()->call_frame();

Symbol* original_name = call_frame->original_name();
if(call_site->name() != original_name) {
call_site->name(original_name);
args.set_name(call_site->name());
int evict_count = 0;
for(int i = 0; i < call_site->depth(); i++) {
if(evict_p[i]) evict_count++;
}

Object* const recv = args.recv();
Class* const recv_class = recv->direct_class(state);
Module* const start = call_frame->module()->superclass();
if(evict_count) {
VM::current()->metrics().machine.inline_cache_evicted += evict_count;

LookupData lookup(call_frame->self(), start, G(sym_private));
Dispatch dispatch(call_site->name());
int new_size = call_site->depth() - evict_count;

if(start->nil_p() || !dispatch.resolve(state, call_site->name(), lookup)) {
if(new_size == 0) {
call_site->depth(0);
delete[] call_site->caches();
call_site->caches(NULL);

LookupData missing_lookup(call_frame->self(),
recv->lookup_begin(state), G(sym_private));
Dispatch missing_dispatch(G(sym_method_missing));
call_site->execute(CallSite::default_execute);
call_site->cache_miss(CallSite::default_execute);

if(!missing_dispatch.resolve(state, G(sym_method_missing), missing_lookup)) {
std::ostringstream msg;
msg << "no method_missing for ";
msg << recv_class->to_string(state);
msg << "#" << call_site->name()->to_string(state);
return;
}

Exception::internal_error(state, msg.str().c_str());
return 0;
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];
}
}

args.unshift(state, call_site->name());
dispatch.method = missing_dispatch.method;
dispatch.module = missing_dispatch.module;
dispatch.method_missing = eSuper;
state->vm()->set_method_missing_reason(dispatch.method_missing);
state->vm()->global_cache()->add_seen(state, call_site->name());
call_site->caches()->depth(new_size);
}

state->vm()->metrics().machine.methods_invoked++;

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

Executable* meth = dispatch.method;
Module* mod = dispatch.module;

if(meth->custom_call_site_p()) {
CallSiteInformation info(call_site->executable(), call_site->ip());
state->set_call_site_information(&info);
Object* res = meth->execute(state, meth, mod, args);
state->set_call_site_information(NULL);
return res;
} else {
return meth->execute(state, meth, mod, args);
for(int i = 0; i < call_site->depth(); i++) {
indexes[i] = i;
}
}

void CallSite::empty_cache_updater(STATE, CallSite* call_site, Class* klass, Dispatch& dispatch) {
MonoInlineCache* cache = MonoInlineCache::create(state, call_site, klass, dispatch);
call_site->update_call_site(state, cache);
}
InlineCaches* caches = call_site->caches();

bool CallSite::update_and_validate(STATE, Object* recv, Symbol* vis, int serial) {
Class* const recv_class = recv->direct_class(state);
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;

if(MonoInlineCache* mono = try_as<MonoInlineCache>(this)) {
if(recv_class->data_raw() == mono->receiver_data_raw()) {
return mono->method()->serial()->to_native() == serial;
// TODO: pass State through the GC!
VM::current()->metrics().machine.inline_cache_reordered++;
}
}

if(PolyInlineCache* cache = try_as<PolyInlineCache>(this)) {
InlineCacheEntry* ice = cache->get_entry(recv_class);
if(likely(ice)) return ice->method()->serial()->to_native() == serial;
}
if(reorder_p) {
InlineCache* inline_caches = static_cast<InlineCache*>(
alloca(sizeof(CallSite) * call_site->depth()));

LookupData lookup(state->vm()->call_frame()->self(),
recv->lookup_begin(state), G(sym_public));
Dispatch dispatch(name());
for(int i = 0; i < call_site->depth(); i++) {
inline_caches[i] = caches->cache[i];
}

if(dispatch.resolve(state, name(), lookup)) {
update(state, recv_class, dispatch);
return dispatch.method->serial()->to_native() == serial;
for(int i = 0; i < call_site->depth(); i++) {
caches->cache[i] = inline_caches[indexes[i]];
}
}
return false;
}

bool CallSite::lookup_method_missing(STATE,
Arguments& args, Dispatch& dispatch, Object* self, Module* begin)
{
LookupData missing_lookup(self, begin, G(sym_private));
Dispatch missing_dispatch(G(sym_method_missing));

if(!missing_dispatch.resolve(state, G(sym_method_missing), missing_lookup)) {
std::ostringstream msg;
msg << "no method_missing for ";
msg << begin->to_string(state);
msg << "#" << dispatch.name->to_string(state);
// 3. Mark remaining caches.
for(int i = 0; i < call_site->depth(); i++) {
InlineCache* cache = &caches->cache[i];

Exception::internal_error(state, msg.str().c_str());
return false;
}

args.unshift(state, dispatch.name);
dispatch.method = missing_dispatch.method;
dispatch.module = missing_dispatch.module;
state->vm()->set_method_missing_reason(dispatch.method_missing);
state->vm()->global_cache()->add_seen(state, dispatch.name);
if(Object* ref = mark.call(cache->receiver_class())) {
cache->receiver_class(as<Class>(ref));
mark.just_set(call_site, ref);
}

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

void CallSite::Info::mark(Object* obj, memory::ObjectMark& mark) {
auto_mark(obj, mark);
if(Object* ref = mark.call(cache->executable())) {
cache->executable(as<Executable>(ref));
mark.just_set(call_site, ref);
}
}
}

}
511 changes: 443 additions & 68 deletions machine/builtin/call_site.hpp

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions machine/builtin/class.hpp
Original file line number Diff line number Diff line change
@@ -23,6 +23,14 @@ namespace rubinius {
union ClassData {
struct ClassFlags f;
uint64_t raw;

uint32_t class_id() const {
return f.class_id;
}

uint32_t serial_id() const {
return f.serial_id;
}
};

class Class : public Module {
17 changes: 17 additions & 0 deletions machine/builtin/exception.cpp
Original file line number Diff line number Diff line change
@@ -101,6 +101,19 @@ namespace rubinius {
RubyException::raise(exc);
}

Exception* Exception::make_no_method_error(STATE, Arguments& args) {
std::ostringstream msg;
msg << "undefined method `" << args.name()->cpp_str(state)
<< "' for " << args.recv()->to_s(state)->c_str(state);

return Exception::make_exception(state,
get_no_method_error(state), msg.str().c_str());
}

void Exception::raise_no_method_error(STATE, Arguments& args) {
RubyException::raise(Exception::make_no_method_error(state, args), true);
}

Exception* Exception::make_frozen_exception(STATE, Object* obj) {
std::ostringstream msg;
msg << "can't modify frozen instance of ";
@@ -472,6 +485,10 @@ namespace rubinius {
return as<Class>(G(object)->get_const(state, "NotImplementedError"));
}

Class* Exception::get_no_method_error(STATE) {
return as<Class>(G(object)->get_const(state, "NoMethodError"));
}

Class* Exception::get_errno_error(STATE, Fixnum* ern) {
if(Class* cls = try_as<Class>(G(errno_mapping)->fetch(state, ern))) {
return cls;
4 changes: 4 additions & 0 deletions machine/builtin/exception.hpp
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ namespace rubinius {
class Class;
class Array;
class CompiledCode;
class Arguments;

class Exception : public Object {
public:
@@ -47,6 +48,7 @@ namespace rubinius {
static Exception* make_argument_error(STATE, int expected, int given, Symbol* name=0);
static Exception* make_encoding_compatibility_error(STATE, Object* a, Object* b);
static Exception* make_frozen_exception(STATE, Object* obj);
static Exception* make_no_method_error(STATE, Arguments& args);

NORETURN(static void raise_argument_error(STATE, int expected, int given));
NORETURN(static void raise_argument_error(STATE, const char* reason));
@@ -74,6 +76,7 @@ namespace rubinius {
NORETURN(static void raise_fiber_error(STATE, const char* reason));
NORETURN(static void raise_memory_error(STATE));
NORETURN(static void raise_frozen_error(STATE, Object* obj));
NORETURN(static void raise_no_method_error(STATE, Arguments& args));
NORETURN(static void raise_encoding_compatibility_error(STATE, Object* a, Object* b));
NORETURN(static void raise_not_implemented_error(STATE, const char* feature));
NORETURN(static void raise_errno_wait_readable(STATE, int error));
@@ -125,6 +128,7 @@ namespace rubinius {
static Class* get_runtime_error(STATE);
static Class* get_encoding_compatibility_error(STATE);
static Class* get_not_implemented_error(STATE);
static Class* get_no_method_error(STATE);

class Info : public TypeInfo {
public:
131 changes: 0 additions & 131 deletions machine/builtin/mono_inline_cache.cpp

This file was deleted.

77 changes: 0 additions & 77 deletions machine/builtin/mono_inline_cache.hpp

This file was deleted.

22 changes: 1 addition & 21 deletions machine/builtin/object.cpp
Original file line number Diff line number Diff line change
@@ -24,7 +24,6 @@
#include "builtin/method_table.hpp"
#include "builtin/object.hpp"
#include "builtin/packed_object.hpp"
#include "builtin/respond_to_cache.hpp"
#include "builtin/symbol.hpp"
#include "builtin/string.hpp"
#include "builtin/tuple.hpp"
@@ -842,26 +841,7 @@ namespace rubinius {
Object* self = this;
OnStack<1> os(state, self);

Object* responds = respond_to(state, name, priv);

if(!responds) return NULL;

CompiledCode* code = NULL;
CallSiteInformation* info = state->vm()->saved_call_site_information();

if(info && (code = try_as<CompiledCode>(info->executable))) {
CallSite* existing = code->machine_code()->call_site(state, info->ip);
if(RespondToCache* rct = try_as<RespondToCache>(existing)) {
existing = rct->fallback_call_site();
}
RespondToCache* cache = RespondToCache::create(state, existing,
self, name, priv, responds, 1);
state->vm()->global_cache()->add_seen(state, name);
atomic::memory_barrier();
existing->update_call_site(state, cache);
}

return responds;
return respond_to(state, name, priv);
}

Object* Object::respond_to(STATE, Symbol* name, Object* priv) {
193 changes: 0 additions & 193 deletions machine/builtin/poly_inline_cache.cpp

This file was deleted.

152 changes: 0 additions & 152 deletions machine/builtin/poly_inline_cache.hpp

This file was deleted.

75 changes: 0 additions & 75 deletions machine/builtin/respond_to_cache.cpp

This file was deleted.

80 changes: 0 additions & 80 deletions machine/builtin/respond_to_cache.hpp

This file was deleted.

8 changes: 1 addition & 7 deletions machine/dispatch.cpp
Original file line number Diff line number Diff line change
@@ -28,13 +28,7 @@ namespace rubinius {
method_missing = reason;
lookup.min_visibility = G(sym_private);
if(!resolve(state, G(sym_method_missing), lookup)) {
std::ostringstream msg;
msg << "no method_missing for ";
msg << lookup.from->to_string(state);
msg << "#" << original_name->to_string(state);

Exception::internal_error(state, msg.str().c_str());
return 0;
Exception::raise_no_method_error(state, args);
}

method_missing = reason;
8 changes: 2 additions & 6 deletions machine/globals.hpp
Original file line number Diff line number Diff line change
@@ -112,9 +112,7 @@ namespace rubinius {
memory::TypedRoot<Class*> exc_vm_internal;
memory::TypedRoot<Class*> exc_vm_bad_bytecode;
memory::TypedRoot<Class*> call_site;
memory::TypedRoot<Class*> mono_inline_cache;
memory::TypedRoot<Class*> poly_inline_cache;
memory::TypedRoot<Class*> inline_cache_entry;
memory::TypedRoot<Class*> inline_cache;
memory::TypedRoot<Class*> call_custom_cache;
memory::TypedRoot<Class*> respond_to_cache;
memory::TypedRoot<Class*> constant_cache;
@@ -247,9 +245,7 @@ namespace rubinius {
exc_vm_internal(&roots),
exc_vm_bad_bytecode(&roots),
call_site(&roots),
mono_inline_cache(&roots),
poly_inline_cache(&roots),
inline_cache_entry(&roots),
inline_cache(&roots),
call_custom_cache(&roots),
respond_to_cache(&roots),
constant_cache(&roots),
4 changes: 2 additions & 2 deletions machine/instructions.def
Original file line number Diff line number Diff line change
@@ -1807,7 +1807,7 @@ instruction check_serial(literal serial) [ receiver -- boolean ]
Object* recv = stack_pop();
CallSite* call_site = reinterpret_cast<CallSite*>(literal);

stack_push(RBOOL(call_site->update_and_validate(state,
stack_push(RBOOL(call_site->valid_serial_p(state,
recv, G(sym_public), serial)));
end

@@ -1821,7 +1821,7 @@ instruction check_serial_private(literal serial) [ receiver -- boolean ]
Object* recv = stack_pop();
CallSite* call_site = reinterpret_cast<CallSite*>(literal);

stack_push(RBOOL(call_site->update_and_validate(state,
stack_push(RBOOL(call_site->valid_serial_p(state,
recv, G(sym_private), serial)));
end

11 changes: 8 additions & 3 deletions machine/jit/llvm/inline.cpp
Original file line number Diff line number Diff line change
@@ -9,11 +9,10 @@
#include "jit/llvm/stack_args.hpp"

#include "builtin/alias.hpp"
#include "builtin/call_site.hpp"
#include "builtin/method_table.hpp"
#include "builtin/native_function.hpp"
#include "builtin/lookup_table.hpp"
#include "builtin/mono_inline_cache.hpp"
#include "builtin/poly_inline_cache.hpp"

#include "ffi_util.hpp"

@@ -31,13 +30,18 @@ namespace rubinius {
}

bool Inliner::consider_mono() {
return false;
/* TODO: inline cache
MonoInlineCache* cache = try_as<MonoInlineCache>(call_site_);
if(!cache) return false;
int hits = cache->hits();
return inline_for_class(cache->receiver_class(), cache->receiver_data(), hits);
*/
}

bool Inliner::consider_poly() {
return false;
/* TODO: inline cache
PolyInlineCache* cache = try_as<PolyInlineCache>(call_site_);
if(!cache) return false;
@@ -142,14 +146,15 @@ namespace rubinius {
set_result(phi);
return true;
*/
}

bool Inliner::inline_for_class(Class* klass, ClassData data, int hits) {
if(!klass) return false;

Module* defined_in = 0;
Executable* meth = klass->find_method(
ops_.llvm_state()->state(),call_site_->name(), &defined_in);
ops_.llvm_state()->state(), call_site_->name(), &defined_in);

if(!meth) {
if(ops_.llvm_state()->config().jit_inline_debug) {
32 changes: 9 additions & 23 deletions machine/jit/llvm/offset.hpp
Original file line number Diff line number Diff line change
@@ -121,15 +121,16 @@ namespace Float {
namespace HeaderWord {
const static int flags64 = 0;
}
namespace InlineCacheEntry {
namespace InlineCache {
const static int header = 0;
const static int stored_module = 1;
const static int receiver_class = 2;
const static int method = 3;
const static int receiver_class_id = 4;
const static int receiver_serial_id = 5;
const static int method_missing = 6;
const static int hits = 7;
const static int receiver_class = 1;
const static int stored_module = 2;
const static int executable = 3;
const static int next = 4;
const static int receiver_class_id = 5;
const static int receiver_serial_id = 6;
const static int method_missing = 7;
const static int hits = 8;
}
namespace Module {
const static int header = 0;
@@ -142,16 +143,6 @@ namespace Module {
const static int mirror = 7;
const static int subclasses = 8;
}
namespace MonoInlineCache {
const static int header = 0;
const static int receiver_class_id = 1;
const static int receiver_serial_id = 2;
const static int receiver_class = 3;
const static int stored_module = 4;
const static int method = 5;
const static int method_missing = 6;
const static int hits = 7;
}
namespace Numeric {
const static int header = 0;
}
@@ -168,11 +159,6 @@ namespace ObjectHeader {
const static int ivars = 2;
const static int body = 3;
}
namespace PolyInlineCache {
const static int header = 0;
const static int entries = 1;
const static int seen_classes_overflow = 2;
}
namespace Proc {
const static int block = 0;
const static int lambda = 1;
383 changes: 156 additions & 227 deletions machine/jit/llvm/types32.cpp.gen

Large diffs are not rendered by default.

37 changes: 8 additions & 29 deletions machine/jit/llvm/types32.ll
Original file line number Diff line number Diff line change
@@ -70,45 +70,24 @@ declare void @outputDispatch(%"struct.rubinius::Dispatch"*)
%"struct.rubinius::Object"* (%"struct.rubinius::State"*, %"struct.rubinius::CallSite"*, %"struct.rubinius::Arguments"*)*, ; executor
%"struct.rubinius::Object"* (%"struct.rubinius::State"*, %"struct.rubinius::CallSite"*, %"struct.rubinius::Arguments"*)*, ; fallback
void (%"struct.rubinius::State"*, %"struct.rubinius::CallSite"*, %"struct.rubinius::Class"*, %"struct.rubinius::Dispatch"*)*, ; updater
%"struct.rubinius::Executable"*, ; executable
i32 ; ip
%"struct.rubinius::Executable"* ; executable
}

declare void @outputCallSite(%"struct.rubinius::CallSite"*)

%"struct.rubinius::MonoInlineCache" = type {
%"struct.rubinius::CallSite", ; header
i32, ; receiver_class_id
i32, ; receiver_serial_id
%"struct.rubinius::InlineCache" = type {
%"struct.rubinius::Object", ; header
%"struct.rubinius::Class"*, ; receiver_class
%"struct.rubinius::Module"*, ; stored_module
%"struct.rubinius::Executable"*, ; method
%"struct.rubinius::Executable"*, ; executable
%"struct.rubinius::Object"*, ; next
i32, ; receiver_class_id
i32, ; receiver_serial_id
i32, ; method_missing
i32 ; hits
}

declare void @outputMonoInlineCache(%"struct.rubinius::MonoInlineCache"*)

%"struct.rubinius::PolyInlineCache" = type {
%"struct.rubinius::CallSite", ; header
[3 x %"struct.rubinius::InlineCacheEntry"*], ; entries
i32 ; seen_classes_overflow
}

declare void @outputPolyInlineCache(%"struct.rubinius::PolyInlineCache"*)

%"struct.rubinius::InlineCacheEntry" = type {
%"struct.rubinius::Object", ; header
%"struct.rubinius::Module"*, ; stored_module
%"struct.rubinius::Class"*, ; receiver_class
%"struct.rubinius::Executable"*, ; method
i32, ; receiver_class_id
i32, ; receiver_serial_id
i32, ; method_missing
i32 ; hits
}

declare void @outputInlineCacheEntry(%"struct.rubinius::InlineCacheEntry"*)
declare void @outputInlineCache(%"struct.rubinius::InlineCache"*)

%"struct.rubinius::ConstantCache" = type {
%"struct.rubinius::Object", ; header
382 changes: 156 additions & 226 deletions machine/jit/llvm/types64.cpp.gen

Large diffs are not rendered by default.

34 changes: 7 additions & 27 deletions machine/jit/llvm/types64.ll
Original file line number Diff line number Diff line change
@@ -76,39 +76,19 @@ declare void @outputDispatch(%"struct.rubinius::Dispatch"*)

declare void @outputCallSite(%"struct.rubinius::CallSite"*)

%"struct.rubinius::MonoInlineCache" = type {
%"struct.rubinius::CallSite", ; header
i32, ; receiver_class_id
i32, ; receiver_serial_id
%"struct.rubinius::InlineCache" = type {
%"struct.rubinius::Object", ; header
%"struct.rubinius::Class"*, ; receiver_class
%"struct.rubinius::Module"*, ; stored_module
%"struct.rubinius::Executable"*, ; method
%"struct.rubinius::Executable"*, ; executable
%"struct.rubinius::Object"*, ; next
i32, ; receiver_class_id
i32, ; receiver_serial_id
i32, ; method_missing
i32 ; hits
}

declare void @outputMonoInlineCache(%"struct.rubinius::MonoInlineCache"*)

%"struct.rubinius::PolyInlineCache" = type {
%"struct.rubinius::CallSite", ; header
[3 x %"struct.rubinius::InlineCacheEntry"*], ; entries
i32 ; seen_classes_overflow
}

declare void @outputPolyInlineCache(%"struct.rubinius::PolyInlineCache"*)

%"struct.rubinius::InlineCacheEntry" = type {
%"struct.rubinius::Object", ; header
%"struct.rubinius::Module"*, ; stored_module
%"struct.rubinius::Class"*, ; receiver_class
%"struct.rubinius::Executable"*, ; method
i32, ; receiver_class_id
i32, ; receiver_serial_id
i32, ; method_missing
i32 ; hits
}

declare void @outputInlineCacheEntry(%"struct.rubinius::InlineCacheEntry"*)
declare void @outputInlineCache(%"struct.rubinius::InlineCache"*)

%"struct.rubinius::ConstantCache" = type {
%"struct.rubinius::Object", ; header
10 changes: 4 additions & 6 deletions machine/jit/llvm/util.cpp
Original file line number Diff line number Diff line change
@@ -680,14 +680,12 @@ extern "C" {
return ary;
}

Object* rbx_check_serial(STATE, CallSite* call_site,
int serial, Object* recv) {
return RBOOL(call_site->update_and_validate(state, recv, G(sym_public), serial));
Object* rbx_check_serial(STATE, CallSite* call_site, int serial, Object* recv) {
return RBOOL(call_site->valid_serial_p(state, recv, G(sym_public), serial));
}

Object* rbx_check_serial_private(STATE, CallSite* call_site,
int serial, Object* recv) {
return RBOOL(call_site->update_and_validate(state, recv, G(sym_private), serial));
Object* rbx_check_serial_private(STATE, CallSite* call_site, int serial, Object* recv) {
return RBOOL(call_site->valid_serial_p(state, recv, G(sym_private), serial));
}

Object* rbx_find_const(STATE, int index, Object* top) {
26 changes: 17 additions & 9 deletions machine/jit/llvm/visit.hpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#include "instructions_util.hpp"

#include "builtin/code_db.hpp"
#include "builtin/call_site.hpp"
#include "builtin/symbol.hpp"
#include "builtin/tuple.hpp"
#include "builtin/constant_cache.hpp"
#include "builtin/mono_inline_cache.hpp"
#include "builtin/poly_inline_cache.hpp"
#include "builtin/respond_to_cache.hpp"
#include "builtin/lookup_table.hpp"

#include "jit/llvm/operations.hpp"
@@ -1377,6 +1375,7 @@ namespace rubinius {
b().CreateBr(info().return_pad());
}

/* TODO: inline cache
void emit_respond_to(RespondToCache* cache, opcode& which, opcode args) {
BasicBlock* cont = new_block("check_class_respond_to");
BasicBlock* success = new_block("success");
@@ -1433,6 +1432,7 @@ namespace rubinius {
stack_push(ret);
}
}
*/

void visit_invoke_primitive(opcode which, opcode args) {
InvokePrimitive invoker = reinterpret_cast<InvokePrimitive>(which);
@@ -1534,8 +1534,9 @@ namespace rubinius {

void visit_send_stack(opcode& which, opcode args) {
CallSite** call_site_ptr = reinterpret_cast<CallSite**>(&which);
CallSite* call_site = *call_site_ptr;
// CallSite* call_site = *call_site_ptr;

/* TODO: inline cache
if(RespondToCache* respond_to = try_as<RespondToCache>(call_site)) {
emit_respond_to(respond_to, which, args);
return;
@@ -1545,17 +1546,20 @@ namespace rubinius {
invoke_call_site(which, args);
return;
}
*/

BasicBlock* class_failure = new_block("class_fallback");
BasicBlock* serial_failure = new_block("serial_fallback");
BasicBlock* cont = new_block("continue");

Inliner inl(ctx_, *this, call_site_ptr, args, class_failure, serial_failure);

bool res = false;

/* TODO: inline cache
MonoInlineCache* mono = try_as<MonoInlineCache>(call_site);
PolyInlineCache* poly = try_as<PolyInlineCache>(call_site);
bool res = false;
if(mono) {
res = inl.consider_mono();
} else if(poly) {
@@ -1568,6 +1572,7 @@ namespace rubinius {
if(poly && poly->seen_classes_overflow() > llvm_state()->shared().config.jit_limit_deoptimize) {
inl.use_send_for_failure();
}
*/

if(!res) {
invoke_call_site(which, args);
@@ -1591,7 +1596,8 @@ namespace rubinius {
}
stack_push(inl.result());

if(mono) {
// TODO: inline cache; if(mono) {
if(false) {
type::KnownType kt = inl.guarded_type();

if(kt.local_source_p() && kt.known_p()) {
@@ -1795,10 +1801,11 @@ namespace rubinius {
set_has_side_effects();

CallSite** call_site_ptr = reinterpret_cast<CallSite**>(&which);
CallSite* call_site = *call_site_ptr;
// TODO: inline cache
// CallSite* call_site = *call_site_ptr;
CompiledCode* block_code = 0;

if(call_site->regular_call() &&
if(false /* TODO: inline cache call_site->regular_call() */ &&
llvm_state()->config().jit_inline_blocks &&
!ctx_->inlined_block()) {
if(current_block_) {
@@ -3062,7 +3069,7 @@ namespace rubinius {
}

void emit_check_serial(opcode& index, opcode serial, const char* function) {

/* TODO: inline cache
CallSite** call_site_ptr = reinterpret_cast<CallSite**>(&index);
Value* call_site_ptr_const = b().CreateIntToPtr(
clong(reinterpret_cast<uintptr_t>(call_site_ptr)),
@@ -3213,6 +3220,7 @@ namespace rubinius {
phi->addIncoming(fallback_result, fallback);
stack_push(phi);
*/
}

void visit_check_serial(opcode& index, opcode serial) {
8 changes: 7 additions & 1 deletion machine/lookup_data.hpp
Original file line number Diff line number Diff line change
@@ -10,11 +10,17 @@ namespace rubinius {
Module* from;
Symbol* min_visibility;

LookupData()
: recv(NULL)
, from(NULL)
, min_visibility(NULL)
{ }

LookupData(Object* recv, Module* mod, Symbol* min_vis)
: recv(recv)
, from(mod)
, min_visibility(min_vis)
{}
{ }
};
}

2 changes: 1 addition & 1 deletion machine/machine_code.cpp
Original file line number Diff line number Diff line change
@@ -248,7 +248,7 @@ namespace rubinius {
Symbol* name = try_as<Symbol>(lits->at(opcodes[ip + 1]));
if(!name) name = nil<Symbol>();

CallSite* call_site = CallSite::empty(state, name, original, ip);
CallSite* call_site = CallSite::create(state, name, ip);

if(op == InstructionSequence::insn_send_vcall) {
allow_private = true;
14 changes: 14 additions & 0 deletions machine/metrics.cpp
Original file line number Diff line number Diff line change
@@ -362,12 +362,26 @@ namespace rubinius {
"machine.global_cache.misses", metrics_data_.machine.global_cache_misses));
metrics_map_.push_back(new MetricsItem(
"machine.call_site.count", metrics_data_.machine.call_site_count));
metrics_map_.push_back(new MetricsItem(
"machine.call_site.full", metrics_data_.machine.call_site_full));
metrics_map_.push_back(new MetricsItem(
"machine.call_site.polymorphic", metrics_data_.machine.call_site_polymorphic));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.count", metrics_data_.machine.inline_cache_count));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.hits", metrics_data_.machine.inline_cache_hits));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.misses", metrics_data_.machine.inline_cache_misses));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.evicted", metrics_data_.machine.inline_cache_evicted));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.updated", metrics_data_.machine.inline_cache_updated));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.replaced", metrics_data_.machine.inline_cache_replaced));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.reordered", metrics_data_.machine.inline_cache_reordered));
metrics_map_.push_back(new MetricsItem(
"machine.inline_cache.disabled", metrics_data_.machine.inline_cache_disabled));
metrics_map_.push_back(new MetricsItem(
"machine.cache.resets", metrics_data_.machine.cache_resets));
metrics_map_.push_back(new MetricsItem(
21 changes: 21 additions & 0 deletions machine/metrics.hpp
Original file line number Diff line number Diff line change
@@ -166,9 +166,16 @@ namespace rubinius {
metric global_cache_hits;
metric global_cache_misses;
metric call_site_count;
metric call_site_full;
metric call_site_polymorphic;
metric inline_cache_count;
metric inline_cache_hits;
metric inline_cache_misses;
metric inline_cache_evicted;
metric inline_cache_updated;
metric inline_cache_replaced;
metric inline_cache_reordered;
metric inline_cache_disabled;
metric cache_resets;
metric methods_invoked;
metric blocks_invoked;
@@ -185,9 +192,16 @@ namespace rubinius {
global_cache_hits = 0;
global_cache_misses = 0;
call_site_count = 0;
call_site_full = 0;
call_site_polymorphic = 0;
inline_cache_count = 0;
inline_cache_hits = 0;
inline_cache_misses = 0;
inline_cache_evicted = 0;
inline_cache_updated = 0;
inline_cache_replaced = 0;
inline_cache_reordered = 0;
inline_cache_disabled = 0;
cache_resets = 0;
methods_invoked = 0;
blocks_invoked = 0;
@@ -202,12 +216,19 @@ namespace rubinius {
checkpoints += data.checkpoints;
stops += data.stops;
call_site_count += data.call_site_count;
call_site_full += data.call_site_full;
call_site_polymorphic += data.call_site_polymorphic;
global_cache_count += data.global_cache_count;
global_cache_hits += data.global_cache_hits;
global_cache_misses += data.global_cache_misses;
inline_cache_count += data.inline_cache_count;
inline_cache_hits += data.inline_cache_hits;
inline_cache_misses += data.inline_cache_misses;
inline_cache_evicted += data.inline_cache_evicted;
inline_cache_updated += data.inline_cache_updated;
inline_cache_replaced += data.inline_cache_replaced;
inline_cache_reordered += data.inline_cache_reordered;
inline_cache_disabled += data.inline_cache_disabled;
cache_resets += data.cache_resets;
methods_invoked += data.methods_invoked;
blocks_invoked += data.blocks_invoked;
7 changes: 1 addition & 6 deletions machine/ontology.cpp
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
#include "builtin/basic_object.hpp"
#include "builtin/block_environment.hpp"
#include "builtin/byte_array.hpp"
#include "builtin/call_site.hpp"
#include "builtin/character.hpp"
#include "builtin/class.hpp"
#include "builtin/code_db.hpp"
@@ -52,9 +53,6 @@
#include "builtin/proc.hpp"
#include "builtin/variable_scope.hpp"
#include "builtin/location.hpp"
#include "builtin/mono_inline_cache.hpp"
#include "builtin/poly_inline_cache.hpp"
#include "builtin/respond_to_cache.hpp"
#include "builtin/constant_cache.hpp"
#include "builtin/weakref.hpp"
#include "builtin/fiber.hpp"
@@ -256,10 +254,7 @@ namespace rubinius {
NativeMethod::bootstrap(state);

CallSite::bootstrap(state);
MonoInlineCache::bootstrap(state);
PolyInlineCache::bootstrap(state);
ConstantCache::bootstrap(state);
RespondToCache::bootstrap(state);
Fiber::bootstrap(state);
Alias::bootstrap(state);
Randomizer::bootstrap(state);
8 changes: 0 additions & 8 deletions machine/vm.cpp
Original file line number Diff line number Diff line change
@@ -489,10 +489,6 @@ namespace rubinius {
void VM::gc_scan(memory::GarbageCollector* gc) {
gc->walk_call_frame(call_frame_);

if(CallSiteInformation* info = saved_call_site_information()) {
info->executable = as<Executable>(gc->mark_object(info->executable));
}

State ls(this);

shared.tool_broker()->at_gc(&ls);
@@ -508,9 +504,5 @@ namespace rubinius {

void VM::gc_verify(memory::GarbageCollector* gc) {
gc->verify_call_frame(call_frame_);

if(CallSiteInformation* info = saved_call_site_information()) {
info->executable->validate();
}
}
};
14 changes: 7 additions & 7 deletions rakelib/jit.rake
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
namespace :jit do
task :generate_header do
puts "GEN machine/llvm/types{32|64}.cpp.gen"
`llvm-as < machine/llvm/types32.ll > machine/gen/types32.bc`
`llvm-as < machine/llvm/types64.ll > machine/gen/types64.bc`
`llc -march=cpp -cppgen=contents -o machine/llvm/types32.cpp.gen machine/gen/types32.bc`
`llc -march=cpp -cppgen=contents -o machine/llvm/types64.cpp.gen machine/gen/types64.bc`
puts "GEN machine/jit/llvm/types{32|64}.cpp.gen"
`llvm-as < machine/jit/llvm/types32.ll > machine/gen/types32.bc`
`llvm-as < machine/jit/llvm/types64.ll > machine/gen/types64.bc`
`llc -march=cpp -cppgen=contents -o machine/jit/llvm/types32.cpp.gen machine/gen/types32.bc`
`llc -march=cpp -cppgen=contents -o machine/jit/llvm/types64.cpp.gen machine/gen/types64.bc`
end

task :generate_offsets do
classes = {}
File.open "machine/llvm/types64.ll" do |f|
File.open "machine/jit/llvm/types64.ll" do |f|
while line = f.gets
if m1 = /%"?(struct|union)\.rubinius::([^"]*)"?\s*=\s*type\s*\{\n/.match(line)
line = f.gets
@@ -30,7 +30,7 @@ namespace :jit do
end
end

File.open "machine/llvm/offset.hpp", "w" do |f|
File.open "machine/jit/llvm/offset.hpp", "w" do |f|
f.puts "#ifndef RBX_LLVM_OFFSET_HPP"
f.puts "#define RBX_LLVM_OFFSET_HPP"
f.puts ""
3 changes: 0 additions & 3 deletions rakelib/vm.rake
Original file line number Diff line number Diff line change
@@ -111,9 +111,6 @@ field_extract_headers = %w[
machine/builtin/location.hpp
machine/builtin/constant_cache.hpp
machine/builtin/call_site.hpp
machine/builtin/mono_inline_cache.hpp
machine/builtin/poly_inline_cache.hpp
machine/builtin/respond_to_cache.hpp
machine/builtin/weakref.hpp
machine/builtin/fiber.hpp
machine/builtin/thunk.hpp
20 changes: 20 additions & 0 deletions spec/core/callsite/depth_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
require File.expand_path('../../fixtures/call_site.rb', __FILE__)

describe "Rubinius::CallSite#invokes" do
before :each do
@executable = CallSiteSpecs::A.executable(:miss)
end

it "returns 0 before the call site has executed" do
@executable.call_sites.first.invokes.should == 0
end

it "returns the number of invocations that do not hit a cache entry" do
obj = CallSiteSpecs::A.new
obj.miss(1).should == "1"
obj.miss("2").should == "2"

@executable.call_sites.first.invokes.should == 2
end
end

11 changes: 0 additions & 11 deletions spec/core/callsite/executable_spec.rb

This file was deleted.

26 changes: 13 additions & 13 deletions spec/core/callsite/hits_spec.rb
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
require File.expand_path('../../fixtures/call_site.rb', __FILE__)

describe "Rubinius::CallSite#hits" do
before :each do
@executable = CallSiteSpecs::A.executable(:c)
@klass = Class.new do
def m(a)
a.to_s
end
end
end

it "returns 0 before the call site has executed" do
@executable.call_sites.first.hits.should == 0
@klass.new.method(:m).executable.call_sites.first.hits.should == 0
end

it "returns the number of times the call site has executed" do
obj = CallSiteSpecs::A.new
obj.c
obj.c
it "returns the call site invocations that have hit the cache entries" do
obj = @klass.new

obj.m :a
obj.m :b
obj.m :c

# needs to retrieve the new call site because it has been replaced
@executable.call_sites.first.hits.should == 2
obj.method(:m).executable.call_sites.first.hits.should == 2
end
end




23 changes: 23 additions & 0 deletions spec/core/callsite/invokes_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require File.expand_path('../../fixtures/call_site.rb', __FILE__)

describe "Rubinius::CallSite#invokes" do
it "returns 0 before the call site has executed" do
executable = CallSiteSpecs::A.executable(:c)
executable.call_sites.first.invokes.should == 0
end

it "returns the call site invocations that do not hit the cache" do
obj = Class.new do
def m(a)
a.to_s
end
end.new

obj.m 1
obj.m :a
obj.m :b
obj.m "2"

obj.method(:m).executable.call_sites.first.invokes.should == 3
end
end
11 changes: 0 additions & 11 deletions spec/core/callsite/location_spec.rb

This file was deleted.

26 changes: 26 additions & 0 deletions spec/core/callsite/misses_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
describe "Rubinius::CallSite#misses" do
before :each do
@klass = Class.new do
def m(a)
a.to_s
end
end
end

it "returns 0 before the call site has executed" do
@klass.new.method(:m).executable.call_sites.first.misses.should == 0
end

it "returns the call site invocations that have missed the cache entries" do
obj = @klass.new

obj.m 1
obj.m :a
obj.m "a"
obj.m Object.new
obj.m []

obj.method(:m).executable.call_sites.first.misses.should == 4
end
end

2 changes: 1 addition & 1 deletion spec/core/constantcache/location_spec.rb
Original file line number Diff line number Diff line change
@@ -6,6 +6,6 @@
end

it "returns the file and line number of the call site" do
@cache.location.should =~ %r{spec/core/fixtures/call_site\.rb:74$}
@cache.location.should =~ %r{spec/core/fixtures/call_site\.rb:78$}
end
end
4 changes: 4 additions & 0 deletions spec/core/fixtures/call_site.rb
Original file line number Diff line number Diff line change
@@ -51,6 +51,10 @@ def p
a B.new
a BB.new
end

def miss(a)
a.to_s
end
end

class B
14 changes: 0 additions & 14 deletions spec/core/monoinlinecache/executable_spec.rb

This file was deleted.

15 changes: 0 additions & 15 deletions spec/core/monoinlinecache/hits_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/monoinlinecache/ip_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/monoinlinecache/location_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/monoinlinecache/method_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/monoinlinecache/name_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/monoinlinecache/receiver_class_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/monoinlinecache/stored_module_spec.rb

This file was deleted.

22 changes: 0 additions & 22 deletions spec/core/polyinlinecache/entries_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/polyinlinecache/executable_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/polyinlinecache/hits_spec.rb

This file was deleted.

13 changes: 0 additions & 13 deletions spec/core/polyinlinecache/ip_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/polyinlinecache/location_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/polyinlinecache/name_spec.rb

This file was deleted.

12 changes: 0 additions & 12 deletions spec/core/respondtocache/executable_spec.rb

This file was deleted.

15 changes: 0 additions & 15 deletions spec/core/respondtocache/hits_spec.rb

This file was deleted.

13 changes: 0 additions & 13 deletions spec/core/respondtocache/ip_spec.rb

This file was deleted.

13 changes: 0 additions & 13 deletions spec/core/respondtocache/location_spec.rb

This file was deleted.

13 changes: 0 additions & 13 deletions spec/core/respondtocache/name_spec.rb

This file was deleted.

13 changes: 0 additions & 13 deletions spec/core/respondtocache/receiver_class_spec.rb

This file was deleted.

31 changes: 0 additions & 31 deletions spec/core/respondtocache/responds_spec.rb

This file was deleted.

13 changes: 0 additions & 13 deletions spec/core/respondtocache/visibility_spec.rb

This file was deleted.

0 comments on commit f65a474

Please sign in to comment.