// ------------------------------------------------------------------ // 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. ShouldNotReachHere(); return NULL; }
void klassKlass::oop_verify_on(oop obj, outputStream* st) { Klass::oop_verify_on(obj, st); guarantee(obj->is_perm(), "should be in permspace"); guarantee(obj->is_klass(), "should be klass"); Klass* k = Klass::cast(klassOop(obj)); if (k->super() != NULL) { guarantee(k->super()->is_perm(), "should be in permspace"); guarantee(k->super()->is_klass(), "should be klass"); } klassOop ko = k->secondary_super_cache(); if( ko != NULL ) { guarantee(ko->is_perm(), "should be in permspace"); guarantee(ko->is_klass(), "should be klass"); } for( uint i = 0; i < primary_super_limit(); i++ ) { oop ko = k->adr_primary_supers()[i]; // Cannot use normal accessor because it asserts if( ko != NULL ) { guarantee(ko->is_perm(), "should be in permspace"); guarantee(ko->is_klass(), "should be klass"); } } if (k->java_mirror() != NULL || (k->oop_is_instance() && instanceKlass::cast(klassOop(obj))->is_loaded())) { guarantee(k->java_mirror() != NULL, "should be allocated"); guarantee(k->java_mirror()->is_perm(), "should be in permspace"); guarantee(k->java_mirror()->is_instance(), "should be instance"); } if (k->name() != NULL) { guarantee(Universe::heap()->is_in_permanent(k->name()), "should be in permspace"); guarantee(k->name()->is_symbol(), "should be symbol"); } }
void Dictionary::verify() { guarantee(number_of_entries() >= 0, "Verify of system dictionary failed"); int element_count = 0; for (int index = 0; index < table_size(); index++) { for (DictionaryEntry* probe = bucket(index); probe != NULL; probe = probe->next()) { Klass* e = probe->klass(); ClassLoaderData* loader_data = probe->loader_data(); guarantee(e->oop_is_instance(), "Verify of system dictionary failed"); // class loader must be present; a null class loader is the // boostrap loader guarantee(loader_data != NULL || DumpSharedSpaces || loader_data->class_loader() == NULL || loader_data->class_loader()->is_instance(), "checking type of class_loader"); e->verify(); probe->verify_protection_domain_set(); element_count++; } } guarantee(number_of_entries() == element_count, "Verify of system dictionary failed"); debug_only(verify_lookup_length((double)number_of_entries() / table_size())); _pd_cache_table->verify(); }
void InstanceMirrorKlass::oop_pc_follow_contents(oop obj, ParCompactionManager* cm) { InstanceKlass::oop_pc_follow_contents(obj, cm); // Follow the klass field in the mirror. Klass* klass = java_lang_Class::as_Klass(obj); if (klass != NULL) { // An anonymous class doesn't have its own class loader, so the call // to follow_klass will mark and push its java mirror instead of the // class loader. When handling the java mirror for an anonymous class // we need to make sure its class loader data is claimed, this is done // by calling follow_class_loader explicitly. For non-anonymous classes // the call to follow_class_loader is made when the class loader itself // is handled. if (klass->oop_is_instance() && InstanceKlass::cast(klass)->is_anonymous()) { PSParallelCompact::follow_class_loader(cm, klass->class_loader_data()); } else { PSParallelCompact::follow_klass(cm, klass); } } else { // If klass is NULL then this a mirror for a primitive type. // We don't have to follow them, since they are handled as strong // roots in Universe::oops_do. assert(java_lang_Class::is_primitive(obj), "Sanity check"); } PSParallelCompact::MarkAndPushClosure cl(cm); oop_oop_iterate_statics<true>(obj, &cl); }
void ClassLoaderData::classes_do(void f(InstanceKlass*)) { for (Klass* k = _klasses; k != NULL; k = k->next_link()) { if (k->oop_is_instance()) { f(InstanceKlass::cast(k)); } assert(k != k->next_link(), "no loops!"); } }
void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) { // Lock to avoid classes being modified/added/removed during iteration MutexLockerEx ml(metaspace_lock(), Mutex::_no_safepoint_check_flag); for (Klass* k = _klasses; k != NULL; k = k->next_link()) { // Do not filter ArrayKlass oops here... if (k->oop_is_array() || (k->oop_is_instance() && InstanceKlass::cast(k)->is_loaded())) { klass_closure->do_klass(k); } } }
// ------------------------------------------------------------------ // ciObjectFactory::create_new_metadata // // Create a new ciMetadata from a Metadata*. // // 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 && o->is_klass()) { Klass* holder = ((Klass*)o); if (holder->oop_is_instance() && InstanceKlass::cast(holder)->is_anonymous()) { // Though ciInstanceKlass records class loader oop, it's not enough to keep // VM anonymous classes alive (loader == NULL). Klass holder should be used instead. // It is enough to record a ciObject, since cached elements are never removed // during ciObjectFactory lifetime. ciObjectFactory itself is created for // every compilation and lives for the whole duration of the compilation. ciObject* h = get(holder->klass_holder()); } } 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); ciEnv *env = CURRENT_THREAD_ENV; ciInstanceKlass* holder = env->get_instance_klass(h_m()->method_holder()); return new (arena()) ciMethod(h_m, holder); } 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 Metadata* is of some type not supported by the compiler interface. ShouldNotReachHere(); return NULL; }
object_type ClassifyObjectClosure::classify_object(oop obj, bool count) { object_type type = unknown_type; Klass* k = obj->blueprint(); if (k->as_klassOop() == SystemDictionary::Object_klass()) { tty->print_cr("Found the class!"); } if (count) { k->set_alloc_count(k->alloc_count() + 1); } if (obj->is_instance()) { if (k->oop_is_instanceRef()) { type = instanceRef_type; } else { type = instance_type; } } else if (obj->is_typeArray()) { type = typeArray_type; } else if (obj->is_objArray()) { type = objArray_type; } else if (obj->is_symbol()) { type = symbol_type; } else if (obj->is_klass()) { Klass* k = ((klassOop)obj)->klass_part(); if (k->oop_is_instance()) { type = instanceKlass_type; } else { type = klass_type; } } else if (obj->is_method()) { type = method_type; } else if (obj->is_constMethod()) { type = constMethod_type; } else if (obj->is_methodData()) { ShouldNotReachHere(); } else if (obj->is_constantPool()) { type = constantPool_type; } else if (obj->is_constantPoolCache()) { type = constantPoolCache_type; } else if (obj->is_compiledICHolder()) { type = compiledICHolder_type; } else { ShouldNotReachHere(); } assert(type != unknown_type, "found object of unknown type."); return type; }
// Walk all methods in the class list and assign a fingerprint. // so that this part of the ConstMethod* is read only. static void calculate_fingerprints() { for (int i = 0; i < _global_klass_objects->length(); i++) { Klass* k = _global_klass_objects->at(i); if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k); for (int i = 0; i < ik->methods()->length(); i++) { Method* m = ik->methods()->at(i); Fingerprinter fp(m); // The side effect of this call sets method's fingerprint field. fp.fingerprint(); } } } }
Method* ConstantPoolCacheEntry::method_if_resolved(constantPoolHandle cpool) { // Decode the action of set_method and set_interface_call Bytecodes::Code invoke_code = bytecode_1(); if (invoke_code != (Bytecodes::Code)0) { Metadata* f1 = f1_ord(); if (f1 != NULL) { switch (invoke_code) { case Bytecodes::_invokeinterface: assert(f1->is_klass(), ""); return klassItable::method_for_itable_index((Klass*)f1, f2_as_index()); case Bytecodes::_invokestatic: case Bytecodes::_invokespecial: assert(!has_appendix(), ""); case Bytecodes::_invokehandle: case Bytecodes::_invokedynamic: assert(f1->is_method(), ""); return (Method*)f1; } } } invoke_code = bytecode_2(); if (invoke_code != (Bytecodes::Code)0) { switch (invoke_code) { case Bytecodes::_invokevirtual: if (is_vfinal()) { // invokevirtual Method* m = f2_as_vfinal_method(); assert(m->is_method(), ""); return m; } else { int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index()); if (cpool->tag_at(holder_index).is_klass()) { Klass* klass = cpool->resolved_klass_at(holder_index); if (!klass->oop_is_instance()) klass = SystemDictionary::Object_klass(); return InstanceKlass::cast(klass)->method_at_vtable(f2_as_index()); } } break; } } return NULL; }
// Unevolving classes may point to methods of the evolving class directly // from their constantpool caches and vtables/itables. Fix this. static void adjust_cpool_cache_and_vtable(klassOop k_oop, oop loader) { Klass *k = k_oop->klass_part(); if (k->oop_is_instance()) { instanceKlass *ik = (instanceKlass *) k; bool previous_version; if (java_core_class_name(ik->name()->as_utf8())) return; // By this time we have already replaced the constantpool pointer in the evolving // class itself. However, we need to fix the entries in the old constantpool, which // is still referenced by active old methods of this class. constantPoolCacheOop cp_cache = (k_oop == _evolving_koop) ? _old_constants->cache() : ik->constants()->cache(); do { if (cp_cache != NULL) { cp_cache->adjust_method_entries(_old_methods, _new_methods); } // Fix vtable (this is needed for the evolving class itself and its subclasses). if (ik->vtable_length() > 0 && ik->is_subclass_of(_evolving_koop)) { ik->vtable()->adjust_entries(_old_methods, _new_methods); } // Fix itable, if it exists. if (ik->itable_length() > 0) { ik->itable()->adjust_method_entries(_old_methods, _new_methods); } // Previous version methods could be still on stack so adjust entries // in all previous versions. if (ik->has_previous_version()) { ik = (instanceKlass *)(ik->previous_version())->klass_part(); cp_cache = ik->constants()->cache(); previous_version = true; } else { previous_version = false; } } while (previous_version); } }
// Assumes the vtable is in first slot in object. static void patch_klass_vtables(void** vtbl_list, void* new_vtable_start) { int n = _global_klass_objects->length(); for (int i = 0; i < n; i++) { Klass* obj = _global_klass_objects->at(i); // Note oop_is_instance() is a virtual call. After patching vtables // all virtual calls on the dummy vtables will restore the original! if (obj->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(obj); *(void**)ik = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, ik); ConstantPool* cp = ik->constants(); *(void**)cp = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, cp); for (int j = 0; j < ik->methods()->length(); j++) { Method* m = ik->methods()->at(j); *(void**)m = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, m); } } else { // Array klasses Klass* k = obj; *(void**)k = find_matching_vtbl_ptr(vtbl_list, new_vtable_start, k); } } }
// ------------------------------------------------------------------ // ciFieldLayout::fill_in_instance_fields // // Set up the instance fields in this ciFieldLayout. void ciFieldLayout::fill_in_instance_fields(GrowableArray<BasicType>* fieldtypes, GrowableArray<int>* fieldoffsets, GrowableArray<int>* aflags, int& pos, klassOop current) { Klass* k = current->klass_part(); assert(k->oop_is_instance(), "must be instanceKlass"); instanceKlass* ik = (instanceKlass*)k; klassOop super = k->super(); if (super) { fill_in_instance_fields(fieldtypes, fieldoffsets, aflags, pos, super); } // Fill in this klass's instance fields. typeArrayOop field_list = ik->fields(); constantPoolOop cpool = ik->constants(); uint num_fields = field_list->length(); for (uint i = 0; i < num_fields; i += instanceKlass::next_offset) { AccessFlags flags; flags.set_flags(field_list->short_at(i + instanceKlass::access_flags_offset)); if (!flags.is_static()) { // This is an instance field. Add it to our list. int field_offset = ik->offset_from_fields( i ); // Add the type to our list. symbolOop type_sym = cpool->symbol_at(field_list->short_at(i+ instanceKlass::signature_index_offset)); BasicType field_type; field_type = type2field[FieldType::basic_type(type_sym)]; fieldtypes->at_put_grow(pos, field_type, T_VOID); aflags->at_put_grow(pos, flags.as_int(), 0); // The field offset we set here includes the header_size fieldoffsets->at_put_grow(pos, field_offset, 0); pos++; } } }
inline instanceKlass* klassVtable::ik() const { Klass* k = _klass()->klass_part(); assert(k->oop_is_instance(), "not an instanceKlass"); return (instanceKlass*)k; }
// ------------------------------------------------------------------ // ciObjectFactory::create_new_object // // Create a new ciObject from an oop. // // Implementation note: this functionality could be virtual behavior // of the oop itself. For now, we explicitly marshal the object. ciObject* ciObjectFactory::create_new_object(oop o) { EXCEPTION_CONTEXT; if (o->is_symbol()) { symbolHandle h_o(THREAD, (symbolOop)o); assert(vmSymbols::find_sid(h_o()) == vmSymbols::NO_SID, ""); return new (arena()) ciSymbol(h_o, vmSymbols::NO_SID); } else 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_symbol()) { return new (arena()) ciSymbolKlass(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()) { instanceHandle h_i(THREAD, (instanceOop)o); if (java_dyn_CallSite::is_instance(o)) return new (arena()) ciCallSite(h_i); else if (java_dyn_MethodHandle::is_instance(o)) return new (arena()) ciMethodHandle(h_i); else return new (arena()) ciInstance(h_i); } else if (o->is_objArray()) { objArrayHandle h_oa(THREAD, (objArrayOop)o); return new (arena()) ciObjArray(h_oa); } 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; }