hotspot/src/share/vm/code/nmethod.cpp

Print this page
rev 611 : Merge

@@ -1,10 +1,10 @@
 #ifdef USE_PRAGMA_IDENT_SRC
 #pragma ident "@(#)nmethod.cpp  1.371 08/02/29 12:46:11 JVM"
 #endif
 /*
- * Copyright 1997-2007 Sun Microsystems, Inc.  All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc.  All Rights Reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License version 2 only, as
  * published by the Free Software Foundation.

@@ -28,11 +28,10 @@
 # include "incls/_precompiled.incl"
 # include "incls/_nmethod.cpp.incl"
 
 #ifdef DTRACE_ENABLED
 
-
 // Only bother with this argument setup if dtrace is available
 
 HS_DTRACE_PROBE_DECL8(hotspot, compiled__method__load, 
   const char*, int, const char*, int, const char*, int, void*, size_t);
 

@@ -439,11 +438,10 @@
   // create nmethod
   nmethod* nm = NULL;
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     int native_nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
-    const int dummy = -1;               // Flag to force proper "operator new"
     CodeOffsets offsets;
     offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
     offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
     nm = new (native_nmethod_size)
       nmethod(method(), native_nmethod_size, &offsets,

@@ -462,10 +460,45 @@
   }
 
   return nm;
 }
 
+#ifdef HAVE_DTRACE_H
+nmethod* nmethod::new_dtrace_nmethod(methodHandle method,
+                                     CodeBuffer *code_buffer,
+                                     int vep_offset,
+                                     int trap_offset,
+                                     int frame_complete,
+                                     int frame_size) {
+  // create nmethod
+  nmethod* nm = NULL;
+  {
+    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    int nmethod_size = allocation_size(code_buffer, sizeof(nmethod));
+    CodeOffsets offsets;
+    offsets.set_value(CodeOffsets::Verified_Entry, vep_offset);
+    offsets.set_value(CodeOffsets::Dtrace_trap, trap_offset);
+    offsets.set_value(CodeOffsets::Frame_Complete, frame_complete);
+
+    nm = new (nmethod_size) nmethod(method(), nmethod_size, &offsets, code_buffer, frame_size);
+
+    NOT_PRODUCT(if (nm != NULL)  nmethod_stats.note_nmethod(nm));
+    if (PrintAssembly && nm != NULL)
+      Disassembler::decode(nm);
+  }
+  // verify nmethod
+  debug_only(if (nm) nm->verify();) // might block
+
+  if (nm != NULL) {
+    nm->log_new_nmethod();
+  }
+
+  return nm;
+}
+
+#endif // def HAVE_DTRACE_H
+
 nmethod* nmethod::new_nmethod(methodHandle method,
   int compile_id,
   int entry_bci,
   CodeOffsets* offsets,
   int orig_pc_offset,

@@ -559,10 +592,13 @@
     // We have no exception handler or deopt handler make the
     // values something that will never match a pc like the nmethod vtable entry
     _exception_offset        = 0;
     _deoptimize_offset       = 0;
     _orig_pc_offset          = 0;
+#ifdef HAVE_DTRACE_H
+    _trap_offset             = 0;
+#endif // def HAVE_DTRACE_H
     _stub_offset             = data_offset();
     _consts_offset           = data_offset();
     _scopes_data_offset      = data_offset();
     _scopes_pcs_offset       = _scopes_data_offset;
     _dependencies_offset     = _scopes_pcs_offset;

@@ -616,10 +652,94 @@
     }
   }
   Events::log("Create nmethod " INTPTR_FORMAT, this);
 }
 
+// For dtrace wrappers
+#ifdef HAVE_DTRACE_H
+nmethod::nmethod(
+  methodOop method,
+  int nmethod_size,
+  CodeOffsets* offsets,
+  CodeBuffer* code_buffer,
+  int frame_size)
+  : CodeBlob("dtrace nmethod", code_buffer, sizeof(nmethod),
+             nmethod_size, offsets->value(CodeOffsets::Frame_Complete), frame_size, NULL),
+  _compiled_synchronized_native_basic_lock_owner_sp_offset(in_ByteSize(-1)),
+  _compiled_synchronized_native_basic_lock_sp_offset(in_ByteSize(-1))
+{
+  {
+    debug_only(No_Safepoint_Verifier nsv;)
+    assert_locked_or_safepoint(CodeCache_lock);
+
+    NOT_PRODUCT(_has_debug_info = false; )
+    _method                  = method;
+    _entry_bci               = InvocationEntryBci;
+    _link                    = NULL;
+    _compiler                = NULL;
+    // We have no exception handler or deopt handler make the
+    // values something that will never match a pc like the nmethod vtable entry
+    _exception_offset        = 0;
+    _deoptimize_offset       = 0;
+    _trap_offset             = offsets->value(CodeOffsets::Dtrace_trap);
+    _orig_pc_offset          = 0;
+    _stub_offset             = data_offset();
+    _consts_offset           = data_offset();
+    _scopes_data_offset      = data_offset();
+    _scopes_pcs_offset       = _scopes_data_offset;
+    _dependencies_offset     = _scopes_pcs_offset;
+    _handler_table_offset    = _dependencies_offset;
+    _nul_chk_table_offset    = _handler_table_offset;
+    _nmethod_end_offset      = _nul_chk_table_offset;
+    _compile_id              = 0;  // default
+    _comp_level              = CompLevel_none;
+    _entry_point             = instructions_begin();
+    _verified_entry_point    = instructions_begin() + offsets->value(CodeOffsets::Verified_Entry);
+    _osr_entry_point         = NULL;
+    _exception_cache         = NULL;
+    _pc_desc_cache.reset_to(NULL);
+
+    flags.clear();
+    flags.state              = alive;
+    _markedForDeoptimization = 0;
+
+    _lock_count = 0;
+    _stack_traversal_mark    = 0;
+
+    code_buffer->copy_oops_to(this);
+    debug_only(check_store();)
+    CodeCache::commit(this);
+    VTune::create_nmethod(this);
+  }
+
+  if (PrintNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) {
+    ttyLocker ttyl;  // keep the following output all in one block
+    // This output goes directly to the tty, not the compiler log.
+    // To enable tools to match it up with the compilation activity,
+    // be sure to tag this tty output with the compile ID.
+    if (xtty != NULL) {
+      xtty->begin_head("print_dtrace_nmethod");
+      xtty->method(_method);
+      xtty->stamp();
+      xtty->end_head(" address='" INTPTR_FORMAT "'", (intptr_t) this);
+    }
+    // print the header part first
+    print();
+    // then print the requested information
+    if (PrintNMethods) {
+      print_code();
+    }
+    if (PrintRelocations) {
+      print_relocations();
+    }
+    if (xtty != NULL) {
+      xtty->tail("print_dtrace_nmethod");
+    }
+  }
+  Events::log("Create nmethod " INTPTR_FORMAT, this);
+}
+#endif // def HAVE_DTRACE_H
 
 void* nmethod::operator new(size_t size, int nmethod_size) {  
   // Always leave some room in the CodeCache for I2C/C2I adapters  
   if (CodeCache::unallocated_capacity() < CodeCacheMinimumFreeSpace) return NULL;
   return CodeCache::allocate(nmethod_size);    

@@ -659,10 +779,13 @@
     _comp_level              = comp_level;
     _entry_bci               = entry_bci;
     _link                    = NULL;
     _compiler                = compiler;
     _orig_pc_offset          = orig_pc_offset;
+#ifdef HAVE_DTRACE_H
+    _trap_offset             = 0;
+#endif // def HAVE_DTRACE_H
     _stub_offset             = instructions_offset() + code_buffer->total_offset_of(code_buffer->stubs()->start());
 
     // Exception handler and deopt handler are in the stub section
     _exception_offset        = _stub_offset + offsets->value(CodeOffsets::Exceptions);
     _deoptimize_offset       = _stub_offset + offsets->value(CodeOffsets::Deopt);

@@ -708,11 +831,13 @@
     assert(compiler->is_c2() || 
            _method->is_static() == (entry_point() == _verified_entry_point),
            " entry points must be same for static methods and vice versa");
   }
 
-  bool printnmethods = PrintNMethods || CompilerOracle::has_option_string(_method, "PrintNMethods");
+  bool printnmethods = PrintNMethods
+    || CompilerOracle::should_print(_method)
+    || CompilerOracle::has_option_string(_method, "PrintNMethods");
   if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
     print_nmethod(printnmethods);
   }
 
   // Note: Do not verify in here as the CodeCache_lock is

@@ -799,11 +924,10 @@
     }
   }
 }
 
 
-#ifndef PRODUCT
 void nmethod::print_nmethod(bool printmethod) {
   ttyLocker ttyl;  // keep the following output all in one block
   if (xtty != NULL) {
     xtty->begin_head("print_nmethod");
     xtty->stamp();

@@ -832,11 +956,10 @@
   }
   if (xtty != NULL) {
     xtty->tail("print_nmethod");
   }
 }
-#endif
 
 
 void nmethod::set_version(int v) {
   flags.version = v;
 }

@@ -1228,15 +1351,11 @@
       // The oop should be kept alive
       keep_alive->do_oop(root);
       return false;
     }
   }
-  if (!UseParallelOldGC || !VerifyParallelOldWithMarkSweep) {
-    // Cannot do this test if verification of the UseParallelOldGC
-    // code using the PSMarkSweep code is being done.
     assert(unloading_occurred, "Inconsistency in unloading");
-  }
   make_unloaded(is_alive, obj);
   return true;
 }
 
 // ------------------------------------------------------------------

@@ -1871,10 +1990,11 @@
       }
     }
   }
 }
 
+#endif // PRODUCT
 
 // Printing operations
 
 void nmethod::print() const {
   ResourceMark rm;

@@ -1885,11 +2005,10 @@
   if (is_compiled_by_c1()) {
     tty->print("(c1) ");
   } else if (is_compiled_by_c2()) {
     tty->print("(c2) ");
   } else {
-    assert(is_native_method(), "Who else?");
     tty->print("(nm) ");
   }
 
   print_on(tty, "nmethod");
   tty->cr();

@@ -1949,10 +2068,18 @@
                                               oops_begin(),
                                               oops_end(),
                                               oops_size());
 }
 
+void nmethod::print_code() {
+  HandleMark hm;
+  ResourceMark m;
+  Disassembler::decode(this);
+}
+
+
+#ifndef PRODUCT
 
 void nmethod::print_scopes() {
   // Find the first pc desc for all scopes in the code and print it.
   ResourceMark rm;
   for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) {

@@ -1980,17 +2107,10 @@
     deps.log_dependency();  // put it into the xml log also
   }
 }
 
 
-void nmethod::print_code() {
-  HandleMark hm;
-  ResourceMark m;
-  Disassembler().decode(this);
-}
-
-
 void nmethod::print_relocations() {
   ResourceMark m;       // in case methods get printed via the debugger
   tty->print_cr("relocations:");
   RelocIterator iter(this);
   iter.print();

@@ -2022,10 +2142,11 @@
   for (PcDesc* p = scopes_pcs_begin(); p < scopes_pcs_end(); p++) {
     p->print(this);
   }
 }
 
+#endif // PRODUCT
 
 const char* nmethod::reloc_string_for(u_char* begin, u_char* end) {
   RelocIterator iter(this, begin, end);
   bool have_one = false;
   while (iter.next()) {

@@ -2056,11 +2177,10 @@
     }
   }
   return have_one ? "other" : NULL;
 }
 
-
 // Return a the last scope in (begin..end]
 ScopeDesc* nmethod::scope_desc_in(address begin, address end) {
   PcDesc* p = pc_desc_near(begin+1);
   if (p != NULL && p->real_pc(this) <= end) {
     return new ScopeDesc(this, p->scope_decode_offset(),

@@ -2079,33 +2199,30 @@
     for (int i = 0, imax = oms->size(); i < imax; i++) {
       OopMap* om = oms->at(i);
       address pc = base + om->offset();
       if (pc > begin) {
         if (pc <= end) {
-          st->fill_to(column);
-          if (st == tty) {
-            st->print("; OopMap ");
-            om->print();
-            tty->cr();
-          } else {
-            st->print_cr("; OopMap #%d offset:%d", i, om->offset());
-          }
+          st->move_to(column);
+          st->print("; ");
+          om->print_on(st);
         }
         break;
       }
     }
   }
+
+  // Print any debug info present at this pc.
   ScopeDesc* sd  = scope_desc_in(begin, end);  
   if (sd != NULL) {
-    st->fill_to(column);
+    st->move_to(column);
     if (sd->bci() == SynchronizationEntryBCI) {
       st->print(";*synchronization entry");
     } else {
       if (sd->method().is_null()) {
-        tty->print("method is NULL");
+        st->print("method is NULL");
       } else if (sd->method()->is_native()) {
-        tty->print("method is native");
+        st->print("method is native");
       } else {
         address bcp  = sd->method()->bcp_from(sd->bci());
         Bytecodes::Code bc = Bytecodes::java_code_at(bcp);
         st->print(";*%s", Bytecodes::name(bc));
         switch (bc) {

@@ -2138,17 +2255,17 @@
               st->print("<UNKNOWN>");
           }
         }
       }
     }
-    st->cr();
+
     // Print all scopes
     for (;sd != NULL; sd = sd->sender()) {
-      st->fill_to(column);
+      st->move_to(column);
       st->print("; -");
       if (sd->method().is_null()) {
-        tty->print("method is NULL");
+        st->print("method is NULL");
       } else {
         sd->method()->print_short_name(st);
       }
       int lineno = sd->method()->line_number_from_bci(sd->bci());
       if (lineno != -1) {

@@ -2162,21 +2279,23 @@
 
   // Print relocation information
   const char* str = reloc_string_for(begin, end);
   if (str != NULL) {
     if (sd != NULL) st->cr();
-    st->fill_to(column);
+    st->move_to(column);
     st->print(";   {%s}", str);
   }
   int cont_offset = ImplicitExceptionTable(this).at(begin - instructions_begin());
   if (cont_offset != 0) {
-    st->fill_to(column);
+    st->move_to(column);
     st->print("; implicit exception: dispatches to " INTPTR_FORMAT, instructions_begin() + cont_offset);
   }
 
 }
 
+#ifndef PRODUCT
+
 void nmethod::print_value_on(outputStream* st) const {
   print_on(st, "nmethod");
 }
 
 void nmethod::print_calls(outputStream* st) {