< prev index next >

src/hotspot/share/ci/ciObjectFactory.cpp

Print this page

 27 #include "ci/ciInstanceKlass.hpp"
 28 #include "ci/ciMemberName.hpp"
 29 #include "ci/ciMethod.hpp"
 30 #include "ci/ciMethodData.hpp"
 31 #include "ci/ciMethodHandle.hpp"
 32 #include "ci/ciMethodType.hpp"
 33 #include "ci/ciNullObject.hpp"
 34 #include "ci/ciObjArray.hpp"
 35 #include "ci/ciObjArrayKlass.hpp"
 36 #include "ci/ciObject.hpp"
 37 #include "ci/ciObjectFactory.hpp"
 38 #include "ci/ciReplay.hpp"
 39 #include "ci/ciSymbol.hpp"
 40 #include "ci/ciSymbols.hpp"
 41 #include "ci/ciTypeArray.hpp"
 42 #include "ci/ciTypeArrayKlass.hpp"
 43 #include "ci/ciUtilities.inline.hpp"
 44 #include "classfile/javaClasses.inline.hpp"
 45 #include "classfile/vmClasses.hpp"
 46 #include "compiler/compiler_globals.hpp"

 47 #include "gc/shared/collectedHeap.inline.hpp"
 48 #include "memory/allocation.inline.hpp"
 49 #include "memory/universe.hpp"
 50 #include "oops/oop.inline.hpp"

 51 #include "runtime/handles.inline.hpp"
 52 #include "runtime/signature.hpp"
 53 #include "utilities/macros.hpp"
 54 
 55 // ciObjectFactory
 56 //
 57 // This class handles requests for the creation of new instances
 58 // of ciObject and its subclasses.  It contains a caching mechanism
 59 // which ensures that for each oop, at most one ciObject is created.
 60 // This invariant allows more efficient implementation of ciObject.
 61 //
 62 // Implementation note: the oop->ciObject mapping is represented as
 63 // a table stored in an array.  Even though objects are moved
 64 // by the garbage collector, the compactor preserves their relative
 65 // order; address comparison of oops (in perm space) is safe so long
 66 // as we prohibit GC during our comparisons.  We currently use binary
 67 // search to find the oop in the table, and inserting a new oop
 68 // into the table may be costly.  If this cost ends up being
 69 // problematic the underlying data structure can be switched to some
 70 // sort of balanced binary tree.

215 
216 // Decrement the refcount when done on symbols referenced by this compilation.
217 void ciObjectFactory::remove_symbols() {
218   for (int i = 0; i < _symbols.length(); i++) {
219     ciSymbol* s = _symbols.at(i);
220     s->get_symbol()->decrement_refcount();
221   }
222   // Since _symbols is resource allocated we're not allowed to delete it
223   // but it'll go away just the same.
224 }
225 
226 // ------------------------------------------------------------------
227 // ciObjectFactory::get
228 //
229 // Get the ciObject corresponding to some oop.  If the ciObject has
230 // already been created, it is returned.  Otherwise, a new ciObject
231 // is created.
232 ciObject* ciObjectFactory::get(oop key) {
233   ASSERT_IN_VM;
234 
235   assert(Universe::heap()->is_in(key), "must be");

236 
237   NonPermObject* &bucket = find_non_perm(key);
238   if (bucket != nullptr) {
239     return bucket->object();
240   }
241 
242   // The ciObject does not yet exist.  Create it and insert it
243   // into the cache.
244   Handle keyHandle(Thread::current(), key);
245   ciObject* new_object = create_new_object(keyHandle());
246   assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
247   init_ident_of(new_object);
248   assert(Universe::heap()->is_in(new_object->get_oop()), "must be");
249 
250   // Not a perm-space object.
251   insert_non_perm(bucket, keyHandle(), new_object);

252   return new_object;
253 }
254 













255 int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) {
256   Metadata* value = elt->constant_encoding();
257   if (key < value)      return -1;
258   else if (key > value) return 1;
259   else                  return 0;
260 }
261 
262 // ------------------------------------------------------------------
263 // ciObjectFactory::cached_metadata
264 //
265 // Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
266 // already been created, it is returned. Otherwise, null is returned.
267 ciMetadata* ciObjectFactory::cached_metadata(Metadata* key) {
268   ASSERT_IN_VM;
269 
270   bool found = false;
271   int index = _ci_metadata.find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
272 
273   if (!found) {
274     return nullptr;

314         assert(index == i, " bad lookup");
315       }
316     }
317   }
318 #endif
319 
320   if (!found) {
321     // The ciMetadata does not yet exist. Create it and insert it
322     // into the cache.
323     ciMetadata* new_object = create_new_metadata(key);
324     init_ident_of(new_object);
325     assert(new_object->is_metadata(), "must be");
326 
327     if (len != _ci_metadata.length()) {
328       // creating the new object has recursively entered new objects
329       // into the table.  We need to recompute our index.
330       index = _ci_metadata.find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
331     }
332     assert(!found, "no double insert");
333     _ci_metadata.insert_before(index, new_object);

334     return new_object;
335   }
336   return _ci_metadata.at(index)->as_metadata();
337 }
338 
339 // ------------------------------------------------------------------
340 // ciObjectFactory::create_new_object
341 //
342 // Create a new ciObject from an oop.
343 //
344 // Implementation note: this functionality could be virtual behavior
345 // of the oop itself.  For now, we explicitly marshal the object.
346 ciObject* ciObjectFactory::create_new_object(oop o) {
347   EXCEPTION_CONTEXT;
348 
349   if (o->is_instance()) {
350     instanceHandle h_i(THREAD, (instanceOop)o);
351     if (java_lang_invoke_CallSite::is_instance(o))
352       return new (arena()) ciCallSite(h_i);
353     else if (java_lang_invoke_MemberName::is_instance(o))

619   ciReturnAddress* new_ret_addr = new (arena()) ciReturnAddress(bci);
620   init_ident_of(new_ret_addr);
621   _return_addresses.append(new_ret_addr);
622   return new_ret_addr;
623 }
624 
625 // ------------------------------------------------------------------
626 // ciObjectFactory::init_ident_of
627 void ciObjectFactory::init_ident_of(ciBaseObject* obj) {
628   obj->set_ident(_next_ident++);
629 }
630 
631 static ciObjectFactory::NonPermObject* emptyBucket = nullptr;
632 
633 // ------------------------------------------------------------------
634 // ciObjectFactory::find_non_perm
635 //
636 // Use a small hash table, hashed on the klass of the key.
637 // If there is no entry in the cache corresponding to this oop, return
638 // the null tail of the bucket into which the oop should be inserted.
639 ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
640   assert(Universe::heap()->is_in(key), "must be");
641   ciMetadata* klass = get_metadata(key->klass());
642   NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS];
643   for (NonPermObject* p; (p = (*bp)) != nullptr; bp = &p->next()) {
644     if (is_equal(p, key))  break;
645   }
646   return (*bp);
647 }
648 
649 
650 
651 // ------------------------------------------------------------------
652 // Code for for NonPermObject
653 //
654 inline ciObjectFactory::NonPermObject::NonPermObject(ciObjectFactory::NonPermObject* &bucket, oop key, ciObject* object) {
655   assert(ciObjectFactory::is_initialized(), "");
656   _object = object;
657   _next = bucket;
658   bucket = this;
659 }
660 
661 
662 
663 // ------------------------------------------------------------------
664 // ciObjectFactory::insert_non_perm
665 //
666 // Insert a ciObject into the non-perm table.
667 void ciObjectFactory::insert_non_perm(ciObjectFactory::NonPermObject* &where, oop key, ciObject* obj) {
668   assert(Universe::heap()->is_in_or_null(key), "must be");
669   assert(&where != &emptyBucket, "must not try to fill empty bucket");
670   NonPermObject* p = new (arena()) NonPermObject(where, key, obj);
671   assert(where == p && is_equal(p, key) && p->object() == obj, "entry must match");
672   assert(find_non_perm(key) == p, "must find the same spot");
673   ++_non_perm_count;
674 }
675 
676 // ------------------------------------------------------------------
677 // ciObjectFactory::vm_symbol_at
678 // Get the ciSymbol corresponding to some index in vmSymbols.
679 ciSymbol* ciObjectFactory::vm_symbol_at(vmSymbolID sid) {
680   int index = vmSymbols::as_int(sid);
681   return _shared_ci_symbols[index];
682 }
683 
684 // ------------------------------------------------------------------
685 // ciObjectFactory::metadata_do
686 void ciObjectFactory::metadata_do(MetadataClosure* f) {
687   for (int j = 0; j < _ci_metadata.length(); j++) {
688     Metadata* o = _ci_metadata.at(j)->constant_encoding();
689     f->do_metadata(o);
690   }
691 }
692 

 27 #include "ci/ciInstanceKlass.hpp"
 28 #include "ci/ciMemberName.hpp"
 29 #include "ci/ciMethod.hpp"
 30 #include "ci/ciMethodData.hpp"
 31 #include "ci/ciMethodHandle.hpp"
 32 #include "ci/ciMethodType.hpp"
 33 #include "ci/ciNullObject.hpp"
 34 #include "ci/ciObjArray.hpp"
 35 #include "ci/ciObjArrayKlass.hpp"
 36 #include "ci/ciObject.hpp"
 37 #include "ci/ciObjectFactory.hpp"
 38 #include "ci/ciReplay.hpp"
 39 #include "ci/ciSymbol.hpp"
 40 #include "ci/ciSymbols.hpp"
 41 #include "ci/ciTypeArray.hpp"
 42 #include "ci/ciTypeArrayKlass.hpp"
 43 #include "ci/ciUtilities.inline.hpp"
 44 #include "classfile/javaClasses.inline.hpp"
 45 #include "classfile/vmClasses.hpp"
 46 #include "compiler/compiler_globals.hpp"
 47 #include "compiler/compileTask.hpp"
 48 #include "gc/shared/collectedHeap.inline.hpp"
 49 #include "memory/allocation.inline.hpp"
 50 #include "memory/universe.hpp"
 51 #include "oops/oop.inline.hpp"
 52 #include "oops/trainingData.hpp"
 53 #include "runtime/handles.inline.hpp"
 54 #include "runtime/signature.hpp"
 55 #include "utilities/macros.hpp"
 56 
 57 // ciObjectFactory
 58 //
 59 // This class handles requests for the creation of new instances
 60 // of ciObject and its subclasses.  It contains a caching mechanism
 61 // which ensures that for each oop, at most one ciObject is created.
 62 // This invariant allows more efficient implementation of ciObject.
 63 //
 64 // Implementation note: the oop->ciObject mapping is represented as
 65 // a table stored in an array.  Even though objects are moved
 66 // by the garbage collector, the compactor preserves their relative
 67 // order; address comparison of oops (in perm space) is safe so long
 68 // as we prohibit GC during our comparisons.  We currently use binary
 69 // search to find the oop in the table, and inserting a new oop
 70 // into the table may be costly.  If this cost ends up being
 71 // problematic the underlying data structure can be switched to some
 72 // sort of balanced binary tree.

217 
218 // Decrement the refcount when done on symbols referenced by this compilation.
219 void ciObjectFactory::remove_symbols() {
220   for (int i = 0; i < _symbols.length(); i++) {
221     ciSymbol* s = _symbols.at(i);
222     s->get_symbol()->decrement_refcount();
223   }
224   // Since _symbols is resource allocated we're not allowed to delete it
225   // but it'll go away just the same.
226 }
227 
228 // ------------------------------------------------------------------
229 // ciObjectFactory::get
230 //
231 // Get the ciObject corresponding to some oop.  If the ciObject has
232 // already been created, it is returned.  Otherwise, a new ciObject
233 // is created.
234 ciObject* ciObjectFactory::get(oop key) {
235   ASSERT_IN_VM;
236 
237   Handle keyHandle(Thread::current(), key);
238   assert(Universe::heap()->is_in(keyHandle()), "must be");
239 
240   NonPermObject* &bucket = find_non_perm(keyHandle);
241   if (bucket != nullptr) {
242     return bucket->object();
243   }
244 
245   // The ciObject does not yet exist.  Create it and insert it
246   // into the cache.

247   ciObject* new_object = create_new_object(keyHandle());
248   assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
249   init_ident_of(new_object);
250   assert(Universe::heap()->is_in(new_object->get_oop()), "must be");
251 
252   // Not a perm-space object.
253   insert_non_perm(bucket, keyHandle, new_object);
254   notice_new_object(new_object);
255   return new_object;
256 }
257 
258 void ciObjectFactory::notice_new_object(ciBaseObject* new_object) {
259   if (TrainingData::need_data()) {
260     ciEnv* env = ciEnv::current();
261     if (env->task() != nullptr) {
262       // Note: task will be null during init_compiler_runtime.
263       CompileTrainingData* td = env->task()->training_data();
264       if (td != nullptr) {
265         td->notice_jit_observation(env, new_object);
266       }
267     }
268   }
269 }
270 
271 int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) {
272   Metadata* value = elt->constant_encoding();
273   if (key < value)      return -1;
274   else if (key > value) return 1;
275   else                  return 0;
276 }
277 
278 // ------------------------------------------------------------------
279 // ciObjectFactory::cached_metadata
280 //
281 // Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
282 // already been created, it is returned. Otherwise, null is returned.
283 ciMetadata* ciObjectFactory::cached_metadata(Metadata* key) {
284   ASSERT_IN_VM;
285 
286   bool found = false;
287   int index = _ci_metadata.find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
288 
289   if (!found) {
290     return nullptr;

330         assert(index == i, " bad lookup");
331       }
332     }
333   }
334 #endif
335 
336   if (!found) {
337     // The ciMetadata does not yet exist. Create it and insert it
338     // into the cache.
339     ciMetadata* new_object = create_new_metadata(key);
340     init_ident_of(new_object);
341     assert(new_object->is_metadata(), "must be");
342 
343     if (len != _ci_metadata.length()) {
344       // creating the new object has recursively entered new objects
345       // into the table.  We need to recompute our index.
346       index = _ci_metadata.find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
347     }
348     assert(!found, "no double insert");
349     _ci_metadata.insert_before(index, new_object);
350     notice_new_object(new_object);
351     return new_object;
352   }
353   return _ci_metadata.at(index)->as_metadata();
354 }
355 
356 // ------------------------------------------------------------------
357 // ciObjectFactory::create_new_object
358 //
359 // Create a new ciObject from an oop.
360 //
361 // Implementation note: this functionality could be virtual behavior
362 // of the oop itself.  For now, we explicitly marshal the object.
363 ciObject* ciObjectFactory::create_new_object(oop o) {
364   EXCEPTION_CONTEXT;
365 
366   if (o->is_instance()) {
367     instanceHandle h_i(THREAD, (instanceOop)o);
368     if (java_lang_invoke_CallSite::is_instance(o))
369       return new (arena()) ciCallSite(h_i);
370     else if (java_lang_invoke_MemberName::is_instance(o))

636   ciReturnAddress* new_ret_addr = new (arena()) ciReturnAddress(bci);
637   init_ident_of(new_ret_addr);
638   _return_addresses.append(new_ret_addr);
639   return new_ret_addr;
640 }
641 
642 // ------------------------------------------------------------------
643 // ciObjectFactory::init_ident_of
644 void ciObjectFactory::init_ident_of(ciBaseObject* obj) {
645   obj->set_ident(_next_ident++);
646 }
647 
648 static ciObjectFactory::NonPermObject* emptyBucket = nullptr;
649 
650 // ------------------------------------------------------------------
651 // ciObjectFactory::find_non_perm
652 //
653 // Use a small hash table, hashed on the klass of the key.
654 // If there is no entry in the cache corresponding to this oop, return
655 // the null tail of the bucket into which the oop should be inserted.
656 ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(Handle keyHandle) {
657   assert(Universe::heap()->is_in(keyHandle()), "must be");
658   ciMetadata* klass = get_metadata(keyHandle->klass()); // This may safepoint!
659   NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS];
660   for (NonPermObject* p; (p = (*bp)) != nullptr; bp = &p->next()) {
661     if (is_equal(p, keyHandle()))  break;
662   }
663   return (*bp);
664 }
665 
666 
667 
668 // ------------------------------------------------------------------
669 // Code for for NonPermObject
670 //
671 inline ciObjectFactory::NonPermObject::NonPermObject(ciObjectFactory::NonPermObject* &bucket, oop key, ciObject* object) {
672   assert(ciObjectFactory::is_initialized(), "");
673   _object = object;
674   _next = bucket;
675   bucket = this;
676 }
677 
678 
679 
680 // ------------------------------------------------------------------
681 // ciObjectFactory::insert_non_perm
682 //
683 // Insert a ciObject into the non-perm table.
684 void ciObjectFactory::insert_non_perm(ciObjectFactory::NonPermObject* &where, Handle keyHandle, ciObject* obj) {
685   assert(Universe::heap()->is_in_or_null(keyHandle()), "must be");
686   assert(&where != &emptyBucket, "must not try to fill empty bucket");
687   NonPermObject* p = new (arena()) NonPermObject(where, keyHandle(), obj);
688   assert(where == p && is_equal(p, keyHandle()) && p->object() == obj, "entry must match");
689   assert(find_non_perm(keyHandle) == p, "must find the same spot");
690   ++_non_perm_count;
691 }
692 
693 // ------------------------------------------------------------------
694 // ciObjectFactory::vm_symbol_at
695 // Get the ciSymbol corresponding to some index in vmSymbols.
696 ciSymbol* ciObjectFactory::vm_symbol_at(vmSymbolID sid) {
697   int index = vmSymbols::as_int(sid);
698   return _shared_ci_symbols[index];
699 }
700 
701 // ------------------------------------------------------------------
702 // ciObjectFactory::metadata_do
703 void ciObjectFactory::metadata_do(MetadataClosure* f) {
704   for (int j = 0; j < _ci_metadata.length(); j++) {
705     Metadata* o = _ci_metadata.at(j)->constant_encoding();
706     f->do_metadata(o);
707   }
708 }
709 
< prev index next >