Exemplo n.º 1
0
  Object* CallSite::empty_cache(STATE, CallSite* call_site, CallFrame* call_frame,
                                   Arguments& args)
  {
    Object* const recv = args.recv();
    Class*  const recv_class  = recv->direct_class(state);

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

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

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

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

    Executable* meth = dis.method;
    Module* mod = dis.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, call_frame, meth, mod, args);
      state->set_call_site_information(NULL);
      return res;
    } else {
      return meth->execute(state, call_frame, meth, mod, args);
    }
  }
Exemplo n.º 2
0
  Object* CallSite::empty_cache_super(STATE, CallSite* call_site, CallFrame* call_frame,
                                   Arguments& args)
  {
    Symbol* original_name = call_frame->original_name();
    if(call_site->name_ != original_name) {
      call_site->name_ = original_name;
      args.set_name(call_site->name_);
    }

    Object* const recv = args.recv();
    Class* const recv_class = recv->direct_class(state);
    Module* const start = call_frame->module()->superclass();

    LookupData lookup(call_frame->self(), start, G(sym_private));
    Dispatch dis(call_site->name());

    if(start->nil_p() || !dis.resolve(state, call_site->name(), lookup)) {

      LookupData missing_lookup(call_frame->self(), recv->lookup_begin(state), G(sym_private));
      Dispatch missing_dis(G(sym_method_missing));

      if(!missing_dis.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);

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

      args.unshift(state, call_site->name());
      dis.method = missing_dis.method;
      dis.module = missing_dis.module;
      dis.method_missing = eSuper;
      state->vm()->set_method_missing_reason(dis.method_missing);
      state->vm()->global_cache()->add_seen(state, call_site->name());
    }

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

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

    Executable* meth = dis.method;
    Module* mod = dis.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, call_frame, meth, mod, args);
      state->set_call_site_information(NULL);
      return res;
    } else {
      return meth->execute(state, call_frame, meth, mod, args);
    }
  }
Exemplo n.º 3
0
  Object* CallSite::empty_cache_super(STATE, CallSite* call_site, CallFrame* call_frame,
                                   Arguments& args)
  {
    Symbol* original_name = call_frame->original_name();
    if(call_site->name_ != original_name) {
      call_site->name_ = original_name;
      args.set_name(call_site->name_);
    }

    Object* const recv = args.recv();
    Class* const recv_class = recv->lookup_begin(state);
    Module* const start = call_frame->module()->superclass();


    LookupData lookup(call_frame->self(), start, G(sym_private));
    Dispatch dis(call_site->name());

    if(start->nil_p() || !dis.resolve(state, call_site->name(), lookup)) {

      LookupData missing_lookup(call_frame->self(), recv_class, G(sym_private));
      Dispatch missing_dis(G(sym_method_missing));
      missing_dis.resolve(state, G(sym_method_missing), missing_lookup);

      if(missing_dis.method_missing != eNone) {
        Exception::internal_error(state, call_frame, "no method_missing");
        return 0;
      }

      args.unshift(state, call_site->name());
      dis.method = missing_dis.method;
      dis.module = missing_dis.module;
      dis.method_missing = eSuper;
      state->vm()->set_method_missing_reason(dis.method_missing);
    }

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

    Executable* meth = dis.method;
    Module* mod = dis.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, call_frame, meth, mod, args);
      state->set_call_site_information(NULL);
      return res;
    } else {
      return meth->execute(state, call_frame, meth, mod, args);
    }
  }
Exemplo n.º 4
0
  Object* InlineCache::empty_cache(STATE, InlineCache* cache, CallFrame* call_frame,
                                   Arguments& args)
  {
    args.set_name(cache->name);
    Object* const recv = args.recv();
    Class* const recv_class = recv->lookup_begin(state);

    MethodCacheEntry* mce = 0;

    MethodMissingReason reason =
      cache->fill_public(state, call_frame->self(), cache->name,
                         recv_class, mce);

    if(reason != eNone) {
      state->vm()->set_method_missing_reason(reason);

      if(!cache->fill_method_missing(state, recv_class, mce)) {
        Exception::internal_error(state, call_frame, "no method_missing");
        return 0;
      }

      args.unshift(state, cache->name);
      cache->execute_backend_ = check_cache_mm;
    } else {
      if(recv->fixnum_p()) {
        cache->execute_backend_ = check_cache_fixnum;
      } else if(recv->symbol_p()) {
        cache->execute_backend_ = check_cache_symbol;
      } else if(recv->reference_p()) {
        cache->execute_backend_ = check_cache_reference;
      } else {
        cache->execute_backend_ = check_cache;
      }
    }

    // Make sure we sync here, so the MethodCacheEntry mce is
    // guaranteed completely initialized. Otherwise another thread
    // might see an incompletely initialized MethodCacheEntry.
    atomic::memory_barrier();

    cache->cache_ = mce;
    cache->update_seen_classes(mce);

    call_frame->cm->write_barrier(state, mce);

    Executable* meth = mce->method();
    Module* mod = mce->stored_module();

    return meth->execute(state, call_frame, meth, mod, args);
  }
Exemplo n.º 5
0
  Object* InlineCache::empty_cache_super(STATE, InlineCache* cache, CallFrame* call_frame,
                                   Arguments& args)
  {
    Symbol* original_name = call_frame->original_name();
    if(cache->name != original_name) {
      cache->name = original_name;
    }

    args.set_name(cache->name);
    Object* const recv = args.recv();
    Class* const recv_class = recv->lookup_begin(state);

    MethodCacheEntry* mce = 0;

    Module* const start = call_frame->module()->superclass();

    if(start->nil_p() || !cache->fill_private(state, cache->name, start, recv_class, mce)) {
      state->vm()->set_method_missing_reason(eSuper);

      // Don't use start when looking up method_missing!
      // Always completely redispatch for method_missing.
      // github#157
      if(!cache->fill_method_missing(state, recv_class, mce)) {
        Exception::internal_error(state, call_frame, "no method_missing");
        return 0;
      }

      args.unshift(state, cache->name);
      cache->execute_backend_ = check_cache_super_mm;
    } else {
      cache->execute_backend_ = check_cache_super;
    }

    // Make sure we sync here, so the MethodCacheEntry mce is
    // guaranteed completely initialized. Otherwise another thread
    // might see an incompletely initialized MethodCacheEntry.
    atomic::memory_barrier();

    cache->cache_ = mce;
    cache->update_seen_classes(mce);

    call_frame->cm->write_barrier(state, mce);

    Executable* meth = mce->method();
    Module* mod = mce->stored_module();

    return meth->execute(state, call_frame, meth, mod, args);
  }
Exemplo n.º 6
0
  Object* InlineCache::check_cache(STATE, InlineCache* cache, CallFrame* call_frame,
                                   Arguments& args)
  {
    MethodCacheEntry* mce = cache->cache_;

    args.set_name(cache->name);
    if(likely(mce && mce->receiver_class() == args.recv()->lookup_begin(state))) {

      Executable* meth = mce->method();
      Module* mod = mce->stored_module();

      return meth->execute(state, call_frame, meth, mod, args);
    }

    return cache->initialize(state, call_frame, args);
  }
Exemplo n.º 7
0
  Object* PolyInlineCache::check_cache(STATE, CallSite* call_site,
                                   Arguments& args)
  {
    Class* const recv_class = args.recv()->direct_class(state);

    PolyInlineCache* cache = static_cast<PolyInlineCache*>(call_site);
    InlineCacheEntry* entry = cache->get_entry(recv_class);

    if(likely(entry)) {
      Executable* meth = entry->method();
      Module* mod = entry->stored_module();
      entry->hit();
      state->vm()->metrics().machine.methods_invoked++;

      return meth->execute(state, meth, mod, args);
    }

    return cache->fallback(state, args);
  }
Exemplo n.º 8
0
  Object* InlineCache::check_cache_super_mm(STATE, InlineCache* cache, CallFrame* call_frame,
                                   Arguments& args)
  {
    MethodCacheEntry* mce = cache->cache_;
    Symbol* current_name = call_frame->original_name();

    args.set_name(cache->name);

    if(likely(mce && mce->receiver_class() == args.recv()->lookup_begin(state)
                  && current_name == cache->name))
    {
      args.unshift(state, cache->name);

      Executable* meth = mce->method();
      Module* mod = mce->stored_module();

      return meth->execute(state, call_frame, meth, mod, args);
    }

    cache->name = current_name;

    return cache->initialize(state, call_frame, args);
  }
Exemplo n.º 9
0
  Object* InlineCache::check_cache_reference(STATE, InlineCache* cache,
      CallFrame* call_frame, Arguments& args)
  {
    MethodCacheEntry* mce = cache->cache_;

    args.set_name(cache->name);
    Object* const recv = args.recv();

    if(likely(mce && recv->reference_p() &&
              recv->reference_class() == mce->receiver_class())) {

      Executable* meth = mce->method();
      Module* mod = mce->stored_module();

      // if(mce->execute) {
        // return mce->execute(state, call_frame, meth, mod, args);
      // }

      return meth->execute(state, call_frame, meth, mod, args);
    }

    return cache->initialize(state, call_frame, args);
  }