예제 #1
0
void ciField::initialize_from(fieldDescriptor* fd) {
  // Get the flags, offset, and canonical holder of the field.
  _flags = ciFlags(fd->access_flags());
  _offset = fd->offset();
  _holder = CURRENT_ENV->get_object(fd->field_holder())->as_instance_klass();

  // Check to see if the field is constant.
  if (_holder->is_initialized() && this->is_final()) {
    if (!this->is_static()) {
      // A field can be constant if it's a final static field or if
      // it's a final non-static field of a trusted class (classes in
      // java.lang.invoke and sun.invoke packages and subpackages).
      if (trust_final_non_static_fields(_holder)) {
        _is_constant = true;
        return;
      }
      _is_constant = false;
      return;
    }

    // This field just may be constant.  The only cases where it will
    // not be constant are:
    //
    // 1. The field holds a non-perm-space oop.  The field is, strictly
    //    speaking, constant but we cannot embed non-perm-space oops into
    //    generated code.  For the time being we need to consider the
    //    field to be not constant.
    // 2. The field is a *special* static&final field whose value
    //    may change.  The three examples are java.lang.System.in,
    //    java.lang.System.out, and java.lang.System.err.

    KlassHandle k = _holder->get_klassOop();
    assert( SystemDictionary::System_klass() != NULL, "Check once per vm");
    if( k() == SystemDictionary::System_klass() ) {
      // Check offsets for case 2: System.in, System.out, or System.err
      if( _offset == java_lang_System::in_offset_in_bytes()  ||
          _offset == java_lang_System::out_offset_in_bytes() ||
          _offset == java_lang_System::err_offset_in_bytes() ) {
        _is_constant = false;
        return;
      }
    }

    Handle mirror = k->java_mirror();

    _is_constant = true;
    switch(type()->basic_type()) {
    case T_BYTE:
      _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset));
      break;
    case T_CHAR:
      _constant_value = ciConstant(type()->basic_type(), mirror->char_field(_offset));
      break;
    case T_SHORT:
      _constant_value = ciConstant(type()->basic_type(), mirror->short_field(_offset));
      break;
    case T_BOOLEAN:
      _constant_value = ciConstant(type()->basic_type(), mirror->bool_field(_offset));
      break;
    case T_INT:
      _constant_value = ciConstant(type()->basic_type(), mirror->int_field(_offset));
      break;
    case T_FLOAT:
      _constant_value = ciConstant(mirror->float_field(_offset));
      break;
    case T_DOUBLE:
      _constant_value = ciConstant(mirror->double_field(_offset));
      break;
    case T_LONG:
      _constant_value = ciConstant(mirror->long_field(_offset));
      break;
    case T_OBJECT:
    case T_ARRAY:
      {
        oop o = mirror->obj_field(_offset);

        // A field will be "constant" if it is known always to be
        // a non-null reference to an instance of a particular class,
        // or to a particular array.  This can happen even if the instance
        // or array is not perm.  In such a case, an "unloaded" ciArray
        // or ciInstance is created.  The compiler may be able to use
        // information about the object's class (which is exact) or length.

        if (o == NULL) {
          _constant_value = ciConstant(type()->basic_type(), ciNullObject::make());
        } else {
          _constant_value = ciConstant(type()->basic_type(), CURRENT_ENV->get_object(o));
          assert(_constant_value.as_object() == CURRENT_ENV->get_object(o), "check interning");
        }
      }
    }
  } else {
    _is_constant = false;
  }
}