1 /*
   2  * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "precompiled.hpp"
  26 #include "asm/macroAssembler.hpp"
  27 #include "asm/macroAssembler.inline.hpp"
  28 #include "code/codeCache.hpp"
  29 #include "compiler/disassembler.hpp"
  30 #include "oops/oop.inline.hpp"
  31 #include "prims/forte.hpp"
  32 #include "runtime/stubCodeGenerator.hpp"
  33 
  34 
  35 // Implementation of StubCodeDesc
  36 
  37 StubCodeDesc* StubCodeDesc::_list = NULL;
  38 int           StubCodeDesc::_count = 0;
  39 
  40 
  41 StubCodeDesc* StubCodeDesc::desc_for(address pc) {
  42   StubCodeDesc* p = _list;
  43   while (p != NULL && !p->contains(pc)) p = p->_next;
  44   // p == NULL || p->contains(pc)
  45   return p;
  46 }
  47 
  48 
  49 StubCodeDesc* StubCodeDesc::desc_for_index(int index) {
  50   StubCodeDesc* p = _list;
  51   while (p != NULL && p->index() != index) p = p->_next;
  52   return p;
  53 }
  54 
  55 
  56 const char* StubCodeDesc::name_for(address pc) {
  57   StubCodeDesc* p = desc_for(pc);
  58   return p == NULL ? NULL : p->name();
  59 }
  60 
  61 
  62 void StubCodeDesc::print_on(outputStream* st) const {
  63   st->print("%s", group());
  64   st->print("::");
  65   st->print("%s", name());
  66   st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT "[ (%d bytes)", p2i(begin()), p2i(end()), size_in_bytes());
  67 }
  68 
  69 // Implementation of StubCodeGenerator
  70 
  71 StubCodeGenerator::StubCodeGenerator(CodeBuffer* code, bool print_code) {
  72   _masm = new MacroAssembler(code);
  73   _first_stub = _last_stub = NULL;
  74   _print_code = print_code;
  75 }
  76 
  77 extern "C" {
  78   static int compare_cdesc(const void* void_a, const void* void_b) {
  79     int ai = (*((StubCodeDesc**) void_a))->index();
  80     int bi = (*((StubCodeDesc**) void_b))->index();
  81     return ai - bi;
  82   }
  83 }
  84 
  85 StubCodeGenerator::~StubCodeGenerator() {
  86   if (PrintStubCode || _print_code) {
  87     CodeBuffer* cbuf = _masm->code();
  88     CodeBlob*   blob = CodeCache::find_blob_unsafe(cbuf->insts()->start());
  89     if (blob != NULL) {
  90       blob->set_strings(cbuf->strings());
  91     }
  92     bool saw_first = false;
  93     StubCodeDesc* toprint[1000];
  94     int toprint_len = 0;
  95     for (StubCodeDesc* cdesc = _last_stub; cdesc != NULL; cdesc = cdesc->_next) {
  96       toprint[toprint_len++] = cdesc;
  97       if (cdesc == _first_stub) { saw_first = true; break; }
  98     }
  99     assert(toprint_len == 0 || saw_first, "must get both first & last");
 100     // Print in reverse order:
 101     qsort(toprint, toprint_len, sizeof(toprint[0]), compare_cdesc);
 102     for (int i = 0; i < toprint_len; i++) {
 103       StubCodeDesc* cdesc = toprint[i];
 104       cdesc->print();
 105       tty->cr();
 106       Disassembler::decode(cdesc->begin(), cdesc->end());
 107       tty->cr();
 108     }
 109   }
 110 }
 111 
 112 
 113 void StubCodeGenerator::stub_prolog(StubCodeDesc* cdesc) {
 114   // default implementation - do nothing
 115 }
 116 
 117 
 118 void StubCodeGenerator::stub_epilog(StubCodeDesc* cdesc) {
 119   // default implementation - record the cdesc
 120   if (_first_stub == NULL)  _first_stub = cdesc;
 121   _last_stub = cdesc;
 122 }
 123 
 124 
 125 // Implementation of CodeMark
 126 
 127 StubCodeMark::StubCodeMark(StubCodeGenerator* cgen, const char* group, const char* name) {
 128   _cgen  = cgen;
 129   _cdesc = new StubCodeDesc(group, name, _cgen->assembler()->pc());
 130   _cgen->stub_prolog(_cdesc);
 131   // define the stub's beginning (= entry point) to be after the prolog:
 132   _cdesc->set_begin(_cgen->assembler()->pc());
 133 }
 134 
 135 StubCodeMark::~StubCodeMark() {
 136   _cgen->assembler()->flush();
 137   _cdesc->set_end(_cgen->assembler()->pc());
 138   assert(StubCodeDesc::_list == _cdesc, "expected order on list");
 139   _cgen->stub_epilog(_cdesc);
 140   Forte::register_stub(_cdesc->name(), _cdesc->begin(), _cdesc->end());
 141 
 142   if (JvmtiExport::should_post_dynamic_code_generated()) {
 143     JvmtiExport::post_dynamic_code_generated(_cdesc->name(), _cdesc->begin(), _cdesc->end());
 144   }
 145 }