LCOV - code coverage report
Current view: top level - vm - initialize.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 43 54 79.6 %
Date: 2015-06-10 18:10:59 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /* src/vm/initialize.cpp - static class initializer functions
       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 <string.h>
      29             : 
      30             : #include "vm/types.hpp"
      31             : 
      32             : #include "threads/thread.hpp"
      33             : #include "threads/atomic.hpp"           // for write_memory_barrier
      34             : #include "threads/lock.hpp"
      35             : 
      36             : #include "toolbox/logging.hpp"
      37             : 
      38             : #include "vm/jit/builtin.hpp"
      39             : #include "vm/class.hpp"
      40             : #include "vm/exceptions.hpp"
      41             : #include "vm/global.hpp"
      42             : #include "vm/globals.hpp"
      43             : #include "vm/initialize.hpp"
      44             : #include "vm/loader.hpp"
      45             : #include "vm/options.hpp"
      46             : #include "vm/vm.hpp"
      47             : #include "vm/statistics.hpp"
      48             : 
      49             : 
      50             : STAT_REGISTER_VAR(int,count_class_inits,0,"class inits","Number of class inits")
      51             : 
      52             : /* private functions **********************************************************/
      53             : 
      54             : static bool initialize_class_intern(classinfo *c);
      55             : 
      56             : 
      57             : /* initialize_init *************************************************************
      58             : 
      59             :    Initialize important system classes.
      60             : 
      61             : *******************************************************************************/
      62             : 
      63         163 : void initialize_init(void)
      64             : {
      65         163 :         TRACESUBSYSTEMINITIALIZATION("initialize_init");
      66             : 
      67             : #if defined(ENABLE_JAVASE)
      68             : # if defined(WITH_JAVA_RUNTIME_LIBRARY_GNU_CLASSPATH)
      69             : 
      70             :         /* Nothing. */
      71             : 
      72             : # elif defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
      73             : 
      74             :         if (!initialize_class(class_java_lang_String))
      75             :                 vm_abort("initialize_init: Initialization failed: java.lang.String");
      76             : 
      77             :         if (!initialize_class(class_java_lang_System))
      78             :                 vm_abort("initialize_init: Initialization failed: java.lang.System");
      79             : 
      80             :         if (!initialize_class(class_java_lang_ThreadGroup))
      81             :                 vm_abort("initialize_init: Initialization failed: java.lang.ThreadGroup");
      82             : 
      83             :         if (!initialize_class(class_java_lang_Thread))
      84             :                 vm_abort("initialize_init: Initialization failed: java.lang.Thread");
      85             : 
      86             :         if (!initialize_class(class_java_lang_Class))
      87             :                 vm_abort("initialize_init: Initialization failed: java.lang.Class");
      88             : 
      89             : # else
      90             : #  error unknown classpath configuration
      91             : # endif
      92             : 
      93             : #elif defined(ENABLE_JAVAME_CLDC1_1)
      94             : 
      95             :         /* Nothing. */
      96             : 
      97             : #else
      98             : # error unknown Java configuration
      99             : #endif
     100         163 : }
     101             : 
     102             : /* initialize_class ************************************************************
     103             : 
     104             :    In Java, every class can have a static initialization
     105             :    function. This function has to be called BEFORE calling other
     106             :    methods or accessing static variables.
     107             : 
     108             : *******************************************************************************/
     109             : 
     110      105526 : bool initialize_class(classinfo *c)
     111             : {
     112             :         bool r;
     113             : 
     114      105526 :         if (!makeinitializations)
     115           0 :                 return true;
     116             : 
     117      105526 :         LOCK_MONITOR_ENTER(c);
     118             : 
     119             :         /* maybe the class is already initalized or the current thread, which can
     120             :            pass the monitor, is currently initalizing this class */
     121             : 
     122      105526 :         if (class_is_or_almost_initialized(c)) {
     123       79508 :                 LOCK_MONITOR_EXIT(c);
     124             : 
     125       79508 :                 return true;
     126             :         }
     127             : 
     128             :         /* if <clinit> throw an Error before, the class was marked with an
     129             :        error and we have to throw a NoClassDefFoundError */
     130             : 
     131       26018 :         if (c->state & CLASS_ERROR) {
     132           0 :                 exceptions_throw_noclassdeffounderror(c->name);
     133             : 
     134           0 :                 LOCK_MONITOR_EXIT(c);
     135             : 
     136             :                 /* ...but return true, this is ok (mauve test) */
     137             : 
     138           0 :                 return true;
     139             :         }
     140             : 
     141             :         /* this initalizing run begins NOW */
     142             : 
     143       26018 :         c->initializing_thread = thread_get_current();
     144       26018 :         c->state |= CLASS_INITIALIZING;
     145             : 
     146             :         /* call the internal function */
     147             : 
     148       26018 :         r = initialize_class_intern(c);
     149             : 
     150             :         /* if return value is not NULL everything was ok and the class is
     151             :            initialized */
     152             : 
     153       26018 :         if (r) {
     154             :         // Let's make sure that everything is flushed out to memory before
     155             :         // marking the class as initialized.
     156       26015 :         Atomic::write_memory_barrier();
     157             : 
     158       26015 :         c->state |= CLASS_INITIALIZED;
     159             :     }
     160             : 
     161             :         /* this initalizing run is done */
     162             : 
     163       26018 :         c->state &= ~CLASS_INITIALIZING;
     164             : 
     165       26018 :         LOCK_MONITOR_EXIT(c);
     166             : 
     167       26018 :         return r;
     168             : }
     169             : 
     170             : 
     171             : /* initialize_class_intern *****************************************************
     172             : 
     173             :    This function MUST NOT be called directly, because of thread
     174             :    <clinit> race conditions.
     175             : 
     176             : *******************************************************************************/
     177             : 
     178       26018 : static bool initialize_class_intern(classinfo *c)
     179             : {
     180             :         methodinfo    *m;
     181             :         java_handle_t *cause;
     182             :         classinfo     *clazz;
     183             : 
     184             :         /* maybe the class is not already linked */
     185             : 
     186       26018 :         if (!(c->state & CLASS_LINKED))
     187          26 :                 if (!link_class(c))
     188           0 :                         return false;
     189             : 
     190             :         STATISTICS(count_class_inits++);
     191             : 
     192             :         /* Initialize super class. */
     193             : 
     194       26018 :         if (c->super != NULL) {
     195       25855 :                 if (!(c->super->state & CLASS_INITIALIZED)) {
     196             : #if !defined(NDEBUG)
     197        5772 :                         if (initverbose)
     198             :                                 log_message_class_message_class("Initialize super class ",
     199             :                                                                                                 c->super,
     200             :                                                                                                 " from ",
     201           0 :                                                                                                 c);
     202             : #endif
     203             : 
     204        5772 :                         if (!initialize_class(c->super))
     205           0 :                                 return false;
     206             :                 }
     207             :         }
     208             : 
     209             :         /* interfaces implemented need not to be initialized (VM Spec 2.17.4) */
     210             : 
     211       26018 :         m = class_findmethod(c, utf8::clinit, utf8::void__void);
     212             : 
     213       26018 :         if (m == NULL) {
     214             : #if !defined(NDEBUG)
     215       18589 :                 if (initverbose)
     216           0 :                         log_message_class("Class has no static class initializer: ", c);
     217             : #endif
     218             : 
     219       18589 :                 return true;
     220             :         }
     221             : 
     222             :         /* Sun's and IBM's JVM don't care about the static flag */
     223             : /*      if (!(m->flags & ACC_STATIC)) { */
     224             : /*              log_text("Class initializer is not static!"); */
     225             : 
     226             : #if !defined(NDEBUG)
     227        7429 :         if (initverbose)
     228           0 :                 log_message_class("Starting static class initializer for class: ", c);
     229             : #endif
     230             : 
     231             :         /* now call the initializer */
     232             : 
     233        7429 :         (void) vm_call_method(m, NULL);
     234             : 
     235             :         /* we have an exception or error */
     236             : 
     237        7429 :         cause = exceptions_get_exception();
     238             : 
     239        7429 :         if (cause != NULL) {
     240             :                 /* class is NOT initialized and is marked with error */
     241             : 
     242           3 :                 c->state |= CLASS_ERROR;
     243             : 
     244             :                 /* Load java/lang/Exception for the instanceof check. */
     245             : 
     246           3 :                 clazz = load_class_bootstrap(utf8::java_lang_Exception);
     247             : 
     248           3 :                 if (clazz == NULL)
     249           0 :                         return false;
     250             : 
     251             :                 /* Is this an exception?  Yes, than wrap it. */
     252             : 
     253           3 :                 if (builtin_instanceof(cause, clazz)) {
     254             :                         /* clear exception, because we are calling jit code again */
     255             : 
     256           3 :                         exceptions_clear_exception();
     257             : 
     258             :                         /* wrap the exception */
     259             : 
     260           3 :                         exceptions_throw_exceptionininitializererror(cause);
     261             :                 }
     262             : 
     263           3 :                 return false;
     264             :         }
     265             : 
     266             : #if !defined(NDEBUG)
     267        7426 :         if (initverbose)
     268           0 :                 log_message_class("Finished static class initializer for class: ", c);
     269             : #endif
     270             : 
     271        7426 :         return true;
     272             : }
     273             : 
     274             : 
     275             : /*
     276             :  * These are local overrides for various environment variables in Emacs.
     277             :  * Please do not remove this and leave it at the end of the file, where
     278             :  * Emacs will automagically detect them.
     279             :  * ---------------------------------------------------------------------
     280             :  * Local variables:
     281             :  * mode: c++
     282             :  * indent-tabs-mode: t
     283             :  * c-basic-offset: 4
     284             :  * tab-width: 4
     285             :  * End:
     286             :  * vim:noexpandtab:sw=4:ts=4:
     287             :  */

Generated by: LCOV version 1.11