void Parse::do_field_access(bool is_get, bool is_field) {
  bool will_link;
  ciField* field = iter().get_field(will_link);
  assert(will_link, "getfield: typeflow responsibility");

  ciInstanceKlass* field_holder = field->holder();

  if (is_field == field->is_static()) {
    // Interpreter will throw java_lang_IncompatibleClassChangeError
    // Check this before allowing <clinit> methods to access static fields
    uncommon_trap(Deoptimization::Reason_unhandled,
                  Deoptimization::Action_none);
    return;
  }

  if (!is_field && !field_holder->is_initialized()) {
    if (!static_field_ok_in_clinit(field, method())) {
      uncommon_trap(Deoptimization::Reason_uninitialized,
                    Deoptimization::Action_reinterpret,
                    NULL, "!static_field_ok_in_clinit");
      return;
    }
  }

  assert(field->will_link(method()->holder(), bc()), "getfield: typeflow responsibility");

  // Note:  We do not check for an unloaded field type here any more.

  // Generate code for the object pointer.
  Node* obj;
  if (is_field) {
    int obj_depth = is_get ? 0 : field->type()->size();
    obj = do_null_check(peek(obj_depth), T_OBJECT);
    // Compile-time detect of null-exception?
    if (stopped())  return;

#ifdef ASSERT
    const TypeInstPtr *tjp = TypeInstPtr::make(TypePtr::NotNull, iter().get_declared_field_holder());
    assert(_gvn.type(obj)->higher_equal(tjp), "cast_up is no longer needed");
#endif

    if (is_get) {
      --_sp;  // pop receiver before getting
      do_get_xxx(obj, field, is_field);
    } else {
      do_put_xxx(obj, field, is_field);
      --_sp;  // pop receiver after putting
    }
  } else {
    const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror());
    obj = _gvn.makecon(tip);
    if (is_get) {
      do_get_xxx(obj, field, is_field);
    } else {
      do_put_xxx(obj, field, is_field);
    }
  }
}
示例#2
0
 // Do a null check on the receiver, which is in argument(0).
 Node* null_check_receiver(ciMethod* callee) {
   assert(!callee->is_static(), "must be a virtual method");
   int nargs = 1 + callee->signature()->size();
   // Null check on self without removing any arguments.  The argument
   // null check technically happens in the wrong place, which can lead to
   // invalid stack traces when the primitive is inlined into a method
   // which handles NullPointerExceptions.
   Node* receiver = argument(0);
   _sp += nargs;
   receiver = do_null_check(receiver, T_OBJECT);
   _sp -= nargs;
   return receiver;
 }
示例#3
0
//=============================================================================
//------------------------------do_monitor_enter-------------------------------
void Parse::do_monitor_enter() {
  kill_dead_locals();

  // Null check; get casted pointer.
  Node *obj = do_null_check(peek(), T_OBJECT);
  // Check for locking null object
  if (stopped()) return;

  // the monitor object is not part of debug info expression stack
  pop();

  // Insert a FastLockNode which takes as arguments the current thread pointer,
  // the obj pointer & the address of the stack slot pair used for the lock.
  shared_lock(obj);
}
// uncommon-trap call-sites where callee is unloaded, uninitialized or will not link
bool Parse::can_not_compile_call_site(ciMethod *dest_method, ciInstanceKlass* klass) {
  // Additional inputs to consider...
  // bc      = bc()
  // caller  = method()
  // iter().get_method_holder_index()
  assert( dest_method->is_loaded(), "ciTypeFlow should not let us get here" );
  // Interface classes can be loaded & linked and never get around to
  // being initialized.  Uncommon-trap for not-initialized static or
  // v-calls.  Let interface calls happen.
  ciInstanceKlass* holder_klass  = dest_method->holder();
  if (!holder_klass->is_initialized() &&
      !holder_klass->is_interface()) {

    if( method()->is_static() && method()->name() == ciSymbol::class_initializer_name() )
      return false;             // OK to inline inside of <clinit>
    if( method()->name() == ciSymbol::object_initializer_name() )
      // because any thread calling the constructor must first have
      // synchronized on the class by executing a '_new' bytecode.
      return false;

    // Here we have decided that we cannot make the call because the method
    // holder is not initialized.  We can still check for a null-receiver at
    // runtime and throw the NPE - which avoids a deopt if the user is
    // expecting the NPE.
if(!dest_method->is_static()){
int nargs=1+dest_method->signature()->size();
assert(sp()>=nargs,"stack accepts only positive values");
Node*receiver=stack(sp()-nargs);
      receiver = do_null_check(receiver, T_OBJECT, "nullchk receiver");
    }
    uncommon_trap(Deoptimization::Reason_uninitialized,holder_klass,"call site where called method holder is not initialized",false);
    return true;
  }

  assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
  return false;
}