--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Fri Aug 31 16:39:35 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Sat Sep 01 13:25:18 2012 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -23,25 +23,21 @@
*/
#include "precompiled.hpp"
-#include "ci/ciCPCache.hpp"
#include "ci/ciCallSite.hpp"
#include "ci/ciInstance.hpp"
#include "ci/ciInstanceKlass.hpp"
-#include "ci/ciInstanceKlassKlass.hpp"
#include "ci/ciMemberName.hpp"
#include "ci/ciMethod.hpp"
#include "ci/ciMethodData.hpp"
#include "ci/ciMethodHandle.hpp"
-#include "ci/ciMethodKlass.hpp"
#include "ci/ciNullObject.hpp"
#include "ci/ciObjArray.hpp"
#include "ci/ciObjArrayKlass.hpp"
-#include "ci/ciObjArrayKlassKlass.hpp"
+#include "ci/ciObject.hpp"
#include "ci/ciObjectFactory.hpp"
#include "ci/ciSymbol.hpp"
#include "ci/ciTypeArray.hpp"
#include "ci/ciTypeArrayKlass.hpp"
-#include "ci/ciTypeArrayKlassKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
@@ -67,7 +63,7 @@
// problematic the underlying data structure can be switched to some
// sort of balanced binary tree.
-GrowableArray<ciObject*>* ciObjectFactory::_shared_ci_objects = NULL;
+GrowableArray<ciMetadata*>* ciObjectFactory::_shared_ci_metadata = NULL;
ciSymbol* ciObjectFactory::_shared_ci_symbols[vmSymbols::SID_LIMIT];
int ciObjectFactory::_shared_ident_limit = 0;
volatile bool ciObjectFactory::_initialized = false;
@@ -85,12 +81,12 @@
_next_ident = _shared_ident_limit;
_arena = arena;
- _ci_objects = new (arena) GrowableArray<ciObject*>(arena, expected_size, 0, NULL);
+ _ci_metadata = new (arena) GrowableArray<ciMetadata*>(arena, expected_size, 0, NULL);
// If the shared ci objects exist append them to this factory's objects
- if (_shared_ci_objects != NULL) {
- _ci_objects->appendAll(_shared_ci_objects);
+ if (_shared_ci_metadata != NULL) {
+ _ci_metadata->appendAll(_shared_ci_metadata);
}
_unloaded_methods = new (arena) GrowableArray<ciMethod*>(arena, 4, 0, NULL);
@@ -126,7 +122,7 @@
_next_ident = 1; // start numbering CI objects at 1
{
- // Create the shared symbols, but not in _shared_ci_objects.
+ // 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);
@@ -145,7 +141,7 @@
#endif
}
- _ci_objects = new (_arena) GrowableArray<ciObject*>(_arena, 64, 0, NULL);
+ _ci_metadata = new (_arena) GrowableArray<ciMetadata*>(_arena, 64, 0, NULL);
for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) {
BasicType t = (BasicType)i;
@@ -157,31 +153,19 @@
ciEnv::_null_object_instance = new (_arena) ciNullObject();
init_ident_of(ciEnv::_null_object_instance);
- ciEnv::_method_klass_instance =
- get(Universe::methodKlassObj())->as_method_klass();
- ciEnv::_klass_klass_instance =
- get(Universe::klassKlassObj())->as_klass_klass();
- ciEnv::_instance_klass_klass_instance =
- get(Universe::instanceKlassKlassObj())
- ->as_instance_klass_klass();
- ciEnv::_type_array_klass_klass_instance =
- get(Universe::typeArrayKlassKlassObj())
- ->as_type_array_klass_klass();
- ciEnv::_obj_array_klass_klass_instance =
- get(Universe::objArrayKlassKlassObj())
- ->as_obj_array_klass_klass();
#define WK_KLASS_DEFN(name, ignore_s, opt) \
if (SystemDictionary::name() != NULL) \
- ciEnv::_##name = get(SystemDictionary::name())->as_instance_klass();
+ 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_objects->length(); ) {
- len = _ci_objects->length();
+ for (int len = -1; len != _ci_metadata->length(); ) {
+ len = _ci_metadata->length();
for (int i2 = 0; i2 < len; i2++) {
- ciObject* obj = _ci_objects->at(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();
}
@@ -189,21 +173,21 @@
}
ciEnv::_unloaded_cisymbol = ciObjectFactory::get_symbol(vmSymbols::dummy_symbol());
- // Create dummy instanceKlass and objArrayKlass object and assign them idents
+ // 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(Universe::boolArrayKlassObj());
- get(Universe::charArrayKlassObj());
- get(Universe::singleArrayKlassObj());
- get(Universe::doubleArrayKlassObj());
- get(Universe::byteArrayKlassObj());
- get(Universe::shortArrayKlassObj());
- get(Universe::intArrayKlassObj());
- get(Universe::longArrayKlassObj());
+ 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());
@@ -215,7 +199,7 @@
// while the higher numbers are recycled afresh by each new ciEnv.
_shared_ident_limit = _next_ident;
- _shared_ci_objects = _ci_objects;
+ _shared_ci_metadata = _ci_metadata;
}
@@ -251,29 +235,8 @@
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.
+ assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be");
+
NonPermObject* &bucket = find_non_perm(key);
if (bucket != NULL) {
return bucket->object();
@@ -285,21 +248,62 @@
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()) {
+ 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;
}
- if (len != _ci_objects->length()) {
+
+// ------------------------------------------------------------------
+// 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.
+ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
+ ASSERT_IN_VM;
+
+ assert(key == NULL || key->is_metadata(), "must be");
+
+#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 ciObject does not yet exist. Create it and insert it
+ // into the cache.
+ ciMetadata* new_object = create_new_object(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(keyHandle(), _ci_objects);
+ index = find(key, _ci_metadata);
}
- assert(!is_found_at(index, keyHandle(), _ci_objects), "no double insert");
- insert(index, new_object, _ci_objects);
+ assert(!is_found_at(index, key, _ci_metadata), "no double insert");
+ insert(index, new_object, _ci_metadata);
return new_object;
}
- return _ci_objects->at(index);
+ return _ci_metadata->at(index)->as_metadata();
}
// ------------------------------------------------------------------
@@ -312,36 +316,7 @@
ciObject* ciObjectFactory::create_new_object(oop o) {
EXCEPTION_CONTEXT;
- if (o->is_klass()) {
- KlassHandle h_k(THREAD, (klassOop)o);
- Klass* k = ((klassOop)o)->klass_part();
- if (k->oop_is_instance()) {
- return new (arena()) ciInstanceKlass(h_k);
- } else if (k->oop_is_objArray()) {
- return new (arena()) ciObjArrayKlass(h_k);
- } else if (k->oop_is_typeArray()) {
- return new (arena()) ciTypeArrayKlass(h_k);
- } else if (k->oop_is_method()) {
- return new (arena()) ciMethodKlass(h_k);
- } else if (k->oop_is_klass()) {
- if (k->oop_is_objArrayKlass()) {
- return new (arena()) ciObjArrayKlassKlass(h_k);
- } else if (k->oop_is_typeArrayKlass()) {
- return new (arena()) ciTypeArrayKlassKlass(h_k);
- } else if (k->oop_is_instanceKlass()) {
- return new (arena()) ciInstanceKlassKlass(h_k);
- } else {
- assert(o == Universe::klassKlassObj(), "bad klassKlass");
- return new (arena()) ciKlassKlass(h_k);
- }
- }
- } else if (o->is_method()) {
- methodHandle h_m(THREAD, (methodOop)o);
- return new (arena()) ciMethod(h_m);
- } else if (o->is_methodData()) {
- methodDataHandle h_md(THREAD, (methodDataOop)o);
- return new (arena()) ciMethodData(h_md);
- } else if (o->is_instance()) {
+ if (o->is_instance()) {
instanceHandle h_i(THREAD, (instanceOop)o);
if (java_lang_invoke_CallSite::is_instance(o))
return new (arena()) ciCallSite(h_i);
@@ -357,9 +332,40 @@
} else if (o->is_typeArray()) {
typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
return new (arena()) ciTypeArray(h_ta);
- } else if (o->is_constantPoolCache()) {
- constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o);
- return new (arena()) ciCPCache(h_cpc);
+ }
+
+ // The oop is of some type not supported by the compiler interface.
+ ShouldNotReachHere();
+ return NULL;
+}
+
+// ------------------------------------------------------------------
+// ciObjectFactory::create_new_object
+//
+// Create a new ciObject 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) {
+ EXCEPTION_CONTEXT;
+
+ if (o->is_klass()) {
+ KlassHandle h_k(THREAD, (Klass*)o);
+ Klass* k = (Klass*)o;
+ if (k->oop_is_instance()) {
+ return new (arena()) ciInstanceKlass(h_k);
+ } else if (k->oop_is_objArray()) {
+ return new (arena()) ciObjArrayKlass(h_k);
+ } else if (k->oop_is_typeArray()) {
+ return new (arena()) ciTypeArrayKlass(h_k);
+ }
+ } else if (o->is_method()) {
+ methodHandle h_m(THREAD, (Method*)o);
+ return new (arena()) ciMethod(h_m);
+ } else if (o->is_methodData()) {
+ // Hold methodHandle alive - might not be necessary ???
+ methodHandle h_m(THREAD, ((MethodData*)o)->method());
+ return new (arena()) ciMethodData((MethodData*)o);
}
// The oop is of some type not supported by the compiler interface.
@@ -446,7 +452,7 @@
ciKlass* new_klass = NULL;
// Two cases: this is an unloaded objArrayKlass or an
- // unloaded instanceKlass. Deal with both.
+ // unloaded InstanceKlass. Deal with both.
if (name->byte_at(0) == '[') {
// Decompose the name.'
FieldArrayInfo fd;
@@ -590,22 +596,17 @@
// ------------------------------------------------------------------
// ciObjectFactory::init_ident_of
-void ciObjectFactory::init_ident_of(ciObject* obj) {
+void ciObjectFactory::init_ident_of(ciBaseObject* obj) {
obj->set_ident(_next_ident++);
}
-void ciObjectFactory::init_ident_of(ciSymbol* obj) {
- obj->set_ident(_next_ident++);
-}
-
-
// ------------------------------------------------------------------
// ciObjectFactory::find
//
// Use binary search to find the position of this oop in the cache.
// If there is no entry in the cache corresponding to this oop, return
// the position at which the oop should be inserted.
-int ciObjectFactory::find(oop key, GrowableArray<ciObject*>* objects) {
+int ciObjectFactory::find(Metadata* key, GrowableArray<ciMetadata*>* objects) {
int min = 0;
int max = objects->length()-1;
@@ -613,7 +614,7 @@
while (max >= min) {
int mid = (max + min) / 2;
- oop value = objects->at(mid)->get_oop();
+ Metadata* value = objects->at(mid)->constant_encoding();
if (value < key) {
min = mid + 1;
} else if (value > key) {
@@ -629,9 +630,9 @@
// ciObjectFactory::is_found_at
//
// Verify that the binary seach found the given key.
-bool ciObjectFactory::is_found_at(int index, oop key, GrowableArray<ciObject*>* objects) {
+bool ciObjectFactory::is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects) {
return (index < objects->length() &&
- objects->at(index)->get_oop() == key);
+ objects->at(index)->constant_encoding() == key);
}
@@ -639,7 +640,7 @@
// ciObjectFactory::insert
//
// Insert a ciObject into the table at some index.
-void ciObjectFactory::insert(int index, ciObject* obj, GrowableArray<ciObject*>* objects) {
+void ciObjectFactory::insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects) {
int len = objects->length();
if (len == index) {
objects->append(obj);
@@ -651,16 +652,6 @@
}
objects->at_put(index, obj);
}
-#ifdef ASSERT
- if (CIObjectFactoryVerify) {
- oop last = NULL;
- for (int j = 0; j< objects->length(); j++) {
- oop o = objects->at(j)->get_oop();
- assert(last < o, "out of order");
- last = o;
- }
- }
-#endif // ASSERT
}
static ciObjectFactory::NonPermObject* emptyBucket = NULL;
@@ -672,25 +663,8 @@
// 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) {
- // Be careful: is_perm might change from false to true.
- // Thus, there might be a matching perm object in the table.
- // If there is, this probe must find it.
- if (key->is_perm() && _non_perm_count == 0) {
- return emptyBucket;
- } else if (key->is_instance()) {
- if (key->klass() == SystemDictionary::Class_klass() && JavaObjectsInPerm) {
- // class mirror instances are always perm
- return emptyBucket;
- }
- // fall through to probe
- } else if (key->is_array()) {
- // fall through to probe
- } else {
- // not an array or instance
- return emptyBucket;
- }
-
- ciObject* klass = get(key->klass());
+ assert(Universe::heap()->is_in_reserved_or_null(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()) {
if (is_equal(p, key)) break;
@@ -717,6 +691,7 @@
//
// Insert a ciObject into the non-perm table.
void ciObjectFactory::insert_non_perm(ciObjectFactory::NonPermObject* &where, oop key, ciObject* obj) {
+ assert(Universe::heap()->is_in_reserved_or_null(key), "must be");
assert(&where != &emptyBucket, "must not try to fill empty bucket");
NonPermObject* p = new (arena()) NonPermObject(where, key, obj);
assert(where == p && is_equal(p, key) && p->object() == obj, "entry must match");
@@ -733,12 +708,22 @@
}
// ------------------------------------------------------------------
+// ciObjectFactory::metadata_do
+void ciObjectFactory::metadata_do(void f(Metadata*)) {
+ if (_ci_metadata == NULL) return;
+ for (int j = 0; j< _ci_metadata->length(); j++) {
+ Metadata* o = _ci_metadata->at(j)->constant_encoding();
+ f(o);
+ }
+}
+
+// ------------------------------------------------------------------
// ciObjectFactory::print_contents_impl
void ciObjectFactory::print_contents_impl() {
- int len = _ci_objects->length();
- tty->print_cr("ciObjectFactory (%d) oop contents:", len);
+ int len = _ci_metadata->length();
+ tty->print_cr("ciObjectFactory (%d) meta data contents:", len);
for (int i=0; i<len; i++) {
- _ci_objects->at(i)->print();
+ _ci_metadata->at(i)->print();
tty->cr();
}
}
@@ -756,8 +741,8 @@
//
// Print debugging information about the object factory
void ciObjectFactory::print() {
- tty->print("<ciObjectFactory oops=%d unloaded_methods=%d unloaded_instances=%d unloaded_klasses=%d>",
- _ci_objects->length(), _unloaded_methods->length(),
+ tty->print("<ciObjectFactory oops=%d metadata=%d unloaded_methods=%d unloaded_instances=%d unloaded_klasses=%d>",
+ _non_perm_count, _ci_metadata->length(), _unloaded_methods->length(),
_unloaded_instances->length(),
_unloaded_klasses->length());
}