bool symbolKlass::allocate_symbols(int names_count, const char** names, int* lengths, symbolOop* sym_oops, TRAPS) { if (UseConcMarkSweepGC || UseParallelGC) { // Concurrent GC needs to mark all the allocated symbol oops after // the remark phase which isn't done below (except the first symbol oop). // So return false which will let the symbols be allocated one by one. // The parallel collector uses an object start array to find the // start of objects on a dirty card. The object start array is not // updated for the start of each symbol so is not precise. During // object array verification this causes a verification failure. // In a product build this causes extra searching for the start of // a symbol. As with the concurrent collector a return of false will // cause each symbol to be allocated separately and in the case // of the parallel collector will cause the object // start array to be updated. return false; } assert(names_count > 0, "can't allocate 0 symbols"); int total_size = 0; int i, sizes[SymbolTable::symbol_alloc_batch_size]; for (i=0; i<names_count; i++) { int len = lengths[i]; if (len > symbolOopDesc::max_length()) { return false; } int sz = symbolOopDesc::object_size(len); sizes[i] = sz * HeapWordSize; total_size += sz; } symbolKlassHandle h_k(THREAD, as_klassOop()); HeapWord* base = Universe::heap()->permanent_mem_allocate(total_size); if (base == NULL) { return false; } // CAN'T take any safepoint during the initialization of the symbol oops ! No_Safepoint_Verifier nosafepoint; klassOop sk = h_k(); int pos = 0; for (i=0; i<names_count; i++) { symbolOop s = (symbolOop) (((char*)base) + pos); s->set_mark(markOopDesc::prototype()); s->set_klass(sk); s->set_utf8_length(lengths[i]); const char* name = names[i]; for (int j=0; j<lengths[i]; j++) { s->byte_at_put(j, name[j]); } assert(s->is_parsable(), "should be parsable here."); sym_oops[i] = s; pos += sizes[i]; } return true; }
constMethodOop constMethodKlass::allocate(int byte_code_size, int compressed_line_number_size, int localvariable_table_length, int checked_exceptions_length, bool is_conc_safe, TRAPS) { int size = constMethodOopDesc::object_size(byte_code_size, compressed_line_number_size, localvariable_table_length, checked_exceptions_length); KlassHandle h_k(THREAD, as_klassOop()); constMethodOop cm = (constMethodOop) CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL); assert(!cm->is_parsable(), "Not yet safely parsable"); No_Safepoint_Verifier no_safepoint; cm->set_interpreter_kind(Interpreter::invalid); cm->init_fingerprint(); cm->set_method(NULL); cm->set_stackmap_data(NULL); cm->set_exception_table(NULL); cm->set_code_size(byte_code_size); cm->set_constMethod_size(size); cm->set_inlined_tables_length(checked_exceptions_length, compressed_line_number_size, localvariable_table_length); assert(cm->size() == size, "wrong size for object"); cm->set_is_conc_safe(is_conc_safe); cm->set_partially_loaded(); assert(cm->is_parsable(), "Is safely parsable by gc"); return cm; }
/** * 为某一类型对应的java.lang.Class实例分配存储空间 */ instanceOop instanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) { // Query before forming handle. int size = instance_size(k); KlassHandle h_k(THREAD, as_klassOop()); instanceOop i = (instanceOop) CollectedHeap::Class_obj_allocate(h_k, size, k, CHECK_NULL); return i; }
typeArrayOop TypeArrayKlass::allocate(int length, HeapColor color, TRAPS) { assert(log2_element_size() >= 0, "bad scale"); if (length >= 0) { if (length <= max_length()) { size_t size = typeArrayOopDesc::object_size(layout_helper(), length); KlassHandle h_k(THREAD, this); typeArrayOop t; CollectedHeap* ch = Universe::heap(); /* if (size < ch->large_typearray_limit()) { */ t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, color, CHECK_NULL); /* } else { t = (typeArrayOop)CollectedHeap::large_typearray_allocate(h_k, (int)size, length, color, CHECK_NULL); } */ //assert(t->is_parsable(), "Don't publish unless parsable"); return t; } else { report_java_out_of_memory("Requested array size exceeds VM limit"); THROW_OOP_0(Universe::out_of_memory_error_array_size()); } } else { THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); } }
// ------------------------------------------------------------------ // 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; }
typeArrayOop typeArrayKlass::allocate_permanent(int length, TRAPS) { if (length < 0) THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); int size = typeArrayOopDesc::object_size(layout_helper(), length); KlassHandle h_k(THREAD, as_klassOop()); typeArrayOop t = (typeArrayOop) CollectedHeap::permanent_array_allocate(h_k, size, length, CHECK_NULL); assert(t->is_parsable(), "Can't publish until parsable"); return t; }
compiledICHolderOop compiledICHolderKlass::allocate(TRAPS) { KlassHandle h_k(THREAD, as_klassOop()); int size = compiledICHolderOopDesc::object_size(); compiledICHolderOop c = (compiledICHolderOop) CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL); c->set_holder_method(NULL); c->set_holder_klass(NULL); return c; }
instanceOop InstanceMirrorKlass::allocate_instance(KlassHandle k, TRAPS) { // Query before forming handle. int size = instance_size(k); KlassHandle h_k(THREAD, this); instanceOop i = (instanceOop)CollectedHeap::obj_allocate(h_k, size, CHECK_NULL); // Since mirrors can be variable sized because of the static fields, store // the size in the mirror itself. java_lang_Class::set_oop_size(i, size); return i; }
methodDataOop methodDataKlass::allocate(methodHandle method, TRAPS) { int size = methodDataOopDesc::compute_allocation_size_in_words(method()); KlassHandle h_k(THREAD, as_klassOop()); methodDataOop mdo = (methodDataOop)CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_0); assert(!mdo->is_parsable(), "not expecting parsability yet."); No_GC_Verifier nogc; // the init function should not GC mdo->initialize(method()); assert(mdo->is_parsable(), "should be parsable here."); assert(size == mdo->object_size(), "wrong size for methodDataOop"); return mdo; }
// ------------------------------------------------------------------ // 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; }
symbolOop symbolKlass::allocate_symbol(u1* name, int len, TRAPS) { // Don't allow symbol oops to be created which cannot fit in a symbolOop. if (len > symbolOopDesc::max_length()) { THROW_MSG_0(vmSymbols::java_lang_InternalError(), "name is too long to represent"); } int size = symbolOopDesc::object_size(len); symbolKlassHandle h_k(THREAD, as_klassOop()); symbolOop sym = (symbolOop) CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_0); assert(!sym->is_parsable(), "not expecting parsability yet."); sym->set_next(NULL); sym->set_utf8_length(len); for (int i = 0; i < len; i++) { sym->byte_at_put(i, name[i]); } // Let the first emptySymbol be created and // ensure only one is ever created. assert(sym->is_parsable() || Universe::emptySymbol() == NULL, "should be parsable here."); return sym; }
typeArrayOop TypeArrayKlass::allocate_common(int length, bool do_zero, TRAPS) { assert(log2_element_size() >= 0, "bad scale"); if (length >= 0) { if (length <= max_length()) { size_t size = typeArrayOopDesc::object_size(layout_helper(), length); KlassHandle h_k(THREAD, this); typeArrayOop t; CollectedHeap* ch = Universe::heap(); if (do_zero) { t = (typeArrayOop)CollectedHeap::array_allocate(h_k, (int)size, length, CHECK_NULL); } else { t = (typeArrayOop)CollectedHeap::array_allocate_nozero(h_k, (int)size, length, CHECK_NULL); } return t; } else { report_java_out_of_memory("Requested array size exceeds VM limit"); JvmtiExport::post_array_size_exhausted(); THROW_OOP_0(Universe::out_of_memory_error_array_size()); } } else { THROW_0(vmSymbols::java_lang_NegativeArraySizeException()); } }
methodOop methodKlass::allocate(constMethodHandle xconst, AccessFlags access_flags, TRAPS) { int size = methodOopDesc::object_size(access_flags.is_native()); KlassHandle h_k(THREAD, as_klassOop()); assert(xconst()->is_parsable(), "possible publication protocol violation"); methodOop m = (methodOop)CollectedHeap::permanent_obj_allocate(h_k, size, CHECK_NULL); assert(!m->is_parsable(), "not expecting parsability yet."); No_Safepoint_Verifier no_safepoint; // until m becomes parsable below m->set_constMethod(xconst()); m->set_access_flags(access_flags); m->set_method_size(size); m->set_name_index(0); m->set_signature_index(0); #ifdef CC_INTERP m->set_result_index(T_VOID); #endif m->set_constants(NULL); m->set_max_stack(0); m->set_max_locals(0); m->set_intrinsic_id(vmIntrinsics::_none); m->set_method_data(NULL); m->set_interpreter_throwout_count(0); m->set_vtable_index(methodOopDesc::garbage_vtable_index); // Fix and bury in methodOop m->set_interpreter_entry(NULL); // sets i2i entry and from_int m->set_highest_tier_compile(CompLevel_none); m->set_adapter_entry(NULL); m->clear_code(); // from_c/from_i get set to c2i/i2i if (access_flags.is_native()) { m->clear_native_function(); m->set_signature_handler(NULL); } NOT_PRODUCT(m->set_compiled_invocation_count(0);)
// ------------------------------------------------------------------ // 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; }