aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "interpreter/interpreter.hpp" aoqi@0: #include "oops/oop.inline.hpp" aoqi@0: #include "oops/symbol.hpp" aoqi@0: #include "runtime/frame.inline.hpp" aoqi@0: #include "runtime/rframe.hpp" aoqi@0: #include "runtime/vframe.hpp" aoqi@0: #include "runtime/vframe_hp.hpp" aoqi@0: aoqi@0: aoqi@0: static RFrame*const noCaller = (RFrame*) 0x1; // no caller (i.e., initial frame) aoqi@0: static RFrame*const noCallerYet = (RFrame*) 0x0; // caller not yet computed aoqi@0: aoqi@0: RFrame::RFrame(frame fr, JavaThread* thread, RFrame*const callee) : aoqi@0: _fr(fr), _thread(thread), _callee(callee), _num(callee ? callee->num() + 1 : 0) { aoqi@0: _caller = (RFrame*)noCallerYet; aoqi@0: _invocations = 0; aoqi@0: _distance = 0; aoqi@0: } aoqi@0: aoqi@0: void RFrame::set_distance(int d) { aoqi@0: assert(is_compiled() || d >= 0, "should be positive"); aoqi@0: _distance = d; aoqi@0: } aoqi@0: aoqi@0: InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, RFrame*const callee) aoqi@0: : RFrame(fr, thread, callee) { aoqi@0: RegisterMap map(thread, false); aoqi@0: _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); aoqi@0: _method = methodHandle(thread, _vf->method()); aoqi@0: assert( _vf->is_interpreted_frame(), "must be interpreted"); aoqi@0: init(); aoqi@0: } aoqi@0: aoqi@0: InterpretedRFrame::InterpretedRFrame(frame fr, JavaThread* thread, methodHandle m) aoqi@0: : RFrame(fr, thread, NULL) { aoqi@0: RegisterMap map(thread, false); aoqi@0: _vf = javaVFrame::cast(vframe::new_vframe(&_fr, &map, thread)); aoqi@0: _method = m; aoqi@0: aoqi@0: assert( _vf->is_interpreted_frame(), "must be interpreted"); aoqi@0: init(); aoqi@0: } aoqi@0: aoqi@0: CompiledRFrame::CompiledRFrame(frame fr, JavaThread* thread, RFrame*const callee) aoqi@0: : RFrame(fr, thread, callee) { aoqi@0: init(); aoqi@0: } aoqi@0: aoqi@0: CompiledRFrame::CompiledRFrame(frame fr, JavaThread* thread) aoqi@0: : RFrame(fr, thread, NULL) { aoqi@0: init(); aoqi@0: } aoqi@0: aoqi@0: DeoptimizedRFrame::DeoptimizedRFrame(frame fr, JavaThread* thread, RFrame*const callee) aoqi@0: : InterpretedRFrame(fr, thread, callee) {} aoqi@0: aoqi@0: RFrame* RFrame::new_RFrame(frame fr, JavaThread* thread, RFrame*const callee) { aoqi@0: RFrame* rf; aoqi@0: int dist = callee ? callee->distance() : -1; aoqi@0: if (fr.is_interpreted_frame()) { aoqi@0: rf = new InterpretedRFrame(fr, thread, callee); aoqi@0: dist++; aoqi@0: } else if (fr.is_compiled_frame()) { aoqi@0: // Even deopted frames look compiled because the deopt aoqi@0: // is invisible until it happens. aoqi@0: rf = new CompiledRFrame(fr, thread, callee); aoqi@0: } else { aoqi@0: assert(false, "Unhandled frame type"); aoqi@0: } aoqi@0: rf->set_distance(dist); aoqi@0: rf->init(); aoqi@0: return rf; aoqi@0: } aoqi@0: aoqi@0: RFrame* RFrame::caller() { aoqi@0: if (_caller != noCallerYet) return (_caller == noCaller) ? NULL : _caller; // already computed caller aoqi@0: aoqi@0: // caller not yet computed; do it now aoqi@0: if (_fr.is_first_java_frame()) { aoqi@0: _caller = (RFrame*)noCaller; aoqi@0: return NULL; aoqi@0: } aoqi@0: aoqi@0: RegisterMap map(_thread, false); aoqi@0: frame sender = _fr.real_sender(&map); aoqi@0: if (sender.is_java_frame()) { aoqi@0: _caller = new_RFrame(sender, thread(), this); aoqi@0: return _caller; aoqi@0: } aoqi@0: aoqi@0: // Real caller is not java related aoqi@0: _caller = (RFrame*)noCaller; aoqi@0: return NULL; aoqi@0: } aoqi@0: aoqi@0: int InterpretedRFrame::cost() const { aoqi@0: return _method->code_size(); // fix this aoqi@0: //return _method->estimated_inline_cost(_receiverKlass); aoqi@0: } aoqi@0: aoqi@0: int CompiledRFrame::cost() const { aoqi@0: nmethod* nm = top_method()->code(); aoqi@0: if (nm != NULL) { aoqi@0: return nm->insts_size(); aoqi@0: } else { aoqi@0: return top_method()->code_size(); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void CompiledRFrame::init() { aoqi@0: RegisterMap map(thread(), false); aoqi@0: vframe* vf = vframe::new_vframe(&_fr, &map, thread()); aoqi@0: assert(vf->is_compiled_frame(), "must be compiled"); aoqi@0: _nm = compiledVFrame::cast(vf)->code(); aoqi@0: vf = vf->top(); aoqi@0: _vf = javaVFrame::cast(vf); aoqi@0: _method = methodHandle(thread(), CodeCache::find_nmethod(_fr.pc())->method()); aoqi@0: assert(_method(), "should have found a method"); aoqi@0: #ifndef PRODUCT aoqi@0: _invocations = _method->compiled_invocation_count(); aoqi@0: #endif aoqi@0: } aoqi@0: aoqi@0: void InterpretedRFrame::init() { aoqi@0: _invocations = _method->invocation_count() + _method->backedge_count(); aoqi@0: } aoqi@0: aoqi@0: void RFrame::print(const char* kind) { aoqi@0: #ifndef PRODUCT aoqi@0: #ifdef COMPILER2 aoqi@0: int cnt = top_method()->interpreter_invocation_count(); aoqi@0: #else aoqi@0: int cnt = top_method()->invocation_count(); aoqi@0: #endif aoqi@0: tty->print("%3d %s ", _num, is_interpreted() ? "I" : "C"); aoqi@0: top_method()->print_short_name(tty); aoqi@0: tty->print_cr(": inv=%5d(%d) cst=%4d", _invocations, cnt, cost()); aoqi@0: #endif aoqi@0: } aoqi@0: aoqi@0: void CompiledRFrame::print() { aoqi@0: RFrame::print("comp"); aoqi@0: } aoqi@0: aoqi@0: void InterpretedRFrame::print() { aoqi@0: RFrame::print("int."); aoqi@0: } aoqi@0: aoqi@0: void DeoptimizedRFrame::print() { aoqi@0: RFrame::print("deopt."); aoqi@0: }