コード例 #1
0
//------------------------------------------------------------------
// ciObjectFactory::get_unloaded_method
//
// Get the ciMethod representing an unloaded/unfound method.
//
// Implementation note: unloaded methods are currently stored in
// an unordered array, requiring a linear-time lookup for each
// unloaded method.  This may need to change.
ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder,
                                               ciSymbol*        name,
                                               ciSymbol*        signature,
                                               ciInstanceKlass* accessor) {
  ciSignature* that = NULL;
  for (int i = 0; i < _unloaded_methods->length(); i++) {
    ciMethod* entry = _unloaded_methods->at(i);
    if (entry->holder()->equals(holder) &&
        entry->name()->equals(name) &&
        entry->signature()->as_symbol()->equals(signature)) {
      // Short-circuit slow resolve.
      if (entry->signature()->accessing_klass() == accessor) {
        // We've found a match.
        return entry;
      } else {
        // Lazily create ciSignature
        if (that == NULL)  that = new (arena()) ciSignature(accessor, constantPoolHandle(), signature);
        if (entry->signature()->equals(that)) {
          // We've found a match.
          return entry;
        }
      }
    }
  }

  // This is a new unloaded method.  Create it and stick it in
  // the cache.
  ciMethod* new_method = new (arena()) ciMethod(holder, name, signature, accessor);

  init_ident_of(new_method);
  _unloaded_methods->append(new_method);

  return new_method;
}
コード例 #2
0
//------------------------------------------------------------------
// ciObjectFactory::get_return_address
//
// Get a ciReturnAddress for a specified bci.
ciReturnAddress* ciObjectFactory::get_return_address(int bci) {
  for (int i=0; i<_return_addresses->length(); i++) {
    ciReturnAddress* entry = _return_addresses->at(i);
    if (entry->bci() == bci) {
      // We've found a match.
      return entry;
    }
  }

  ciReturnAddress* new_ret_addr = new (arena()) ciReturnAddress(bci);
  init_ident_of(new_ret_addr);
  _return_addresses->append(new_ret_addr);
  return new_ret_addr;
}
コード例 #3
0
// ------------------------------------------------------------------
// ciObjectFactory::get_metadata
//
// Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
// already been created, it is returned. Otherwise, a new ciMetadata
// is created.
ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
  ASSERT_IN_VM;

#ifdef ASSERT
  if (CIObjectFactoryVerify) {
    Metadata* last = NULL;
    for (int j = 0; j< _ci_metadata->length(); j++) {
      Metadata* o = _ci_metadata->at(j)->constant_encoding();
      assert(last < o, "out of order");
      last = o;
    }
  }
#endif // ASSERT
  int len = _ci_metadata->length();
  int index = find(key, _ci_metadata);
#ifdef ASSERT
  if (CIObjectFactoryVerify) {
    for (int i=0; i<_ci_metadata->length(); i++) {
      if (_ci_metadata->at(i)->constant_encoding() == key) {
        assert(index == i, " bad lookup");
      }
    }
  }
#endif
  if (!is_found_at(index, key, _ci_metadata)) {
    // The ciMetadata does not yet exist. Create it and insert it
    // into the cache.
    ciMetadata* new_object = create_new_metadata(key);
    init_ident_of(new_object);
    assert(new_object->is_metadata(), "must be");

    if (len != _ci_metadata->length()) {
      // creating the new object has recursively entered new objects
      // into the table.  We need to recompute our index.
      index = find(key, _ci_metadata);
    }
    assert(!is_found_at(index, key, _ci_metadata), "no double insert");
    insert(index, new_object, _ci_metadata);
    return new_object;
  }
  return _ci_metadata->at(index)->as_metadata();
}
コード例 #4
0
//------------------------------------------------------------------
// ciObjectFactory::get_unloaded_instance
//
// Get a ciInstance representing an as-yet undetermined instance of a given class.
//
ciInstance* ciObjectFactory::get_unloaded_instance(ciInstanceKlass* instance_klass) {
  for (int i=0; i<_unloaded_instances->length(); i++) {
    ciInstance* entry = _unloaded_instances->at(i);
    if (entry->klass()->equals(instance_klass)) {
      // We've found a match.
      return entry;
    }
  }

  // This is a new unloaded instance.  Create it and stick it in
  // the cache.
  ciInstance* new_instance = new (arena()) ciInstance(instance_klass);

  init_ident_of(new_instance);
  _unloaded_instances->append(new_instance);

  // make sure it looks the way we want:
  assert(!new_instance->is_loaded(), "");
  assert(new_instance->klass() == instance_klass, "");

  return new_instance;
}
コード例 #5
0
// ------------------------------------------------------------------
// ciObjectFactory::get
//
// Get the ciObject corresponding to some oop.  If the ciObject has
// already been created, it is returned.  Otherwise, a new ciObject
// is created.
ciObject* ciObjectFactory::get(oop key) {
  ASSERT_IN_VM;

  assert(Universe::heap()->is_in_reserved(key), "must be");

  NonPermObject* &bucket = find_non_perm(key);
  if (bucket != NULL) {
    return bucket->object();
  }

  // The ciObject does not yet exist.  Create it and insert it
  // into the cache.
  Handle keyHandle(key);
  ciObject* new_object = create_new_object(keyHandle());
  assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
  init_ident_of(new_object);
  assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be");

  // Not a perm-space object.
  insert_non_perm(bucket, keyHandle(), new_object);
  return new_object;
}
コード例 #6
0
ファイル: ciObjectFactory.cpp プロジェクト: ericbbcc/hotspot
//------------------------------------------------------------------
// ciObjectFactory::get_unloaded_method
//
// Get the ciMethod representing an unloaded/unfound method.
//
// Implementation note: unloaded methods are currently stored in
// an unordered array, requiring a linear-time lookup for each
// unloaded method.  This may need to change.
ciMethod* ciObjectFactory::get_unloaded_method(ciInstanceKlass* holder,
                                               ciSymbol*        name,
                                               ciSymbol*        signature) {
  for (int i=0; i<_unloaded_methods->length(); i++) {
    ciMethod* entry = _unloaded_methods->at(i);
    if (entry->holder()->equals(holder) &&
        entry->name()->equals(name) &&
        entry->signature()->as_symbol()->equals(signature)) {
      // We've found a match.
      return entry;
    }
  }

  // This is a new unloaded method.  Create it and stick it in
  // the cache.
  ciMethod* new_method = new (arena()) ciMethod(holder, name, signature);

  init_ident_of(new_method);
  _unloaded_methods->append(new_method);

  return new_method;
}
コード例 #7
0
//------------------------------------------------------------------
// ciObjectFactory::get_empty_methodData
//
// Get the ciMethodData representing the methodData for a method with
// none.
ciMethodData* ciObjectFactory::get_empty_methodData() {
  ciMethodData* new_methodData = new (arena()) ciMethodData();
  init_ident_of(new_methodData);
  return new_methodData;
}
コード例 #8
0
//------------------------------------------------------------------
// ciObjectFactory::get_unloaded_klass
//
// Get a ciKlass representing an unloaded klass.
//
// Implementation note: unloaded klasses are currently stored in
// an unordered array, requiring a linear-time lookup for each
// unloaded klass.  This may need to change.
ciKlass* ciObjectFactory::get_unloaded_klass(ciKlass* accessing_klass,
                                             ciSymbol* name,
                                             bool create_if_not_found) {
  EXCEPTION_CONTEXT;
  oop loader = NULL;
  oop domain = NULL;
  if (accessing_klass != NULL) {
    loader = accessing_klass->loader();
    domain = accessing_klass->protection_domain();
  }
  for (int i=0; i<_unloaded_klasses->length(); i++) {
    ciKlass* entry = _unloaded_klasses->at(i);
    if (entry->name()->equals(name) &&
        entry->loader() == loader &&
        entry->protection_domain() == domain) {
      // We've found a match.
      return entry;
    }
  }

  if (!create_if_not_found)
    return NULL;

  // This is a new unloaded klass.  Create it and stick it in
  // the cache.
  ciKlass* new_klass = NULL;

  // Two cases: this is an unloaded ObjArrayKlass or an
  // unloaded InstanceKlass.  Deal with both.
  if (name->byte_at(0) == '[') {
    // Decompose the name.'
    FieldArrayInfo fd;
    BasicType element_type = FieldType::get_array_info(name->get_symbol(),
                                                       fd, THREAD);
    if (HAS_PENDING_EXCEPTION) {
      CLEAR_PENDING_EXCEPTION;
      CURRENT_THREAD_ENV->record_out_of_memory_failure();
      return ciEnv::_unloaded_ciobjarrayklass;
    }
    int dimension = fd.dimension();
    assert(element_type != T_ARRAY, "unsuccessful decomposition");
    ciKlass* element_klass = NULL;
    if (element_type == T_OBJECT) {
      ciEnv *env = CURRENT_THREAD_ENV;
      ciSymbol* ci_name = env->get_symbol(fd.object_key());
      element_klass =
        env->get_klass_by_name(accessing_klass, ci_name, false)->as_instance_klass();
    } else {
      assert(dimension > 1, "one dimensional type arrays are always loaded.");

      // The type array itself takes care of one of the dimensions.
      dimension--;

      // The element klass is a TypeArrayKlass.
      element_klass = ciTypeArrayKlass::make(element_type);
    }
    new_klass = new (arena()) ciObjArrayKlass(name, element_klass, dimension);
  } else {
    jobject loader_handle = NULL;
    jobject domain_handle = NULL;
    if (accessing_klass != NULL) {
      loader_handle = accessing_klass->loader_handle();
      domain_handle = accessing_klass->protection_domain_handle();
    }
    new_klass = new (arena()) ciInstanceKlass(name, loader_handle, domain_handle);
  }
  init_ident_of(new_klass);
  _unloaded_klasses->append(new_klass);

  return new_klass;
}
コード例 #9
0
void ciObjectFactory::init_shared_objects() {

  _next_ident = 1;  // start numbering CI objects at 1

  {
    // Create the shared symbols, but not in _shared_ci_metadata.
    int i;
    for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) {
      Symbol* vmsym = vmSymbols::symbol_at((vmSymbols::SID) i);
      assert(vmSymbols::find_sid(vmsym) == i, "1-1 mapping");
      ciSymbol* sym = new (_arena) ciSymbol(vmsym, (vmSymbols::SID) i);
      init_ident_of(sym);
      _shared_ci_symbols[i] = sym;
    }
#ifdef ASSERT
    for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) {
      Symbol* vmsym = vmSymbols::symbol_at((vmSymbols::SID) i);
      ciSymbol* sym = vm_symbol_at((vmSymbols::SID) i);
      assert(sym->get_symbol() == vmsym, "oop must match");
    }
    assert(ciSymbol::void_class_signature()->get_symbol() == vmSymbols::void_class_signature(), "spot check");
#endif
  }

  _ci_metadata = new (_arena) GrowableArray<ciMetadata*>(_arena, 64, 0, NULL);

  for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) {
    BasicType t = (BasicType)i;
    if (type2name(t) != NULL && t != T_OBJECT && t != T_ARRAY && t != T_NARROWOOP && t != T_NARROWKLASS) {
      ciType::_basic_types[t] = new (_arena) ciType(t);
      init_ident_of(ciType::_basic_types[t]);
    }
  }

  ciEnv::_null_object_instance = new (_arena) ciNullObject();
  init_ident_of(ciEnv::_null_object_instance);

#define WK_KLASS_DEFN(name, ignore_s, opt)                              \
  if (SystemDictionary::name() != NULL) \
    ciEnv::_##name = get_metadata(SystemDictionary::name())->as_instance_klass();

  WK_KLASSES_DO(WK_KLASS_DEFN)
#undef WK_KLASS_DEFN

  for (int len = -1; len != _ci_metadata->length(); ) {
    len = _ci_metadata->length();
    for (int i2 = 0; i2 < len; i2++) {
      ciMetadata* obj = _ci_metadata->at(i2);
      assert (obj->is_metadata(), "what else would it be?");
      if (obj->is_loaded() && obj->is_instance_klass()) {
        obj->as_instance_klass()->compute_nonstatic_fields();
      }
    }
  }

  ciEnv::_unloaded_cisymbol = ciObjectFactory::get_symbol(vmSymbols::dummy_symbol());
  // Create dummy InstanceKlass and ObjArrayKlass object and assign them idents
  ciEnv::_unloaded_ciinstance_klass = new (_arena) ciInstanceKlass(ciEnv::_unloaded_cisymbol, NULL, NULL);
  init_ident_of(ciEnv::_unloaded_ciinstance_klass);
  ciEnv::_unloaded_ciobjarrayklass = new (_arena) ciObjArrayKlass(ciEnv::_unloaded_cisymbol, ciEnv::_unloaded_ciinstance_klass, 1);
  init_ident_of(ciEnv::_unloaded_ciobjarrayklass);
  assert(ciEnv::_unloaded_ciobjarrayklass->is_obj_array_klass(), "just checking");

  get_metadata(Universe::boolArrayKlassObj());
  get_metadata(Universe::charArrayKlassObj());
  get_metadata(Universe::singleArrayKlassObj());
  get_metadata(Universe::doubleArrayKlassObj());
  get_metadata(Universe::byteArrayKlassObj());
  get_metadata(Universe::shortArrayKlassObj());
  get_metadata(Universe::intArrayKlassObj());
  get_metadata(Universe::longArrayKlassObj());



  assert(_non_perm_count == 0, "no shared non-perm objects");

  // The shared_ident_limit is the first ident number that will
  // be used for non-shared objects.  That is, numbers less than
  // this limit are permanently assigned to shared CI objects,
  // while the higher numbers are recycled afresh by each new ciEnv.

  _shared_ident_limit = _next_ident;
  _shared_ci_metadata = _ci_metadata;
}
コード例 #10
0
ファイル: ciObjectFactory.cpp プロジェクト: ericbbcc/hotspot
// ------------------------------------------------------------------
// ciObjectFactory::get
//
// Get the ciObject corresponding to some oop.  If the ciObject has
// already been created, it is returned.  Otherwise, a new ciObject
// is created.
ciObject* ciObjectFactory::get(oop key) {
  ASSERT_IN_VM;

#ifdef ASSERT
  if (CIObjectFactoryVerify) {
    oop last = NULL;
    for (int j = 0; j< _ci_objects->length(); j++) {
      oop o = _ci_objects->at(j)->get_oop();
      assert(last < o, "out of order");
      last = o;
    }
  }
#endif // ASSERT
  int len = _ci_objects->length();
  int index = find(key, _ci_objects);
#ifdef ASSERT
  if (CIObjectFactoryVerify) {
    for (int i=0; i<_ci_objects->length(); i++) {
      if (_ci_objects->at(i)->get_oop() == key) {
        assert(index == i, " bad lookup");
      }
    }
  }
#endif
  if (!is_found_at(index, key, _ci_objects)) {
    // Check in the non-perm area before putting it in the list.
    NonPermObject* &bucket = find_non_perm(key);
    if (bucket != NULL) {
      return bucket->object();
    }

    // Check in the shared symbol area before putting it in the list.
    if (key->is_symbol()) {
      vmSymbols::SID sid = vmSymbols::find_sid((symbolOop)key);
      if (sid != vmSymbols::NO_SID) {
        // do not pollute the main cache with it
        return vm_symbol_at(sid);
      }
    }

    // The ciObject does not yet exist.  Create it and insert it
    // into the cache.
    Handle keyHandle(key);
    ciObject* new_object = create_new_object(keyHandle());
    assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
    init_ident_of(new_object);
    if (!new_object->is_perm()) {
      // Not a perm-space object.
      insert_non_perm(bucket, keyHandle(), new_object);
      return new_object;
    }
    if (len != _ci_objects->length()) {
      // creating the new object has recursively entered new objects
      // into the table.  We need to recompute our index.
      index = find(keyHandle(), _ci_objects);
    }
    assert(!is_found_at(index, keyHandle(), _ci_objects), "no double insert");
    insert(index, new_object, _ci_objects);
    return new_object;
  }
  return _ci_objects->at(index);
}