Esempio n. 1
0
bool ConstantPoolCacheEntry::is_interesting_method_entry(klassOop k) {
  if (!is_method_entry()) {
    // not a method entry so not interesting by default
    return false;
  }

  methodOop m = NULL;
  if (is_vfinal()) {
    // virtual and final so _f2 contains method ptr instead of vtable index
    m = f2_as_vfinal_method();
  } else if (is_f1_null()) {
    // NULL _f1 means this is a virtual entry so also not interesting
    return false;
  } else {
    oop f1 = _f1;  // _f1 is volatile
    if (!f1->is_method()) {
      // _f1 can also contain a klassOop for an interface
      return false;
    }
    m = f1_as_method();
  }

  assert(m != NULL && m->is_method(), "sanity check");
  if (m == NULL || !m->is_method() || m->method_holder() != k) {
    // robustness for above sanity checks or method is not in
    // the interesting class
    return false;
  }

  // the method is in the interesting class so the entry is interesting
  return true;
}
oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
  if (is_f1_null() || !has_method_type())
    return NULL;
  const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset;
  objArrayOop resolved_references = cpool->resolved_references();
  return resolved_references->obj_at(ref_index);
}
Esempio n. 3
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;
}
void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
                                                      Bytecodes::Code invoke_code,
                                                      const CallInfo &call_info) {
  // NOTE: This CPCE can be the subject of data races.
  // There are three words to update: flags, refs[f2], f1 (in that order).
  // Writers must store all other values before f1.
  // Readers must test f1 first for non-null before reading other fields.
  // Competing writers must acquire exclusive access via a lock.
  // A losing writer waits on the lock until the winner writes f1 and leaves
  // the lock, so that when the losing writer returns, he can use the linked
  // cache entry.

  MonitorLockerEx ml(cpool->lock());
  if (!is_f1_null()) {
    return;
  }

  const methodHandle adapter = call_info.resolved_method();
  const Handle appendix      = call_info.resolved_appendix();
  const Handle method_type   = call_info.resolved_method_type();
  const bool has_appendix    = appendix.not_null();
  const bool has_method_type = method_type.not_null();

  // Write the flags.
  set_method_flags(as_TosState(adapter->result_type()),
                   ((has_appendix    ? 1 : 0) << has_appendix_shift   ) |
                   ((has_method_type ? 1 : 0) << has_method_type_shift) |
                   (                   1      << is_final_shift       ),
                   adapter->size_of_parameters());

  if (TraceInvokeDynamic) {
    tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ",
                  invoke_code,
                  (void *)appendix(),    (has_appendix    ? "" : " (unused)"),
                  (void *)method_type(), (has_method_type ? "" : " (unused)"),
                  (intptr_t)adapter());
    adapter->print();
    if (has_appendix)  appendix()->print();
  }

  // Method handle invokes and invokedynamic sites use both cp cache words.
  // refs[f2], if not null, contains a value passed as a trailing argument to the adapter.
  // In the general case, this could be the call site's MethodType,
  // for use with java.lang.Invokers.checkExactType, or else a CallSite object.
  // f1 contains the adapter method which manages the actual call.
  // In the general case, this is a compiled LambdaForm.
  // (The Java code is free to optimize these calls by binding other
  // sorts of methods and appendices to call sites.)
  // JVM-level linking is via f1, as if for invokespecial, and signatures are erased.
  // The appendix argument (if any) is added to the signature, and is counted in the parameter_size bits.
  // Even with the appendix, the method will never take more than 255 parameter slots.
  //
  // This means that given a call site like (List)mh.invoke("foo"),
  // the f1 method has signature '(Ljl/Object;Ljl/invoke/MethodType;)Ljl/Object;',
  // not '(Ljava/lang/String;)Ljava/util/List;'.
  // The fact that String and List are involved is encoded in the MethodType in refs[f2].
  // This allows us to create fewer method oops, while keeping type safety.
  //

  objArrayHandle resolved_references = cpool->resolved_references();
  // Store appendix, if any.
  if (has_appendix) {
    const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
    assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
    assert(resolved_references->obj_at(appendix_index) == NULL, "init just once");
    resolved_references->obj_at_put(appendix_index, appendix());
  }

  // Store MethodType, if any.
  if (has_method_type) {
    const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset;
    assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob");
    assert(resolved_references->obj_at(method_type_index) == NULL, "init just once");
    resolved_references->obj_at_put(method_type_index, method_type());
  }

  release_set_f1(adapter());  // This must be the last one to set (see NOTE above)!

  // The interpreter assembly code does not check byte_2,
  // but it is used by is_resolved, method_if_resolved, etc.
  set_bytecode_1(invoke_code);
  NOT_PRODUCT(verify(tty));
  if (TraceInvokeDynamic) {
    this->print(tty, 0);
  }
}
Esempio n. 5
0
oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
  if (is_f1_null() || !has_method_type())
    return NULL;
  return f1_as_instance();
}
Esempio n. 6
0
oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) {
  if (is_f1_null() || !has_appendix())
    return NULL;
  return f1_appendix();
}
Esempio n. 7
0
void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
                                                      Bytecodes::Code invoke_code,
                                                      methodHandle adapter,
                                                      Handle appendix, Handle method_type) {
  // NOTE: This CPCE can be the subject of data races.
  // There are three words to update: flags, f2, f1 (in that order).
  // Writers must store all other values before f1.
  // Readers must test f1 first for non-null before reading other fields.
  // Competing writers must acquire exclusive access via a lock.
  // A losing writer waits on the lock until the winner writes f1 and leaves
  // the lock, so that when the losing writer returns, he can use the linked
  // cache entry.

  Thread* THREAD = Thread::current();
  ObjectLocker ol(cpool, THREAD);
  if (!is_f1_null()) {
    return;
  }

  const bool has_appendix    = appendix.not_null();
  const bool has_method_type = method_type.not_null();

  if (!has_appendix) {
    // The extra argument is not used, but we need a non-null value to signify linkage state.
    // Set it to something benign that will never leak memory.
    appendix = Universe::void_mirror();
  }

  // Write the flags.
  set_method_flags(as_TosState(adapter->result_type()),
                   ((has_appendix    ? 1 : 0) << has_appendix_shift)    |
                   ((has_method_type ? 1 : 0) << has_method_type_shift) |
                   (                   1      << is_vfinal_shift)       |
                   (                   1      << is_final_shift),
                   adapter->size_of_parameters());

  if (TraceInvokeDynamic) {
    tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ",
                  invoke_code,
                  (intptr_t)appendix(),    (has_appendix    ? "" : " (unused)"),
                  (intptr_t)method_type(), (has_method_type ? "" : " (unused)"),
                  (intptr_t)adapter());
    adapter->print();
    if (has_appendix)  appendix()->print();
  }

  // Method handle invokes and invokedynamic sites use both cp cache words.
  // f1, if not null, contains a value passed as a trailing argument to the adapter.
  // In the general case, this could be the call site's MethodType,
  // for use with java.lang.Invokers.checkExactType, or else a CallSite object.
  // f2 contains the adapter method which manages the actual call.
  // In the general case, this is a compiled LambdaForm.
  // (The Java code is free to optimize these calls by binding other
  // sorts of methods and appendices to call sites.)
  // JVM-level linking is via f2, as if for invokevfinal, and signatures are erased.
  // The appendix argument (if any) is added to the signature, and is counted in the parameter_size bits.
  // In principle this means that the method (with appendix) could take up to 256 parameter slots.
  //
  // This means that given a call site like (List)mh.invoke("foo"),
  // the f2 method has signature '(Ljl/Object;Ljl/invoke/MethodType;)Ljl/Object;',
  // not '(Ljava/lang/String;)Ljava/util/List;'.
  // The fact that String and List are involved is encoded in the MethodType in f1.
  // This allows us to create fewer method oops, while keeping type safety.
  //

  set_f2_as_vfinal_method(adapter());

  // Store MethodType, if any.
  if (has_method_type) {
    ConstantPoolCacheEntry* e2 = cpool->cache()->find_secondary_entry_for(this);

    // Write the flags.
    e2->set_method_flags(as_TosState(adapter->result_type()),
                     ((has_method_type ? 1 : 0) << has_method_type_shift) |
                     (                   1      << is_vfinal_shift)       |
                     (                   1      << is_final_shift),
                     adapter->size_of_parameters());
    e2->release_set_f1(method_type());
  }

  assert(appendix.not_null(), "needed for linkage state");
  release_set_f1(appendix());  // This must be the last one to set (see NOTE above)!

  if (!is_secondary_entry()) {
    // The interpreter assembly code does not check byte_2,
    // but it is used by is_resolved, method_if_resolved, etc.
    set_bytecode_2(invoke_code);
  }

  NOT_PRODUCT(verify(tty));
  if (TraceInvokeDynamic) {
    this->print(tty, 0);
  }
}