Mercurial > hg > truffle
diff src/share/vm/runtime/deoptimization.cpp @ 6948:e522a00b91aa
Merge with http://hg.openjdk.java.net/hsx/hsx25/hotspot/ after NPG - C++ build works
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Mon, 12 Nov 2012 23:14:12 +0100 |
parents | 6278ac5829ce 18fb7da42534 |
children | 9ba90252ce08 |
line wrap: on
line diff
--- a/src/share/vm/runtime/deoptimization.cpp Mon Nov 12 18:11:17 2012 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Mon Nov 12 23:14:12 2012 +0100 @@ -34,8 +34,11 @@ #include "memory/allocation.inline.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" -#include "oops/methodOop.hpp" +#include "oops/method.hpp" #include "oops/oop.inline.hpp" +#ifdef GRAAL +#include "oops/fieldStreams.hpp" +#endif #include "prims/jvmtiThreadState.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/compilationPolicy.hpp" @@ -254,7 +257,8 @@ assert(result == NULL || result->is_oop(), "must be oop"); return_value = Handle(thread, result); assert(Universe::heap()->is_in_or_null(result), "must be heap pointer"); - if (PrintDeoptimizationDetails) { + if (TraceDeoptimization) { + ttyLocker ttyl; tty->print_cr("SAVED OOP RESULT " INTPTR_FORMAT " in thread " INTPTR_FORMAT, result, thread); } } @@ -267,12 +271,12 @@ if (reallocated) { reassign_fields(&deoptee, &map, objects); #ifndef PRODUCT - if (PrintDeoptimizationDetails) { + if (TraceDeoptimization) { ttyLocker ttyl; tty->print_cr("REALLOC OBJECTS in thread " INTPTR_FORMAT, thread); print_objects(objects); } -#endif // !PRODUCT +#endif } if (save_oop_result) { // Restore result. @@ -519,7 +523,8 @@ info->set_initial_info((intptr_t) array->sender().initial_deoptimization_info()); if (array->frames() > 1) { - if (PrintDeoptimizationDetails) { + if (VerifyStack && TraceDeoptimization) { + ttyLocker ttyl; tty->print_cr("Deoptimizing method containing inlining"); } } @@ -599,7 +604,8 @@ vframeArray* array = thread->vframe_array_head(); #ifndef PRODUCT - if (PrintDeoptimizationDetails) { + if (TraceDeoptimization) { + ttyLocker ttyl; tty->print_cr("DEOPT UNPACKING thread " INTPTR_FORMAT " vframeArray " INTPTR_FORMAT " mode %d", thread, array, exec_mode); } #endif @@ -775,19 +781,19 @@ assert(objects->at(i)->is_object(), "invalid debug information"); ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(((ConstantOopReadValue*) sv->klass())->value()()); + KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); oop obj = NULL; if (k->oop_is_instance()) { - instanceKlass* ik = instanceKlass::cast(k()); + InstanceKlass* ik = InstanceKlass::cast(k()); obj = ik->allocate_instance(CHECK_(false)); } else if (k->oop_is_typeArray()) { - typeArrayKlass* ak = typeArrayKlass::cast(k()); + TypeArrayKlass* ak = TypeArrayKlass::cast(k()); assert(sv->field_size() % type2size[ak->element_type()] == 0, "non-integral array length"); int len = sv->field_size() / type2size[ak->element_type()]; obj = ak->allocate(len, CHECK_(false)); } else if (k->oop_is_objArray()) { - objArrayKlass* ak = objArrayKlass::cast(k()); + ObjArrayKlass* ak = ObjArrayKlass::cast(k()); obj = ak->allocate(sv->field_size(), CHECK_(false)); } @@ -809,7 +815,7 @@ frame* _fr; RegisterMap* _reg_map; ObjectValue* _sv; - instanceKlass* _ik; + InstanceKlass* _ik; oop _obj; int _i; @@ -936,12 +942,78 @@ } } +#ifdef GRAAL +// Restore fields of an eliminated instance object using the same field order +// returned by HotSpotResolvedJavaType.getInstanceFields(true) +static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj) { + if (klass->superklass() != NULL) { + svIndex = reassign_fields_by_klass(klass->superklass(), fr, reg_map, sv, svIndex, obj); + } + + for (AllFieldStream fs(klass); !fs.done(); fs.next()) { + if (fs.access_flags().is_static()) { + continue; + } + intptr_t val; + StackValue* value = StackValue::create_stack_value(fr, reg_map, sv->field_at(svIndex)); + int offset = fs.offset(); + BasicType type = FieldType::basic_type(fs.signature()); + switch (type) { + case T_OBJECT: case T_ARRAY: + assert(value->type() == T_OBJECT, "Agreement."); + obj->obj_field_put(offset, value->get_obj()()); + break; + + case T_LONG: case T_DOUBLE: { + assert(value->type() == T_INT, "Agreement."); + StackValue* low = StackValue::create_stack_value(fr, reg_map, sv->field_at(++svIndex)); +#ifdef _LP64 + jlong res = (jlong)low->get_int(); +#else +#ifdef SPARC + // For SPARC we have to swap high and low words. + jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int()); +#else + jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int()); +#endif //SPARC +#endif + obj->long_field_put(offset, res); + break; + } + // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem. + case T_INT: case T_FLOAT: // 4 bytes. + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->int_field_put(offset, (jint)*((jint*)&val)); + break; + + case T_SHORT: case T_CHAR: // 2 bytes + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->short_field_put(offset, (jshort)*((jint*)&val)); + break; + + case T_BOOLEAN: case T_BYTE: // 1 byte + assert(value->type() == T_INT, "Agreement."); + val = value->get_int(); + obj->bool_field_put(offset, (jboolean)*((jint*)&val)); + break; + + default: + ShouldNotReachHere(); + } + svIndex++; + } + return svIndex; +} +#endif + // restore fields of all eliminated objects and arrays void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray<ScopeValue*>* objects) { for (int i = 0; i < objects->length(); i++) { ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(((ConstantOopReadValue*) sv->klass())->value()()); + KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); Handle obj = sv->value(); assert(obj.not_null(), "reallocation was missed"); if (PrintDeoptimizationDetails) { @@ -949,11 +1021,15 @@ } if (k->oop_is_instance()) { - instanceKlass* ik = instanceKlass::cast(k()); + InstanceKlass* ik = InstanceKlass::cast(k()); +#ifndef GRAAL FieldReassigner reassign(fr, reg_map, sv, obj()); ik->do_nonstatic_fields(&reassign); +#else + reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj()); +#endif } else if (k->oop_is_typeArray()) { - typeArrayKlass* ak = typeArrayKlass::cast(k()); + TypeArrayKlass* ak = TypeArrayKlass::cast(k()); reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type()); } else if (k->oop_is_objArray()) { reassign_object_array_elements(fr, reg_map, sv, (objArrayOop) obj()); @@ -995,11 +1071,11 @@ for (int i = 0; i < objects->length(); i++) { ObjectValue* sv = (ObjectValue*) objects->at(i); - KlassHandle k(((ConstantOopReadValue*) sv->klass())->value()()); + KlassHandle k(java_lang_Class::as_Klass(sv->klass()->as_ConstantOopReadValue()->value()())); Handle obj = sv->value(); tty->print(" object <" INTPTR_FORMAT "> of type ", sv->value()()); - k->as_klassOop()->print_value(); + k->print_value(); tty->print(" allocated (%d bytes)", obj->size() * HeapWordSize); tty->cr(); @@ -1212,18 +1288,18 @@ void Deoptimization::load_class_by_index(constantPoolHandle constant_pool, int index, TRAPS) { // in case of an unresolved klass entry, load the class. if (constant_pool->tag_at(index).is_unresolved_klass()) { - klassOop tk = constant_pool->klass_at(index, CHECK); + Klass* tk = constant_pool->klass_at(index, CHECK); return; } if (!constant_pool->tag_at(index).is_symbol()) return; - Handle class_loader (THREAD, instanceKlass::cast(constant_pool->pool_holder())->class_loader()); + Handle class_loader (THREAD, constant_pool->pool_holder()->class_loader()); Symbol* symbol = constant_pool->symbol_at(index); // class name? if (symbol->byte_at(0) != '(') { - Handle protection_domain (THREAD, Klass::cast(constant_pool->pool_holder())->protection_domain()); + Handle protection_domain (THREAD, constant_pool->pool_holder()->protection_domain()); SystemDictionary::resolve_or_null(symbol, class_loader, protection_domain, CHECK); return; } @@ -1233,7 +1309,7 @@ for (SignatureStream ss(symbol); !ss.is_done(); ss.next()) { if (ss.is_object()) { Symbol* class_name = ss.as_symbol(CHECK); - Handle protection_domain (THREAD, Klass::cast(constant_pool->pool_holder())->protection_domain()); + Handle protection_domain (THREAD, constant_pool->pool_holder()->protection_domain()); SystemDictionary::resolve_or_null(class_name, class_loader, protection_domain, CHECK); } } @@ -1318,7 +1394,7 @@ if (trap_scope->rethrow_exception()) { if (PrintDeoptimizationDetails) { - tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", instanceKlass::cast(trap_method->method_holder())->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci); + tty->print_cr("Exception to be rethrown in the interpreter for method %s::%s at bci %d", trap_method->method_holder()->name()->as_C_string(), trap_method->name()->as_C_string(), trap_bci); } GrowableArray<ScopeValue*>* expressions = trap_scope->expressions(); guarantee(expressions != NULL, "must have exception to throw"); @@ -1333,8 +1409,8 @@ // Ensure that we can record deopt. history: bool create_if_missing = ProfileTraps; - methodDataHandle trap_mdo - (THREAD, get_method_data(thread, trap_method, create_if_missing)); + MethodData* trap_mdo = + get_method_data(thread, trap_method, create_if_missing); // Print a bunch of diagnostics, if requested. if (TraceDeoptimization || LogCompilation) { @@ -1362,7 +1438,7 @@ if (xtty != NULL) xtty->name(class_name); } - if (xtty != NULL && trap_mdo.not_null()) { + if (xtty != NULL && trap_mdo != NULL) { // Dump the relevant MDO state. // This is the deopt count for the current reason, any previous // reasons or recompiles seen at this point. @@ -1387,9 +1463,9 @@ if (TraceDeoptimization) { // make noise on the tty tty->print("Uncommon trap occurred in"); nm->method()->print_short_name(tty); - tty->print(" (@" INTPTR_FORMAT ") thread=%d reason=%s action=%s unloaded_class_index=%d", + tty->print(" (@" INTPTR_FORMAT ") thread=" UINTX_FORMAT " reason=%s action=%s unloaded_class_index=%d", fr.pc(), - (int) os::current_thread_id(), + os::current_thread_id(), trap_reason_name(reason), trap_action_name(action), unloaded_class_index); @@ -1445,7 +1521,7 @@ // PerMethodRecompilationCutoff, the method is abandoned. // This should only happen if the method is very large and has // many "lukewarm" deoptimizations. The code which enforces this - // limit is elsewhere (class nmethod, class methodOopDesc). + // limit is elsewhere (class nmethod, class Method). // // Note that the per-BCI 'is_recompiled' bit gives the compiler one chance // to recompile at each bytecode independently of the per-BCI cutoff. @@ -1514,15 +1590,15 @@ // Setting +ProfileTraps fixes the following, on all platforms: // 4852688: ProfileInterpreter is off by default for ia64. The result is // infinite heroic-opt-uncommon-trap/deopt/recompile cycles, since the - // recompile relies on a methodDataOop to record heroic opt failures. + // recompile relies on a MethodData* to record heroic opt failures. // Whether the interpreter is producing MDO data or not, we also need // to use the MDO to detect hot deoptimization points and control // aggressive optimization. bool inc_recompile_count = false; ProfileData* pdata = NULL; - if (ProfileTraps && update_trap_state && trap_mdo.not_null()) { - assert(trap_mdo() == get_method_data(thread, trap_method, false), "sanity"); + if (ProfileTraps && update_trap_state && trap_mdo != NULL) { + assert(trap_mdo == get_method_data(thread, trap_method, false), "sanity"); uint this_trap_count = 0; bool maybe_prior_trap = false; bool maybe_prior_recompile = false; @@ -1638,15 +1714,15 @@ } JRT_END -methodDataOop +MethodData* Deoptimization::get_method_data(JavaThread* thread, methodHandle m, bool create_if_missing) { Thread* THREAD = thread; - methodDataOop mdo = m()->method_data(); + MethodData* mdo = m()->method_data(); if (mdo == NULL && create_if_missing && !HAS_PENDING_EXCEPTION) { // Build an MDO. Ignore errors like OutOfMemory; // that simply means we won't have an MDO to update. - methodOopDesc::build_interpreter_method_data(m, THREAD); + Method::build_interpreter_method_data(m, THREAD); if (HAS_PENDING_EXCEPTION) { assert((PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())), "we expect only an OOM error here"); CLEAR_PENDING_EXCEPTION; @@ -1657,7 +1733,7 @@ } ProfileData* -Deoptimization::query_update_method_data(methodDataHandle trap_mdo, +Deoptimization::query_update_method_data(MethodData* trap_mdo, int trap_bci, Deoptimization::DeoptReason reason, bool update_total_trap_count, @@ -1723,7 +1799,7 @@ } void -Deoptimization::update_method_data_from_interpreter(methodDataHandle trap_mdo, int trap_bci, int reason) { +Deoptimization::update_method_data_from_interpreter(MethodData* trap_mdo, int trap_bci, int reason) { ResourceMark rm; // Ignored outputs: uint ignore_this_trap_count; @@ -2032,7 +2108,7 @@ } void -Deoptimization::update_method_data_from_interpreter(methodDataHandle trap_mdo, int trap_bci, int reason) { +Deoptimization::update_method_data_from_interpreter(MethodData* trap_mdo, int trap_bci, int reason) { // no udpate }