LCOV - code coverage report
Current view: top level - vm/jit/optimizing - recompiler.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 9 53 17.0 %
Date: 2017-07-14 10:03:36 Functions: 2 7 28.6 %

          Line data    Source code
       1             : /* src/vm/jit/optimizing/recompiler.cpp - recompilation system
       2             : 
       3             :    Copyright (C) 1996-2013
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             : 
       6             :    This file is part of CACAO.
       7             : 
       8             :    This program is free software; you can redistribute it and/or
       9             :    modify it under the terms of the GNU General Public License as
      10             :    published by the Free Software Foundation; either version 2, or (at
      11             :    your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful, but
      14             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :    General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program; if not, write to the Free Software
      20             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      21             :    02110-1301, USA.
      22             : 
      23             : */
      24             : 
      25             : 
      26             : #include "config.h"
      27             : 
      28             : #include <assert.h>
      29             : 
      30             : #include "threads/condition.hpp"
      31             : #include "threads/mutex.hpp"
      32             : #include "threads/thread.hpp"
      33             : 
      34             : #include "vm/classcache.hpp"
      35             : #include "vm/exceptions.hpp"
      36             : #include "vm/options.hpp"
      37             : 
      38             : #include "vm/jit/builtin.hpp"
      39             : #include "vm/jit/code.hpp"
      40             : #include "vm/jit/jit.hpp"
      41             : 
      42             : #include "vm/jit/optimizing/recompiler.hpp"
      43             : 
      44             : 
      45             : /**
      46             :  * Stop the worker thread.
      47             :  */
      48           0 : Recompiler::~Recompiler()
      49             : {
      50             :         // Set the running flag to false.
      51           0 :         _run = false;
      52             : 
      53             :         // Now signal the worker thread.
      54           0 :         _cond.signal();
      55             : 
      56             :         // TODO We should wait here until the thread exits.
      57           0 : }
      58             : 
      59             : 
      60             : /* recompile_replace_vftbl *****************************************************
      61             : 
      62             :    XXX
      63             : 
      64             : *******************************************************************************/
      65             : 
      66           0 : static void recompile_replace_vftbl(methodinfo *m)
      67             : {
      68             :         codeinfo               *code;
      69             :         codeinfo               *pcode;
      70             :         u4                      slot;
      71             :         classcache_name_entry  *nmen;
      72             :         classcache_class_entry *clsen;
      73             :         classinfo              *c;
      74             :         vftbl_t                *vftbl;
      75             :         s4                      i;
      76             : 
      77             :         /* get current and previous codeinfo structure */
      78             : 
      79           0 :         code  = m->code;
      80           0 :         pcode = code->prev;
      81             : 
      82           0 :         assert(pcode);
      83             : 
      84             :         /* iterate over all classes */
      85             : 
      86           0 :         for (slot = 0; slot < hashtable_classcache.size; slot++) {
      87           0 :                 nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
      88             : 
      89           0 :                 for (; nmen; nmen = nmen->hashlink) {
      90             :                         /* iterate over all class entries */
      91             : 
      92           0 :                         for (clsen = nmen->classes; clsen; clsen = clsen->next) {
      93           0 :                                 c = clsen->classobj;
      94             : 
      95           0 :                                 if (c == NULL)
      96           0 :                                         continue;
      97             : 
      98             :                                 /* Search for entrypoint of the previous codeinfo in
      99             :                                    the vftbl and replace it with the current one. */
     100             : 
     101           0 :                                 vftbl = c->vftbl;
     102             : 
     103             :                                 /* Is the class linked? Means, is the vftbl finished? */
     104             : 
     105           0 :                                 if (!(c->state & CLASS_LINKED))
     106           0 :                                         continue;
     107             : 
     108             :                                 /* Does the class have a vftbl? Some internal classes
     109             :                                    (e.g. $NEW$) are linked, but do not have a
     110             :                                    vftbl. */
     111             : 
     112           0 :                                 if (vftbl == NULL)
     113           0 :                                         continue;
     114             : 
     115           0 :                                 for (i = 0; i < vftbl->vftbllength; i++) {
     116           0 :                                         if (vftbl->table[i] == pcode->entrypoint) {
     117             : #if !defined(NDEBUG)
     118           0 :                                                 printf("replacing vftbl in: ");
     119           0 :                                                 class_println(c);
     120             : #endif
     121           0 :                                                 vftbl->table[i] = code->entrypoint;
     122             :                                         }
     123             :                                 }
     124             :                         }
     125             :                 }
     126             :         }
     127           0 : }
     128             : 
     129             : 
     130             : /**
     131             :  * The actual recompilation thread.
     132             :  */
     133         163 : void Recompiler::thread()
     134             : {
     135             :         // FIXME This just works for one recompiler.
     136         163 :         Recompiler& r = VM::get_current()->get_recompiler();
     137             : 
     138         326 :         while (r._run == true) {
     139             :                 // Enter the recompile mutex, so we can call wait.
     140         163 :                 r._mutex.lock();
     141             : 
     142             :                 // Wait forever on that condition until we are signaled.
     143         163 :                 r._cond.wait(r._mutex);
     144             : 
     145             :                 // Leave the mutex.
     146           0 :                 r._mutex.unlock();
     147             : 
     148             :                 // FIXME Move this into the for loop.
     149           0 :                 if (r._run == false)
     150           0 :                         break;
     151             : 
     152             :                 // Get the next method form the queue and recompile it.
     153           0 :                 while (r._methods.empty() == false) {
     154           0 :                         methodinfo* m = r._methods.front();
     155             : 
     156             :                         // Recompile this method.
     157           0 :                         if (jit_recompile(m) != NULL) {
     158             :                                 // Replace in vftbl's.
     159           0 :                                 recompile_replace_vftbl(m);
     160             :                         }
     161             :                         else {
     162             :                                 // XXX What is the right-thing(tm) to do here?
     163           0 :                                 exceptions_print_current_exception();
     164             :                         }
     165             : 
     166             :                         // Remove the method from the queue.
     167           0 :                         r._methods.pop();
     168             :                 }
     169             :         }
     170           0 : }
     171             : 
     172             : 
     173             : /**
     174             :  * Start the recompilation thread.
     175             :  *
     176             :  * @return true on success, false otherwise.
     177             :  */
     178         163 : bool Recompiler::start()
     179             : {
     180         163 :         Utf8String name = Utf8String::from_utf8("Recompiler");
     181             : 
     182         163 :         if (!threads_thread_start_internal(name, (functionptr) &Recompiler::thread))
     183           0 :                 return false;
     184             : 
     185         163 :         return true;
     186             : }
     187             : 
     188             : 
     189             : /**
     190             :  * Add a method to the recompilation queue and signal the
     191             :  * recompilation thread that there is some work to do.
     192             :  *
     193             :  * @param m Method to recompile.
     194             :  */
     195           0 : void Recompiler::queue_method(methodinfo *m)
     196             : {
     197             :         // Add the method to the queue.
     198           0 :         _methods.push(m);
     199             : 
     200             :         // Enter the recompile mutex, so we can call notify.
     201           0 :         _mutex.lock();
     202             : 
     203             :         // Signal the recompiler thread.
     204           0 :         _cond.signal();
     205             : 
     206             :         // Leave the mutex.
     207           0 :         _mutex.unlock();
     208           0 : }
     209             : 
     210             : 
     211             : 
     212             : // Legacy C interface.
     213           0 : void Recompiler_queue_method(methodinfo* m) { VM::get_current()->get_recompiler().queue_method(m); }
     214             : 
     215             : /*
     216             :  * These are local overrides for various environment variables in Emacs.
     217             :  * Please do not remove this and leave it at the end of the file, where
     218             :  * Emacs will automagically detect them.
     219             :  * ---------------------------------------------------------------------
     220             :  * Local variables:
     221             :  * mode: c++
     222             :  * indent-tabs-mode: t
     223             :  * c-basic-offset: 4
     224             :  * tab-width: 4
     225             :  * End:
     226             :  * vim:noexpandtab:sw=4:ts=4:
     227             :  */

Generated by: LCOV version 1.11