changeset 3637:ff6a991c6e3c

Use GraalEnv to look up types.
author Thomas Wuerthinger <thomas.wuerthinger@oracle.com>
date Wed, 16 Nov 2011 01:48:25 +0100
parents c7d4198a9bce
children e53cfcb230a7
files src/share/vm/graal/graalCompiler.cpp src/share/vm/graal/graalCompiler.hpp src/share/vm/graal/graalVMEntries.cpp src/share/vm/oops/instanceKlass.hpp src/share/vm/runtime/fieldDescriptor.hpp
diffstat 5 files changed, 134 insertions(+), 113 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/graal/graalCompiler.cpp	Tue Nov 15 22:06:02 2011 +0100
+++ b/src/share/vm/graal/graalCompiler.cpp	Wed Nov 16 01:48:25 2011 +0100
@@ -27,6 +27,7 @@
 #include "graal/graalVMExits.hpp"
 #include "graal/graalVMEntries.hpp"
 #include "graal/graalVmIds.hpp"
+#include "graal/graalEnv.hpp"
 #include "c1/c1_Runtime1.hpp"
 #include "runtime/arguments.hpp"
 
@@ -124,33 +125,62 @@
   TRACE_graal_1("GraalCompiler::print_timers");
 }
 
-oop GraalCompiler::get_RiType(KlassHandle klass, KlassHandle accessor, TRAPS) {
-  if (klass->oop_is_instance_slow()) {
-    assert(instanceKlass::cast(klass())->is_initialized(), "unexpected unresolved klass");
-  } else if (klass->oop_is_javaArray_slow()){
+oop GraalCompiler::get_RiType(Symbol* klass_name, TRAPS) {
+   return VMExits::createRiTypeUnresolved(VmIds::toString<Handle>(klass_name, THREAD), THREAD);
+}
+
+oop GraalCompiler::get_RiTypeFromSignature(constantPoolHandle cp, int index, KlassHandle loading_klass, TRAPS) {
+  
+  Symbol* signature = cp->symbol_at(index);
+  BasicType field_type = FieldType::basic_type(signature);
+  // If the field is a pointer type, get the klass of the
+  // field.
+  if (field_type == T_OBJECT || field_type == T_ARRAY) {
+    KlassHandle handle = GraalEnv::get_klass_by_name(loading_klass, signature, false);
+    if (handle.is_null()) {
+      return get_RiType(signature, CHECK_NULL);
+    } else {
+      return get_RiType(handle, CHECK_NULL);
+    }
   } else {
-    klass()->print();
-    assert(false, "unexpected klass");
+    return VMExits::createRiTypePrimitive(field_type, CHECK_NULL);
   }
+}
+
+oop GraalCompiler::get_RiType(constantPoolHandle cp, int index, KlassHandle loading_klass, TRAPS) {
+  bool is_accessible = false;
+
+  KlassHandle klass = GraalEnv::get_klass_by_index(cp, index, is_accessible, loading_klass);
+  oop catch_class = NULL;
+  if (klass.is_null()) {
+    // We have to lock the cpool to keep the oop from being resolved
+    // while we are accessing it.
+    ObjectLocker ol(cp, THREAD);
+
+    Symbol* klass_name = NULL;
+    constantTag tag = cp->tag_at(index);
+    if (tag.is_klass()) {
+      // The klass has been inserted into the constant pool
+      // very recently.
+      return GraalCompiler::get_RiType(cp->resolved_klass_at(index), CHECK_NULL);
+    } else if (tag.is_symbol()) {
+      klass_name = cp->symbol_at(index);
+    } else {
+      assert(cp->tag_at(index).is_unresolved_klass(), "wrong tag");
+      klass_name = cp->unresolved_klass_at(index);
+    }
+    return GraalCompiler::get_RiType(klass_name, CHECK_NULL);
+  } else {
+    return GraalCompiler::get_RiType(klass, CHECK_NULL);
+  }
+}
+
+oop GraalCompiler::get_RiType(KlassHandle klass, TRAPS) {
   Handle name = VmIds::toString<Handle>(klass->name(), THREAD);
   return createHotSpotTypeResolved(klass, name, CHECK_NULL);
 }
 
-  oop GraalCompiler::get_RiType(ciType *type, KlassHandle accessor, TRAPS) {
-    if (type->is_loaded()) {
-      if (type->is_primitive_type()) {
-        return VMExits::createRiTypePrimitive((int) type->basic_type(), THREAD);
-      }
-      KlassHandle klass = (klassOop) type->get_oop();
-      Handle name = VmIds::toString<Handle>(klass->name(), THREAD);
-      return createHotSpotTypeResolved(klass, name, CHECK_NULL);
-    } else {
-      Symbol* name = ((ciKlass *) type)->name()->get_symbol();
-      return VMExits::createRiTypeUnresolved(VmIds::toString<Handle>(name, THREAD), THREAD);
-    }
-}
-
-oop GraalCompiler::get_RiField(ciField *field, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS) {
+oop GraalCompiler::get_RiField(ciField *field, ciInstanceKlass* accessor_klass, Handle field_holder, Handle field_type, Bytecodes::Code byteCode, TRAPS) {
   int offset;
   if (byteCode != Bytecodes::_illegal) {
     bool will_link = field->will_link_from_vm(accessor_klass, byteCode);
@@ -159,8 +189,6 @@
     offset = field->offset();
   }
   Handle field_name = VmIds::toString<Handle>(field->name()->get_symbol(), CHECK_0);
-  Handle field_holder = get_RiType(field->holder(), accessor, CHECK_0);
-  Handle field_type = get_RiType(field->type(), accessor, CHECK_0);
   int flags = field->flags().as_int();
   return VMExits::createRiField(field_holder, field_name, field_type, offset, flags, THREAD);
 }
--- a/src/share/vm/graal/graalCompiler.hpp	Tue Nov 15 22:06:02 2011 +0100
+++ b/src/share/vm/graal/graalCompiler.hpp	Wed Nov 16 01:48:25 2011 +0100
@@ -56,10 +56,12 @@
 
   // Print compilation timers and statistics
   virtual void print_timers();
-
-  static oop get_RiType(KlassHandle klass, KlassHandle accessor, TRAPS);
-  static oop get_RiType(ciType *klass, KlassHandle accessor, TRAPS);
-  static oop get_RiField(ciField *ciField, ciInstanceKlass* accessor_klass, KlassHandle accessor, Bytecodes::Code byteCode, TRAPS);
+  
+  static oop get_RiTypeFromSignature(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS);
+  static oop get_RiType(constantPoolHandle cp, int index, KlassHandle accessor, TRAPS);
+  static oop get_RiType(Symbol* klass_name, TRAPS);
+  static oop get_RiType(KlassHandle klass, TRAPS);
+  static oop get_RiField(ciField *field, ciInstanceKlass* accessor_klass, Handle field_holder, Handle field_type, Bytecodes::Code byteCode, TRAPS);
 
   static oop createHotSpotTypeResolved(KlassHandle klass, Handle name, TRAPS);
   static oop createHotSpotMethodResolved(methodHandle method, TRAPS);
--- a/src/share/vm/graal/graalVMEntries.cpp	Tue Nov 15 22:06:02 2011 +0100
+++ b/src/share/vm/graal/graalVMEntries.cpp	Wed Nov 16 01:48:25 2011 +0100
@@ -22,11 +22,13 @@
  */
 
 #include "precompiled.hpp"
+#include "runtime/fieldDescriptor.hpp"
 #include "c1/c1_Runtime1.hpp"
 #include "ci/ciMethodData.hpp"
 #include "compiler/compileBroker.hpp"
 #include "graal/graalVMEntries.hpp"
 #include "graal/graalCompiler.hpp"
+#include "graal/graalEnv.hpp"
 #include "graal/graalJavaAccess.hpp"
 #include "graal/graalCodeInstaller.hpp"
 #include "graal/graalVMExits.hpp"
@@ -120,11 +122,8 @@
       HotSpotExceptionHandler::set_catchClass(entry, NULL);
     } else {
       constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants();
-      ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(method->method_holder());
-      bool is_accessible = false;
-      ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, catch_class_index, is_accessible, loading_klass);
-      oop catch_class = GraalCompiler::get_RiType(klass, method->method_holder(), CHECK_NULL);
-
+      KlassHandle loading_klass = method->method_holder();
+      oop catch_class = GraalCompiler::get_RiType(cp, catch_class_index, loading_klass, CHECK_NULL);
       HotSpotExceptionHandler::set_catchClass(entry, catch_class);
     }
     array->obj_at_put(i, entry());
@@ -308,7 +307,7 @@
           if (receiver.is_null())  continue;
 
           float prob = recv->receiver_count(i) / (float) total_count;
-          oop type = GraalCompiler::get_RiType(receiver, KlassHandle(), CHECK_NULL);
+          oop type = GraalCompiler::get_RiType(receiver, CHECK_NULL);
 
           probabilities->float_at_put(pos, prob);
           types->obj_at_put(pos, type);
@@ -512,9 +511,8 @@
     result = VMExits::createCiConstantObject(string, CHECK_0);
   } else if (tag.is_klass() || tag.is_unresolved_klass()) {
     bool ignore;
-    ciInstanceKlass* accessor = (ciInstanceKlass*) ciEnv::current()->get_object(cp->pool_holder());
-    ciKlass* klass = ciEnv::current()->get_klass_by_index(cp, index, ignore, accessor);
-    result = GraalCompiler::get_RiType(klass, cp->pool_holder(), CHECK_NULL);
+    KlassHandle klass = GraalEnv::get_klass_by_index(cp, index, ignore, cp->pool_holder());
+    result = GraalCompiler::get_RiType(klass, CHECK_NULL);
   } else if (tag.is_object()) {
     oop obj = cp->object_at(index);
     assert(obj->is_instance(), "must be an instance");
@@ -531,7 +529,7 @@
   TRACE_graal_3("VMEntries::RiConstantPool_lookupMethod");
   VM_ENTRY_MARK;
   index = GraalCompiler::to_cp_index_u2(index);
-  constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants();
+  constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants();
 
   Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF);
   ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder());
@@ -541,10 +539,12 @@
     oop ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL);
     return JNIHandles::make_local(THREAD, ret);
   } else {
-    Handle name = VmIds::toString<Handle>(cimethod->name()->get_symbol(), CHECK_NULL);
-    Handle signature = VmIds::toString<Handle>(cimethod->signature()->as_symbol()->get_symbol(), CHECK_NULL);
-    Handle holder = GraalCompiler::get_RiType(cimethod->holder(), cp->klass(), THREAD);
-    return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, holder, THREAD));
+    // Get the method's name and signature.
+    Handle name = VmIds::toString<Handle>(cp->name_ref_at(index), CHECK_NULL);
+    Handle signature  = VmIds::toString<Handle>(cp->signature_ref_at(index), CHECK_NULL);
+    int holder_index = cp->klass_ref_index_at(index);
+    Handle type = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
+    return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, type, THREAD));
   }
 }
 
@@ -554,11 +554,8 @@
   VM_ENTRY_MARK;
 
   constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants();
-
-  ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder());
-  bool is_accessible = false;
-  ciKlass *klass = CURRENT_ENV->get_klass_by_index(cp, index, is_accessible, loading_klass);
-  return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(klass, cp->klass(), THREAD));
+  oop result = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL);
+  return JNIHandles::make_local(THREAD, result);
 }
 
 // public void RiConstantPool_loadReferencedType(long vmId, int cpi);
@@ -586,18 +583,37 @@
 }
 
 // public RiField RiConstantPool_lookupField(long vmId, int cpi);
-JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode) {
+JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode) {
   TRACE_graal_3("VMEntries::RiConstantPool_lookupField");
   VM_ENTRY_MARK;
 
   index = GraalCompiler::to_cp_index_u2(index);
-  constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants();
+  constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(constantPoolHolder)))->constants();
 
   ciInstanceKlass* loading_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(cp->pool_holder());
   ciField *field = CURRENT_ENV->get_field_by_index(loading_klass, index);
   
+  int nt_index = cp->name_and_type_ref_index_at(index);
+  int sig_index = cp->signature_ref_index_at(nt_index);
+  Symbol* signature = cp->symbol_at(sig_index);
+  int holder_index = cp->klass_ref_index_at(index);
+  Handle holder = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL);
+  
   Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF);
-  Handle field_handle = GraalCompiler::get_RiField(field, loading_klass, cp->pool_holder(), code, THREAD);
+  if (holder->klass() == SystemDictionary::HotSpotTypeResolved_klass()) {
+    FieldAccessInfo result;
+    LinkResolver::resolve_field(result, cp, index,
+                                Bytecodes::java_code(code),
+                                true, false, Thread::current());
+    if (HAS_PENDING_EXCEPTION) {
+      CLEAR_PENDING_EXCEPTION;
+    }
+    //result.field_offset();
+    holder = GraalCompiler::get_RiType(result.klass(), CHECK_NULL);
+  }
+
+  Handle type = GraalCompiler::get_RiTypeFromSignature(cp, sig_index, cp->pool_holder(), CHECK_NULL);
+  Handle field_handle = GraalCompiler::get_RiField(field, loading_klass, holder, type, code, THREAD);
   bool is_constant = field->is_constant();
   if (is_constant && field->is_static()) {
     ciConstant constant = field->constant_value();
@@ -692,17 +708,12 @@
 // public RiType RiType_componentType(HotSpotResolvedType klass);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1componentType(JNIEnv *, jobject, jobject klass) {
   TRACE_graal_3("VMEntries::RiType_componentType");
-  ciArrayKlass* array_klass;
-  {
-    VM_ENTRY_MARK;
-    assert(JNIHandles::resolve(klass) != NULL, "");
-    array_klass = (ciArrayKlass *) CURRENT_ENV->get_object(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
-  }
-  ciType* element_type = array_klass->element_type();
-
   VM_ENTRY_MARK;
+  KlassHandle array_klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
+  assert(array_klass->oop_is_objArray(), "just checking");
+  klassOop element_type = objArrayKlass::cast(array_klass())->element_klass();
   assert(JNIHandles::resolve(klass) != NULL, "");
-  return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)), THREAD));
+  return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, THREAD));
 }
 
 // public RiType RiType_superType(HotSpotResolvedType klass);
@@ -710,18 +721,17 @@
   TRACE_graal_3("VMEntries::RiType_superType");
   VM_ENTRY_MARK;
   KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
-  ciInstanceKlass* k = NULL;
+  klassOop k;
 
   if (klass_handle->oop_is_array()) {
-    k = (ciInstanceKlass *) CURRENT_ENV->get_object(SystemDictionary::Object_klass());
+    k = SystemDictionary::Object_klass();
   } else {
     guarantee(klass_handle->oop_is_instance(), "must be instance klass");  
-    k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle());
-    k = k->super();
+    k = klass_handle->super();
   }
 
   if (k != NULL) {
-    return JNIHandles::make_local(GraalCompiler::get_RiType(k, klass_handle, THREAD));
+    return JNIHandles::make_local(GraalCompiler::get_RiType(k, THREAD));
   } else {
     return NULL;
   }
@@ -730,25 +740,12 @@
 // public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) {
   TRACE_graal_3("VMEntries::RiType_uniqueConcreteSubtype");
-  Thread* THREAD = Thread::current();
+  VM_ENTRY_MARK;
   KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)));
-  ciInstanceKlass* k = NULL;
-  {
-    VM_ENTRY_MARK;
-    k = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle());
+  Klass *up_cast = klass_handle->up_cast_abstract();
+  if (up_cast->is_leaf_class()) {
+    return JNIHandles::make_local(GraalCompiler::get_RiType(up_cast, THREAD));
   }
-
-  if (k->is_abstract()) {
-    ciInstanceKlass* sub = k->unique_concrete_subklass();
-    if (sub != NULL && sub->is_leaf_type()) {
-      VM_ENTRY_MARK;
-      return JNIHandles::make_local(GraalCompiler::get_RiType(sub, klass_handle, THREAD));
-    }
-  } else if (k->is_leaf_type()) {
-    assert(!k->is_interface(), "");
-    return klass;
-  }
-
   return NULL;
 }
 
@@ -774,39 +771,32 @@
 // public RiField[] RiType_fields(HotSpotTypeResolved klass);
 JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1fields(JNIEnv *, jobject, jobject klass) {
   TRACE_graal_3("VMEntries::RiType_fields");
-  KlassHandle klass_handle;
-  ciInstanceKlass* instance_klass;
-  objArrayHandle fieldsArray;
-  HandleMark hm;
-  {
-    VM_ENTRY_MARK;
-    klass_handle = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
-    instance_klass = (ciInstanceKlass *) CURRENT_ENV->get_object(klass_handle());
-  }
-  GrowableArray<ciField*>* fields = instance_klass->non_static_fields();
-  {
-    VM_ENTRY_MARK;
+  VM_ENTRY_MARK;
+
+  instanceKlassHandle k = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass));
+  objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::RiField_klass(), k->fields()->length() / instanceKlass::next_offset, CHECK_NULL);
+  class MyFieldClosure : public FieldClosure {
+   public:
+    instanceKlassHandle _holder;
+    Handle _resolved_type_holder;
+    objArrayHandle _field_array;
+    int _current;
+
+    MyFieldClosure(instanceKlassHandle& holder, Handle resolved_type_holder, objArrayHandle field_array) : _holder(holder), _resolved_type_holder(resolved_type_holder), _field_array(field_array), _current(0) { }
     
-    int count = 0;
-    for (int i = 0; i < fields->length(); i++) {
-      ciField* field = fields->at(i);
-      if (field->holder() == instance_klass) {
-        count++;
+    virtual void do_field(fieldDescriptor* fd) {
+      if (!Thread::current()->has_pending_exception()) {
+        if (fd->field_holder() == _holder()) {
+          Handle type = GraalCompiler::get_RiTypeFromSignature(fd->constants(), fd->signature_index(), fd->field_holder(), Thread::current());
+          Handle field = VMExits::createRiField(_resolved_type_holder, VmIds::toString<Handle>(fd->name(), Thread::current()), type, fd->offset(), fd->access_flags().as_int(), Thread::current());
+          _field_array->obj_at_put(_current++, field());
+        }
       }
     }
-
-    fieldsArray = oopFactory::new_objArray(SystemDictionary::RiField_klass(), count, CHECK_NULL);
-    int z = 0;
-    for (int i = 0; i < fields->length(); i++) {
-      ciField* field = fields->at(i);
-      if (field->holder() == instance_klass) {
-        Handle field_handle = GraalCompiler::get_RiField(field, instance_klass, klass_handle, Bytecodes::_illegal, CHECK_NULL);
-        fieldsArray->obj_at_put(z, field_handle());
-        z++;
-      }
-    }
-  }
-  return JNIHandles::make_local(fieldsArray());
+  };
+  MyFieldClosure closure(k, JNIHandles::resolve(klass), field_array);
+  k->do_nonstatic_fields(&closure);
+  return JNIHandles::make_local(field_array());
 }
 
 // public RiType getPrimitiveArrayType(CiKind kind);
@@ -815,8 +805,7 @@
   VM_ENTRY_MARK;
   BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(kind));
   assert(type != T_OBJECT, "primitive type expecteds");
-  ciKlass* klass = ciTypeArrayKlass::make(type);
-  return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(klass, KlassHandle(), THREAD));
+  return JNIHandles::make_local(THREAD, GraalCompiler::get_RiType(Universe::typeArrayKlassObj(type), THREAD));
 }
 
 // public long getMaxCallTargetOffset(CiRuntimeCall rtcall);
--- a/src/share/vm/oops/instanceKlass.hpp	Tue Nov 15 22:06:02 2011 +0100
+++ b/src/share/vm/oops/instanceKlass.hpp	Wed Nov 16 01:48:25 2011 +0100
@@ -634,7 +634,7 @@
   void process_interfaces(Thread *thread);
 
   // virtual operations from Klass
-  bool is_leaf_class() const               { return _subklass == NULL; }
+  bool is_leaf_class() const               { return _subklass == NULL && _nof_implementors == 0; }
   objArrayOop compute_secondary_supers(int num_extra_slots, TRAPS);
   bool compute_is_subtype_of(klassOop k);
   bool can_be_primary_super_slow() const;
--- a/src/share/vm/runtime/fieldDescriptor.hpp	Tue Nov 15 22:06:02 2011 +0100
+++ b/src/share/vm/runtime/fieldDescriptor.hpp	Wed Nov 16 01:48:25 2011 +0100
@@ -49,6 +49,8 @@
   constantPoolHandle  _cp;
 
  public:
+  int name_index() const               { return _name_index; }
+  int signature_index() const          { return _signature_index; }
   Symbol* name() const                 { return _cp->symbol_at(_name_index); }
   Symbol* signature() const            { return _cp->symbol_at(_signature_index); }
   klassOop field_holder() const        { return _cp->pool_holder(); }