src/share/vm/ci/ciObjectFactory.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/share/vm/ci

src/share/vm/ci/ciObjectFactory.cpp

Print this page
rev 10204 : 8007986: GrowableArray should implement binary search
Summary: binary search method for GrowableArray
Reviewed-by:


 243   assert(Universe::heap()->is_in_reserved(key), "must be");
 244 
 245   NonPermObject* &bucket = find_non_perm(key);
 246   if (bucket != NULL) {
 247     return bucket->object();
 248   }
 249 
 250   // The ciObject does not yet exist.  Create it and insert it
 251   // into the cache.
 252   Handle keyHandle(key);
 253   ciObject* new_object = create_new_object(keyHandle());
 254   assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
 255   init_ident_of(new_object);
 256   assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be");
 257 
 258   // Not a perm-space object.
 259   insert_non_perm(bucket, keyHandle(), new_object);
 260   return new_object;
 261 }
 262 







 263 // ------------------------------------------------------------------
 264 // ciObjectFactory::get_metadata
 265 //
 266 // Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
 267 // already been created, it is returned. Otherwise, a new ciMetadata
 268 // is created.
 269 ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
 270   ASSERT_IN_VM;
 271 
 272 #ifdef ASSERT
 273   if (CIObjectFactoryVerify) {
 274     Metadata* last = NULL;
 275     for (int j = 0; j< _ci_metadata->length(); j++) {
 276       Metadata* o = _ci_metadata->at(j)->constant_encoding();
 277       assert(last < o, "out of order");
 278       last = o;
 279     }
 280   }
 281 #endif // ASSERT
 282   int len = _ci_metadata->length();
 283   int index = find(key, _ci_metadata);

 284 #ifdef ASSERT
 285   if (CIObjectFactoryVerify) {
 286     for (int i=0; i<_ci_metadata->length(); i++) {
 287       if (_ci_metadata->at(i)->constant_encoding() == key) {
 288         assert(index == i, " bad lookup");
 289       }
 290     }
 291   }
 292 #endif
 293   if (!is_found_at(index, key, _ci_metadata)) {

 294     // The ciMetadata does not yet exist. Create it and insert it
 295     // into the cache.
 296     ciMetadata* new_object = create_new_metadata(key);
 297     init_ident_of(new_object);
 298     assert(new_object->is_metadata(), "must be");
 299 
 300     if (len != _ci_metadata->length()) {
 301       // creating the new object has recursively entered new objects
 302       // into the table.  We need to recompute our index.
 303       index = find(key, _ci_metadata);
 304     }
 305     assert(!is_found_at(index, key, _ci_metadata), "no double insert");
 306     insert(index, new_object, _ci_metadata);
 307     return new_object;
 308   }
 309   return _ci_metadata->at(index)->as_metadata();
 310 }
 311 
 312 // ------------------------------------------------------------------
 313 // ciObjectFactory::create_new_object
 314 //
 315 // Create a new ciObject from an oop.
 316 //
 317 // Implementation note: this functionality could be virtual behavior
 318 // of the oop itself.  For now, we explicitly marshal the object.
 319 ciObject* ciObjectFactory::create_new_object(oop o) {
 320   EXCEPTION_CONTEXT;
 321 
 322   if (o->is_instance()) {
 323     instanceHandle h_i(THREAD, (instanceOop)o);
 324     if (java_lang_invoke_CallSite::is_instance(o))
 325       return new (arena()) ciCallSite(h_i);
 326     else if (java_lang_invoke_MemberName::is_instance(o))


 636 // Get a ciReturnAddress for a specified bci.
 637 ciReturnAddress* ciObjectFactory::get_return_address(int bci) {
 638   for (int i=0; i<_return_addresses->length(); i++) {
 639     ciReturnAddress* entry = _return_addresses->at(i);
 640     if (entry->bci() == bci) {
 641       // We've found a match.
 642       return entry;
 643     }
 644   }
 645 
 646   ciReturnAddress* new_ret_addr = new (arena()) ciReturnAddress(bci);
 647   init_ident_of(new_ret_addr);
 648   _return_addresses->append(new_ret_addr);
 649   return new_ret_addr;
 650 }
 651 
 652 // ------------------------------------------------------------------
 653 // ciObjectFactory::init_ident_of
 654 void ciObjectFactory::init_ident_of(ciBaseObject* obj) {
 655   obj->set_ident(_next_ident++);
 656 }
 657 
 658 // ------------------------------------------------------------------
 659 // ciObjectFactory::find
 660 //
 661 // Use binary search to find the position of this oop in the cache.
 662 // If there is no entry in the cache corresponding to this oop, return
 663 // the position at which the oop should be inserted.
 664 int ciObjectFactory::find(Metadata* key, GrowableArray<ciMetadata*>* objects) {
 665   int min = 0;
 666   int max = objects->length()-1;
 667 
 668   // print_contents();
 669 
 670   while (max >= min) {
 671     int mid = (max + min) / 2;
 672     Metadata* value = objects->at(mid)->constant_encoding();
 673     if (value < key) {
 674       min = mid + 1;
 675     } else if (value > key) {
 676       max = mid - 1;
 677     } else {
 678       return mid;
 679     }
 680   }
 681   return min;
 682 }
 683 
 684 // ------------------------------------------------------------------
 685 // ciObjectFactory::is_found_at
 686 //
 687 // Verify that the binary seach found the given key.
 688 bool ciObjectFactory::is_found_at(int index, Metadata* key, GrowableArray<ciMetadata*>* objects) {
 689   return (index < objects->length() &&
 690           objects->at(index)->constant_encoding() == key);
 691 }
 692 
 693 
 694 // ------------------------------------------------------------------
 695 // ciObjectFactory::insert
 696 //
 697 // Insert a ciObject into the table at some index.
 698 void ciObjectFactory::insert(int index, ciMetadata* obj, GrowableArray<ciMetadata*>* objects) {
 699   int len = objects->length();
 700   if (len == index) {
 701     objects->append(obj);
 702   } else {
 703     objects->append(objects->at(len-1));
 704     int pos;
 705     for (pos = len-2; pos >= index; pos--) {
 706       objects->at_put(pos+1,objects->at(pos));
 707     }
 708     objects->at_put(index, obj);
 709   }
 710 }
 711 
 712 static ciObjectFactory::NonPermObject* emptyBucket = NULL;
 713 
 714 // ------------------------------------------------------------------
 715 // ciObjectFactory::find_non_perm
 716 //
 717 // Use a small hash table, hashed on the klass of the key.
 718 // If there is no entry in the cache corresponding to this oop, return
 719 // the null tail of the bucket into which the oop should be inserted.
 720 ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
 721   assert(Universe::heap()->is_in_reserved(key), "must be");
 722   ciMetadata* klass = get_metadata(key->klass());
 723   NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS];
 724   for (NonPermObject* p; (p = (*bp)) != NULL; bp = &p->next()) {
 725     if (is_equal(p, key))  break;
 726   }
 727   return (*bp);
 728 }
 729 




 243   assert(Universe::heap()->is_in_reserved(key), "must be");
 244 
 245   NonPermObject* &bucket = find_non_perm(key);
 246   if (bucket != NULL) {
 247     return bucket->object();
 248   }
 249 
 250   // The ciObject does not yet exist.  Create it and insert it
 251   // into the cache.
 252   Handle keyHandle(key);
 253   ciObject* new_object = create_new_object(keyHandle());
 254   assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
 255   init_ident_of(new_object);
 256   assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be");
 257 
 258   // Not a perm-space object.
 259   insert_non_perm(bucket, keyHandle(), new_object);
 260   return new_object;
 261 }
 262 
 263 int ciObjectFactory::metadata_compare(Metadata* const& key, ciMetadata* const& elt) {
 264   Metadata* value = elt->constant_encoding();
 265   if (key < value)      return -1;
 266   else if (key > value) return 1;
 267   else                  return 0;
 268 }
 269 
 270 // ------------------------------------------------------------------
 271 // ciObjectFactory::get_metadata
 272 //
 273 // Get the ciMetadata corresponding to some Metadata. If the ciMetadata has
 274 // already been created, it is returned. Otherwise, a new ciMetadata
 275 // is created.
 276 ciMetadata* ciObjectFactory::get_metadata(Metadata* key) {
 277   ASSERT_IN_VM;
 278 
 279 #ifdef ASSERT
 280   if (CIObjectFactoryVerify) {
 281     Metadata* last = NULL;
 282     for (int j = 0; j< _ci_metadata->length(); j++) {
 283       Metadata* o = _ci_metadata->at(j)->constant_encoding();
 284       assert(last < o, "out of order");
 285       last = o;
 286     }
 287   }
 288 #endif // ASSERT
 289   int len = _ci_metadata->length();
 290   bool found = false;
 291   int index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
 292 #ifdef ASSERT
 293   if (CIObjectFactoryVerify) {
 294     for (int i=0; i<_ci_metadata->length(); i++) {
 295       if (_ci_metadata->at(i)->constant_encoding() == key) {
 296         assert(index == i, " bad lookup");
 297       }
 298     }
 299   }
 300 #endif
 301   
 302   if (!found) {
 303     // The ciMetadata does not yet exist. Create it and insert it
 304     // into the cache.
 305     ciMetadata* new_object = create_new_metadata(key);
 306     init_ident_of(new_object);
 307     assert(new_object->is_metadata(), "must be");
 308 
 309     if (len != _ci_metadata->length()) {
 310       // creating the new object has recursively entered new objects
 311       // into the table.  We need to recompute our index.
 312       index = _ci_metadata->find_sorted<Metadata*, ciObjectFactory::metadata_compare>(key, found);
 313     }
 314     assert(!found, "no double insert");
 315     _ci_metadata->insert_before(index, new_object);
 316     return new_object;
 317   }
 318   return _ci_metadata->at(index)->as_metadata();
 319 }
 320 
 321 // ------------------------------------------------------------------
 322 // ciObjectFactory::create_new_object
 323 //
 324 // Create a new ciObject from an oop.
 325 //
 326 // Implementation note: this functionality could be virtual behavior
 327 // of the oop itself.  For now, we explicitly marshal the object.
 328 ciObject* ciObjectFactory::create_new_object(oop o) {
 329   EXCEPTION_CONTEXT;
 330 
 331   if (o->is_instance()) {
 332     instanceHandle h_i(THREAD, (instanceOop)o);
 333     if (java_lang_invoke_CallSite::is_instance(o))
 334       return new (arena()) ciCallSite(h_i);
 335     else if (java_lang_invoke_MemberName::is_instance(o))


 645 // Get a ciReturnAddress for a specified bci.
 646 ciReturnAddress* ciObjectFactory::get_return_address(int bci) {
 647   for (int i=0; i<_return_addresses->length(); i++) {
 648     ciReturnAddress* entry = _return_addresses->at(i);
 649     if (entry->bci() == bci) {
 650       // We've found a match.
 651       return entry;
 652     }
 653   }
 654 
 655   ciReturnAddress* new_ret_addr = new (arena()) ciReturnAddress(bci);
 656   init_ident_of(new_ret_addr);
 657   _return_addresses->append(new_ret_addr);
 658   return new_ret_addr;
 659 }
 660 
 661 // ------------------------------------------------------------------
 662 // ciObjectFactory::init_ident_of
 663 void ciObjectFactory::init_ident_of(ciBaseObject* obj) {
 664   obj->set_ident(_next_ident++);






















































 665 }
 666 
 667 static ciObjectFactory::NonPermObject* emptyBucket = NULL;
 668 
 669 // ------------------------------------------------------------------
 670 // ciObjectFactory::find_non_perm
 671 //
 672 // Use a small hash table, hashed on the klass of the key.
 673 // If there is no entry in the cache corresponding to this oop, return
 674 // the null tail of the bucket into which the oop should be inserted.
 675 ciObjectFactory::NonPermObject* &ciObjectFactory::find_non_perm(oop key) {
 676   assert(Universe::heap()->is_in_reserved(key), "must be");
 677   ciMetadata* klass = get_metadata(key->klass());
 678   NonPermObject* *bp = &_non_perm_bucket[(unsigned) klass->hash() % NON_PERM_BUCKETS];
 679   for (NonPermObject* p; (p = (*bp)) != NULL; bp = &p->next()) {
 680     if (is_equal(p, key))  break;
 681   }
 682   return (*bp);
 683 }
 684 


src/share/vm/ci/ciObjectFactory.cpp
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File