Пример #1
0
void InterpretedIC::replace(LookupResult result, klassOop receiver_klass) {
  // IC entries before modification - used for loging only
  Bytecodes::Code code_before  = send_code();
  oop             word1_before = first_word();
  oop             word2_before = second_word();
  int             transition   = 0;
  // modify IC
  guarantee(word2_before == receiver_klass, "klass should be the same");
  if (result.is_empty()) {
    clear();
    transition = 1;
  } else if (result.is_method()) {
    if (send_type() == Bytecodes::megamorphic_send) {
      set(send_code(), result.method(), receiver_klass);
      transition = 2;
    } else {
      // Please Fix this Robert
      // implement set_monomorphic(klass, method)
      clear();
      transition = 3;
    }
  } else {
    if (send_type() == Bytecodes::megamorphic_send) {
      set(send_code(), oop(result.entry()), receiver_klass);
      transition = 4;
    } else {
      assert(result.is_entry(), "must be jump table entry");
      // a jump table entry of a nmethod is found so let's update the current send
      set(Bytecodes::compiled_send_code_for(send_code()), oop(result.entry()), receiver_klass);
      transition = 5;
    }
  }
  // IC entries after modification - used for loging only
  Bytecodes::Code code_after  = send_code();
  oop             word1_after = first_word();
  oop             word2_after = second_word();
  // log modification
  LOG_EVENT3("InterpretedIC::replace: IC at 0x%x: entry for klass 0x%x replaced (transition %d)", this, receiver_klass, transition);
  LOG_EVENT3("  from (%s, 0x%x, 0x%x)", Bytecodes::name(code_before), word1_before, word2_before);
  LOG_EVENT3("  to   (%s, 0x%x, 0x%x)", Bytecodes::name(code_after ), word1_after , word2_after );
}
Пример #2
0
void InterpretedIC::update_inline_cache(InterpretedIC* ic, frame* f, Bytecodes::Code send_code, klassOop klass, LookupResult result) {
  // update inline cache
  if (ic->is_empty() && ic->send_type() != Bytecodes::megamorphic_send) {
    // fill ic for the first time
    Bytecodes::Code new_send_code = Bytecodes::halt;
    if (result.is_entry()) {

      methodOop method = result.method();
      if (UseAccessMethods && Bytecodes::has_access_send_code(send_code) && method->is_accessMethod()) {
        // access method found ==> switch to access send
        new_send_code = Bytecodes::access_send_code_for(send_code);
        ic->set(new_send_code, method, klass);

      } else if (UsePredictedMethods && Bytecodes::has_predicted_send_code(send_code) && method->is_special_primitiveMethod()) {
        // predictable method found ==> switch to predicted send
        // NB: ic of predicted send should be empty so that the compiler knows whether another type occurred or not
        // i.e., {predicted + empty} --> 1 class, {predicted + nonempty} --> 2 klasses (polymorphic)
        // but: this actually doesn't work (yet?) since the interpreter fills the ic on any failure (e.g. overflow)
        new_send_code = method->special_primitive_code();
        method = methodOop(ic->selector()); // ic must stay empty
        klass  = NULL;                     // ic must stay empty
        ic->set(new_send_code, method, klass);

      } else {
        // jump table entry found ==> switch to compiled send
        new_send_code = Bytecodes::compiled_send_code_for(send_code);
        ic->set(new_send_code, oop(result.entry()->entry_point()), klass);
      }
    } else {
      // methodOop found
      methodOop method = result.method();

      if (UseAccessMethods && Bytecodes::has_access_send_code(send_code) && method->is_accessMethod()) {
        // access method found ==> switch to access send
        new_send_code = Bytecodes::access_send_code_for(send_code);

      } else if (UsePredictedMethods && Bytecodes::has_predicted_send_code(send_code) && method->is_special_primitiveMethod()) {
        // predictable method found ==> switch to predicted send
        // NB: ic of predicted send should be empty so that the compiler knows whether another type occurred or not
        // i.e., {predicted + empty} --> 1 class, {predicted + nonempty} --> 2 klasses (polymorphic)
        // but: this actually doesn't work (yet?) since the interpreter fills the ic on any failure (e.g. overflow)
        new_send_code = method->special_primitive_code();
        method = methodOop(ic->selector()); // ic must stay empty
        klass  = NULL;                     // ic must stay empty

      } else if (UsePrimitiveMethods && method->is_primitiveMethod()) {
        // primitive method found ==> switch to primitive send
        new_send_code = Bytecodes::primitive_send_code_for(send_code);
        Unimplemented(); // take this out when all primitive send bytecodes implemented

      } else {
        // normal interpreted send ==> do not change
        new_send_code = send_code;
        assert(new_send_code == Bytecodes::original_send_code_for(send_code), "bytecode should not change");
      }
      assert(new_send_code != Bytecodes::halt, "new_send_code not set");
      ic->set(new_send_code, method, klass);
    }
  } else {
    // ic not empty
    switch (ic->send_type()) {
      // monomorphic send
  case Bytecodes::accessor_send   : // fall through
  case Bytecodes::predicted_send  : // fall through
  case Bytecodes::compiled_send   : // fall through
  case Bytecodes::interpreted_send: {
    // switch to polymorphic send with 2 entries
    objArrayOop pic = Interpreter_PICs::allocate(2);
    Interpreter_PICs::set_first(pic, ic->first_word(), ic->second_word());
    Interpreter_PICs::set_second(pic, result.value(), klass);
    ic->set(Bytecodes::polymorphic_send_code_for(send_code), ic->selector(), pic);
    break;
                                    }

                                    // polymorphic send
  case Bytecodes::polymorphic_send: {

    objArrayOop old_pic = ic->pic_array();
    objArrayOop new_pic = Interpreter_PICs::extend(old_pic); // add an entry to the PIC if appropriate
    if (new_pic == NULL) {
      // switch to megamorphic send
      if (Bytecodes::is_super_send(send_code)) {
        ic->set(Bytecodes::megamorphic_send_code_for(send_code), result.value(), klass);
      } else {
        ic->set(Bytecodes::megamorphic_send_code_for(send_code), ic->selector(), NULL);
      }
    } else {
      // still a polymorphic send, add entry and set ic to new_pic
      Interpreter_PICs::set_last(new_pic, result.value(), klass);
      ic->set(send_code, ic->selector(), new_pic);
    }
    // recycle old pic
    Interpreter_PICs::deallocate(old_pic);
    break;
                                    }

                                    // megamorphic send
  case Bytecodes::megamorphic_send: {
    if (Bytecodes::is_super_send(send_code)) {
      ic->set(send_code, result.value(), klass);
    }
    break;
                                    }

  default: ShouldNotReachHere();
    }
  }

  // redo send (reset instruction pointer)
  f->set_hp(ic->send_code_addr());
}