* src/vm/global.h (jni_callblock): Removed.
[cacao.git] / src / cacao / cacao.c
1 /* src/cacao/cacao.c - contains main() of cacao
2
3    Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    Contact: cacao@cacaojvm.org
26
27    Authors: Reinhard Grafl
28
29    Changes: Andi Krall
30             Mark Probst
31             Philipp Tomsich
32             Christian Thalinger
33
34    $Id: cacao.c 4552 2006-03-04 17:15:44Z twisti $
35
36 */
37
38
39 #include "config.h"
40
41 #include <assert.h>
42 #include <stdlib.h>
43 #include <string.h>
44
45 #include "vm/types.h"
46
47 #include "mm/boehm.h"
48 #include "mm/memory.h"
49 #include "native/jni.h"
50 #include "native/include/java_lang_String.h"
51
52 #if defined(ENABLE_JVMTI)
53 #include "native/jvmti/jvmti.h"
54 #include "native/jvmti/dbg.h"
55 #include <sys/types.h>
56 #include <signal.h>
57 #include <sys/wait.h>
58 #endif
59
60 #include "toolbox/logging.h"
61 #include "vm/classcache.h"
62 #include "vm/exceptions.h"
63 #include "vm/global.h"
64 #include "vm/loader.h"
65 #include "vm/options.h"
66 #include "vm/statistics.h"
67 #include "vm/stringlocal.h"
68 #include "vm/suck.h"
69 #include "vm/vm.h"
70 #include "vm/jit/asmpart.h"
71 #include "vm/jit/jit.h"
72
73 #ifdef TYPEINFO_DEBUG_TEST
74 #include "vm/jit/verify/typeinfo.h"
75 #endif
76
77
78 #ifdef TYPECHECK_STATISTICS
79 void typecheck_print_statistics(FILE *file);
80 #endif
81
82 /* setup_debugger_process *****************************************************
83
84    Helper function to start JDWP threads
85
86 *******************************************************************************/
87 #if defined(ENABLE_JVMTI)
88
89 static void setup_debugger_process(char* transport) {
90         java_objectheader *o;
91         methodinfo *m;
92         java_lang_String  *s;
93
94         /* new gnu.classpath.jdwp.Jdwp() */
95         mainclass = 
96                 load_class_from_sysloader(utf_new_char("gnu.classpath.jdwp.Jdwp"));
97         if (!mainclass)
98                 throw_main_exception_exit();
99
100         o = builtin_new(mainclass);
101
102         if (!o)
103                 throw_main_exception_exit();
104         
105         m = class_resolveclassmethod(mainclass,
106                                                                  utf_init, 
107                                                                  utf_java_lang_String__void,
108                                                                  class_java_lang_Object,
109                                                                  true);
110         if (!m)
111                 throw_main_exception_exit();
112
113         (void) vm_call_method_intern(m, o, NULL, NULL, NULL);
114
115         /* configure(transport,NULL) */
116         m = class_resolveclassmethod(
117                 mainclass, utf_new_char("configure"), 
118                 utf_new_char("(Ljava/lang/String;Ljava/lang/Thread;)V"),
119                 class_java_lang_Object,
120                 false);
121
122
123         s = javastring_new_char(transport);
124
125         (void) vm_call_method_intern(m, o, s, NULL, NULL);
126
127         if (!m)
128                 throw_main_exception_exit();
129
130         /* _doInitialization */
131         m = class_resolveclassmethod(mainclass,
132                                                                  utf_new_char("_doInitialization"), 
133                                                                  utf_new_char("()V"),
134                                                                  mainclass,
135                                                                  false);
136         
137         if (!m)
138                 throw_main_exception_exit();
139
140         (void) vm_call_method_intern(m, o, NULL, NULL, NULL);
141 }
142 #endif
143
144
145 /* getmainclassfromjar *********************************************************
146
147    Gets the name of the main class form a JAR's manifest file.
148
149 *******************************************************************************/
150
151 static char *getmainclassnamefromjar(char *mainstring)
152 {
153         classinfo         *c;
154         java_objectheader *o;
155         methodinfo        *m;
156         java_lang_String  *s;
157
158         c = load_class_from_sysloader(utf_new_char("java/util/jar/JarFile"));
159
160         if (!c)
161                 throw_main_exception_exit();
162         
163         /* create JarFile object */
164
165         o = builtin_new(c);
166
167         if (!o)
168                 throw_main_exception_exit();
169
170
171         m = class_resolveclassmethod(c,
172                                                                  utf_init, 
173                                                                  utf_java_lang_String__void,
174                                                                  class_java_lang_Object,
175                                                                  true);
176
177         if (!m)
178                 throw_main_exception_exit();
179
180         s = javastring_new_char(mainstring);
181
182         (void) vm_call_method_intern(m, o, s, NULL, NULL);
183
184         if (*exceptionptr)
185                 throw_main_exception_exit();
186
187         /* get manifest object */
188
189         m = class_resolveclassmethod(c,
190                                                                  utf_new_char("getManifest"), 
191                                                                  utf_new_char("()Ljava/util/jar/Manifest;"),
192                                                                  class_java_lang_Object,
193                                                                  true);
194
195         if (!m)
196                 throw_main_exception_exit();
197
198         o = vm_call_method_intern(m, o, NULL, NULL, NULL);
199
200         if (o == NULL) {
201                 fprintf(stderr, "Could not get manifest from %s (invalid or corrupt jarfile?)\n", mainstring);
202                 vm_exit(1);
203         }
204
205
206         /* get Main Attributes */
207
208         m = class_resolveclassmethod(o->vftbl->class,
209                                                                  utf_new_char("getMainAttributes"), 
210                                                                  utf_new_char("()Ljava/util/jar/Attributes;"),
211                                                                  class_java_lang_Object,
212                                                                  true);
213
214         if (!m)
215                 throw_main_exception_exit();
216
217         o = vm_call_method_intern(m, o, NULL, NULL, NULL);
218
219         if (o == NULL) {
220                 fprintf(stderr, "Could not get main attributes from %s (invalid or corrupt jarfile?)\n", mainstring);
221                 vm_exit(1);
222         }
223
224
225         /* get property Main-Class */
226
227         m = class_resolveclassmethod(o->vftbl->class,
228                                                                  utf_new_char("getValue"), 
229                                                                  utf_new_char("(Ljava/lang/String;)Ljava/lang/String;"),
230                                                                  class_java_lang_Object,
231                                                                  true);
232
233         if (!m)
234                 throw_main_exception_exit();
235
236         s = javastring_new_char("Main-Class");
237
238         o = vm_call_method_intern(m, o, s, NULL, NULL);
239
240         if (!o)
241                 throw_main_exception_exit();
242
243         return javastring_tochar(o);
244 }
245
246
247 void exit_handler(void);
248
249
250 /* main ************************************************************************
251
252    The main program.
253    
254 *******************************************************************************/
255
256 int main(int argc, char **argv)
257 {
258         void *dummy;
259         s4 i;
260         
261         /* local variables ********************************************************/
262
263         JavaVMInitArgs *vm_args;
264         JavaVM         *jvm;                /* denotes a Java VM                  */
265
266 #if defined(ENABLE_JVMTI)
267         bool dbg = false;
268         char *transport;
269         int waitval;
270 #endif
271
272 #if defined(USE_THREADS) && !defined(NATIVE_THREADS)
273         stackbottom = &dummy;
274 #endif
275         
276         if (atexit(vm_exit_handler))
277                 throw_cacao_exception_exit(string_java_lang_InternalError,
278                                                                    "Unable to register exit_handler");
279
280
281         /**************************** Program start *****************************/
282
283         if (opt_verbose)
284                 log_text("CACAO started -------------------------------------------------------");
285
286         /* prepare the options */
287
288         vm_args = options_prepare(argc, argv);
289         
290         /* load and initialize a Java VM, return a JNI interface pointer in env */
291
292         JNI_CreateJavaVM(&jvm, (void **) &_Jv_env, vm_args);
293
294 #if defined(ENABLE_JVMTI)
295         set_jvmti_phase(JVMTI_PHASE_START);
296 #endif
297
298         /* do we have a main class? */
299
300         if (mainstring == NULL)
301                 usage();
302
303
304         /* start worker routines **************************************************/
305
306         if (opt_run == true) {
307                 utf              *mainutf;
308                 classinfo        *mainclass;
309                 methodinfo       *m;
310                 java_objectarray *oa; 
311                 s4                oalength;
312                 java_lang_String *s;
313                 s4                status;
314
315                 /* set return value to OK */
316
317                 status = 0;
318
319                 if (opt_jar == true) {
320                         /* open jar file with java.util.jar.JarFile */
321                         mainstring = getmainclassnamefromjar(mainstring);
322                 }
323
324                 /* load the main class */
325
326                 mainutf = utf_new_char(mainstring);
327
328                 if (!(mainclass = load_class_from_sysloader(mainutf)))
329                         throw_main_exception_exit();
330
331                 /* error loading class, clear exceptionptr for new exception */
332
333                 if (*exceptionptr || !mainclass) {
334 /*                      *exceptionptr = NULL; */
335
336 /*                      *exceptionptr = */
337 /*                              new_exception_message(string_java_lang_NoClassDefFoundError, */
338 /*                                                                        mainstring); */
339                         throw_main_exception_exit();
340                 }
341
342                 if (!link_class(mainclass))
343                         throw_main_exception_exit();
344                         
345                 /* find the `main' method of the main class */
346
347                 m = class_resolveclassmethod(mainclass,
348                                                                          utf_new_char("main"), 
349                                                                          utf_new_char("([Ljava/lang/String;)V"),
350                                                                          class_java_lang_Object,
351                                                                          false);
352
353                 if (*exceptionptr) {
354                         throw_main_exception_exit();
355                 }
356
357                 /* there is no main method or it isn't static */
358
359                 if (!m || !(m->flags & ACC_STATIC)) {
360                         *exceptionptr = NULL;
361
362                         *exceptionptr =
363                                 new_exception_message(string_java_lang_NoSuchMethodError,
364                                                                           "main");
365                         throw_main_exception_exit();
366                 }
367
368                 /* build argument array */
369
370                 oalength = vm_args->nOptions - opt_index;
371
372                 oa = builtin_anewarray(oalength, class_java_lang_String);
373
374                 for (i = 0; i < oalength; i++) {
375                         s = javastring_new(utf_new_char(vm_args->options[opt_index + i].optionString));
376                         oa->data[i] = (java_objectheader *) s;
377                 }
378
379 #ifdef TYPEINFO_DEBUG_TEST
380                 /* test the typeinfo system */
381                 typeinfo_test();
382 #endif
383                 /*class_showmethods(currentThread->group->header.vftbl->class); */
384
385 #if defined(ENABLE_JVMTI) && defined(NATIVE_THREADS)
386                 if(dbg) {
387                         debuggee = fork();
388                         if (debuggee == (-1)) {
389                                 log_text("fork error");
390                                 exit(1);
391                         } else {
392                                 if (debuggee == 0) {
393                                         /* child: allow helper process to trace us  */
394                                         if (TRACEME != 0)  exit(0);
395                                         
396                                         /* give parent/helper debugger process control */
397                                         kill(0, SIGTRAP);  /* do we need this at this stage ? */
398
399                                         /* continue with normal startup */      
400
401                                 } else {
402
403                                         /* parent/helper debugger process */
404                                         wait(&waitval);
405
406                                         remotedbgjvmtienv = new_jvmtienv();
407                                         /* set eventcallbacks */
408                                         if (JVMTI_ERROR_NONE == 
409                                                 remotedbgjvmtienv->
410                                                 SetEventCallbacks(remotedbgjvmtienv,
411                                                                                   &jvmti_jdwp_EventCallbacks,
412                                                                                   sizeof(jvmti_jdwp_EventCallbacks))){
413                                                 log_text("unable to setup event callbacks");
414                                                 vm_exit(1);
415                                         }
416
417                                         /* setup listening process (JDWP) */
418                                         setup_debugger_process(transport);
419
420                                         /* start to be debugged program */
421                                         CONT(debuggee);
422
423                     /* exit debugger process - todo: cleanup */
424                                         joinAllThreads();
425                                         cacao_exit(0);
426                                 }
427                         }
428                 }
429                 else 
430                         debuggee= -1;
431                 
432 #endif
433                 /* here we go... */
434
435                 (void) vm_call_method_intern(m, oa, NULL, NULL, NULL);
436
437                 /* exception occurred? */
438
439                 if (*exceptionptr) {
440                         throw_main_exception();
441                         status = 1;
442                 }
443
444                 /* unload the JavaVM */
445
446                 vm_destroy(jvm);
447
448                 /* and exit */
449
450                 vm_exit(status);
451         }
452
453         /************* If requested, compile all methods ********************/
454
455         if (compileall) {
456                 classinfo *c;
457                 methodinfo *m;
458                 u4 slot;
459                 s4 i;
460                 classcache_name_entry *nmen;
461                 classcache_class_entry *clsen;
462
463                 /* create all classes found in the bootclasspath */
464                 /* XXX currently only works with zip/jar's */
465
466                 loader_load_all_classes();
467
468                 /* link all classes */
469
470                 for (slot = 0; slot < hashtable_classcache.size; slot++) {
471                         nmen = (classcache_name_entry *) hashtable_classcache.ptr[slot];
472
473                         for (; nmen; nmen = nmen->hashlink) {
474                                 /* iterate over all class entries */
475
476                                 for (clsen = nmen->classes; clsen; clsen = clsen->next) {
477                                         c = clsen->classobj;
478
479                                         if (!c)
480                                                 continue;
481
482                                         if (!(c->state & CLASS_LINKED)) {
483                                                 if (!link_class(c)) {
484                                                         fprintf(stderr, "Error linking: ");
485                                                         utf_fprint_classname(stderr, c->name);
486                                                         fprintf(stderr, "\n");
487
488                                                         /* print out exception and cause */
489
490                                                         exceptions_print_exception(*exceptionptr);
491
492                                                         /* goto next class */
493
494                                                         continue;
495                                                 }
496                                         }
497
498                                         /* compile all class methods */
499
500                                         for (i = 0; i < c->methodscount; i++) {
501                                                 m = &(c->methods[i]);
502
503                                                 if (m->jcode) {
504                                                         if (!jit_compile(m)) {
505                                                                 fprintf(stderr, "Error compiling: ");
506                                                                 utf_fprint_classname(stderr, c->name);
507                                                                 fprintf(stderr, ".");
508                                                                 utf_fprint(stderr, m->name);
509                                                                 utf_fprint(stderr, m->descriptor);
510                                                                 fprintf(stderr, "\n");
511
512                                                                 /* print out exception and cause */
513
514                                                                 exceptions_print_exception(*exceptionptr);
515                                                         }
516                                                 }
517                                         }
518                                 }
519                         }
520                 }
521         }
522
523
524         /******** If requested, compile a specific method ***************/
525
526         if (opt_method != NULL) {
527                 methodinfo *m;
528
529                 /* create, load and link the main class */
530
531                 if (!(mainclass = load_class_bootstrap(utf_new_char(mainstring))))
532                         throw_main_exception_exit();
533
534                 if (!link_class(mainclass))
535                         throw_main_exception_exit();
536
537                 if (opt_signature != NULL) {
538                         m = class_resolveclassmethod(mainclass,
539                                                                                  utf_new_char(opt_method),
540                                                                                  utf_new_char(opt_signature),
541                                                                                  mainclass,
542                                                                                  false);
543                 } else {
544                         m = class_resolveclassmethod(mainclass,
545                                                                                  utf_new_char(opt_method),
546                                                                                  NULL,
547                                                                                  mainclass,
548                                                                                  false);
549                 }
550
551                 if (!m) {
552                         char message[MAXLOGTEXT];
553                         sprintf(message, "%s%s", opt_method,
554                                         opt_signature ? opt_signature : "");
555
556                         *exceptionptr =
557                                 new_exception_message(string_java_lang_NoSuchMethodException,
558                                                                           message);
559                                                                                  
560                         throw_main_exception_exit();
561                 }
562                 
563                 jit_compile(m);
564         }
565
566         vm_shutdown(0);
567
568         /* keep compiler happy */
569
570         return 0;
571 }
572
573
574 /*
575  * These are local overrides for various environment variables in Emacs.
576  * Please do not remove this and leave it at the end of the file, where
577  * Emacs will automagically detect them.
578  * ---------------------------------------------------------------------
579  * Local variables:
580  * mode: c
581  * indent-tabs-mode: t
582  * c-basic-offset: 4
583  * tab-width: 4
584  * End:
585  */