Example #1
0
void mixinOopDesc::customize_for(klassOop klass) {
  objArrayOop array = methods();
  for (int index = 1; index <= array->length(); index++) {
    methodOop m = methodOop(array->obj_at(index));
    m->customize_for(klass, this);
  }
}
Example #2
0
void mixinOopDesc::uncustomize_methods() {
  objArrayOop array = methods();
  for (int index = 1; index <= array->length(); index++) {
    methodOop m = methodOop(array->obj_at(index));
    m->uncustomize_for(this);
  }
}
Example #3
0
// size is the new size of the instruction at bci. Hence, if size is less than the current
// instruction sice, we will shrink the code.
methodHandle Relocator::insert_space_at(int bci, int size, u_char inst_buffer[], TRAPS) {
  _changes = new GrowableArray<ChangeItem*> (10);
  _changes->push(new ChangeWiden(bci, size, inst_buffer));

  if (TraceRelocator) {
    tty->print_cr("Space at: %d Size: %d", bci, size);
    _method->print();
    _method->print_codes();
    tty->print_cr("-------------------------------------------------");
  }

  if (!handle_code_changes()) return methodOop(NULL);

  // Construct the new method
  methodHandle new_method = methodOopDesc::clone_with_new_data(method(), code_array(), code_length(), 
                              compressed_line_number_table(), compressed_line_number_table_size(), CHECK_(methodOop(NULL)));
  set_method(new_method);

  if (TraceRelocator) {
    tty->print_cr("-------------------------------------------------");
    tty->print_cr("new method");
    _method->print_codes();
  }

  return new_method;
}
Example #4
0
 SimpleScopeDesc(nmethod* code,address pc) {
   PcDesc* pc_desc = code->pc_desc_at(pc);
   assert(pc_desc != NULL, "Must be able to find matching PcDesc");
   DebugInfoReadStream buffer(code, pc_desc->scope_decode_offset());
   int ignore_sender = buffer.read_int();
   _method           = methodOop(buffer.read_oop());
   _bci              = buffer.read_bci();
 }
Example #5
0
 SimpleScopeDesc(nmethod* code,address pc,bool at_call) {
   PcDesc* pc_desc = code->pc_desc_at(pc, at_call);
   assert(pc_desc != NULL, "Must be able to find matching PcDesc");
   u_char* buffer = code->scopes_data_begin() + pc_desc->scope_decode_offset();
   CompressedReadStream::raw_read_int(buffer);
   _method = methodOop(code->oop_at(CompressedReadStream::raw_read_int(buffer)));
   _bci = CompressedReadStream::raw_read_int(buffer);
 }
Example #6
0
bool mixinOopDesc::includes_method(methodOop method) {
  objArrayOop array = methods();
  for (int index = 1; index <= array->length(); index++) {
    methodOop m = methodOop(array->obj_at(index));
    if (m == method) return true;
  }
  return false;
}
Example #7
0
// this function computes the vtable size (including the size needed for miranda
// methods) and the number of miranda methods in this class
// Note on Miranda methods: Let's say there is a class C that implements
// interface I.  Let's say there is a method m in I that neither C nor any
// of its super classes implement (i.e there is no method of any access, with
// the same name and signature as m), then m is a Miranda method which is
// entered as a public abstract method in C's vtable.  From then on it should
// treated as any other public method in C for method over-ride purposes.
void klassVtable::compute_vtable_size_and_num_mirandas(int &vtable_length,
                                                       int &num_miranda_methods,
                                                       klassOop super,
                                                       objArrayOop methods,
                                                       AccessFlags class_flags,
                                                       Handle classloader,
                                                       Symbol* classname,
                                                       objArrayOop local_interfaces,
                                                       TRAPS
                                                       ) {

  No_Safepoint_Verifier nsv;

  // set up default result values
  vtable_length = 0;
  num_miranda_methods = 0;

  // start off with super's vtable length
  instanceKlass* sk = (instanceKlass*)super->klass_part();
  vtable_length = super == NULL ? 0 : sk->vtable_length();

  // go thru each method in the methods table to see if it needs a new entry
  int len = methods->length();
  for (int i = 0; i < len; i++) {
    assert(methods->obj_at(i)->is_method(), "must be a methodOop");
    methodHandle mh(THREAD, methodOop(methods->obj_at(i)));

    if (needs_new_vtable_entry(mh, super, classloader, classname, class_flags, THREAD)) {
      vtable_length += vtableEntry::size(); // we need a new entry
    }
  }

  // compute the number of mirandas methods that must be added to the end
  num_miranda_methods = get_num_mirandas(super, methods, local_interfaces);
  vtable_length += (num_miranda_methods * vtableEntry::size());

  if (Universe::is_bootstrapping() && vtable_length == 0) {
    // array classes don't have their superclass set correctly during
    // bootstrapping
    vtable_length = Universe::base_vtable_size();
  }

  if (super == NULL && !Universe::is_bootstrapping() &&
      vtable_length != Universe::base_vtable_size()) {
    // Someone is attempting to redefine java.lang.Object incorrectly.  The
    // only way this should happen is from
    // SystemDictionary::resolve_from_stream(), which will detect this later
    // and throw a security exception.  So don't assert here to let
    // the exception occur.
    vtable_length = Universe::base_vtable_size();
  }
  assert(super != NULL || vtable_length == Universe::base_vtable_size(),
         "bad vtable size for class Object");
  assert(vtable_length % vtableEntry::size() == 0, "bad vtable length");
  assert(vtable_length >= Universe::base_vtable_size(), "vtable too small");
}
Example #8
0
void vframeStream::fill_from_compiled_frame(nmethod* code, int decode_offset) {
  _mode = compiled_mode;
  _code = code;

  // Decode first part of scopeDesc
  u_char* buffer = code->scopes_data_begin() + decode_offset;
  _sender_decode_offset = CompressedReadStream::raw_read_int(buffer);
  _method               = methodOop(_code->oop_at(CompressedReadStream::raw_read_int(buffer)));
  _bci                  = CompressedReadStream::raw_read_int(buffer);

  assert(_method->is_method(), "checking type of decoded method");  
}
Example #9
0
methodOop frame::method() const {
  assert(is_interpreted_frame(), "must be interpreter frame");
  // First we will check the interpreter frame is valid by checking the frame size.
  // The interpreter guarantees hp is valid if the frame is at least 4 in size. 
  // (return address, link, receiver, hcode pointer)
  if (frame_size() < minimum_size_for_deoptimized_frame) return NULL;

  u_char* h = hp();
  if (!Universe::old_gen.contains(h)) return NULL; 
  memOop obj = as_memOop(Universe::object_start((oop*) h));  
  return obj->is_method() ? methodOop(obj) : NULL;
}
Example #10
0
symbolOop InterpretedIC::selector() const {
  oop fw = first_word();
  if (fw->is_symbol()) {
    return symbolOop(fw);
  } else if (fw->is_method()) {
    return methodOop(fw)->selector();
  } else {
    jumpTableEntry* e = jump_table_entry();
    nmethod* nm = e->method();
    assert(nm != NULL, "must have an nmethod");
    return nm->key.selector();
  }
}
Example #11
0
void pp(void* p) {
  Command c("pp");
  FlagSetting fl(PrintVMMessages, true);
  if (p == NULL) {
    lprintf("0x0");
    return;
  }

  if (Universe::is_heap((oop*) p)) {
    memOop obj = as_memOop(Universe::object_start((oop*) p));
    obj->print();
    if (obj->is_method()) {
      int bci = methodOop(obj)->bci_from((u_char*) p);
      prettyPrinter::print(methodOop(obj), NULL, bci);
    }
    return;
  }

  if (oop(p)->is_smi() || oop(p)->is_mark()) {
    oop(p)->print();
    return;
  }
}
Example #12
0
methodOop ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) {
  if (is_secondary_entry()) {
    if (!is_f1_null())
      return f2_as_vfinal_method();
    return NULL;
  }
  // Decode the action of set_method and set_interface_call
  Bytecodes::Code invoke_code = bytecode_1();
  if (invoke_code != (Bytecodes::Code)0) {
    oop f1 = _f1;
    if (f1 != NULL) {
      switch (invoke_code) {
      case Bytecodes::_invokeinterface:
        assert(f1->is_klass(), "");
        return klassItable::method_for_itable_index(klassOop(f1), f2_as_index());
      case Bytecodes::_invokestatic:
      case Bytecodes::_invokespecial:
        assert(!has_appendix(), "");
        assert(f1->is_method(), "");
        return methodOop(f1);
      }
    }
  }
  invoke_code = bytecode_2();
  if (invoke_code != (Bytecodes::Code)0) {
    switch (invoke_code) {
    case Bytecodes::_invokevirtual:
      if (is_vfinal()) {
        // invokevirtual
        methodOop m = f2_as_vfinal_method();
        assert(m->is_method(), "");
        return m;
      } else {
        int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index());
        if (cpool->tag_at(holder_index).is_klass()) {
          klassOop klass = cpool->resolved_klass_at(holder_index);
          if (!Klass::cast(klass)->oop_is_instance())
            klass = SystemDictionary::Object_klass();
          return instanceKlass::cast(klass)->method_at_vtable(f2_as_index());
        }
      }
      break;
    case Bytecodes::_invokehandle:
    case Bytecodes::_invokedynamic:
      return f2_as_vfinal_method();
    }
  }
  return NULL;
}
Example #13
0
  void do_object(oop obj) {
    if (obj->is_klass() && obj->blueprint()->oop_is_instanceKlass()) {
      instanceKlass* ik = instanceKlass::cast((klassOop)obj);
      int i;

      mark_and_move_for_policy(OP_favor_startup, ik->name(), _move_ro);

      if (ik->super() != NULL) {
        do_object(ik->super());
      }

      objArrayOop interfaces = ik->local_interfaces();
      mark_and_move_for_policy(OP_favor_startup, interfaces, _move_ro);
      for(i = 0; i < interfaces->length(); i++) {
        klassOop k = klassOop(interfaces->obj_at(i));
        mark_and_move_for_policy(OP_favor_startup, k->klass_part()->name(), _move_ro);
        do_object(k);
      }

      objArrayOop methods = ik->methods();
      for(i = 0; i < methods->length(); i++) {
        methodOop m = methodOop(methods->obj_at(i));
        mark_and_move_for_policy(OP_favor_startup, m->constMethod(), _move_ro);
        mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->exception_table(), _move_ro);
        mark_and_move_for_policy(OP_favor_runtime, m->constMethod()->stackmap_data(), _move_ro);

        // We don't move the name symbolOop here because it may invalidate
        // method ordering, which is dependent on the address of the name
        // symbolOop.  It will get promoted later with the other symbols.
        // Method name is rarely accessed during classloading anyway.
        // mark_and_move_for_policy(OP_balanced, m->name(), _move_ro);

        mark_and_move_for_policy(OP_favor_startup, m->signature(), _move_ro);
      }

      mark_and_move_for_policy(OP_favor_startup, ik->transitive_interfaces(), _move_ro);
      mark_and_move_for_policy(OP_favor_startup, ik->fields(), _move_ro);

      mark_and_move_for_policy(OP_favor_runtime, ik->secondary_supers(),  _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->method_ordering(),   _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->class_annotations(), _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->fields_annotations(), _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->methods_annotations(), _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->methods_parameter_annotations(), _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->methods_default_annotations(), _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->inner_classes(), _move_ro);
      mark_and_move_for_policy(OP_favor_runtime, ik->secondary_supers(), _move_ro);
    }
  }
Example #14
0
void mixinOopDesc::add_method(methodOop method) {
  objArrayOop old_array = methods();
  symbolOop selector = method->selector();
  // Find out if a method with the same selector exists.
  for (int index = 1; index <= old_array->length(); index++) {
    assert(old_array->obj_at(index)->is_method(), "must be method");
    methodOop m = methodOop(old_array->obj_at(index));
    if (m->selector() == selector) {
      objArrayOop new_array = old_array->copy();
      new_array->obj_at_put(index, method);
      set_methods(new_array);
      return;
    }
  }
  // Extend the array
  set_methods(old_array->copy_add(method));
}
Example #15
0
  void do_object(oop obj) {

    // Mark symbols refered to by method objects.

    if (obj->is_method()) {
      methodOop m = methodOop(obj);
      mark_object(m->name());
      mark_object(m->signature());
    }

    // Mark symbols referenced by klass objects which are read-only.

    else if (obj->is_klass()) {

      if (obj->blueprint()->oop_is_instanceKlass()) {
        instanceKlass* ik = instanceKlass::cast((klassOop)obj);
        mark_object(ik->name());
        mark_object(ik->generic_signature());
        mark_object(ik->source_file_name());
        mark_object(ik->source_debug_extension());

        typeArrayOop inner_classes = ik->inner_classes();
        if (inner_classes != NULL) {
          int length = inner_classes->length();
          for (int i = 0;
                   i < length;
                   i += instanceKlass::inner_class_next_offset) {
            int ioff = i + instanceKlass::inner_class_inner_name_offset;
            int index = inner_classes->ushort_at(ioff);
            if (index != 0) {
              mark_object(ik->constants()->symbol_at(index));
            }
          }
        }
        ik->field_names_and_sigs_iterate(&mark_all);
      }
    }

    // Mark symbols referenced by other constantpool entries.

    if (obj->is_constantPool()) {
      constantPoolOop(obj)->shared_symbols_iterate(&mark_all);
    }
  }
Example #16
0
  void do_object(oop obj) {
    if (obj->is_klass() && obj->blueprint()->oop_is_instanceKlass()) {
      instanceKlass* ik = instanceKlass::cast((klassOop)obj);
      int i;

      mark_and_move_for_policy(OP_favor_startup, ik->as_klassOop(), _move_rw);

      if (ik->super() != NULL) {
        do_object(ik->super());
      }

      objArrayOop interfaces = ik->local_interfaces();
      for(i = 0; i < interfaces->length(); i++) {
        klassOop k = klassOop(interfaces->obj_at(i));
        mark_and_move_for_policy(OP_favor_startup, k, _move_rw);
        do_object(k);
      }

      objArrayOop methods = ik->methods();
      mark_and_move_for_policy(OP_favor_startup, methods, _move_rw);
      for(i = 0; i < methods->length(); i++) {
        methodOop m = methodOop(methods->obj_at(i));
        mark_and_move_for_policy(OP_favor_startup, m, _move_rw);
        mark_and_move_for_policy(OP_favor_startup, ik->constants(), _move_rw);          // idempotent
        mark_and_move_for_policy(OP_balanced, ik->constants()->cache(), _move_rw); // idempotent
        mark_and_move_for_policy(OP_balanced, ik->constants()->tags(), _move_rw);  // idempotent
      }

      mark_and_move_for_policy(OP_favor_startup, ik->as_klassOop()->klass(), _move_rw);
      mark_and_move_for_policy(OP_favor_startup, ik->constants()->klass(), _move_rw);

      // Although Java mirrors are marked in MarkReadWriteObjects,
      // apparently they were never moved into shared spaces since
      // MoveMarkedObjects skips marked instance oops.  This may
      // be a bug in the original implementation or simply the vestige
      // of an abandoned experiment.  Nevertheless we leave a hint
      // here in case this capability is ever correctly implemented.
      //
      // mark_and_move_for_policy(OP_favor_runtime, ik->java_mirror(), _move_rw);
    }
  }
Example #17
0
inline void vframeStreamCommon::fill_from_compiled_frame(int decode_offset) {
  _mode = compiled_mode;

  // Range check to detect ridiculous offsets.
  if (decode_offset == DebugInformationRecorder::serialized_null ||
      decode_offset < 0 ||
      decode_offset >= nm()->scopes_data_size()) {
    // 6379830 AsyncGetCallTrace sometimes feeds us wild frames.
    // If we attempt to read nmethod::scopes_data at serialized_null (== 0),
    // or if we read some at other crazy offset,
    // we will decode garbage and make wild references into the heap,
    // leading to crashes in product mode.
    // (This isn't airtight, of course, since there are internal
    // offsets which are also crazy.)
#ifdef ASSERT
    if (WizardMode) {
      tty->print_cr("Error in fill_from_frame: pc_desc for "
                    INTPTR_FORMAT " not found or invalid at %d",
                    _frame.pc(), decode_offset);
      nm()->print();
      nm()->method()->print_codes();
      nm()->print_code();
      nm()->print_pcs();
    }
#endif
    // Provide a cheap fallback in product mode.  (See comment above.)
    found_bad_method_frame();
    fill_from_compiled_native_frame();
    return;
  }

  // Decode first part of scopeDesc
  DebugInfoReadStream buffer(nm(), decode_offset);
  _sender_decode_offset = buffer.read_int();
  _method               = methodOop(buffer.read_oop());
  _bci                  = buffer.read_bci();

  assert(_method->is_method(), "checking type of decoded method");
}
Example #18
0
bool frame::follow_roots_interpreted_float_frame() {
  methodOop m = methodOop(hp());
  assert(m->is_method(), "must be method");
  // Return if this activation has no floats (the marker is conservative)
  if (!m->has_float_temporaries()) return false;

  // Iterator from stack pointer to end of float section
  oop* end = (oop*) addr_at(m->float_section_start_offset() - m->float_section_size());
  for (oop* p = sp(); p <= end; p++) {
    MarkSweep::follow_root(p);
  }

  // Skip the float section and magic_value

  // Iterate from just before the float section to the first temp
  for (oop* q = (oop*) addr_at(m->float_section_start_offset() + 2); q <= temp_addr(0); q++) {
    MarkSweep::follow_root(q);
  }

  // The receiver
  MarkSweep::follow_root(receiver_addr());

  return true;
}
Example #19
0
 int oop_size(oop obj) const { return object_size(methodOop(obj)->size_of_codes()); }
Example #20
0
 methodOop method() const {
    assert(selector_or_method()->is_method(), "Wrong lookup type");
    return methodOop(selector_or_method());
 }
Example #21
0
 bool is_block_type()  const { return selector_or_method()->is_method() && methodOop(selector_or_method())->is_blockMethod(); }
Example #22
0
methodOop mixinOopDesc::method_at(int index) const {
  return methodOop(methods()->obj_at(index));
}
void instanceKlassKlass::oop_verify_on(oop obj, outputStream* st) {
  klassKlass::oop_verify_on(obj, st);
  if (!obj->partially_loaded()) {
    Thread *thread = Thread::current();
    instanceKlass* ik = instanceKlass::cast(klassOop(obj));   

    // Avoid redundant verifies
    if (ik->_verify_count == Universe::verify_count()) return;
    ik->_verify_count = Universe::verify_count();

    // Verify that klass is present in SystemDictionary
    if (ik->is_loaded()) {
      symbolHandle h_name (thread, ik->name());
      Handle h_loader (thread, ik->class_loader());
      SystemDictionary::verify_obj_klass_present(obj, h_name, h_loader);
    }
    
    // Verify static fields
    VerifyFieldClosure blk;
    ik->iterate_static_fields(&blk);

    // Verify vtables
    if (ik->is_linked()) {
      ResourceMark rm(thread);  
      // $$$ This used to be done only for m/s collections.  Doing it
      // always seemed a valid generalization.  (DLD -- 6/00)
      ik->vtable()->verify(st);
    }
  
    // Verify oop map cache
    if (ik->oop_map_cache() != NULL) {
      ik->oop_map_cache()->verify();
    }

    // Verify first subklass
    if (ik->subklass_oop() != NULL) { 
      guarantee(ik->subklass_oop()->is_perm(),  "should be in permspace");
      guarantee(ik->subklass_oop()->is_klass(), "should be klass");
    }

    // Verify siblings
    klassOop super = ik->super();
    Klass* sib = ik->next_sibling();
    int sib_count = 0;
    while (sib != NULL) {
      if (sib == ik) {
        fatal1("subclass cycle of length %d", sib_count);
      }
      if (sib_count >= 100000) {
        fatal1("suspiciously long subclass list %d", sib_count);
      }
      guarantee(sib->as_klassOop()->is_klass(), "should be klass");
      guarantee(sib->as_klassOop()->is_perm(),  "should be in permspace");
      guarantee(sib->super() == super, "siblings should have same superklass");
      sib = sib->next_sibling();
    }

    // Verify implementor field
    if (ik->implementor() != NULL) {
      guarantee(ik->is_interface(), "only interfaces should have implementor set");
      guarantee(ik->nof_implementors() == 1, "should only have one implementor");
      klassOop im = ik->implementor();
      guarantee(im->is_perm(),  "should be in permspace");
      guarantee(im->is_klass(), "should be klass");
      guarantee(!Klass::cast(klassOop(im))->is_interface(), "implementors cannot be interfaces");
    }
    
    // Verify local interfaces
    objArrayOop local_interfaces = ik->local_interfaces();
    guarantee(local_interfaces->is_perm(),          "should be in permspace");
    guarantee(local_interfaces->is_objArray(),      "should be obj array");
    int j;
    for (j = 0; j < local_interfaces->length(); j++) {
      oop e = local_interfaces->obj_at(j);
      guarantee(e->is_klass() && Klass::cast(klassOop(e))->is_interface(), "invalid local interface");
    }

    // Verify transitive interfaces
    objArrayOop transitive_interfaces = ik->transitive_interfaces();
    guarantee(transitive_interfaces->is_perm(),          "should be in permspace");
    guarantee(transitive_interfaces->is_objArray(),      "should be obj array");
    for (j = 0; j < transitive_interfaces->length(); j++) {
      oop e = transitive_interfaces->obj_at(j);
      guarantee(e->is_klass() && Klass::cast(klassOop(e))->is_interface(), "invalid transitive interface");
    }

    // Verify methods
    objArrayOop methods = ik->methods();
    guarantee(methods->is_perm(),              "should be in permspace");
    guarantee(methods->is_objArray(),          "should be obj array");
    for (j = 0; j < methods->length(); j++) {
      guarantee(methods->obj_at(j)->is_method(), "non-method in methods array");
    }
    for (j = 0; j < methods->length() - 1; j++) {
      methodOop m1 = methodOop(methods->obj_at(j));
      methodOop m2 = methodOop(methods->obj_at(j + 1));
      guarantee(m1->name()->fast_compare(m2->name()) <= 0, "methods not sorted correctly");
    }
    
    // Verify method ordering
    typeArrayOop method_ordering = ik->method_ordering();
    guarantee(method_ordering->is_perm(),              "should be in permspace");
    guarantee(method_ordering->is_typeArray(),         "should be type array");
    int length = method_ordering->length();
    if (jvmdi::enabled()) {
      guarantee(length == methods->length(),           "invalid method ordering length");
      jlong sum = 0;
      for (j = 0; j < length; j++) {
        int original_index = method_ordering->int_at(j);
        guarantee(original_index >= 0 && original_index < length, "invalid method ordering index");
        sum += original_index;
      }
      // Verify sum of indices 0,1,...,length-1
      guarantee(sum == ((jlong)length*(length-1))/2,   "invalid method ordering sum");
    } else {
      guarantee(length == 0,                           "invalid method ordering length");
    }

    // Verify JNI static field/method identifiers
    if (ik->jni_ids() != NULL) {
      ik->jni_ids()->verify(ik->as_klassOop());
    }

    // Verify other fields
    if (ik->array_klasses() != NULL) {
      guarantee(ik->array_klasses()->is_perm(),      "should be in permspace");
      guarantee(ik->array_klasses()->is_klass(),     "should be klass");
    }
    guarantee(ik->fields()->is_perm(),               "should be in permspace");
    guarantee(ik->fields()->is_typeArray(),          "should be type array");
    guarantee(ik->constants()->is_perm(),            "should be in permspace");
    guarantee(ik->constants()->is_constantPool(),    "should be constant pool");
    guarantee(ik->inner_classes()->is_perm(),        "should be in permspace");
    guarantee(ik->inner_classes()->is_typeArray(),   "should be type array");
    if (ik->source_file_name() != NULL) {
      guarantee(ik->source_file_name()->is_perm(),   "should be in permspace");
      guarantee(ik->source_file_name()->is_symbol(), "should be symbol");
    }
    if (ik->source_debug_extension() != NULL) {
      guarantee(ik->source_debug_extension()->is_perm(),   "should be in permspace");
      guarantee(ik->source_debug_extension()->is_symbol(), "should be symbol");
    }
    if (ik->protection_domain() != NULL) {
      guarantee(ik->protection_domain()->is_oop(),  "should be oop");
    }
    if (ik->signers() != NULL) {
      guarantee(ik->signers()->is_objArray(),       "should be obj array");
    }
  }
}
Example #24
0
// Called from assembler in unpack_unoptimized_frames.
// Based on the statics (old_sp, old_fp, and frame_array) this function unpacks
// the array into interpreter frames.
// Returning from this function should activate the most recent deoptimized frame.
extern "C" void unpack_frame_array() {
  BlockScavenge bs;
  ResourceMark rm;

  int* pc_addr = (int*) new_sp - 1;
  assert(*pc_addr = -1, "just checking");

  trace_deoptimization_start();

  bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp;
  bool nlr_target_found     = false; // For verification

  // link for the current frame
  int* link_addr = (int*) new_sp - 2;

  oop* current_sp = new_sp;
  int  pos        = 3;
  int  length     = frame_array->length();
  bool first = true;
  frame current;
  // unpack one frame at at time from most recent to least recent
  do {
    oop receiver     = frame_array->obj_at(pos++);
    methodOop method = methodOop(frame_array->obj_at(pos++));
    assert(method->is_method(), "expecting method");

    smiOop bci_obj = smiOop(frame_array->obj_at(pos++));
    assert(bci_obj->is_smi(), "expecting smi");
    int bci        = bci_obj->value();

    smiOop locals_obj = smiOop(frame_array->obj_at(pos++));
    assert(locals_obj->is_smi(), "expecting smi");
    int locals   = locals_obj->value();

    current = frame(current_sp, (int*) current_sp + locals + 2);

    // fill in the locals
    for (int index = 0; index < locals; index++) {
      current.set_temp(index, frame_array->obj_at(pos++));
    }

    CodeIterator c(method, bci);

    char* current_pc;

    if (first) {
      unpack_first_frame(current_pc, current, c);
    } else {
      current_pc = c.interpreter_return_point();
      current.set_hp(c.next_hp());
    }
    current.set_receiver(receiver);

    current.patch_pc(current_pc);
    current.patch_fp(current.fp());

    // Revive the contexts
    if (!method->is_blockMethod() && method->activation_has_context()) {
      contextOop con = contextOop(current.temp(0));
      assert(con->is_context(), "must be context");
      oop frame_oop = oop(current.fp());
      con->set_parent(frame_oop);

      if (nlr_through_unpacking && nlr_home == (int) cur_fp) {
        if (nlr_home_context == con) {
	  // This frame is the target of the NLR
	  // set nlr_home to frame pointer of current frame
	  nlr_home = (int) current.fp();
	  // compute number of arguments to pop
          nlr_home_id = ~method->number_of_arguments();
          nlr_target_found = true;
	  // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id);
        }
      }
    }

    trace_deoptimization_frame(current, current_sp, current_pc);

    first = false;
    // Next pc
    current_sp += frame::interpreter_frame_size(locals);

  } while (pos <= length);

  if (must_find_nlr_target && !nlr_target_found) {
    fatal("Target for NLR not found when unpacking frame");
  }

  assert (current_sp == old_sp, "We have not reached the end");
  current.set_link(old_fp);
}
Example #25
0
// Called from assembler in unpack_unoptimized_frames.
// Based on the statics (old_sp, old_fp, and frame_array) this function unpacks
// the array into interpreter frames.
// Returning from this function should activate the most recent deoptimized frame.
extern "C" void unpack_frame_array() {
  BlockScavenge bs;
  ResourceMark rm;

  int* pc_addr = (int*) new_sp - 1;
  assert(*pc_addr = -1, "just checking");

  if (TraceDeoptimization) {
    std->print("[Unpacking]");
    if (nlr_through_unpacking) {
      std->print(" NLR %s", (nlr_home == (int) cur_fp) ? "inside" : "outside");
    }
    std->cr();
    std->print(" - array ");
    frame_array->print_value();
    std->print_cr(" @ 0x%lx", old_fp);
  }

  bool must_find_nlr_target = nlr_through_unpacking && nlr_home == (int) cur_fp;
  bool nlr_target_found     = false; // For verification

  // link for the current frame
  int* link_addr = (int*) new_sp - 2;

  oop* current_sp = new_sp;
  int  pos        = 3;
  int  length     = frame_array->length();
  bool first = true;
  frame current;
  // unpack one frame at at time from most recent to least recent
  do {
    oop receiver     = frame_array->obj_at(pos++);
    methodOop method = methodOop(frame_array->obj_at(pos++));
    assert(method->is_method(), "expecting method");

    smiOop bci_obj = smiOop(frame_array->obj_at(pos++));
    assert(bci_obj->is_smi(), "expecting smi");
    int bci        = bci_obj->value();

    smiOop locals_obj = smiOop(frame_array->obj_at(pos++));
    assert(locals_obj->is_smi(), "expecting smi");
    int locals   = locals_obj->value();

    current = frame(current_sp, (int*) current_sp + locals + 2);

    // fill in the locals
    for (int index = 0; index < locals; index++) {
      current.set_temp(index, frame_array->obj_at(pos++));
    }

    CodeIterator c(method, bci);

    char* current_pc;

    if (first) {
      // first vframe in the array
      if (nlr_through_unpacking) {
        // NLR is comming through unpacked vframes
        current_pc = c.interpreter_return_point();
        // current_pc points to a normal return point in the interpreter.
	// To find the nlr return point we first compute the nlr offset.
        current_pc = ic_info_at(current_pc)->NLR_target();
        current.set_hp(c.next_hp());
      } else if (redo_the_send) {
        // Deoptimizing uncommon trap
        current_pc = (char*) redo_bytecode_after_deoptimization;
        current.set_hp(c.next_hp());
	redo_send_offset = c.next_hp() - c.hp();
        redo_the_send = false;
      } else {
        // Normal case
        current_pc = c.interpreter_return_point(true);
        current.set_hp(c.next_hp());
 
        if (c.is_message_send()) {
	  number_of_arguments_through_unpacking = c.ic()->nof_arguments();	  
        } else if (c.is_primitive_call()) {
          number_of_arguments_through_unpacking = c.prim_cache()->number_of_parameters();
	} else if (c.is_dll_call()) {
	  // The callee should not pop the argument since a DLL call is like a c function call.
	  // The continuation code for the DLL call will pop the arguments!
          number_of_arguments_through_unpacking = 0;
	}
      }
    } else {
      current_pc = c.interpreter_return_point();
      current.set_hp(c.next_hp());
    }
    current.set_receiver(receiver);

    current.patch_pc(current_pc);
    current.patch_fp(current.fp());
    
    // Revive the contexts
    if (!method->is_blockMethod() && method->activation_has_context()) {
      contextOop con = contextOop(current.temp(0));
      assert(con->is_context(), "must be context");
      oop frame_oop = oop(current.fp());
      con->set_parent(frame_oop);

      if (nlr_through_unpacking && nlr_home == (int) cur_fp) {
        if (nlr_home_context == con) {
	  // This frame is the target of the NLR
	  // set nlr_home to frame pointer of current frame
	  nlr_home = (int) current.fp();
	  // compute number of arguments to pop
          nlr_home_id = ~method->number_of_arguments();
          nlr_target_found = true;
	  // std->print("target frame for NLR (%d, 0x%lx):",method->number_of_arguments(), nlr_home_id);
        }
      }
    }

    if (TraceDeoptimization) {
      frame v(current_sp, current.fp(), current_pc);
      v.print_for_deoptimization(std);
    }

    first = false;
    // Next pc
    current_sp += frame::interpreter_frame_size(locals);

  } while (pos <= length);

  if (must_find_nlr_target && !nlr_target_found) {
    fatal("Target for NLR not found when unpacking frame");
  }

  assert (current_sp == old_sp, "We have not reached the end");
  current.set_link(old_fp);
}
Example #26
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());
}
void MethodIterator::dispatch(MethodClosure* blk) {
  bool oldFailState = blk->in_prim_failure_block();
  blk->set_prim_failure(_interval->in_prim_failure_block());
  CodeIterator iter(_interval->method(), _interval->begin_bci());
  int lastArgNo = _interval->method()->number_of_arguments() - 1;
  blk->set_method(_interval->method());
  int next_bci = _interval->begin_bci();

  while (next_bci < _interval->end_bci() && !blk->aborting()) {
    iter.set_bci(next_bci);
    blk->set_bci(iter.bci());

    next_bci = iter.next_bci();
    blk->set_next_bci(next_bci);

    switch(iter.code()) {
      case Bytecodes::push_temp_0:
        blk->push_temporary(0);
        break;
      case Bytecodes::push_temp_1:
        blk->push_temporary(1);
        break;
      case Bytecodes::push_temp_2:
        blk->push_temporary(2);
        break;
      case Bytecodes::push_temp_3:
        blk->push_temporary(3);
        break;
      case Bytecodes::push_temp_4:
        blk->push_temporary(4);
        break;
      case Bytecodes::push_temp_5:
        blk->push_temporary(5);
        break;
      case Bytecodes::unimplemented_06:
        unknown_code(Bytecodes::unimplemented_06);
        break;
      case Bytecodes::push_temp_n:
        blk->push_temporary(255 - iter.byte_at(1));
        break;
      case Bytecodes::push_arg_1:
        blk->push_argument(lastArgNo);
        break;
      case Bytecodes::push_arg_2:
        blk->push_argument(lastArgNo - 1);
        break;
      case Bytecodes::push_arg_3:
        blk->push_argument(lastArgNo - 2);
        break;
      case Bytecodes::push_arg_n:
        blk->push_argument(lastArgNo - iter.byte_at(1));
        break;
      case Bytecodes::allocate_temp_1:
        blk->allocate_temporaries(1);
        break;
      case Bytecodes::allocate_temp_2:
        blk->allocate_temporaries(2);
        break;
      case Bytecodes::allocate_temp_3:
        blk->allocate_temporaries(3);
        break;
      case Bytecodes::allocate_temp_n:
        blk->allocate_temporaries(map0to256(iter.byte_at(1)));
        break;
      case Bytecodes::store_temp_0_pop:
        blk->store_temporary(0);
        blk->pop();
        break;
      case Bytecodes::store_temp_1_pop:
        blk->store_temporary(1);
        blk->pop();
        break;
      case Bytecodes::store_temp_2_pop:
        blk->store_temporary(2);
        blk->pop();
        break;
      case Bytecodes::store_temp_3_pop:
        blk->store_temporary(3);
        blk->pop();
        break;
      case Bytecodes::store_temp_4_pop:
        blk->store_temporary(4);
        blk->pop();
        break;
      case Bytecodes::store_temp_5_pop:
        blk->store_temporary(5);
        blk->pop();
        break;
      case Bytecodes::store_temp_n:
        blk->store_temporary(255 - iter.byte_at(1));
        break;
      case Bytecodes::store_temp_n_pop:
        blk->store_temporary(255 - iter.byte_at(1));
        blk->pop();
        break;
      case Bytecodes::push_neg_n:
        blk->push_literal(as_smiOop(-(int) iter.byte_at(1)));
        break;
      case Bytecodes::push_succ_n:
        blk->push_literal(as_smiOop(iter.byte_at(1)+1));
        break;
      case Bytecodes::push_literal:
        blk->push_literal(iter.oop_at(1));
        break;
      case Bytecodes::push_tos:
        blk->push_tos();
        break;
      case Bytecodes::push_self:
        blk->push_self();
        break;
      case Bytecodes::push_nil:
        blk->push_literal(nilObj);
        break;
      case Bytecodes::push_true:
        blk->push_literal(trueObj);
        break;
      case Bytecodes::push_false:
        blk->push_literal(falseObj);
        break;
      case Bytecodes::unimplemented_20:
        unknown_code(Bytecodes::unimplemented_20);
        break;
      case Bytecodes::unimplemented_21:
        unknown_code(Bytecodes::unimplemented_21);
        break;
      case Bytecodes::unimplemented_22:
        unknown_code(Bytecodes::unimplemented_22);
        break;
      case Bytecodes::unimplemented_23:
        unknown_code(Bytecodes::unimplemented_23);
        break;
      case Bytecodes::unimplemented_24:
        unknown_code(Bytecodes::unimplemented_24);
        break;
      case Bytecodes::unimplemented_25:
        unknown_code(Bytecodes::unimplemented_25);
        break;
      case Bytecodes::unimplemented_26:
        unknown_code(Bytecodes::unimplemented_26);
        break;
      case Bytecodes::unimplemented_27:
        unknown_code(Bytecodes::unimplemented_27);
        break;
      case Bytecodes::return_instVar_name: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->push_instVar_name(name);
        blk->method_return(0); 
                                           }
                                           break;
      case Bytecodes::push_classVar: {
        associationOop assoc = associationOop(iter.oop_at(1));
        assert(assoc->is_association(), "must be association");
        blk->push_classVar(assoc); 
                                     }
                                     break;
      case Bytecodes::store_classVar_pop: {
        associationOop assoc = associationOop(iter.oop_at(1));
        assert(assoc->is_association(), "must be association");
        blk->store_classVar(assoc);
        blk->pop(); 
                                          }
                                          break;
      case Bytecodes::store_classVar: {
        associationOop assoc = associationOop(iter.oop_at(1));
        assert(assoc->is_association(), "must be association");
        blk->store_classVar(assoc);
                                      }
                                      break;
      case Bytecodes::return_instVar: {
        smiOop offset = smiOop(iter.oop_at(1));
        assert(offset->is_smi(), "must be smi");
        blk->push_instVar(offset->value());
        blk->method_return(0); 
                                      }
                                      break;
      case Bytecodes::push_instVar: {
        smiOop offset = smiOop(iter.oop_at(1));
        assert(offset->is_smi(), "must be smi");
        blk->push_instVar(offset->value());
                                    }
                                    break;
      case Bytecodes::store_instVar_pop: {
        smiOop offset = smiOop(iter.oop_at(1));
        assert(offset->is_smi(), "must be smi");
        blk->store_instVar(offset->value());
        blk->pop();
                                         }
                                         break;
      case Bytecodes::store_instVar:{
        smiOop offset = smiOop(iter.oop_at(1));
        assert(offset->is_smi(), "must be smi");
        blk->store_instVar(offset->value());
                                    }
                                    break;
      case Bytecodes::float_allocate:
        blk->allocate_temporaries(1 + iter.byte_at(1)*2);
        blk->float_allocate(iter.byte_at(2), iter.byte_at(3));
        break;
      case Bytecodes::float_floatify_pop:
        blk->float_floatify(Floats::floatify, blk->float_at(iter.byte_at(1)));
        break;
      case Bytecodes::float_move:
        blk->float_move(blk->float_at(iter.byte_at(1)), blk->float_at(iter.byte_at(2)));
        break;
      case Bytecodes::float_set:
        blk->float_set(blk->float_at(iter.byte_at(1)), *(doubleOop*)iter.aligned_oop(2));
        break;
      case Bytecodes::float_nullary_op:
        blk->float_nullary(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1)));
        break;
      case Bytecodes::float_unary_op:
        blk->float_unary(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1)));
        break;
      case Bytecodes::float_binary_op:
        blk->float_binary(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1)));
        break;
      case Bytecodes::float_unary_op_to_oop:
        blk->float_unaryToOop(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1)));
        break;
      case Bytecodes::float_binary_op_to_oop:
        blk->float_binaryToOop(Floats::Function(iter.byte_at(2)), blk->float_at(iter.byte_at(1)));
        break;
      case Bytecodes::unimplemented_39:
        unknown_code(Bytecodes::unimplemented_39);
        break;
      case Bytecodes::unimplemented_3a:
        unknown_code(Bytecodes::unimplemented_3a);
        break;
      case Bytecodes::unimplemented_3b:
        unknown_code(Bytecodes::unimplemented_3b); 
        break;
      case Bytecodes::unimplemented_3c:
        unknown_code(Bytecodes::unimplemented_3c); 
        break;
      case Bytecodes::push_instVar_name: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->push_instVar_name(name);
                                         }
                                         break;
      case Bytecodes::store_instVar_pop_name:  {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->store_instVar_name(name);
        blk->pop();
                                               }
                                               break;
      case Bytecodes::store_instVar_name:  {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->store_instVar_name(name);
                                           }
                                           break;
      case Bytecodes::push_temp_0_context_0:
        blk->push_temporary(0, 0);
        break;
      case Bytecodes::push_temp_1_context_0:
        blk->push_temporary(1, 0);
        break;
      case Bytecodes::push_temp_2_context_0:
        blk->push_temporary(2, 0);
        break;
      case Bytecodes::push_temp_n_context_0:
        blk->push_temporary(iter.byte_at(1), 0);
        break;
      case Bytecodes::store_temp_0_context_0_pop:
        blk->store_temporary(0, 0);
        blk->pop();
        break;
      case Bytecodes::store_temp_1_context_0_pop:
        blk->store_temporary(1, 0);
        blk->pop();
        break;
      case Bytecodes::store_temp_2_context_0_pop: 
        blk->store_temporary(2, 0);
        blk->pop();
        break;
      case Bytecodes::store_temp_n_context_0_pop:
        blk->store_temporary(iter.byte_at(1), 0);
        blk->pop();
        break;
      case Bytecodes::push_new_closure_context_0:
        blk->allocate_closure(context_as_scope, 0, methodOop(iter.oop_at(1)));
        break;
      case Bytecodes::push_new_closure_context_1:
        blk->allocate_closure(context_as_scope, 1, methodOop(iter.oop_at(1)));
        break;
      case Bytecodes::push_new_closure_context_2:
        blk->allocate_closure(context_as_scope, 2, methodOop(iter.oop_at(1)));
        break;
      case Bytecodes::push_new_closure_context_n:
        blk->allocate_closure(context_as_scope, iter.byte_at(1), methodOop(iter.oop_at(2)));
        break;
      case Bytecodes::install_new_context_method_0:
        blk->allocate_context(0, true);
        break;
      case Bytecodes::install_new_context_method_1:
        blk->allocate_context(1, true);
        break;
      case Bytecodes::install_new_context_method_2:
        blk->allocate_context(2, true);
        break;
      case Bytecodes::install_new_context_method_n:
        blk->allocate_context(iter.byte_at(1), true);
        break;
      case Bytecodes::push_temp_0_context_1:
        blk->push_temporary(0, 1);
        break;
      case Bytecodes::push_temp_1_context_1:
        blk->push_temporary(1, 1);
        break;
      case Bytecodes::push_temp_2_context_1:
        blk->push_temporary(2, 1);
        break;
      case Bytecodes::push_temp_n_context_1:
        blk->push_temporary(iter.byte_at(1), 1);
        break;
      case Bytecodes::store_temp_0_context_1_pop:
        blk->store_temporary(0, 1);
        blk->pop();
        break;
      case Bytecodes::store_temp_1_context_1_pop:
        blk->store_temporary(1, 1);
        blk->pop();
        break;
      case Bytecodes::store_temp_2_context_1_pop:
        blk->store_temporary(2, 1);
        blk->pop();
        break;
      case Bytecodes::store_temp_n_context_1_pop:
        blk->store_temporary(iter.byte_at(1), 1);
        blk->pop();
        break;
      case Bytecodes::push_new_closure_tos_0:
        blk->allocate_closure(tos_as_scope, 0, methodOop(iter.oop_at(1)));
        break;
      case Bytecodes::push_new_closure_tos_1:
        blk->allocate_closure(tos_as_scope, 1, methodOop(iter.oop_at(1)));
        break;
      case Bytecodes::push_new_closure_tos_2:
        blk->allocate_closure(tos_as_scope, 2, methodOop(iter.oop_at(1)));
        break;
      case Bytecodes::push_new_closure_tos_n:
        blk->allocate_closure(tos_as_scope, iter.byte_at(1), methodOop(iter.oop_at(2)));
        break;
      case Bytecodes::only_pop:
        blk->pop();
        break;
      case Bytecodes::install_new_context_block_1:
        blk->allocate_context(1, false);
        break;
      case Bytecodes::install_new_context_block_2:
        blk->allocate_context(2, false);
        break;
      case Bytecodes::install_new_context_block_n:
        blk->allocate_context(iter.byte_at(1), false);
        break;
      case Bytecodes::push_temp_0_context_n:
        blk->push_temporary(0, iter.byte_at(1));
        break;
      case Bytecodes::push_temp_1_context_n:
        blk->push_temporary(1, iter.byte_at(1));
        break;
      case Bytecodes::push_temp_2_context_n:
        blk->push_temporary(2, iter.byte_at(1));
        break;
      case Bytecodes::push_temp_n_context_n:
        blk->push_temporary(iter.byte_at(1), map0to256(iter.byte_at(2)));
        break;
      case Bytecodes::store_temp_0_context_n_pop:
        blk->store_temporary(0, iter.byte_at(1));
        blk->pop();
        break;
      case Bytecodes::store_temp_1_context_n_pop:
        blk->store_temporary(1, iter.byte_at(1));
        blk->pop();
        break;
      case Bytecodes::store_temp_2_context_n_pop:
        blk->store_temporary(2, iter.byte_at(1));
        blk->pop();
        break;
      case Bytecodes::store_temp_n_context_n_pop:
        blk->store_temporary(iter.byte_at(1), map0to256(iter.byte_at(2)));
        blk->pop();
        break;
      case Bytecodes::set_self_via_context:
        blk->set_self_via_context();
        break;
      case Bytecodes::copy_1_into_context:
        blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 0);
        break;
      case Bytecodes::copy_2_into_context:
        blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 0); 
        blk->copy_argument_into_context(lastArgNo - iter.byte_at(2), 1);
        break;
      case Bytecodes::copy_n_into_context: {
        int len = map0to256(iter.byte_at(1));
        for (int i = 0; i < len; i++)
          blk->copy_argument_into_context(lastArgNo - iter.byte_at(i + 2), i);
        break;
                                           }
      case Bytecodes::copy_self_into_context:
        blk->copy_self_into_context();
        break;
      case Bytecodes::copy_self_1_into_context:
        blk->copy_self_into_context(); 
        blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 1);
        break;
      case Bytecodes::copy_self_2_into_context:
        blk->copy_self_into_context();
        blk->copy_argument_into_context(lastArgNo - iter.byte_at(1), 1); 
        blk->copy_argument_into_context(lastArgNo - iter.byte_at(2), 2);
        break;
      case Bytecodes::copy_self_n_into_context: {
        blk->copy_self_into_context();
        int len = map0to256(iter.byte_at(1));
        for (int i = 0; i < len; i++)
          blk->copy_argument_into_context(lastArgNo - iter.byte_at(i + 2), i+1);
        break;
                                                }
      case Bytecodes::ifTrue_byte: {
        IfNode* node = MethodIterator::factory->new_IfNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), true, iter.byte_at(2), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->if_node(node);
        next_bci = node->end_bci();
        break;
                                   }
      case Bytecodes::ifFalse_byte: {
        IfNode* node = MethodIterator::factory->new_IfNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), false, iter.byte_at(2), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->if_node(node);
        next_bci = node->end_bci();
        break;
                                    }
      case Bytecodes::and_byte: {
        AndNode* node = MethodIterator::factory->new_AndNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->cond_node(node);
        next_bci = node->end_bci();
        break;
                                }
      case Bytecodes::or_byte: {
        OrNode* node = MethodIterator::factory->new_OrNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->cond_node(node);
        next_bci = node->end_bci();
        break;
                               }
      case Bytecodes::whileTrue_byte:
        // ignore since they are inside WhileNode expression body
        break;
      case Bytecodes::whileFalse_byte:
        // ignore since they are inside WhileNode expression body
        break;
      case Bytecodes::jump_else_byte:
        should_never_encounter(Bytecodes::jump_else_byte);
        break;
      case Bytecodes::jump_loop_byte: {
        WhileNode* node = MethodIterator::factory->new_WhileNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.byte_at(2), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->while_node(node);
        next_bci = node->end_bci();
        break;
                                      }
      case Bytecodes::ifTrue_word: {
        IfNode* node = MethodIterator::factory->new_IfNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), true, 
          iter.word_at(2), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->if_node(node);
        next_bci = node->end_bci();
        break;
                                   }
      case Bytecodes::ifFalse_word: {
        IfNode* node = MethodIterator::factory->new_IfNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), false, 
          iter.word_at(2), iter.byte_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->if_node(node);
        next_bci = node->end_bci();
        break;
                                    }
      case Bytecodes::and_word: {
        AndNode* node = MethodIterator::factory->new_AndNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.word_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->cond_node(node);
        next_bci = node->end_bci();
        break;
                                }
      case Bytecodes::or_word: {
        OrNode* node = MethodIterator::factory->new_OrNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.word_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->cond_node(node);
        next_bci = node->end_bci();
        break;
                               }
      case Bytecodes::whileTrue_word:
        // Ignore since they are inside WhileNode expression body
        break;
      case Bytecodes::whileFalse_word:
        // Ignore since they are inside WhileNode expression body
        break;
      case Bytecodes::jump_else_word:
        should_never_encounter(Bytecodes::jump_else_word);
        break;
      case Bytecodes::jump_loop_word: {
        WhileNode* node = MethodIterator::factory->new_WhileNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), 
          iter.word_at(1 + oopSize), iter.word_at(1));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->while_node(node);
        next_bci = node->end_bci();
        break;
                                      }
      case Bytecodes::interpreted_send_0:		// fall through
      case Bytecodes::interpreted_send_1:		// fall through
      case Bytecodes::interpreted_send_2:		// fall through
      case Bytecodes::interpreted_send_n:		// fall through
      case Bytecodes::compiled_send_0:			// fall through
      case Bytecodes::compiled_send_1:			// fall through
      case Bytecodes::compiled_send_2:			// fall through
      case Bytecodes::compiled_send_n:			// fall through
      case Bytecodes::primitive_send_0:			// fall through
      case Bytecodes::primitive_send_1:			// fall through
      case Bytecodes::primitive_send_2:			// fall through
      case Bytecodes::primitive_send_n:			// fall through
      case Bytecodes::polymorphic_send_0:		// fall through
      case Bytecodes::polymorphic_send_1:		// fall through
      case Bytecodes::polymorphic_send_2:		// fall through
      case Bytecodes::polymorphic_send_n:		// fall through
      case Bytecodes::megamorphic_send_0: 		// fall through
      case Bytecodes::megamorphic_send_1: 		// fall through
      case Bytecodes::megamorphic_send_2:		// fall through
      case Bytecodes::megamorphic_send_n:		// fall through
        blk->normal_send(iter.ic());
        break;
      case Bytecodes::interpreted_send_0_pop:		// fall through
      case Bytecodes::interpreted_send_1_pop:		// fall through
      case Bytecodes::interpreted_send_2_pop:		// fall through
      case Bytecodes::interpreted_send_n_pop:		// fall through
      case Bytecodes::compiled_send_0_pop: 		// fall through
      case Bytecodes::compiled_send_1_pop: 		// fall through
      case Bytecodes::compiled_send_2_pop:		// fall through
      case Bytecodes::compiled_send_n_pop:		// fall through
      case Bytecodes::primitive_send_0_pop:		// fall through
      case Bytecodes::primitive_send_1_pop:		// fall through
      case Bytecodes::primitive_send_2_pop:		// fall through
      case Bytecodes::primitive_send_n_pop:		// fall through
      case Bytecodes::polymorphic_send_0_pop:		// fall through
      case Bytecodes::polymorphic_send_1_pop:		// fall through
      case Bytecodes::polymorphic_send_2_pop:		// fall through
      case Bytecodes::polymorphic_send_n_pop:		// fall through
      case Bytecodes::megamorphic_send_0_pop: 		// fall through
      case Bytecodes::megamorphic_send_1_pop: 		// fall through
      case Bytecodes::megamorphic_send_2_pop:		// fall through
      case Bytecodes::megamorphic_send_n_pop:		// fall through
        blk->normal_send(iter.ic());
        blk->pop();
        break;
      case Bytecodes::interpreted_send_self:		// fall through
      case Bytecodes::compiled_send_self:		// fall through
      case Bytecodes::primitive_send_self:		// fall through
      case Bytecodes::polymorphic_send_self:		// fall through
      case Bytecodes::megamorphic_send_self:		// fall through
        blk->self_send(iter.ic());
        break;
      case Bytecodes::interpreted_send_self_pop:	// fall through
      case Bytecodes::compiled_send_self_pop:		// fall through
      case Bytecodes::primitive_send_self_pop:		// fall through
      case Bytecodes::polymorphic_send_self_pop:	// fall through
      case Bytecodes::megamorphic_send_self_pop:	// fall through
        blk->self_send(iter.ic());
        blk->pop();
        break;
      case Bytecodes::interpreted_send_super:		// fall through
      case Bytecodes::compiled_send_super:		// fall through
      case Bytecodes::primitive_send_super:		// fall through
      case Bytecodes::polymorphic_send_super:		// fall through
      case Bytecodes::megamorphic_send_super:		// fall through
        blk->super_send(iter.ic());
        break;
      case Bytecodes::interpreted_send_super_pop:	// fall through
      case Bytecodes::compiled_send_super_pop:		// fall through
      case Bytecodes::primitive_send_super_pop:		// fall through
      case Bytecodes::polymorphic_send_super_pop:	// fall through
      case Bytecodes::megamorphic_send_super_pop:	// fall through
        blk->super_send(iter.ic());
        blk->pop();
        break;
      case Bytecodes::return_tos_pop_0:
        blk->method_return(0);
        break;
      case Bytecodes::return_tos_pop_1:
        blk->method_return(1);
        break;
      case Bytecodes::return_tos_pop_2:
        blk->method_return(2);
        break;
      case Bytecodes::return_tos_pop_n:
        blk->method_return(iter.byte_at(1));
        break;
      case Bytecodes::return_self_pop_0:
        blk->push_self();
        blk->method_return(0);
        break;
      case Bytecodes::return_self_pop_1:
        blk->push_self();
        blk->method_return(1);
        break;
      case Bytecodes::return_self_pop_2:
        blk->push_self();
        blk->method_return(2);
        break;
      case Bytecodes::return_self_pop_n:
        blk->push_self();
        blk->method_return(iter.byte_at(1));
        break;
      case Bytecodes::return_tos_zap_pop_n:
        blk->zap_scope();
        blk->method_return(iter.byte_at(1));
        break;
      case Bytecodes::return_self_zap_pop_n:
        blk->zap_scope();
        blk->push_self();
        blk->method_return(iter.byte_at(1));
        break;
      case Bytecodes::non_local_return_tos_pop_n:
        blk->nonlocal_return(iter.byte_at(1));
        break;
      case Bytecodes::non_local_return_self_pop_n:
        blk->push_self();
        blk->nonlocal_return(iter.byte_at(1));
        break;
      case Bytecodes::prim_call: // fall through
      case Bytecodes::prim_call_self: {
        primitive_desc* pdesc = primitives::lookup((fntype) iter.word_at(1));
        PrimitiveCallNode* node = 
          MethodIterator::factory->new_PrimitiveCallNode(_interval->method(),
          _interval,
          iter.bci(),
          iter.next_bci(),
          pdesc->has_receiver(),
          NULL,
          pdesc);
        // %hack: this assertion fails
        // assert(pdesc->has_receiver() == (iter.code() == Bytecodes::prim_call_self), "just checking");
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->primitive_call_node(node);
        next_bci = node->end_bci();
        break;
                                      }
      case Bytecodes::predict_prim_call:
        blk->predict_prim_call(primitives::lookup((fntype) iter.word_at(1)), -1);
        break;
      case Bytecodes::prim_call_failure: // fall through
      case Bytecodes::prim_call_self_failure: {
        primitive_desc* pdesc = primitives::lookup((fntype) iter.word_at(1));
        PrimitiveCallNode* node = MethodIterator::factory->new_PrimitiveCallNode(
          _interval->method(),
          _interval,
          iter.bci(), 
          iter.next_bci(),
          pdesc->has_receiver(),
          NULL,
          pdesc,
          iter.word_at(1 + oopSize));
        assert(pdesc->has_receiver() == (iter.code() == Bytecodes::prim_call_self_failure), "just checking");
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->primitive_call_node(node);
        next_bci = node->end_bci();
        break;
                                              }
      case Bytecodes::predict_prim_call_failure:
        blk->predict_prim_call(
          primitives::lookup((fntype) iter.word_at(1)),
          iter.next_bci() + iter.word_at(1 + oopSize));
        break;
      case Bytecodes::dll_call_sync: {
        DLLCallNode* node = MethodIterator::factory->new_DLLCallNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.dll_cache());
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->dll_call_node(node);
        next_bci = node->end_bci();
        break;
                                     }
      case Bytecodes::access_send_self:
        blk->self_send(iter.ic());
        break;
      case Bytecodes::unimplemented_bc:
        unknown_code(Bytecodes::unimplemented_bc);
        break;
      case Bytecodes::prim_call_lookup: // fall through
      case Bytecodes::prim_call_self_lookup: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "name must be symbolOop");
        PrimitiveCallNode* node = 
          MethodIterator::factory->new_PrimitiveCallNode(_interval->method(),
          _interval, 
          iter.bci(),
          iter.next_bci(),
          iter.code() == Bytecodes::prim_call_self_lookup,
          name,
          NULL);
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->primitive_call_node(node);
        next_bci = node->end_bci();
        break;
                                             }
      case Bytecodes::predict_prim_call_lookup:
        blk->predict_prim_call(primitives::lookup(symbolOop(iter.word_at(1))), -1);
        break;
      case Bytecodes::prim_call_failure_lookup: // fall through
      case Bytecodes::prim_call_self_failure_lookup: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "name must be symbolOop");
        PrimitiveCallNode* node = MethodIterator::factory->new_PrimitiveCallNode(
          _interval->method(),
          _interval, 
          iter.bci(), 
          iter.next_bci(),
          iter.code() == Bytecodes::prim_call_self_failure_lookup, 
          name,
          NULL,
          iter.word_at(1 + oopSize));
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->primitive_call_node(node);
        next_bci = node->end_bci();
        break;
                                                     }
      case Bytecodes::predict_prim_call_failure_lookup:
        blk->predict_prim_call(
          primitives::lookup(symbolOop(iter.word_at(1))),
          iter.bci() + iter.word_at(1 + oopSize));
        break;
      case Bytecodes::dll_call_async: {
        DLLCallNode* node = MethodIterator::factory->new_DLLCallNode(
          _interval->method(), _interval, iter.bci(), iter.next_bci(), iter.dll_cache());
        assert(node->end_bci() <= _interval->end_bci(), "just checking");
        blk->dll_call_node(node);
        next_bci = node->end_bci();
        break;
                                      }
      case Bytecodes::unimplemented_c7:
        unknown_code(Bytecodes::unimplemented_c7);
        break;
      case Bytecodes::access_send_0:
        blk->normal_send(iter.ic());
        break;
      case Bytecodes::unimplemented_cc:
        unknown_code(Bytecodes::unimplemented_cc);
        break;
      case Bytecodes::unimplemented_dc:
        unknown_code(Bytecodes::unimplemented_dc);
        break;
      case Bytecodes::special_primitive_send_1_hint:
        // ignore - only meaningfull for the interpreter
        break;
      case Bytecodes::unimplemented_de:
        unknown_code(Bytecodes::unimplemented_de);
        break;
      case Bytecodes::unimplemented_df:
        unknown_code(Bytecodes::unimplemented_df);
        break;
      case Bytecodes::smi_add		: // fall through
      case Bytecodes::smi_sub		: // fall through
      case Bytecodes::smi_mult		: // fall through
      case Bytecodes::smi_div		: // fall through
      case Bytecodes::smi_mod		: // fall through
      case Bytecodes::smi_create_point	: // fall through
      case Bytecodes::smi_equal		: // fall through
      case Bytecodes::smi_not_equal	: // fall through
      case Bytecodes::smi_less		: // fall through
      case Bytecodes::smi_less_equal	: // fall through
      case Bytecodes::smi_greater	: // fall through
      case Bytecodes::smi_greater_equal	: // fall through
      case Bytecodes::objArray_at	: // fall through
      case Bytecodes::objArray_at_put	: // fall through
      case Bytecodes::smi_and		: // fall through
      case Bytecodes::smi_or		: // fall through
      case Bytecodes::smi_xor		: // fall through
      case Bytecodes::smi_shift		:
        blk->normal_send(iter.ic());
        break;
      case Bytecodes::double_equal:
        blk->double_equal();
        break;
      case Bytecodes::double_tilde:
        blk->double_not_equal();
        break;
      case Bytecodes::push_global:
        assert(iter.oop_at(1)->is_association(), "must be an association");
        blk->push_global(associationOop(iter.oop_at(1))); 
        break;
      case Bytecodes::store_global_pop:
        assert(iter.oop_at(1)->is_association(), "must be an association");
        blk->store_global(associationOop(iter.oop_at(1)));
        blk->pop(); 
        break;
      case Bytecodes::store_global:
        assert(iter.oop_at(1)->is_association(), "must be an association");
        blk->store_global(associationOop(iter.oop_at(1)));  
        break;
      case Bytecodes::push_classVar_name: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->push_classVar_name(name);
                                          }
                                          break;
      case Bytecodes::store_classVar_pop_name: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->store_classVar_name(name);
        blk->pop();
                                               }
                                               break;
      case Bytecodes::store_classVar_name: {
        symbolOop name = symbolOop(iter.oop_at(1));
        assert(name->is_symbol(), "must be symbol");
        blk->store_classVar_name(name);
                                           }
                                           break;
      case Bytecodes::unimplemented_fa:
        unknown_code(Bytecodes::unimplemented_fa);
        break;
      case Bytecodes::unimplemented_fb:
        unknown_code(Bytecodes::unimplemented_fb);
        break;
      case Bytecodes::unimplemented_fc:
        unknown_code(Bytecodes::unimplemented_fc);
        break;
      case Bytecodes::unimplemented_fd:
        unknown_code(Bytecodes::unimplemented_fd);
        break;
      case Bytecodes::unimplemented_fe:
        unknown_code(Bytecodes::unimplemented_fe);
        break;
      case Bytecodes::halt:
        unknown_code(Bytecodes::halt);
        break;
      default:
        ShouldNotReachHere();
    }
  }
  blk->set_prim_failure(oldFailState);
}
Example #28
0
bool methodKlass::oop_is_parsable(oop obj) const {
  assert(obj->is_method(), "must be method oop");
  return methodOop(obj)->object_is_parsable();
}
Example #29
0
int methodKlass::oop_size(oop obj) const {
  assert(obj->is_method(), "must be method oop");
  return methodOop(obj)->object_size();
}
Example #30
0
void InterpretedIC::cleanup() {
  if (is_empty()) return; // Nothing to cleanup

  switch (send_type()) {
    case Bytecodes::accessor_send:    // fall through
    case Bytecodes::primitive_send:   // fall through
    case Bytecodes::predicted_send:   // fall through
    case Bytecodes::interpreted_send:
      { // check if the interpreted send should be replaced by a compiled send
        klassOop receiver_klass = klassOop(second_word());
        assert(receiver_klass->is_klass(), "receiver klass must be a klass");
        methodOop method = methodOop(first_word());
        assert(method->is_method(), "first word in interpreter IC must be method");
        if (!Bytecodes::is_super_send(send_code())) {
          // super sends cannot be handled since the sending method holder is unknown at this point.
          LookupKey key(receiver_klass, selector());
          LookupResult result = lookupCache::lookup(&key);
          if (!result.matches(method)) {
            replace(result, receiver_klass);
          }
        }
      }
      break;
    case Bytecodes::compiled_send:
      { // check if the current compiled send is valid
        klassOop receiver_klass = klassOop(second_word());
        assert(receiver_klass->is_klass(), "receiver klass must be a klass");
        jumpTableEntry* entry = (jumpTableEntry*) first_word();
        nmethod* nm = entry->method();
        LookupResult result = lookupCache::lookup(&nm->key);
        if (!result.matches(nm)) {
          replace(result, receiver_klass);
        }
      }
      break;
    case Bytecodes::megamorphic_send:
      // Note that with the current definition of is_empty()
      // this will not be called for normal megamorphic sends
      // since they store only the selector.
      { klassOop receiver_klass = klassOop(second_word());
      if (first_word()->is_smi()) {
        jumpTableEntry* entry = (jumpTableEntry*) first_word();
        nmethod* nm = entry->method();
        LookupResult result = lookupCache::lookup(&nm->key);
        if (!result.matches(nm)) {
          replace(result, receiver_klass);
        }
      } else {
        methodOop method = methodOop(first_word());
        assert(method->is_method(), "first word in interpreter IC must be method");
        if (!Bytecodes::is_super_send(send_code())) {
          // super sends cannot be handled since the sending method holder is unknown at this point.
          LookupKey key(receiver_klass, selector());
          LookupResult result = lookupCache::lookup(&key);
          if (!result.matches(method)) {
            replace(result, receiver_klass);
          }
        }
      }
      }
      break;
    case Bytecodes::polymorphic_send:
      {
        // %implementation note:
        //   when cleaning up we can always preserve the old pic since the
        //   the only transitions are:
        //     (compiled    -> compiled)
        //     (compiled    -> interpreted)
        //     (interpreted -> compiled)
        //   in case of a super send we do not have to cleanup because
        //   no nmethods are compiled for super sends.
        if (!Bytecodes::is_super_send(send_code())) {
          objArrayOop pic = pic_array();
          for (int index = pic->length(); index > 0; index -= 2) {
            klassOop klass = klassOop(pic->obj_at(index));
            assert(klass->is_klass(), "receiver klass must be klass");
            oop first = pic->obj_at(index-1);
            if (first->is_smi()) {
              jumpTableEntry* entry = (jumpTableEntry*) first;
              nmethod* nm = entry->method();
              LookupResult result = lookupCache::lookup(&nm->key);
              if (!result.matches(nm)) {
                pic->obj_at_put(index-1, result.value());
              }
            } else {
              methodOop method = methodOop(first);
              assert(method->is_method(), "first word in interpreter IC must be method");
              LookupKey key(klass, selector());
              LookupResult result = lookupCache::lookup(&key);
              if (!result.matches(method)) {
                pic->obj_at_put(index-1, result.value());
              }
            }
          }
        }
      }
  }
}