--- old/src/share/vm/ci/ciObjectFactory.cpp 2014-10-29 17:47:54.000000000 +0400 +++ new/src/share/vm/ci/ciObjectFactory.cpp 2014-10-29 17:47:54.000000000 +0400 @@ -239,7 +239,7 @@ ciObject* ciObjectFactory::get(oop key) { ASSERT_IN_VM; - assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be"); + assert(Universe::heap()->is_in_reserved(key), "must be"); NonPermObject* &bucket = find_non_perm(key); if (bucket != NULL) { @@ -260,10 +260,10 @@ } // ------------------------------------------------------------------ -// ciObjectFactory::get +// ciObjectFactory::get_metadata // -// Get the ciObject corresponding to some oop. If the ciObject has -// already been created, it is returned. Otherwise, a new ciObject +// 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; @@ -290,9 +290,9 @@ } #endif if (!is_found_at(index, key, _ci_metadata)) { - // The ciObject does not yet exist. Create it and insert it + // The ciMetadata does not yet exist. Create it and insert it // into the cache. - ciMetadata* new_object = create_new_object(key); + ciMetadata* new_object = create_new_metadata(key); init_ident_of(new_object); assert(new_object->is_metadata(), "must be"); @@ -346,13 +346,32 @@ // ------------------------------------------------------------------ // ciObjectFactory::create_new_object // -// Create a new ciObject from a Metadata*. +// Create a new ciMetadata from a Metadata*. // -// Implementation note: this functionality could be virtual behavior -// of the oop itself. For now, we explicitly marshal the object. -ciMetadata* ciObjectFactory::create_new_object(Metadata* o) { +// Implementation note: in order to keep Metadata live, an auxiliary ciObject +// is used, which points to it's holder. +ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) { EXCEPTION_CONTEXT; + // Hold metadata from unloading by keeping it's holder alive. + if (_initialized) { + Klass* holder; + if (o->is_klass()) { + holder = ((Klass*)o); + } else if (o->is_method()) { + holder = ((Method*)o)->method_holder(); + } else if (o->is_methodData()) { + holder = ((MethodData*)o)->method()->method_holder(); + } else { + ShouldNotReachHere(); + } + if (holder != NULL && holder->klass_holder() != NULL) { + // It is enough to record a ciObject (which contains JNI handle to the oop), + // since cached elements are never removed during ciObjectFactory lifetime. + ciObject* h = get(holder->klass_holder()); + } + } + if (o->is_klass()) { KlassHandle h_k(THREAD, (Klass*)o); Klass* k = (Klass*)o; @@ -372,7 +391,7 @@ return new (arena()) ciMethodData((MethodData*)o); } - // The oop is of some type not supported by the compiler interface. + // The Metadata* is of some type not supported by the compiler interface. ShouldNotReachHere(); return NULL; } @@ -701,7 +720,7 @@ // If there is no entry in the cache corresponding to this oop, return // the null tail of the bucket into which the oop should be inserted. ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) { - assert(Universe::heap()->is_in_reserved_or_null(key), "must be"); + assert(Universe::heap()->is_in_reserved(key), "must be"); ciMetadata* klass = get_metadata(key->klass()); NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS]; for (NonPermObject* p; (p = (*bp)) != NULL; bp = &p->next()) { --- old/src/share/vm/ci/ciObjectFactory.hpp 2014-10-29 17:48:04.000000000 +0400 +++ new/src/share/vm/ci/ciObjectFactory.hpp 2014-10-29 17:48:03.000000000 +0400 @@ -73,7 +73,7 @@ void insert(int index, ciMetadata* obj, GrowableArray* objects); ciObject* create_new_object(oop o); - ciMetadata* create_new_object(Metadata* o); + ciMetadata* create_new_metadata(Metadata* o); void ensure_metadata_alive(ciMetadata* m);