vframe.cpp

Go to the documentation of this file.
00001 /* Copyright 1994, 1995 LongView Technologies L.L.C. $Revision: 1.100 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
00020 
00021 
00022 */
00023 
00024 
00025 # include "incls/_precompiled.incl"
00026 # include "incls/_vframe.cpp.incl"
00027 
00028 // Ideas:
00029 //   Maybe cache methodOop in deltaVFrame for faster argument access. (Lars 8/10/95)
00030 
00031 // ------------- vframe --------------
00032 
00033 bool vframe::equal(const vframe* f) const {
00034   return _fr.fp() == f->_fr.fp();
00035 }
00036 
00037 oop vframe::callee_argument_at(int index) const {
00038   err->print_cr("vframe::callee_argument_at should be specialized for all vframes calling deltaVFrames");
00039   fatal("aborting");
00040   return NULL;
00041 }
00042 
00043 vframe* vframe::new_vframe(frame* f) {
00044   if (f->is_interpreted_frame()) return new interpretedVFrame(f);
00045   if (f->is_entry_frame())       return new cChunk(f);
00046   if (f->is_deoptimized_frame()) return new deoptimizedVFrame(f);
00047 #ifdef DELTA_COMPILER
00048   if (f->is_compiled_frame()) {
00049     nmethod* nm = f->code();
00050     assert(nm, "nmethod not found");
00051 
00052     // NB: pc points *after* the current instruction (e.g., call), so must adjust it
00053     // to get the right bci; -1 will do portably    -Urs 2/96
00054     char* pc = f->pc() - 1;
00055     PcDesc*    pd = nm->containingPcDesc(pc);
00056     assert(pd, "PcDesc not found");
00057 
00058     ScopeDesc* sd = nm->scopes()->at(pd->scope, pc);
00059     assert(sd, "ScopeDesc not found");
00060     return compiledVFrame::new_vframe(f, sd, pd->byteCode);
00061   }
00062 #endif
00063   return new cVFrame(f);
00064 }
00065 
00066 vframe* vframe::sender() const {
00067   assert(is_top(), "just checking");
00068   frame s = _fr.sender();
00069   if (s.is_first_frame()) return NULL;
00070   return vframe::new_vframe(&s);
00071 }
00072 
00073 vframe* vframe::top() const {
00074   vframe* vf = (vframe*) this;
00075   while (!vf->is_top()) vf = vf->sender();
00076   return vf;
00077 }
00078 
00079 void vframe::print() {
00080   if (WizardMode  || ActivationShowFrame) {
00081     _fr.print();
00082   }
00083 }
00084 
00085 void vframe::print_value() const { 
00086   ((vframe*)this)->print();
00087 }
00088 
00089 // ------------- deltaVFrame --------------
00090 
00091 GrowableArray<oop>* deltaVFrame::arguments() const {
00092   int nargs = method()->number_of_arguments();
00093   GrowableArray<oop>* result = new GrowableArray<oop>(nargs);
00094   vframe* s = sender();
00095   for (int index = 0; index < nargs; index++) {
00096    result->push(argument_at(index)); 
00097   }
00098   return result;
00099 }
00100 
00101 oop deltaVFrame::argument_at(int index) const {
00102   return sender()->callee_argument_at(method()->number_of_arguments() - (index+1));
00103 }
00104 
00105 oop deltaVFrame::callee_argument_at(int index) const {
00106   return expression_at(index);
00107 }
00108 
00109 void deltaVFrame::print() {
00110   lprintf("Delta frame: "); 
00111   vframe::print();
00112 }
00113 
00114 void deltaVFrame::print_activation(int index) const {
00115   ((vframe*)this)->vframe::print();
00116   prettyPrinter::print(index, (deltaVFrame*) this);
00117 }
00118 
00119 
00120 deltaVFrame* deltaVFrame::sender_delta_frame() const {
00121   vframe* f = sender();
00122   while (f != NULL) {
00123     if (f->is_delta_frame()) return (deltaVFrame*) f;
00124     f = f->sender();
00125   }
00126   return NULL;
00127 }
00128 
00129 void deltaVFrame::verify() const {
00130   // Verify the frame
00131   fr().verify();
00132   // Make sure we do not have any context objects in the argument list
00133   int number_of_arguments = method()->number_of_arguments();
00134   for (int index = 0; index < number_of_arguments; index++) {
00135     oop argument = argument_at(index);
00136     if (argument->is_context()) {
00137       std->print_cr("Argument is a context");
00138       print_activation(0);
00139       warning("verify failed");
00140     }
00141   }
00142 }
00143 // ------------- interpretedVFrame --------------
00144 
00145 bool interpretedVFrame::has_interpreter_context() const {
00146   return method()->activation_has_context();
00147 }
00148 
00149 oop interpretedVFrame::temp_at(int offset) const {
00150   assert(offset > 0 || !has_interpreter_context(),
00151          "you cannot use temp(0) when a context is present");
00152   assert(offset < method()->number_of_stack_temporaries(), "checking bounds");
00153   return _fr.temp(offset);
00154 }
00155 
00156 oop interpretedVFrame::context_temp_at(int offset) const {
00157   assert(has_interpreter_context(), "must have context when using context_temp_at");
00158   return interpreter_context()->obj_at(offset);
00159 }
00160 
00161 contextOop interpretedVFrame::interpreter_context() const {
00162   if (!has_interpreter_context()) return NULL;
00163   contextOop result = contextOop(_fr.temp(0));
00164   assert(method()->in_context_allocation(bci()) || result->is_context(), "context type check");
00165   return result;
00166 }
00167 
00168 contextOop interpretedVFrame::canonical_context() const { 
00169   return interpreter_context();
00170 }
00171 
00172 oop interpretedVFrame::expression_at(int index) const {
00173  return *expression_addr(index);
00174 }
00175 
00176 oop* interpretedVFrame::expression_addr(int offset) const {
00177   return (oop*) &((oop*) _fr.sp())[offset]; 
00178 }
00179 
00180 GrowableArray<oop>* interpretedVFrame::expression_stack() const {
00181   int last_temp_number = method()->number_of_stack_temporaries() - 1;
00182   int size = _fr.temp_addr(last_temp_number) - expression_addr(0);
00183   assert(size >= 0, "expr stack size must be non-negative");
00184   GrowableArray<oop>* result = new GrowableArray<oop>(size);
00185   for (int index = 0; index < size; index++) {
00186     oop value = expression_at(index);
00187     assert(!value->is_context(), "checking for contextOop on expression stack");
00188     result->push(expression_at(index));
00189   }
00190 #ifdef ASSERT
00191   int computed_size = method()->expression_stack_mapping(bci())->length();
00192   if (size != computed_size) {
00193     warning("Expression stack size  @%d is %d but computed to %d", bci(), size, computed_size);
00194     std->print_cr("[expression stack:"); 
00195     for (int index = 0; index < result->length(); index++) {
00196       std->print(" - ");
00197       result->at(index)->print_value_on(std);
00198       std->cr();
00199     }
00200     std->print_cr("]"); 
00201     method()->pretty_print();
00202     method()->print_codes();
00203   }
00204 #endif
00205   return result;
00206 }
00207  
00208 u_char* interpretedVFrame::hp() const { 
00209   return _fr.hp();
00210 }
00211 
00212 void interpretedVFrame::set_hp(u_char* p) {
00213   _fr.set_hp(p);
00214 }
00215 
00216 oop interpretedVFrame::receiver() const {
00217   // In case of a block invocation the receiver might be a contextOop
00218   // due to an interpreter optimization (ask Robert for details).
00219   // To provide clean semantics in this case nilObj is returned.
00220   oop r = _fr.receiver();
00221   assert(!r->is_context() || method()->is_blockMethod(), "check: context implies block method");
00222   return r->is_context() ? nilObj : r;
00223 }
00224 
00225 void interpretedVFrame::set_receiver(oop obj) {
00226   _fr.set_receiver(obj);
00227 }
00228 
00229 void interpretedVFrame::temp_at_put(int offset, oop obj) { 
00230   _fr.set_temp(offset, obj);
00231 }
00232 
00233 void interpretedVFrame::expression_at_put(int offset, oop obj) {
00234   // FIX LATER p.set_expr(offset) = obj;
00235   Unimplemented();
00236 }
00237 
00238 bool interpretedVFrame::equal(const vframe* f) const {
00239   if (!f->is_interpreted_frame()) return false;
00240   return vframe::equal(f);
00241 }
00242 
00243 int interpretedVFrame::bci() const {
00244   return method()->bci_from(hp());
00245 }
00246 
00247 methodOop interpretedVFrame::method() const {
00248   memOop m = as_memOop(Universe::object_start((oop*) (hp() - 1)));
00249   assert(m->is_method(), "must be method");
00250   return methodOop(m);
00251 }
00252 
00253 deltaVFrame* interpretedVFrame::parent() const {
00254   methodOop m = method();
00255   
00256   // Return NULL if method is outer.
00257   if (!m->is_blockMethod()) return NULL;
00258 
00259   contextOop target = interpreter_context();
00260   if (!target) return NULL; // Return NULL if no context is present.
00261   
00262   // Walk the stack and find the vframe with outer as context.
00263   // NB: the parent may still be alive even though it cannot be
00264   //     found on this stack. It might reside on another stack.
00265 
00266   for (vframe* p = sender(); p; p = p->sender()) {
00267     if (p->is_interpreted_frame())
00268       if (((interpretedVFrame*)p)->interpreter_context() == target)
00269         return (deltaVFrame*) p;
00270   }
00271 
00272   warning("parent frame is not found on same stack");
00273 
00274   return NULL;
00275 }
00276 
00277 void interpretedVFrame::verify() const {
00278   deltaVFrame::verify();
00279   methodOop m = method();
00280   if(m->activation_has_context()) {
00281     if (!m->in_context_allocation(bci())) {
00282       contextOop con = interpreter_context();
00283       if (!con->is_context()) warning("expecting context");
00284       if (!m->is_blockMethod()) {
00285         if(con->parent_fp() == NULL) warning("expecting frame in context");
00286       }
00287       m->verify_context(con);
00288     }
00289   }
00290 }
00291 
00292 # ifdef DELTA_COMPILER
00293 
00294 // ------------- compiledVFrame --------------
00295 
00296 compiledVFrame* compiledVFrame::new_vframe(const frame* fr, ScopeDesc* sd, int bci) {
00297   if (sd->isMethodScope())
00298     return new compiledMethodVFrame(fr, sd, bci);
00299   if (sd->isTopLevelBlockScope())
00300     return new compiledTopLevelBlockVFrame(fr, sd, bci);
00301   if (sd->isBlockScope()) 
00302     return new compiledBlockVFrame(fr, sd, bci);
00303   fatal("unknown scope desc");
00304   return NULL;
00305 }
00306 
00307 void compiledVFrame::rewind_bci() {
00308   int new_bci = method()->find_bci_from(_bci);
00309   assert(new_bci >= 0, "must be real bci");
00310   std->print_cr("%d -> %d", _bci, new_bci);
00311   _bci = new_bci;
00312 }
00313 
00314 compiledVFrame::compiledVFrame(const frame* fr, ScopeDesc* sd, int bci) : deltaVFrame(fr) {
00315   this->sd   = sd;
00316   this->_bci = bci;
00317 }
00318 
00319 vframe* compiledVFrame::sender() const {
00320   if (sd->isTop()) return vframe::sender();
00321   return compiledVFrame::new_vframe(&_fr, sd->sender(), sd->senderBCI());
00322 }
00323 
00324 oop compiledVFrame::temp_at(int offset) const {
00325   assert(offset > 0 || !method()->activation_has_context(),
00326          "you cannot use temp(0) when a context is present");
00327   assert(offset < method()->number_of_stack_temporaries(), "checking bounds");
00328   return resolve_name(scope()->temporary(offset), this);
00329 }
00330 
00331 class ContextTempFindClosure : public NameDescClosure {
00332  public:
00333   NameDesc* result;
00334   int i;
00335   ContextTempFindClosure(int index) {
00336     i = index;
00337     result = NULL; }
00338   void context_temp (int no, NameDesc* a, char* pc) {
00339     if (no == i) result = a;
00340   }
00341 };
00342 
00343 oop compiledVFrame::context_temp_at(int offset) const {
00344   assert(method()->activation_has_context(),
00345          "you cannot use context_temp_at() when methodOop does not allocate context");
00346   ContextTempFindClosure blk(offset);
00347   sd->iterate(&blk);
00348   assert(blk.result, "must find result");
00349   return resolve_name(blk.result, this);
00350 }
00351 
00352 oop compiledVFrame::expression_at(int index) const {
00353   GrowableArray<oop>* stack = expression_stack();
00354   if (stack->length() <= index) {
00355     // Hack for Robert 1/15/96, probably wrong expression stack
00356     return oopFactory::new_symbol("invalid stack element");
00357   }
00358   return stack->at(index);
00359 }
00360 
00361 class CollectContextInfoClosure : public NameDescClosure {
00362  public:
00363   GrowableArray<NameDesc*>* result;
00364   CollectContextInfoClosure() {
00365     result = new GrowableArray<NameDesc*>(10);
00366   }
00367   void context_temp(int no, NameDesc* a, char* pc) { 
00368     result->append(a);
00369   }
00370 };
00371 
00372 extern "C" contextOop allocateContext(int nofVars);
00373 
00374 contextOop compiledVFrame::compiled_context() const {
00375   if (!method()->activation_has_context()) return NULL;
00376   
00377   // Hack suggested by Urs
00378   // if temp 0 contains nil the compiler has optimized away the
00379   // contextOop.
00380   // A better solution would be adding has_compiled_context to scopeDesc.
00381   oop con = resolve_name(scope()->temporary(0), this); 
00382   if (con == nilObj) return NULL;
00383 
00384   assert(con->is_context(), "context type check");
00385   return contextOop(con);
00386 }
00387 
00388 GrowableArray<oop>* compiledVFrame::expression_stack() const {
00389   GrowableArray<int>* mapping = method()->expression_stack_mapping(bci());
00390   GrowableArray<oop>* result = new GrowableArray<oop>(mapping->length());
00391   for (int index = 0; index < mapping->length(); index++) {
00392     NameDesc* nd    = sd->exprStackElem(mapping->at(index));
00393     oop       value = resolve_name(nd, this);
00394     result->push(value);
00395   }
00396 #ifdef ASSERT
00397   int computed_size = method()->expression_stack_mapping(bci())->length();
00398   if (result->length() != computed_size) {
00399     warning("Expression stack size  @%d is %d but computed to %d", bci(), result->length(), computed_size);
00400     std->print_cr("[expression stack:"); 
00401     for (int index = 0; index < result->length(); index++) {
00402       std->print(" - ");
00403       result->at(index)->print_value_on(std);
00404       std->cr();
00405     }
00406     std->print_cr("]"); 
00407     method()->pretty_print();
00408     method()->print_codes();
00409   }
00410 #endif
00411   return result;
00412 }
00413 
00414 bool compiledVFrame::equal(const vframe* f) const {
00415   if (!f->is_compiled_frame()) return false;
00416   return vframe::equal(f)
00417       && scope()->is_equal(((compiledVFrame*)f)->scope());
00418 }
00419 
00420 int compiledVFrame::bci() const {
00421   return _bci;
00422 }
00423 
00424 methodOop compiledVFrame::method() const {
00425   return sd->method();
00426 }
00427 
00428 nmethod* compiledVFrame::code() const {
00429   return _fr.code();
00430 }
00431 
00432 oop compiledVFrame::resolve_location(Location loc, const compiledVFrame* vf, contextOop con) {
00433 
00434   // Context location
00435   if (loc.isStackLocation()) {
00436     return vf
00437          ? oop(vf->fr().at(loc.offset()))
00438          : filler_oop();
00439   }
00440 
00441   // Context location
00442   if (loc.isContextLocation()) {
00443     if (vf) {
00444       ScopeDesc* scope = vf->code()->scopes()->at(loc.scopeOffs(), vf->fr().pc());
00445       assert(scope->allocates_compiled_context(), "must have context");
00446       assert(scope->compiled_context()->isLocation(), "context must be a location");
00447       contextOop context = contextOop(resolve_location(scope->compiled_context()->location(), vf));
00448       return context->obj_at(loc.tempNo());
00449     }
00450 
00451     if (con) {
00452       return con->obj_at(loc.tempNo());
00453     }
00454 
00455     return filler_oop();
00456   }
00457 
00458   // Register location
00459   if (loc.isRegisterLocation()) {
00460     return SavedRegisters::fetch(loc.number(), vf->fr().fp());
00461   }
00462 
00463   ShouldNotReachHere();
00464   return NULL;
00465 }
00466 
00467 oop compiledVFrame::resolve_name(NameDesc* nd, const compiledVFrame* vf, contextOop con) {
00468   // takes a NameDesc & looks up the oop it describes
00469   // (on the stack, in contexts, etc.)
00470 
00471   if (nd->isLocation()) {
00472     // describes a location where we can find the oop.
00473     Location loc = nd->location();
00474     return resolve_location(loc, vf, con);
00475   }
00476 
00477   if (nd->isValue()) {
00478     // an oop constant.
00479     return nd->value();
00480   }
00481 
00482   if (nd->isBlockValue()) {
00483     // a blockClosureOop that has been completely optimized away.
00484     frame f = vf->fr();
00485     oop result = nd->value(&f);
00486     return result;
00487   }
00488 
00489   if (nd->isMemoizedBlock()) {
00490     // a blockClosureOop that has been partially optimized away.
00491     // if the block doesn't exist yet, we have to create one and store it in the location.
00492     frame f = vf->fr();
00493     oop result = nd->value(&f);
00494     return result;
00495   }
00496 
00497   if (nd->isIllegal()) {
00498     // This should never happen.
00499     // For now, a fake value is returned to avoid crashes when tracing the stack.
00500     // Lars 7/3/95
00501     if (UseNewBackend) {
00502       // This is a hack - we should introduce a special
00503       // nameDesc instead - gri 8-5-96
00504       return nilObj;
00505     }
00506     warning("Compiler Bug: Illegal name desc found in nmethod 0x%lx @ %d",
00507             vf->fr().code(), vf->scope()->offset());
00508     return oopFactory::new_symbol("illegal nameDesc");
00509   }
00510 
00511   ShouldNotReachHere();
00512   return NULL;
00513 }
00514 
00515 oop compiledVFrame::filler_oop() {
00516   return nilObj;
00517   // This is useful for debugging
00518   // return oopFactory::new_symbol("compiledVFrame::filler_oop");
00519 }
00520 
00521 int compiledVFrame::bci_for(ScopeDesc* d) const {
00522   ScopeDesc* s = sd;
00523   int        b = bci();
00524   while (!s->is_equal(d)) {
00525     b = s->senderBCI();
00526     assert(s->sender(), "make sure we have a sender");
00527     s = s->sender();
00528   }
00529   return b;
00530 }
00531 
00532 #define CHECK(n)  if (n->isIllegal()) ok = false
00533 
00534 class VerifyNDClosure : public NameDescClosure {
00535  public:
00536   bool ok;
00537   VerifyNDClosure() { ok = true; }
00538   void arg          (int no, NameDesc* a, char* pc) { CHECK(a); }
00539   void temp         (int no, NameDesc* a, char* pc) { CHECK(a); }
00540   void context_temp (int no, NameDesc* a, char* pc) { CHECK(a); }
00541 };
00542 
00543 void compiledVFrame::verify_debug_info() const {
00544   // verify that all source-visible names / expr stack entries have valid nameDescs
00545   ResourceMark rm;
00546   bool ok = true;
00547   VerifyNDClosure blk;
00548   sd->iterate(&blk);
00549   CHECK(sd->self());
00550 
00551   if (!ok || !blk.ok) {
00552     print_activation(0);
00553     error("illegal nameDescs in vframe");
00554   }
00555 #undef CHECK
00556 }
00557 
00558 contextOop compiledVFrame::compute_canonical_context(ScopeDesc* scope, const compiledVFrame* vf, contextOop con) {
00559   // Computes the canonical contextOop for a scope desc.
00560   // 
00561   // Recipe:
00562   // 1. Search the stack builder context cache (in case we're during deoptimizing)
00563   // 2. Check the forward reference in contextOop.
00564   // 3. Allocate a fresh contextOop.
00565 
00566   // Playing rules for contextOops
00567   // - If there exists a compiled context there is an 1-to-1 mapping to an interpreted context
00568 
00569   if (!scope->allocates_interpreted_context()) {
00570     // This scope does not allocate an interpreter contextOop
00571     if (scope->isMethodScope()) return NULL;
00572     compiledVFrame* parent_vf = (!vf || scope->isTopLevelBlockScope()) ? NULL : (compiledVFrame*) vf->parent();
00573     return compute_canonical_context(scope->parent(true), parent_vf, con);
00574   }
00575 
00576   contextOop result;
00577 
00578   // step 1.
00579   if (vf) {
00580     if ((result = StackChunkBuilder::context_at(vf)) != NULL) {
00581       assert(result->unoptimized_context() == NULL, "cannot have deoptimized context");
00582       return result;
00583     }
00584   }
00585 
00586   // step 2
00587   if (con && con->unoptimized_context()) {
00588     result = con->unoptimized_context();
00589     assert(result->unoptimized_context() == NULL, "cannot have deoptimized context");
00590     return result;
00591   }
00592 
00593   contextOop comp_context = con;
00594   assert(comp_context == NULL || comp_context->is_context(), "must be context");
00595   
00596   // step 3
00597   if (!MaterializeEliminatedBlocks && !StackChunkBuilder::is_deoptimizing()) {
00598     // don't create a context (for better compiler debugging)
00599     // not quite kosher since the return type is expected to be a contextOop,
00600     // but for stack printing code it shouldn't matter
00601     ResourceMark rm;
00602     stringStream st(50);
00603     st.print("eliminated context in ");
00604     scope->selector()->print_symbol_on(&st);
00605     return (contextOop)oopFactory::new_symbol(st.as_string());    // unsafe cast
00606   }
00607 
00608   // collect all NameDescs
00609   CollectContextInfoClosure blk;
00610   scope->iterate(&blk);
00611 
00612   // allocate the new context
00613   result = contextKlass::allocate_context(blk.result->length());
00614 
00615   // fill in the meat
00616   for(int index = 0; index < blk.result->length(); index++) {
00617     NameDesc* nd = blk.result->at(index);
00618     result->obj_at_put(index, resolve_name(nd, vf, comp_context));
00619   }
00620 
00621   if (vf) {
00622     StackChunkBuilder::context_at_put(vf, result);
00623   } else {
00624     // kill the home field
00625     result->kill();
00626   }
00627 
00628   assert(result->unoptimized_context() == NULL, "cannot have deoptimized context");
00629 
00630   // Set parent scope if needed
00631   if (!scope->isMethodScope()) {
00632     contextOop parent = compute_canonical_context(scope->parent(true),
00633                                                   (!vf || scope->isTopLevelBlockScope()) ? NULL : (compiledVFrame*) vf->parent(),
00634                                                   con ? con->outer_context() : NULL);
00635     result->set_parent(parent);
00636   }
00637 
00638   if (StackChunkBuilder::is_deoptimizing() && comp_context) {
00639     // Save the unoptimized context as a forward reference in the
00640     // compiled context.
00641     comp_context->set_unoptimized_context(result);
00642   }
00643 
00644   if (TraceDeoptimization && comp_context) {
00645     std->print(" - ");
00646     comp_context->print_value();
00647     std->print_cr(" -> ");
00648     result->print_value();
00649     std->cr();
00650   }
00651  
00652   assert(result->unoptimized_context() == NULL, "cannot have deoptimized context");
00653   return result;
00654 }
00655 
00656 void compiledVFrame::verify() const {
00657   deltaVFrame::verify();
00658   contextOop con = compiled_context();
00659   if (con) {
00660     if(con->mark()->has_context_forward())
00661       warning("context has forwarder");
00662   }
00663 }
00664 // ------------- compiledMethodVFrame --------------
00665 
00666 compiledMethodVFrame::compiledMethodVFrame(const frame* fr, ScopeDesc* sd, int bci)
00667 : compiledVFrame(fr, sd, bci) {}
00668 
00669 
00670 bool compiledMethodVFrame::is_top() const {
00671   return sd->isTop();
00672 }
00673 
00674 oop compiledMethodVFrame::receiver() const {
00675   return resolve_name(sd->self(), this);
00676 }
00677 
00678 contextOop compiledMethodVFrame::canonical_context() const {
00679   assert(!method()->is_blockMethod(), "check methodOop type");
00680   return compute_canonical_context(scope(), this, compiled_context());
00681 }
00682 
00683 // ------------- compiledBlockVFrame --------------
00684 
00685 compiledBlockVFrame::compiledBlockVFrame(const frame* fr, ScopeDesc* sd, int bci)
00686 : compiledVFrame(fr, sd, bci) {}
00687 
00688 bool compiledBlockVFrame::is_top() const {
00689   return sd->isTop();
00690 }
00691 
00692 oop compiledBlockVFrame::receiver() const {
00693   NameDesc* nd = sd->self();
00694   if (nd) {
00695     return resolve_name(nd, this);
00696   } else {
00697     fatal("self is unknown");   // can't handle this yet -- fix this
00698     return NULL;
00699   }
00700 }
00701 
00702 deltaVFrame* compiledBlockVFrame::parent() const {
00703   ScopeDesc* ps = parent_scope();
00704   int parent_bci = bci_for(ps);
00705   return compiledVFrame::new_vframe(&_fr, ps, parent_bci);
00706 }
00707 
00708 contextOop compiledBlockVFrame::canonical_context() const {
00709   assert(method()->is_blockMethod(), "must be block method");
00710   return compute_canonical_context(scope(), this, compiled_context());
00711 }
00712 
00713 ScopeDesc* compiledBlockVFrame::parent_scope() const {
00714   ScopeDesc* result = scope()->parent();
00715   assert(result, "parent should be within same nmethod");
00716   return result;
00717 }
00718 
00719 // ------------- compiledTopLevelBlockVFrame --------------
00720 
00721 compiledTopLevelBlockVFrame::compiledTopLevelBlockVFrame(const frame* fr, ScopeDesc* sd, int bci)
00722 : compiledVFrame(fr, sd, bci) {}
00723 
00724 oop compiledTopLevelBlockVFrame::receiver() const {
00725   return resolve_name(sd->self(), this);
00726 }
00727 
00728 deltaVFrame* compiledTopLevelBlockVFrame::parent() const {
00729   methodOop m = method();
00730   if (!m->expectsContext()) return NULL;
00731   
00732   contextOop parent_context = m->allocatesInterpretedContext() 
00733                           ? compiled_context()->outer_context()
00734                           : compiled_context();
00735 
00736   // If the context is killed return NULL
00737   if (parent_context->is_dead()) return NULL;
00738 
00739   // Now we have to search for the parent on the stack.
00740   ScopeDesc* ps = parent_scope();
00741   nmethod* parent_nmethod = ps->scopes()->my_nmethod();
00742 
00743   frame v = fr().sender();
00744   do {
00745     if (v.is_compiled_frame()) {
00746       if (v.code() == parent_nmethod) {
00747         compiledVFrame* result = (compiledVFrame*) vframe::new_vframe(&v);
00748         // Run throuch the scopes and find a matching one
00749         while (result) {
00750           assert(result->is_compiled_frame(), "must be compiled frame");
00751           if (result->scope()->is_equal(ps)) {
00752             if (result->compiled_context() == parent_context)
00753               return result;
00754           }
00755           result = result->is_top() ? NULL : (compiledVFrame*) result->sender();
00756         }
00757       }
00758     }
00759     v = v.sender();
00760   } while (!v.is_first_frame());
00761   return NULL;
00762 }
00763 
00764 contextOop compiledTopLevelBlockVFrame::canonical_context() const {
00765   assert(method()->is_blockMethod(), "must be block method");
00766   return compute_canonical_context(scope(), this, compiled_context());
00767 }
00768 
00769 ScopeDesc* compiledTopLevelBlockVFrame::parent_scope() const {
00770   ScopeDesc* result = scope()->parent(true);
00771   assert(result, "parent scope must be present");
00772   return result;
00773 }
00774 
00775 // ------------- deoptimizedVFrame --------------
00776 
00777 objArrayOop deoptimizedVFrame::retrieve_frame_array() const {
00778   objArrayOop array = _fr.frame_array();
00779   assert(array->is_objArray(), "expecting objArray");
00780   return array; 
00781 }
00782 
00783 oop deoptimizedVFrame::obj_at(int index) const {
00784   return frame_array->obj_at(offset + index);
00785 }
00786 
00787 bool deoptimizedVFrame::is_top() const {
00788   return offset + end_of_expressions() > frame_array->length();
00789 }
00790 
00791 int deoptimizedVFrame::end_of_expressions() const {
00792   smiOop n = smiOop(obj_at(locals_size_offset));
00793   assert(n->is_smi(), "expecting smi");
00794   return first_temp_offset + n->value();
00795 }
00796 
00797 deoptimizedVFrame::deoptimizedVFrame(const frame* fr) 
00798  : deltaVFrame(fr) {
00799   // the first frame in the array is located at position 3 (after #frames, #locals)
00800   this->offset      = StackChunkBuilder::first_frame_index;
00801   this->frame_array = retrieve_frame_array();
00802 }
00803 
00804 deoptimizedVFrame::deoptimizedVFrame(const frame* fr, int offset) 
00805  : deltaVFrame(fr) {
00806   this->offset      = offset;
00807   this->frame_array = retrieve_frame_array();
00808 }
00809 
00810 oop deoptimizedVFrame::receiver() const {
00811   return obj_at(receiver_offset);
00812 }
00813 
00814 methodOop deoptimizedVFrame::method() const {
00815   methodOop m = methodOop(obj_at(method_offset));
00816   assert(m->is_method(), "expecting method");
00817   return m;
00818 }
00819 
00820 int deoptimizedVFrame::bci() const {
00821   smiOop b = smiOop(obj_at(bci_offset));
00822   assert(b->is_smi(), "expecting smi");
00823   return b->value();
00824 }
00825 
00826 vframe* deoptimizedVFrame::sender() const {
00827   return is_top() ? vframe::sender()
00828                   : new deoptimizedVFrame(&_fr, offset + end_of_expressions());
00829 }
00830 
00831 bool deoptimizedVFrame::equal(const vframe* f) const {
00832   if (!f->is_deoptimized_frame()) return false;
00833   return vframe::equal(f) 
00834       && offset == ((deoptimizedVFrame*)f)->offset;
00835 }
00836 
00837 oop deoptimizedVFrame::temp_at(int offset) const {
00838   return obj_at(first_temp_offset + offset);
00839 }
00840 
00841 oop deoptimizedVFrame::expression_at(int index) const {
00842   return obj_at(end_of_expressions() - 1 - index);
00843 }
00844 
00845 oop deoptimizedVFrame::context_temp_at(int offset) const {
00846   assert(deoptimized_context(), "must have context when using context_temp_at");
00847   return deoptimized_context()->obj_at(offset);
00848 }
00849 
00850 contextOop deoptimizedVFrame::deoptimized_context() const {
00851   if (!method()->activation_has_context()) return NULL;
00852   contextOop result = contextOop(temp_at(0));
00853   assert(result->is_context(), "context type check");
00854   return result;
00855 }
00856 
00857 contextOop deoptimizedVFrame::canonical_context() const {
00858   return deoptimized_context();
00859 }
00860 
00861 GrowableArray<oop>* deoptimizedVFrame::expression_stack() const {
00862   int locals   = end_of_expressions() - first_temp_offset;
00863   int temps    = method()->number_of_stack_temporaries();
00864   int exp_size = locals - temps;
00865 
00866   GrowableArray<oop>* array = new GrowableArray<oop>(exp_size);
00867   for (int index = 0 ; index < exp_size; index++) {
00868     array->push(expression_at(index));
00869   }
00870 
00871 #ifdef ASSERT
00872   int computed_size = method()->expression_stack_mapping(bci())->length();
00873   if (exp_size != computed_size)
00874     warning("Expression stack size is %d but computed to %d", exp_size, computed_size);
00875 #endif
00876 
00877   return array;
00878 }
00879 
00880 #endif
00881 
00882 // ------------- cVFrame --------------
00883 
00884 void cVFrame::print() {
00885   vframe::print();
00886   std->print_cr("C frame");
00887 }
00888 
00889 void cVFrame::print_value() const {
00890   ((vframe*)this)->print();
00891 }
00892 
00893 // ------------- cChunk --------------
00894 
00895 vframe* cChunk::sender() const {
00896   return cVFrame::sender();
00897 }
00898  
00899 void cChunk::print_value() const { 
00900   ((cChunk*)this)->print();
00901 }
00902 
00903 void cChunk::print() {
00904   vframe::print();
00905   std->print_cr("C Chunk inbetween Delta");
00906   std->print_cr("C     link 0x%lx", _fr.link());
00907 }
00908 
00909 oop cChunk::callee_argument_at(int index) const {
00910   return oop(_fr.sp()[index]); 
00911 }
00912 

Generated on Mon Oct 9 13:37:30 2006 for Strongtalk VM by  doxygen 1.4.7