bool InlineCache::fill_private(STATE, Symbol* name, Module* start) { MethodTableBucket* entry; Module* module = start; // Check the global cache first! GlobalCache::cache_entry* global_entry = state->global_cache->lookup(module, name); if(global_entry && !global_entry->method_missing) { this->method = global_entry->method; this->module = global_entry->module; return true; } do { entry = module->method_table()->find_entry(state, name); /* Nothing, there? Ok, keep looking. */ if(entry) { /* A 'false' method means to terminate method lookup. * (eg. undef_method) */ if(entry->undef_p(state)) return false; /* The method was callable, but we need to keep looking * for the implementation, so make the invocation bypass all further * visibility checks. * * This is pretty much always where a subclass marks a superclass * method as public. We don't move the method, we just put this * marker into the method table. */ if(!entry->method()->nil_p()) { this->method = entry->method(); this->module = module; state->global_cache->retain(state, start, name, this->module, this->method, false, !entry->public_p(state)); return true; } } module = module->superclass(); /* No more places to look, we couldn't find it. */ if(module->nil_p()) return false; } while(1); // Shouldn't be here! rubinius::abort(); }
MethodMissingReason InlineCache::fill_public(STATE, Object* self, Symbol* name) { MethodTableBucket* entry; Module* module = klass_; // Check the global cache first! GlobalCache::cache_entry* global_entry = state->global_cache->lookup(module, name); if(global_entry && global_entry->is_public && !global_entry->method_missing) { this->method = global_entry->method; this->module = global_entry->module; return eNone; } bool skip_vis_check = false; do { entry = module->method_table()->find_entry(state, name); /* Nothing, there? Ok, keep looking. */ if(entry) { /* A 'false' method means to terminate method lookup. * (eg. undef_method) */ if(entry->undef_p(state)) return eNormal; if(!skip_vis_check) { /* The method is private, but this wasn't a private send. */ if(entry->private_p(state)) { return ePrivate; } else if(entry->protected_p(state)) { /* The method is protected, but it's not being called from * the same module */ if(!self->kind_of_p(state, module)) { return eProtected; } } } /* The method was callable, but we need to keep looking * for the implementation, so make the invocation bypass all further * visibility checks. * * This is pretty much always where a subclass marks a superclass * method as public. We don't move the method, we just put this * marker into the method table. */ if(entry->method()->nil_p()) { skip_vis_check = true; } else { this->method = entry->method(); this->module = module; state->global_cache->retain(state, klass_, name, this->module, this->method, false, !entry->public_p(state)); return eNone; } } module = module->superclass(); /* No more places to look, we couldn't find it. */ if(module->nil_p()) return eNormal; } while(1); // Shouldn't be here! rubinius::abort(); }