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