StackValueCollection* interpretedVFrame::expressions() const { int length = fr().interpreter_frame_expression_stack_size(); if (method()->is_native()) { // If the method is native, there is no expression stack length = 0; } int nof_locals = method()->max_locals(); StackValueCollection* result = new StackValueCollection(length); // Get oopmap describing oops and int for current bci InterpreterOopMap oop_mask; method()->mask_for(bci(), &oop_mask); // handle locals for(int i=0; i < length; i++) { // Find stack location intptr_t *addr = expression_stack_addr_at(i); // Depending on oop/int put it in the right package StackValue *sv; if (oop_mask.is_oop(i + nof_locals)) { // oop value Handle h(*(oop *)addr); sv = new StackValue(h); } else { // integer sv = new StackValue(*addr); } assert(sv != NULL, "sanity check"); result->add(sv); } return result; }
bool javaVFrame::structural_compare(javaVFrame* other) { // Check static part if (method() != other->method()) return false; if (bci() != other->bci()) return false; // Check locals StackValueCollection *locs = locals(); StackValueCollection *other_locs = other->locals(); assert(locs->size() == other_locs->size(), "sanity check"); int i; for(i = 0; i < locs->size(); i++) { // it might happen the compiler reports a conflict and // the interpreter reports a bogus int. if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue; if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue; if (!locs->at(i)->equal(other_locs->at(i))) return false; } // Check expressions StackValueCollection* exprs = expressions(); StackValueCollection* other_exprs = other->expressions(); assert(exprs->size() == other_exprs->size(), "sanity check"); for(i = 0; i < exprs->size(); i++) { if (!exprs->at(i)->equal(other_exprs->at(i))) return false; } return true; }
StackValueCollection* compiledVFrame::expressions() const { // Natives has no scope if (scope() == NULL) return new StackValueCollection(0); GrowableArray<ScopeValue*>* scv_list = scope()->expressions(); if (scv_list == NULL) return new StackValueCollection(0); // scv_list is the list of ScopeValues describing the JVM stack state. // There is one scv_list entry for every JVM stack state in use. int length = scv_list->length(); StackValueCollection* result = new StackValueCollection(length); for( int i = 0; i < length; i++ ) result->add( create_stack_value(scv_list->at(i)) ); return result; }
void javaVFrame::print_lock_info(int frame_count) { ResourceMark rm; // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver. if (frame_count == 0 && method()->name() == vmSymbols::wait_name() && instanceKlass::cast(method()->method_holder())->name() == vmSymbols::java_lang_Object()) { StackValueCollection* locs = locals(); if (!locs->is_empty()) { StackValue* sv = locs->at(0); if (sv->type() == T_OBJECT) { Handle o = locs->at(0)->get_obj(); if (o.not_null()) { instanceKlass* ik = instanceKlass::cast(o->klass()); tty->print_cr("\t- waiting on <" INTPTR_FORMAT "> (a %s)", o(), ik->external_name()); } } } } // Print out all monitors that we have locked or are trying to lock GrowableArray<MonitorInfo*>* mons = monitors(); if (!mons->is_empty()) { bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); if (monitor->owner() != NULL) { // // First, assume we have the monitor locked. If we haven't found an // owned monitor before and this is the first frame, then we need to // see if the thread is blocked. // const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { switch (thread()->thread_state()) { case _thread_blocked: case _thread_blocked_trans: lock_state = "waiting to lock"; break; } } found_first_monitor = true; instanceKlass* ik = instanceKlass::cast(monitor->owner()->klass()); tty->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", lock_state, monitor->owner(), ik->external_name()); } } } }
StackValueCollection* interpretedVFrame::locals() const { int length = method()->max_locals(); if (method()->is_native()) { // If the method is native, max_locals is not telling the truth. // maxlocals then equals the size of parameters length = method()->size_of_parameters(); } StackValueCollection* result = new StackValueCollection(length); // Get oopmap describing oops and int for current bci InterpreterOopMap oop_mask; if (TraceDeoptimization && Verbose) { methodHandle m_h(thread(), method()); OopMapCache::compute_one_oop_map(m_h, bci(), &oop_mask); } else { method()->mask_for(bci(), &oop_mask); } // handle locals for(int i=0; i < length; i++) { // Find stack location intptr_t *addr = locals_addr_at(i); // Depending on oop/int put it in the right package StackValue *sv; if (oop_mask.is_oop(i)) { // oop value Handle h(*(oop *)addr); sv = new StackValue(h); } else { // integer sv = new StackValue(*addr); } assert(sv != NULL, "sanity check"); result->add(sv); } return result; }
// Fill LiveStackFrameInfo with locals, monitors, and expressions void LiveFrameStream::fill_live_stackframe(Handle stackFrame, const methodHandle& method, TRAPS) { fill_stackframe(stackFrame, method); if (_jvf != NULL) { StackValueCollection* locals = _jvf->locals(); StackValueCollection* expressions = _jvf->expressions(); GrowableArray<MonitorInfo*>* monitors = _jvf->monitors(); if (!locals->is_empty()) { objArrayHandle locals_h = values_to_object_array(locals, CHECK); java_lang_LiveStackFrameInfo::set_locals(stackFrame(), locals_h()); } if (!expressions->is_empty()) { objArrayHandle expressions_h = values_to_object_array(expressions, CHECK); java_lang_LiveStackFrameInfo::set_operands(stackFrame(), expressions_h()); } if (monitors->length() > 0) { objArrayHandle monitors_h = monitors_to_object_array(monitors, CHECK); java_lang_LiveStackFrameInfo::set_monitors(stackFrame(), monitors_h()); } } }
StackValueCollection* compiledVFrame::locals() const { // Natives has no scope if (scope() == NULL) return new StackValueCollection(0); GrowableArray<ScopeValue*>* scv_list = scope()->locals(); if (scv_list == NULL) return new StackValueCollection(0); // scv_list is the list of ScopeValues describing the JVM stack state. // There is one scv_list entry for every JVM stack state in use. int length = scv_list->length(); StackValueCollection* result = new StackValueCollection(length); // In rare instances set_locals may have occurred in which case // there are local values that are not described by the ScopeValue anymore GrowableArray<jvmtiDeferredLocalVariable*>* deferred = NULL; GrowableArray<jvmtiDeferredLocalVariableSet*>* list = thread()->deferred_locals(); if (list != NULL ) { // In real life this never happens or is typically a single element search for (int i = 0; i < list->length(); i++) { if (list->at(i)->matches((vframe*)this)) { deferred = list->at(i)->locals(); break; } } } for( int i = 0; i < length; i++ ) { result->add( create_stack_value(scv_list->at(i)) ); } // Replace specified locals with any deferred writes that are present if (deferred != NULL) { for ( int l = 0; l < deferred->length() ; l ++) { jvmtiDeferredLocalVariable* val = deferred->at(l); switch (val->type()) { case T_BOOLEAN: result->set_int_at(val->index(), val->value().z); break; case T_CHAR: result->set_int_at(val->index(), val->value().c); break; case T_FLOAT: result->set_float_at(val->index(), val->value().f); break; case T_DOUBLE: result->set_double_at(val->index(), val->value().d); break; case T_BYTE: result->set_int_at(val->index(), val->value().b); break; case T_SHORT: result->set_int_at(val->index(), val->value().s); break; case T_INT: result->set_int_at(val->index(), val->value().i); break; case T_LONG: result->set_long_at(val->index(), val->value().j); break; case T_OBJECT: { Handle obj((oop)val->value().l); result->set_obj_at(val->index(), obj); } break; default: ShouldNotReachHere(); } } } return result; }
void javaVFrame::print_lock_info_on(outputStream* st, int frame_count) { ResourceMark rm; // If this is the first frame, and java.lang.Object.wait(...) then print out the receiver. if (frame_count == 0) { if (method()->name() == vmSymbols::wait_name() && method()->method_holder()->name() == vmSymbols::java_lang_Object()) { StackValueCollection* locs = locals(); if (!locs->is_empty()) { StackValue* sv = locs->at(0); if (sv->type() == T_OBJECT) { Handle o = locs->at(0)->get_obj(); print_locked_object_class_name(st, o, "waiting on"); } } } else if (thread()->current_park_blocker() != NULL) { oop obj = thread()->current_park_blocker(); Klass* k = obj->klass(); st->print_cr("\t- %s <" INTPTR_FORMAT "> (a %s)", "parking to wait for ", (address)obj, k->external_name()); } } // Print out all monitors that we have locked or are trying to lock GrowableArray<MonitorInfo*>* mons = monitors(); if (!mons->is_empty()) { bool found_first_monitor = false; for (int index = (mons->length()-1); index >= 0; index--) { MonitorInfo* monitor = mons->at(index); if (monitor->eliminated() && is_compiled_frame()) { // Eliminated in compiled code if (monitor->owner_is_scalar_replaced()) { Klass* k = java_lang_Class::as_Klass(monitor->owner_klass()); st->print("\t- eliminated <owner is scalar replaced> (a %s)", k->external_name()); } else { oop obj = monitor->owner(); if (obj != NULL) { print_locked_object_class_name(st, obj, "eliminated"); } } continue; } if (monitor->owner() != NULL) { // First, assume we have the monitor locked. If we haven't found an // owned monitor before and this is the first frame, then we need to // see if we have completed the lock or we are blocked trying to // acquire it - we can only be blocked if the monitor is inflated const char *lock_state = "locked"; // assume we have the monitor locked if (!found_first_monitor && frame_count == 0) { markOop mark = monitor->owner()->mark(); if (mark->has_monitor() && mark->monitor() == thread()->current_pending_monitor()) { lock_state = "waiting to lock"; } } found_first_monitor = true; print_locked_object_class_name(st, monitor->owner(), lock_state); } } } }
void vframeArrayElement::fill_in(compiledVFrame* vf) { // Copy the information from the compiled vframe to the // interpreter frame we will be creating to replace vf _method = vf->method(); _bci = vf->raw_bci(); _reexecute = vf->should_reexecute(); int index; // Get the monitors off-stack GrowableArray<MonitorInfo*>* list = vf->monitors(); if (list->is_empty()) { _monitors = NULL; } else { // Allocate monitor chunk _monitors = new MonitorChunk(list->length()); vf->thread()->add_monitor_chunk(_monitors); // Migrate the BasicLocks from the stack to the monitor chunk for (index = 0; index < list->length(); index++) { MonitorInfo* monitor = list->at(index); assert(!monitor->owner_is_scalar_replaced(), "object should be reallocated already"); assert(monitor->owner() == NULL || (!monitor->owner()->is_unlocked() && !monitor->owner()->has_bias_pattern()), "object must be null or locked, and unbiased"); BasicObjectLock* dest = _monitors->at(index); dest->set_obj(monitor->owner()); monitor->lock()->move_to(monitor->owner(), dest->lock()); } } // Convert the vframe locals and expressions to off stack // values. Because we will not gc all oops can be converted to // intptr_t (i.e. a stack slot) and we are fine. This is // good since we are inside a HandleMark and the oops in our // collection would go away between packing them here and // unpacking them in unpack_on_stack. // First the locals go off-stack // FIXME this seems silly it creates a StackValueCollection // in order to get the size to then copy them and // convert the types to intptr_t size slots. Seems like it // could do it in place... Still uses less memory than the // old way though StackValueCollection *locs = vf->locals(); _locals = new StackValueCollection(locs->size()); for(index = 0; index < locs->size(); index++) { StackValue* value = locs->at(index); switch(value->type()) { case T_OBJECT: assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); // preserve object type _locals->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); break; case T_CONFLICT: // A dead local. Will be initialized to null/zero. _locals->add( new StackValue()); break; case T_INT: _locals->add( new StackValue(value->get_int())); break; default: ShouldNotReachHere(); } } // Now the expressions off-stack // Same silliness as above StackValueCollection *exprs = vf->expressions(); _expressions = new StackValueCollection(exprs->size()); for(index = 0; index < exprs->size(); index++) { StackValue* value = exprs->at(index); switch(value->type()) { case T_OBJECT: assert(!value->obj_is_scalar_replaced(), "object should be reallocated already"); // preserve object type _expressions->add( new StackValue((intptr_t) (value->get_obj()()), T_OBJECT )); break; case T_CONFLICT: // A dead stack element. Will be initialized to null/zero. // This can occur when the compiler emits a state in which stack // elements are known to be dead (because of an imminent exception). _expressions->add( new StackValue()); break; case T_INT: _expressions->add( new StackValue(value->get_int())); break; default: ShouldNotReachHere(); } } }