OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [prims.cc] - Blame information for rev 776

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 753 jeremybenn
// prims.cc - Code for core of runtime environment.
2
 
3
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007  Free Software Foundation
4
 
5
   This file is part of libgcj.
6
 
7
This software is copyrighted work licensed under the terms of the
8
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
9
details.  */
10
 
11
#include <config.h>
12
#include <platform.h>
13
 
14
#include <stdlib.h>
15
#include <stdarg.h>
16
#include <stdio.h>
17
#include <string.h>
18
#include <signal.h>
19
 
20
#ifdef HAVE_UNISTD_H
21
#include <unistd.h>
22
#endif
23
 
24
#include <gcj/cni.h>
25
#include <jvm.h>
26
#include <java-signal.h>
27
#include <java-threads.h>
28
#include <java-interp.h>
29
 
30
#ifdef ENABLE_JVMPI
31
#include <jvmpi.h>
32
#include <java/lang/ThreadGroup.h>
33
#endif
34
 
35
#ifdef INTERPRETER
36
#include <jvmti.h>
37
#include "jvmti-int.h"
38
#endif
39
 
40
#ifndef DISABLE_GETENV_PROPERTIES
41
#include <java-props.h>
42
#define PROCESS_GCJ_PROPERTIES process_gcj_properties()
43
#else
44
#define PROCESS_GCJ_PROPERTIES
45
#endif // DISABLE_GETENV_PROPERTIES
46
 
47
#include <java/lang/Class.h>
48
#include <java/lang/ClassLoader.h>
49
#include <java/lang/Runtime.h>
50
#include <java/lang/String.h>
51
#include <java/lang/Thread.h>
52
#include <java/lang/ThreadGroup.h>
53
#include <java/lang/ArrayIndexOutOfBoundsException.h>
54
#include <java/lang/ArithmeticException.h>
55
#include <java/lang/ClassFormatError.h>
56
#include <java/lang/ClassNotFoundException.h>
57
#include <java/lang/InternalError.h>
58
#include <java/lang/NegativeArraySizeException.h>
59
#include <java/lang/NoClassDefFoundError.h>
60
#include <java/lang/NullPointerException.h>
61
#include <java/lang/OutOfMemoryError.h>
62
#include <java/lang/System.h>
63
#include <java/lang/VMClassLoader.h>
64
#include <java/lang/reflect/Modifier.h>
65
#include <java/io/PrintStream.h>
66
#include <java/lang/UnsatisfiedLinkError.h>
67
#include <java/lang/VirtualMachineError.h>
68
#include <gnu/gcj/runtime/ExtensionClassLoader.h>
69
#include <gnu/gcj/runtime/FinalizerThread.h>
70
#include <execution.h>
71
 
72
#ifdef INTERPRETER
73
#include <gnu/classpath/jdwp/Jdwp.h>
74
#include <gnu/classpath/jdwp/VMVirtualMachine.h>
75
#endif // INTERPRETER
76
 
77
#include <gnu/java/lang/MainThread.h>
78
 
79
#ifdef USE_LTDL
80
#include <ltdl.h>
81
#endif
82
 
83
// Execution engine for compiled code.
84
_Jv_CompiledEngine _Jv_soleCompiledEngine;
85
 
86
// Execution engine for code compiled with -findirect-classes
87
_Jv_IndirectCompiledEngine _Jv_soleIndirectCompiledEngine;
88
 
89
// We allocate a single OutOfMemoryError exception which we keep
90
// around for use if we run out of memory.
91
static java::lang::OutOfMemoryError *no_memory;
92
 
93
// Number of bytes in largest array object we create.  This could be
94
// increased to the largest size_t value, so long as the appropriate
95
// functions are changed to take a size_t argument instead of jint.
96
#define MAX_OBJECT_SIZE (((size_t)1<<31) - 1)
97
 
98
// Properties set at compile time.
99
const char **_Jv_Compiler_Properties = NULL;
100
int _Jv_Properties_Count = 0;
101
 
102
#ifndef DISABLE_GETENV_PROPERTIES
103
// Property key/value pairs.
104
property_pair *_Jv_Environment_Properties;
105
#endif
106
 
107
// Stash the argv pointer to benefit native libraries that need it.
108
const char **_Jv_argv;
109
int _Jv_argc;
110
 
111
// Debugging options
112
static bool remoteDebug = false;
113
#ifdef INTERPRETER
114
static char defaultJdwpOptions[] = "";
115
static char *jdwpOptions = defaultJdwpOptions;
116
 
117
// Typedefs for JVMTI agent functions.
118
typedef jint jvmti_agent_onload_func (JavaVM *vm, char *options,
119
                                      void *reserved);
120
typedef jint jvmti_agent_onunload_func (JavaVM *vm);
121
 
122
// JVMTI agent function pointers.
123
static jvmti_agent_onload_func *jvmti_agentonload = NULL;
124
static jvmti_agent_onunload_func *jvmti_agentonunload = NULL;
125
static char *jvmti_agent_opts;
126
#endif // INTERPRETER
127
 
128
// Argument support.
129
int
130
_Jv_GetNbArgs (void)
131
{
132
  // _Jv_argc is 0 if not explicitly initialized.
133
  return _Jv_argc;
134
}
135
 
136
const char *
137
_Jv_GetSafeArg (int index)
138
{
139
  if (index >=0 && index < _Jv_GetNbArgs ())
140
    return _Jv_argv[index];
141
  else
142
    return "";
143
}
144
 
145
void
146
_Jv_SetArgs (int argc, const char **argv)
147
{
148
  _Jv_argc = argc;
149
  _Jv_argv = argv;
150
}
151
 
152
#ifdef ENABLE_JVMPI
153
// Pointer to JVMPI notification functions.
154
void (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (JVMPI_Event *event);
155
void (*_Jv_JVMPI_Notify_THREAD_START) (JVMPI_Event *event);
156
void (*_Jv_JVMPI_Notify_THREAD_END) (JVMPI_Event *event);
157
#endif
158
 
159
 
160
#if defined (HANDLE_SEGV) || defined(HANDLE_FPE)
161
/* Unblock a signal.  Unless we do this, the signal may only be sent
162
   once.  */
163
static void
164
unblock_signal (int signum __attribute__ ((__unused__)))
165
{
166
#ifdef _POSIX_VERSION
167
  sigset_t sigs;
168
 
169
  sigemptyset (&sigs);
170
  sigaddset (&sigs, signum);
171
  sigprocmask (SIG_UNBLOCK, &sigs, NULL);
172
#endif
173
}
174
#endif
175
 
176
#ifdef HANDLE_SEGV
177
SIGNAL_HANDLER (catch_segv)
178
{
179
  unblock_signal (SIGSEGV);
180
  MAKE_THROW_FRAME (nullp);
181
  java::lang::NullPointerException *nullp
182
    = new java::lang::NullPointerException;
183
  throw nullp;
184
}
185
#endif
186
 
187
#ifdef HANDLE_FPE
188
SIGNAL_HANDLER (catch_fpe)
189
{
190
  unblock_signal (SIGFPE);
191
#ifdef HANDLE_DIVIDE_OVERFLOW
192
  HANDLE_DIVIDE_OVERFLOW;
193
#else
194
  MAKE_THROW_FRAME (arithexception);
195
#endif
196
  java::lang::ArithmeticException *arithexception
197
    = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
198
  throw arithexception;
199
}
200
#endif
201
 
202
 
203
jboolean
204
_Jv_equalUtf8Consts (const Utf8Const* a, const Utf8Const *b)
205
{
206
  int len;
207
  const _Jv_ushort *aptr, *bptr;
208
  if (a == b)
209
    return true;
210
  if (a->hash != b->hash)
211
    return false;
212
  len = a->length;
213
  if (b->length != len)
214
    return false;
215
  aptr = (const _Jv_ushort *)a->data;
216
  bptr = (const _Jv_ushort *)b->data;
217
  len = (len + 1) >> 1;
218
  while (--len >= 0)
219
    if (*aptr++ != *bptr++)
220
      return false;
221
  return true;
222
}
223
 
224
/* True iff A is equal to STR.
225
   HASH is STR->hashCode().
226
*/
227
 
228
jboolean
229
_Jv_equal (Utf8Const* a, jstring str, jint hash)
230
{
231
  if (a->hash != (_Jv_ushort) hash)
232
    return false;
233
  jint len = str->length();
234
  jint i = 0;
235
  jchar *sptr = _Jv_GetStringChars (str);
236
  unsigned char* ptr = (unsigned char*) a->data;
237
  unsigned char* limit = ptr + a->length;
238
  for (;; i++, sptr++)
239
    {
240
      int ch = UTF8_GET (ptr, limit);
241
      if (i == len)
242
        return ch < 0;
243
      if (ch != *sptr)
244
        return false;
245
    }
246
  return true;
247
}
248
 
249
/* Like _Jv_equal, but stop after N characters.  */
250
jboolean
251
_Jv_equaln (Utf8Const *a, jstring str, jint n)
252
{
253
  jint len = str->length();
254
  jint i = 0;
255
  jchar *sptr = _Jv_GetStringChars (str);
256
  unsigned char* ptr = (unsigned char*) a->data;
257
  unsigned char* limit = ptr + a->length;
258
  for (; n-- > 0; i++, sptr++)
259
    {
260
      int ch = UTF8_GET (ptr, limit);
261
      if (i == len)
262
        return ch < 0;
263
      if (ch != *sptr)
264
        return false;
265
    }
266
  return true;
267
}
268
 
269
// Determines whether the given Utf8Const object contains
270
// a type which is primitive or some derived form of it, eg.
271
// an array or multi-dimensional array variant.
272
jboolean
273
_Jv_isPrimitiveOrDerived(const Utf8Const *a)
274
{
275
  unsigned char *aptr = (unsigned char *) a->data;
276
  unsigned char *alimit = aptr + a->length;
277
  int ac = UTF8_GET(aptr, alimit);
278
 
279
  // Skips any leading array marks.
280
  while (ac == '[')
281
    ac = UTF8_GET(aptr, alimit);
282
 
283
  // There should not be another character. This implies that
284
  // the type name is only one character long.
285
  if (UTF8_GET(aptr, alimit) == -1)
286
    switch ( ac )
287
      {
288
        case 'Z':
289
        case 'B':
290
        case 'C':
291
        case 'S':
292
        case 'I':
293
        case 'J':
294
        case 'F':
295
        case 'D':
296
          return true;
297
        default:
298
          break;
299
       }
300
 
301
   return false;
302
}
303
 
304
// Find out whether two _Jv_Utf8Const candidates contain the same
305
// classname.
306
// The method is written to handle the different formats of classnames.
307
// Eg. "Ljava/lang/Class;", "Ljava.lang.Class;", "java/lang/Class" and
308
// "java.lang.Class" will be seen as equal.
309
// Warning: This function is not smart enough to declare "Z" and "boolean"
310
// and similar cases as equal (and is not meant to be used this way)!
311
jboolean
312
_Jv_equalUtf8Classnames (const Utf8Const *a, const Utf8Const *b)
313
{
314
  // If the class name's length differs by two characters
315
  // it is possible that we have candidates which are given
316
  // in the two different formats ("Lp1/p2/cn;" vs. "p1/p2/cn")
317
  switch (a->length - b->length)
318
    {
319
      case -2:
320
      case 0:
321
      case 2:
322
        break;
323
      default:
324
        return false;
325
    }
326
 
327
  unsigned char *aptr = (unsigned char *) a->data;
328
  unsigned char *alimit = aptr + a->length;
329
  unsigned char *bptr = (unsigned char *) b->data;
330
  unsigned char *blimit = bptr + b->length;
331
 
332
  if (alimit[-1] == ';')
333
    alimit--;
334
 
335
  if (blimit[-1] == ';')
336
    blimit--;
337
 
338
  int ac = UTF8_GET(aptr, alimit);
339
  int bc = UTF8_GET(bptr, blimit);
340
 
341
  // Checks whether both strings have the same amount of leading [ characters.
342
  while (ac == '[')
343
    {
344
      if (bc == '[')
345
        {
346
          ac = UTF8_GET(aptr, alimit);
347
          bc = UTF8_GET(bptr, blimit);
348
          continue;
349
        }
350
 
351
      return false;
352
    }
353
 
354
  // Skips leading L character.
355
  if (ac == 'L')
356
    ac = UTF8_GET(aptr, alimit);
357
 
358
  if (bc == 'L')
359
    bc = UTF8_GET(bptr, blimit);
360
 
361
  // Compares the remaining characters.
362
  while (ac != -1 && bc != -1)
363
    {
364
      // Replaces package separating dots with slashes.
365
      if (ac == '.')
366
        ac = '/';
367
 
368
      if (bc == '.')
369
        bc = '/';
370
 
371
      // Now classnames differ if there is at least one non-matching
372
      // character.
373
      if (ac != bc)
374
        return false;
375
 
376
      ac = UTF8_GET(aptr, alimit);
377
      bc = UTF8_GET(bptr, blimit);
378
    }
379
 
380
  return (ac == bc);
381
}
382
 
383
/* Count the number of Unicode chars encoded in a given Ut8 string. */
384
int
385
_Jv_strLengthUtf8(const char* str, int len)
386
{
387
  unsigned char* ptr;
388
  unsigned char* limit;
389
  int str_length;
390
 
391
  ptr = (unsigned char*) str;
392
  limit = ptr + len;
393
  str_length = 0;
394
  for (; ptr < limit; str_length++)
395
    {
396
      if (UTF8_GET (ptr, limit) < 0)
397
        return (-1);
398
    }
399
  return (str_length);
400
}
401
 
402
/* Calculate a hash value for a string encoded in Utf8 format.
403
 * This returns the same hash value as specified or java.lang.String.hashCode.
404
 */
405
jint
406
_Jv_hashUtf8String (const char* str, int len)
407
{
408
  unsigned char* ptr = (unsigned char*) str;
409
  unsigned char* limit = ptr + len;
410
  jint hash = 0;
411
 
412
  for (; ptr < limit;)
413
    {
414
      int ch = UTF8_GET (ptr, limit);
415
      /* Updated specification from
416
         http://www.javasoft.com/docs/books/jls/clarify.html. */
417
      hash = (31 * hash) + ch;
418
    }
419
  return hash;
420
}
421
 
422
void
423
_Jv_Utf8Const::init(const char *s, int len)
424
{
425
  ::memcpy (data, s, len);
426
  data[len] = 0;
427
  length = len;
428
  hash = _Jv_hashUtf8String (s, len) & 0xFFFF;
429
}
430
 
431
_Jv_Utf8Const *
432
_Jv_makeUtf8Const (const char* s, int len)
433
{
434
  if (len < 0)
435
    len = strlen (s);
436
  Utf8Const* m
437
    = (Utf8Const*) _Jv_AllocBytes (_Jv_Utf8Const::space_needed(s, len));
438
  m->init(s, len);
439
  return m;
440
}
441
 
442
_Jv_Utf8Const *
443
_Jv_makeUtf8Const (jstring string)
444
{
445
  jint hash = string->hashCode ();
446
  jint len = _Jv_GetStringUTFLength (string);
447
 
448
  Utf8Const* m = (Utf8Const*)
449
    _Jv_AllocBytes (sizeof(Utf8Const) + len + 1);
450
 
451
  m->hash = hash;
452
  m->length = len;
453
 
454
  _Jv_GetStringUTFRegion (string, 0, string->length (), m->data);
455
  m->data[len] = 0;
456
 
457
  return m;
458
}
459
 
460
 
461
 
462
#ifdef __GCJ_DEBUG
463
void
464
_Jv_Abort (const char *function, const char *file, int line,
465
           const char *message)
466
#else
467
void
468
_Jv_Abort (const char *, const char *, int, const char *message)
469
#endif
470
{
471
#ifdef __GCJ_DEBUG
472
  fprintf (stderr,
473
           "libgcj failure: %s\n   in function %s, file %s, line %d\n",
474
           message, function, file, line);
475
#else
476
  fprintf (stderr, "libgcj failure: %s\n", message);
477
#endif
478
  fflush (stderr);
479
  abort ();
480
}
481
 
482
static void
483
fail_on_finalization (jobject)
484
{
485
  JvFail ("object was finalized");
486
}
487
 
488
void
489
_Jv_GCWatch (jobject obj)
490
{
491
  _Jv_RegisterFinalizer (obj, fail_on_finalization);
492
}
493
 
494
void
495
_Jv_ThrowBadArrayIndex(jint bad_index)
496
{
497
  throw new java::lang::ArrayIndexOutOfBoundsException
498
    (java::lang::String::valueOf (bad_index));
499
}
500
 
501
void
502
_Jv_ThrowNullPointerException ()
503
{
504
  throw new java::lang::NullPointerException;
505
}
506
 
507
// Resolve an entry in the constant pool and return the target
508
// address.
509
void *
510
_Jv_ResolvePoolEntry (jclass this_class, jint index)
511
{
512
  _Jv_Constants *pool = &this_class->constants;
513
 
514
  if ((pool->tags[index] & JV_CONSTANT_ResolvedFlag) != 0)
515
    return pool->data[index].field->u.addr;
516
 
517
  JvSynchronize sync (this_class);
518
  return (_Jv_Linker::resolve_pool_entry (this_class, index))
519
    .field->u.addr;
520
}
521
 
522
 
523
// Explicitly throw a no memory exception.
524
// The collector calls this when it encounters an out-of-memory condition.
525
void _Jv_ThrowNoMemory()
526
{
527
  throw no_memory;
528
}
529
 
530
#ifdef ENABLE_JVMPI
531
# define JVMPI_NOTIFY_ALLOC(klass,size,obj) \
532
    if (__builtin_expect (_Jv_JVMPI_Notify_OBJECT_ALLOC != 0, false)) \
533
      jvmpi_notify_alloc(klass,size,obj);
534
static void
535
jvmpi_notify_alloc(jclass klass, jint size, jobject obj)
536
{
537
  // Service JVMPI allocation request.
538
  JVMPI_Event event;
539
 
540
  event.event_type = JVMPI_EVENT_OBJECT_ALLOC;
541
  event.env_id = NULL;
542
  event.u.obj_alloc.arena_id = 0;
543
  event.u.obj_alloc.class_id = (jobjectID) klass;
544
  event.u.obj_alloc.is_array = 0;
545
  event.u.obj_alloc.size = size;
546
  event.u.obj_alloc.obj_id = (jobjectID) obj;
547
 
548
  // FIXME:  This doesn't look right for the Boehm GC.  A GC may
549
  // already be in progress.  _Jv_DisableGC () doesn't wait for it.
550
  // More importantly, I don't see the need for disabling GC, since we
551
  // blatantly have a pointer to obj on our stack, ensuring that the
552
  // object can't be collected.  Even for a nonconservative collector,
553
  // it appears to me that this must be true, since we are about to
554
  // return obj. Isn't this whole approach way too intrusive for
555
  // a useful profiling interface?                      - HB
556
  _Jv_DisableGC ();
557
  (*_Jv_JVMPI_Notify_OBJECT_ALLOC) (&event);
558
  _Jv_EnableGC ();
559
}
560
#else /* !ENABLE_JVMPI */
561
# define JVMPI_NOTIFY_ALLOC(klass,size,obj) /* do nothing */
562
#endif
563
 
564
// Allocate a new object of class KLASS.
565
// First a version that assumes that we have no finalizer, and that
566
// the class is already initialized.
567
// If we know that JVMPI is disabled, this can be replaced by a direct call
568
// to the allocator for the appropriate GC.
569
jobject
570
_Jv_AllocObjectNoInitNoFinalizer (jclass klass)
571
{
572
  jint size = klass->size ();
573
  jobject obj = (jobject) _Jv_AllocObj (size, klass);
574
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
575
  return obj;
576
}
577
 
578
// And now a version that initializes if necessary.
579
jobject
580
_Jv_AllocObjectNoFinalizer (jclass klass)
581
{
582
  if (_Jv_IsPhantomClass(klass) )
583
    throw new java::lang::NoClassDefFoundError(klass->getName());
584
 
585
  _Jv_InitClass (klass);
586
  jint size = klass->size ();
587
  jobject obj = (jobject) _Jv_AllocObj (size, klass);
588
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
589
  return obj;
590
}
591
 
592
// And now the general version that registers a finalizer if necessary.
593
jobject
594
_Jv_AllocObject (jclass klass)
595
{
596
  jobject obj = _Jv_AllocObjectNoFinalizer (klass);
597
 
598
  // We assume that the compiler only generates calls to this routine
599
  // if there really is an interesting finalizer.
600
  // Unfortunately, we still have to the dynamic test, since there may
601
  // be cni calls to this routine.
602
  // Note that on IA64 get_finalizer() returns the starting address of the
603
  // function, not a function pointer.  Thus this still works.
604
  if (klass->vtable->get_finalizer ()
605
      != java::lang::Object::class$.vtable->get_finalizer ())
606
    _Jv_RegisterFinalizer (obj, _Jv_FinalizeObject);
607
  return obj;
608
}
609
 
610
// Allocate a String, including variable length storage.
611
jstring
612
_Jv_AllocString(jsize len)
613
{
614
  using namespace java::lang;
615
 
616
  jsize sz = sizeof(java::lang::String) + len * sizeof(jchar);
617
 
618
  // We assert that for strings allocated this way, the data field
619
  // will always point to the object itself.  Thus there is no reason
620
  // for the garbage collector to scan any of it.
621
  // Furthermore, we're about to overwrite the string data, so
622
  // initialization of the object is not an issue.
623
 
624
  // String needs no initialization, and there is no finalizer, so
625
  // we can go directly to the collector's allocator interface.
626
  jstring obj = (jstring) _Jv_AllocPtrFreeObj(sz, &String::class$);
627
 
628
  obj->data = obj;
629
  obj->boffset = sizeof(java::lang::String);
630
  obj->count = len;
631
  obj->cachedHashCode = 0;
632
 
633
  JVMPI_NOTIFY_ALLOC (&String::class$, sz, obj);
634
 
635
  return obj;
636
}
637
 
638
// A version of the above that assumes the object contains no pointers,
639
// and requires no finalization.  This can't happen if we need pointers
640
// to locks.
641
#ifdef JV_HASH_SYNCHRONIZATION
642
jobject
643
_Jv_AllocPtrFreeObject (jclass klass)
644
{
645
  _Jv_InitClass (klass);
646
  jint size = klass->size ();
647
 
648
  jobject obj = (jobject) _Jv_AllocPtrFreeObj (size, klass);
649
 
650
  JVMPI_NOTIFY_ALLOC (klass, size, obj);
651
 
652
  return obj;
653
}
654
#endif /* JV_HASH_SYNCHRONIZATION */
655
 
656
 
657
// Allocate a new array of Java objects.  Each object is of type
658
// `elementClass'.  `init' is used to initialize each slot in the
659
// array.
660
jobjectArray
661
_Jv_NewObjectArray (jsize count, jclass elementClass, jobject init)
662
{
663
  // Creating an array of an unresolved type is impossible. So we throw
664
  // the NoClassDefFoundError.
665
  if ( _Jv_IsPhantomClass(elementClass) )
666
    throw new java::lang::NoClassDefFoundError(elementClass->getName());
667
 
668
  if (__builtin_expect (count < 0, false))
669
    throw new java::lang::NegativeArraySizeException;
670
 
671
  JvAssert (! elementClass->isPrimitive ());
672
 
673
  // Ensure that elements pointer is properly aligned.
674
  jobjectArray obj = NULL;
675
  size_t size = (size_t) elements (obj);
676
  // Check for overflow.
677
  if (__builtin_expect ((size_t) count >
678
                        (MAX_OBJECT_SIZE - 1 - size) / sizeof (jobject), false))
679
    throw no_memory;
680
 
681
  size += count * sizeof (jobject);
682
 
683
  jclass klass = _Jv_GetArrayClass (elementClass,
684
                                    elementClass->getClassLoaderInternal());
685
 
686
  obj = (jobjectArray) _Jv_AllocArray (size, klass);
687
  // Cast away const.
688
  jsize *lp = const_cast<jsize *> (&obj->length);
689
  *lp = count;
690
  // We know the allocator returns zeroed memory.  So don't bother
691
  // zeroing it again.
692
  if (init)
693
    {
694
      jobject *ptr = elements(obj);
695
      while (--count >= 0)
696
        *ptr++ = init;
697
    }
698
  return obj;
699
}
700
 
701
// Allocate a new array of primitives.  ELTYPE is the type of the
702
// element, COUNT is the size of the array.
703
jobject
704
_Jv_NewPrimArray (jclass eltype, jint count)
705
{
706
  int elsize = eltype->size();
707
  if (__builtin_expect (count < 0, false))
708
    throw new java::lang::NegativeArraySizeException;
709
 
710
  JvAssert (eltype->isPrimitive ());
711
  jobject dummy = NULL;
712
  size_t size = (size_t) _Jv_GetArrayElementFromElementType (dummy, eltype);
713
 
714
  // Check for overflow.
715
  if (__builtin_expect ((size_t) count >
716
                        (MAX_OBJECT_SIZE - size) / elsize, false))
717
    throw no_memory;
718
 
719
  jclass klass = _Jv_GetArrayClass (eltype, 0);
720
 
721
# ifdef JV_HASH_SYNCHRONIZATION
722
  // Since the vtable is always statically allocated,
723
  // these are completely pointerfree!  Make sure the GC doesn't touch them.
724
  __JArray *arr =
725
    (__JArray*) _Jv_AllocPtrFreeObj (size + elsize * count, klass);
726
  memset((char *)arr + size, 0, elsize * count);
727
# else
728
  __JArray *arr = (__JArray*) _Jv_AllocObj (size + elsize * count, klass);
729
  // Note that we assume we are given zeroed memory by the allocator.
730
# endif
731
  // Cast away const.
732
  jsize *lp = const_cast<jsize *> (&arr->length);
733
  *lp = count;
734
 
735
  return arr;
736
}
737
 
738
jobject
739
_Jv_NewArray (jint type, jint size)
740
{
741
  switch (type)
742
    {
743
      case  4:  return JvNewBooleanArray (size);
744
      case  5:  return JvNewCharArray (size);
745
      case  6:  return JvNewFloatArray (size);
746
      case  7:  return JvNewDoubleArray (size);
747
      case  8:  return JvNewByteArray (size);
748
      case  9:  return JvNewShortArray (size);
749
      case 10:  return JvNewIntArray (size);
750
      case 11:  return JvNewLongArray (size);
751
    }
752
  throw new java::lang::InternalError
753
    (JvNewStringLatin1 ("invalid type code in _Jv_NewArray"));
754
}
755
 
756
// Allocate a possibly multi-dimensional array but don't check that
757
// any array length is <0.
758
static jobject
759
_Jv_NewMultiArrayUnchecked (jclass type, jint dimensions, jint *sizes)
760
{
761
  JvAssert (type->isArray());
762
  jclass element_type = type->getComponentType();
763
  jobject result;
764
  if (element_type->isPrimitive())
765
    result = _Jv_NewPrimArray (element_type, sizes[0]);
766
  else
767
    result = _Jv_NewObjectArray (sizes[0], element_type, NULL);
768
 
769
  if (dimensions > 1)
770
    {
771
      JvAssert (! element_type->isPrimitive());
772
      JvAssert (element_type->isArray());
773
      jobject *contents = elements ((jobjectArray) result);
774
      for (int i = 0; i < sizes[0]; ++i)
775
        contents[i] = _Jv_NewMultiArrayUnchecked (element_type, dimensions - 1,
776
                                                  sizes + 1);
777
    }
778
 
779
  return result;
780
}
781
 
782
jobject
783
_Jv_NewMultiArray (jclass type, jint dimensions, jint *sizes)
784
{
785
  for (int i = 0; i < dimensions; ++i)
786
    if (sizes[i] < 0)
787
      throw new java::lang::NegativeArraySizeException;
788
 
789
  return _Jv_NewMultiArrayUnchecked (type, dimensions, sizes);
790
}
791
 
792
jobject
793
_Jv_NewMultiArray (jclass array_type, jint dimensions, ...)
794
{
795
  // Creating an array of an unresolved type is impossible. So we throw
796
  // the NoClassDefFoundError.
797
  if (_Jv_IsPhantomClass(array_type))
798
    throw new java::lang::NoClassDefFoundError(array_type->getName());
799
 
800
  va_list args;
801
  jint sizes[dimensions];
802
  va_start (args, dimensions);
803
  for (int i = 0; i < dimensions; ++i)
804
    {
805
      jint size = va_arg (args, jint);
806
      if (size < 0)
807
        throw new java::lang::NegativeArraySizeException;
808
      sizes[i] = size;
809
    }
810
  va_end (args);
811
 
812
  return _Jv_NewMultiArrayUnchecked (array_type, dimensions, sizes);
813
}
814
 
815
 
816
 
817
// Ensure 8-byte alignment, for hash synchronization.
818
#define DECLARE_PRIM_TYPE(NAME)                 \
819
  java::lang::Class _Jv_##NAME##Class __attribute__ ((aligned (8)));
820
 
821
DECLARE_PRIM_TYPE(byte)
822
DECLARE_PRIM_TYPE(short)
823
DECLARE_PRIM_TYPE(int)
824
DECLARE_PRIM_TYPE(long)
825
DECLARE_PRIM_TYPE(boolean)
826
DECLARE_PRIM_TYPE(char)
827
DECLARE_PRIM_TYPE(float)
828
DECLARE_PRIM_TYPE(double)
829
DECLARE_PRIM_TYPE(void)
830
 
831
void
832
_Jv_InitPrimClass (jclass cl, const char *cname, char sig, int len)
833
{
834
  using namespace java::lang::reflect;
835
 
836
  // We must set the vtable for the class; the Java constructor
837
  // doesn't do this.
838
  (*(_Jv_VTable **) cl) = java::lang::Class::class$.vtable;
839
 
840
  // Initialize the fields we care about.  We do this in the same
841
  // order they are declared in Class.h.
842
  cl->name = _Jv_makeUtf8Const ((char *) cname, -1);
843
  cl->accflags = Modifier::PUBLIC | Modifier::FINAL | Modifier::ABSTRACT;
844
  cl->method_count = sig;
845
  cl->size_in_bytes = len;
846
  cl->vtable = JV_PRIMITIVE_VTABLE;
847
  cl->state = JV_STATE_DONE;
848
  cl->depth = -1;
849
}
850
 
851
jclass
852
_Jv_FindClassFromSignature (char *sig, java::lang::ClassLoader *loader,
853
                            char **endp)
854
{
855
  // First count arrays.
856
  int array_count = 0;
857
  while (*sig == '[')
858
    {
859
      ++sig;
860
      ++array_count;
861
    }
862
 
863
  jclass result = NULL;
864
  switch (*sig)
865
    {
866
    case 'B':
867
      result = JvPrimClass (byte);
868
      break;
869
    case 'S':
870
      result = JvPrimClass (short);
871
      break;
872
    case 'I':
873
      result = JvPrimClass (int);
874
      break;
875
    case 'J':
876
      result = JvPrimClass (long);
877
      break;
878
    case 'Z':
879
      result = JvPrimClass (boolean);
880
      break;
881
    case 'C':
882
      result = JvPrimClass (char);
883
      break;
884
    case 'F':
885
      result = JvPrimClass (float);
886
      break;
887
    case 'D':
888
      result = JvPrimClass (double);
889
      break;
890
    case 'V':
891
      result = JvPrimClass (void);
892
      break;
893
    case 'L':
894
      {
895
        char *save = ++sig;
896
        while (*sig && *sig != ';')
897
          ++sig;
898
        // Do nothing if signature appears to be malformed.
899
        if (*sig == ';')
900
          {
901
            _Jv_Utf8Const *name = _Jv_makeUtf8Const (save, sig - save);
902
            result = _Jv_FindClass (name, loader);
903
          }
904
        break;
905
      }
906
    default:
907
      // Do nothing -- bad signature.
908
      break;
909
    }
910
 
911
  if (endp)
912
    {
913
      // Not really the "end", but the last valid character that we
914
      // looked at.
915
      *endp = sig;
916
    }
917
 
918
  if (! result)
919
    return NULL;
920
 
921
  // Find arrays.
922
  while (array_count-- > 0)
923
    result = _Jv_GetArrayClass (result, loader);
924
  return result;
925
}
926
 
927
 
928
jclass
929
_Jv_FindClassFromSignatureNoException (char *sig, java::lang::ClassLoader *loader,
930
                                       char **endp)
931
{
932
  jclass klass;
933
 
934
  try
935
    {
936
      klass = _Jv_FindClassFromSignature(sig, loader, endp);
937
    }
938
  catch (java::lang::NoClassDefFoundError *ncdfe)
939
    {
940
      return NULL;
941
    }
942
  catch (java::lang::ClassNotFoundException *cnfe)
943
    {
944
      return NULL;
945
    }
946
 
947
  return klass;
948
}
949
 
950
JArray<jstring> *
951
JvConvertArgv (int argc, const char **argv)
952
{
953
  if (argc < 0)
954
    argc = 0;
955
  jobjectArray ar = JvNewObjectArray(argc, &java::lang::String::class$, NULL);
956
  jobject *ptr = elements(ar);
957
  jbyteArray bytes = NULL;
958
  for (int i = 0;  i < argc;  i++)
959
    {
960
      const char *arg = argv[i];
961
      int len = strlen (arg);
962
      if (bytes == NULL || bytes->length < len)
963
        bytes = JvNewByteArray (len);
964
      jbyte *bytePtr = elements (bytes);
965
      // We assume jbyte == char.
966
      memcpy (bytePtr, arg, len);
967
 
968
      // Now convert using the default encoding.
969
      *ptr++ = new java::lang::String (bytes, 0, len);
970
    }
971
  return (JArray<jstring>*) ar;
972
}
973
 
974
// FIXME: These variables are static so that they will be
975
// automatically scanned by the Boehm collector.  This is needed
976
// because with qthreads the collector won't scan the initial stack --
977
// it will only scan the qthreads stacks.
978
 
979
// Command line arguments.
980
static JArray<jstring> *arg_vec;
981
 
982
// The primary thread.
983
static java::lang::Thread *main_thread;
984
 
985
#ifndef DISABLE_GETENV_PROPERTIES
986
 
987
#define c_isspace(c) (memchr (" \t\n\r\v\f", c, 6) != NULL)
988
 
989
static char *
990
next_property_key (char *s, size_t *length)
991
{
992
  size_t l = 0;
993
 
994
  JvAssert (s);
995
 
996
  // Skip over whitespace
997
  while (c_isspace (*s))
998
    s++;
999
 
1000
  // If we've reached the end, return NULL.  Also return NULL if for
1001
  // some reason we've come across a malformed property string.
1002
  if (*s == 0
1003
      || *s == ':'
1004
      || *s == '=')
1005
    return NULL;
1006
 
1007
  // Determine the length of the property key.
1008
  while (s[l] != 0
1009
         && ! c_isspace (s[l])
1010
         && s[l] != ':'
1011
         && s[l] != '=')
1012
    {
1013
      if (s[l] == '\\'
1014
          && s[l+1] != 0)
1015
        l++;
1016
      l++;
1017
    }
1018
 
1019
  *length = l;
1020
 
1021
  return s;
1022
}
1023
 
1024
static char *
1025
next_property_value (char *s, size_t *length)
1026
{
1027
  size_t l = 0;
1028
 
1029
  JvAssert (s);
1030
 
1031
  while (c_isspace (*s))
1032
    s++;
1033
 
1034
  if (*s == ':'
1035
      || *s == '=')
1036
    s++;
1037
 
1038
  while (c_isspace (*s))
1039
    s++;
1040
 
1041
  // Determine the length of the property value.
1042
  while (s[l] != 0
1043
         && ! c_isspace (s[l])
1044
         && s[l] != ':'
1045
         && s[l] != '=')
1046
    {
1047
      if (s[l] == '\\'
1048
          && s[l+1] != 0)
1049
        l += 2;
1050
      else
1051
        l++;
1052
    }
1053
 
1054
  *length = l;
1055
 
1056
  return s;
1057
}
1058
 
1059
static void
1060
process_gcj_properties ()
1061
{
1062
  char *props = getenv("GCJ_PROPERTIES");
1063
 
1064
  if (NULL == props)
1065
    return;
1066
 
1067
  // Later on we will write \0s into this string.  It is simplest to
1068
  // just duplicate it here.
1069
  props = strdup (props);
1070
 
1071
  char *p = props;
1072
  size_t length;
1073
  size_t property_count = 0;
1074
 
1075
  // Whip through props quickly in order to count the number of
1076
  // property values.
1077
  while (p && (p = next_property_key (p, &length)))
1078
    {
1079
      // Skip to the end of the key
1080
      p += length;
1081
 
1082
      p = next_property_value (p, &length);
1083
      if (p)
1084
        p += length;
1085
 
1086
      property_count++;
1087
    }
1088
 
1089
  // Allocate an array of property value/key pairs.
1090
  _Jv_Environment_Properties =
1091
    (property_pair *) malloc (sizeof(property_pair)
1092
                              * (property_count + 1));
1093
 
1094
  // Go through the properties again, initializing _Jv_Properties
1095
  // along the way.
1096
  p = props;
1097
  property_count = 0;
1098
  while (p && (p = next_property_key (p, &length)))
1099
    {
1100
      _Jv_Environment_Properties[property_count].key = p;
1101
      _Jv_Environment_Properties[property_count].key_length = length;
1102
 
1103
      // Skip to the end of the key
1104
      p += length;
1105
 
1106
      p = next_property_value (p, &length);
1107
 
1108
      _Jv_Environment_Properties[property_count].value = p;
1109
      _Jv_Environment_Properties[property_count].value_length = length;
1110
 
1111
      if (p)
1112
        p += length;
1113
 
1114
      property_count++;
1115
    }
1116
  memset ((void *) &_Jv_Environment_Properties[property_count],
1117
          0, sizeof (property_pair));
1118
 
1119
  // Null terminate the strings.
1120
  for (property_pair *prop = &_Jv_Environment_Properties[0];
1121
       prop->key != NULL;
1122
       prop++)
1123
    {
1124
      prop->key[prop->key_length] = 0;
1125
      prop->value[prop->value_length] = 0;
1126
    }
1127
}
1128
#endif // DISABLE_GETENV_PROPERTIES
1129
 
1130
namespace gcj
1131
{
1132
  _Jv_Utf8Const *void_signature;
1133
  _Jv_Utf8Const *clinit_name;
1134
  _Jv_Utf8Const *init_name;
1135
  _Jv_Utf8Const *finit_name;
1136
 
1137
  bool runtimeInitialized = false;
1138
 
1139
  // When true, print debugging information about class loading.
1140
  bool verbose_class_flag;
1141
 
1142
  // When true, enable the bytecode verifier and BC-ABI type verification. 
1143
  bool verifyClasses = true;
1144
 
1145
  // Thread stack size specified by the -Xss runtime argument.
1146
  size_t stack_size = 0;
1147
 
1148
  // Start time of the VM
1149
  jlong startTime = 0;
1150
 
1151
  // Arguments passed to the VM
1152
  JArray<jstring>* vmArgs;
1153
 
1154
  // Currently loaded classes
1155
  jint loadedClasses = 0;
1156
 
1157
  // Unloaded classes
1158
  jlong unloadedClasses = 0;
1159
}
1160
 
1161
// We accept all non-standard options accepted by Sun's java command,
1162
// for compatibility with existing application launch scripts.
1163
static jint
1164
parse_x_arg (char* option_string)
1165
{
1166
  if (strlen (option_string) <= 0)
1167
    return -1;
1168
 
1169
  if (! strcmp (option_string, "int"))
1170
    {
1171
      // FIXME: this should cause the vm to never load shared objects
1172
    }
1173
  else if (! strcmp (option_string, "mixed"))
1174
    {
1175
      // FIXME: allow interpreted and native code
1176
    }
1177
  else if (! strcmp (option_string, "batch"))
1178
    {
1179
      // FIXME: disable background JIT'ing
1180
    }
1181
  else if (! strcmp (option_string, "debug"))
1182
    {
1183
      remoteDebug = true;
1184
    }
1185
#ifdef INTERPRETER
1186
  else if (! strncmp (option_string, "runjdwp:", 8))
1187
    {
1188
      if (strlen (option_string) > 8)
1189
          jdwpOptions = &option_string[8];
1190
      else
1191
        {
1192
          fprintf (stderr,
1193
                   "libgcj: argument required for JDWP options");
1194
          return -1;
1195
        }
1196
    }
1197
#endif // INTERPRETER
1198
  else if (! strncmp (option_string, "bootclasspath:", 14))
1199
    {
1200
      // FIXME: add a parse_bootclasspath_arg function
1201
    }
1202
  else if (! strncmp (option_string, "bootclasspath/a:", 16))
1203
    {
1204
    }
1205
  else if (! strncmp (option_string, "bootclasspath/p:", 16))
1206
    {
1207
    }
1208
  else if (! strcmp (option_string, "check:jni"))
1209
    {
1210
      // FIXME: enable strict JNI checking
1211
    }
1212
  else if (! strcmp (option_string, "future"))
1213
    {
1214
      // FIXME: enable strict class file format checks
1215
    }
1216
  else if (! strcmp (option_string, "noclassgc"))
1217
    {
1218
      // FIXME: disable garbage collection for classes
1219
    }
1220
  else if (! strcmp (option_string, "incgc"))
1221
    {
1222
      // FIXME: incremental garbage collection
1223
    }
1224
  else if (! strncmp (option_string, "loggc:", 6))
1225
    {
1226
      if (option_string[6] == '\0')
1227
        {
1228
          fprintf (stderr,
1229
                   "libgcj: filename argument expected for loggc option\n");
1230
          return -1;
1231
        }
1232
      // FIXME: set gc logging filename
1233
    }
1234
  else if (! strncmp (option_string, "ms", 2))
1235
    {
1236
      // FIXME: ignore this option until PR 20699 is fixed.
1237
      // _Jv_SetInitialHeapSize (option_string + 2);
1238
    }
1239
  else if (! strncmp (option_string, "mx", 2))
1240
    _Jv_SetMaximumHeapSize (option_string + 2);
1241
  else if (! strcmp (option_string, "prof"))
1242
    {
1243
      // FIXME: enable profiling of program running in vm
1244
    }
1245
  else if (! strncmp (option_string, "runhprof:", 9))
1246
    {
1247
      // FIXME: enable specific type of vm profiling.  add a
1248
      // parse_runhprof_arg function
1249
    }
1250
  else if (! strcmp (option_string, "rs"))
1251
    {
1252
      // FIXME: reduced system signal usage.  disable thread dumps,
1253
      // only terminate in response to user-initiated calls,
1254
      // e.g. System.exit()
1255
    }
1256
  else if (! strncmp (option_string, "ss", 2))
1257
    {
1258
      _Jv_SetStackSize (option_string + 2);
1259
    }
1260
  else if (! strcmp (option_string, "X:+UseAltSigs"))
1261
    {
1262
      // FIXME: use signals other than SIGUSR1 and SIGUSR2
1263
    }
1264
  else if (! strcmp (option_string, "share:off"))
1265
    {
1266
      // FIXME: don't share class data
1267
    }
1268
  else if (! strcmp (option_string, "share:auto"))
1269
    {
1270
      // FIXME: share class data where possible
1271
    }
1272
  else if (! strcmp (option_string, "share:on"))
1273
    {
1274
      // FIXME: fail if impossible to share class data
1275
    }
1276
  else
1277
    {
1278
      // Unrecognized.
1279
      return -1;
1280
    }
1281
  return 0;
1282
}
1283
 
1284
static jint
1285
parse_verbose_args (char* option_string,
1286
                    bool ignore_unrecognized)
1287
{
1288
  size_t len = sizeof ("-verbose") - 1;
1289
 
1290
  if (strlen (option_string) < len)
1291
    return -1;
1292
 
1293
  if (option_string[len] == ':'
1294
      && option_string[len + 1] != '\0')
1295
    {
1296
      char* verbose_args = option_string + len + 1;
1297
 
1298
      do
1299
        {
1300
          if (! strncmp (verbose_args,
1301
                         "gc", sizeof ("gc") - 1))
1302
            {
1303
              if (verbose_args[sizeof ("gc") - 1] == '\0'
1304
                  || verbose_args[sizeof ("gc") - 1] == ',')
1305
                {
1306
                  // FIXME: we should add functions to boehm-gc that
1307
                  // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
1308
                  // GC_print_back_height.
1309
                  verbose_args += sizeof ("gc") - 1;
1310
                }
1311
              else
1312
                {
1313
                verbose_arg_err:
1314
                  fprintf (stderr, "libgcj: unknown verbose option: %s\n",
1315
                           option_string);
1316
                  return -1;
1317
                }
1318
            }
1319
          else if (! strncmp (verbose_args,
1320
                              "class",
1321
                              sizeof ("class") - 1))
1322
            {
1323
              if (verbose_args[sizeof ("class") - 1] == '\0'
1324
                  || verbose_args[sizeof ("class") - 1] == ',')
1325
                {
1326
                  gcj::verbose_class_flag = true;
1327
                  verbose_args += sizeof ("class") - 1;
1328
                }
1329
              else
1330
                goto verbose_arg_err;
1331
            }
1332
          else if (! strncmp (verbose_args, "jni",
1333
                              sizeof ("jni") - 1))
1334
            {
1335
              if (verbose_args[sizeof ("jni") - 1] == '\0'
1336
                  || verbose_args[sizeof ("jni") - 1] == ',')
1337
                {
1338
                  // FIXME: enable JNI messages.
1339
                  verbose_args += sizeof ("jni") - 1;
1340
                }
1341
              else
1342
                goto verbose_arg_err;
1343
            }
1344
          else if (ignore_unrecognized
1345
                   && verbose_args[0] == 'X')
1346
            {
1347
              // ignore unrecognized non-standard verbose option
1348
              while (verbose_args[0] != '\0'
1349
                     && verbose_args[0] != ',')
1350
                verbose_args++;
1351
            }
1352
          else if (verbose_args[0] == ',')
1353
            {
1354
              verbose_args++;
1355
            }
1356
          else
1357
            goto verbose_arg_err;
1358
 
1359
          if (verbose_args[0] == ',')
1360
            verbose_args++;
1361
        }
1362
      while (verbose_args[0] != '\0');
1363
    }
1364
  else if (option_string[len] == 'g'
1365
           && option_string[len + 1] == 'c'
1366
           && option_string[len + 2] == '\0')
1367
    {
1368
      // FIXME: we should add functions to boehm-gc that
1369
      // toggle GC_print_stats, GC_PRINT_ADDRESS_MAP and
1370
      // GC_print_back_height.
1371
      return 0;
1372
    }
1373
  else if (option_string[len] == '\0')
1374
    {
1375
      gcj::verbose_class_flag = true;
1376
      return 0;
1377
    }
1378
  else
1379
    {
1380
      // unrecognized option beginning with -verbose
1381
      return -1;
1382
    }
1383
  return 0;
1384
}
1385
 
1386
#ifdef INTERPRETER
1387
// This function loads the agent functions for JVMTI from the library indicated
1388
// by name.  It returns a negative value on failure, the value of which
1389
// indicates where ltdl failed, it also prints an error message.
1390
static jint
1391
load_jvmti_agent (const char *name)
1392
{
1393
#ifdef USE_LTDL
1394
  if (lt_dlinit ())
1395
    {
1396
      fprintf (stderr,
1397
              "libgcj: Error in ltdl init while loading agent library.\n");
1398
      return -1;
1399
    }
1400
 
1401
  lt_dlhandle lib = lt_dlopenext (name);
1402
  if (!lib)
1403
    {
1404
      fprintf (stderr,
1405
               "libgcj: Error opening agent library.\n");
1406
      return -2;
1407
    }
1408
 
1409
  if (lib)
1410
    {
1411
      jvmti_agentonload
1412
        = (jvmti_agent_onload_func *) lt_dlsym (lib, "Agent_OnLoad");
1413
 
1414
      if (!jvmti_agentonload)
1415
        {
1416
          fprintf (stderr,
1417
                   "libgcj: Error finding agent function in library %s.\n",
1418
                   name);
1419
          lt_dlclose (lib);
1420
          lib = NULL;
1421
          return -4;
1422
        }
1423
      else
1424
        {
1425
          jvmti_agentonunload
1426
            = (jvmti_agent_onunload_func *) lt_dlsym (lib, "Agent_OnUnload");
1427
 
1428
          return 0;
1429
        }
1430
    }
1431
  else
1432
    {
1433
      fprintf (stderr, "libgcj: Library %s not found in library path.\n", name);
1434
      return -3;
1435
    }
1436
 
1437
#endif /* USE_LTDL */
1438
 
1439
  // If LTDL cannot be used, return an error code indicating this.
1440
  return -99;
1441
}
1442
#endif // INTERPRETER
1443
 
1444
static jint
1445
parse_init_args (JvVMInitArgs* vm_args)
1446
{
1447
  // if _Jv_Compiler_Properties is non-NULL then it needs to be
1448
  // re-allocated dynamically.
1449
  if (_Jv_Compiler_Properties)
1450
    {
1451
      const char** props = _Jv_Compiler_Properties;
1452
      _Jv_Compiler_Properties = NULL;
1453
 
1454
      for (int i = 0; props[i]; i++)
1455
        {
1456
          _Jv_Compiler_Properties = (const char**) _Jv_Realloc
1457
            (_Jv_Compiler_Properties,
1458
             (_Jv_Properties_Count + 1) * sizeof (const char*));
1459
          _Jv_Compiler_Properties[_Jv_Properties_Count++] = props[i];
1460
        }
1461
    }
1462
 
1463
  if (vm_args == NULL)
1464
    return 0;
1465
 
1466
  for (int i = 0; i < vm_args->nOptions; ++i)
1467
    {
1468
      char* option_string = vm_args->options[i].optionString;
1469
 
1470
      if (! strcmp (option_string, "vfprintf")
1471
          || ! strcmp (option_string, "exit")
1472
          || ! strcmp (option_string, "abort"))
1473
        {
1474
          // FIXME: we are required to recognize these, but for
1475
          // now we don't handle them in any way.
1476
          continue;
1477
        }
1478
      else if (! strncmp (option_string,
1479
                          "-verbose", sizeof ("-verbose") - 1))
1480
        {
1481
          jint result = parse_verbose_args (option_string,
1482
                                            vm_args->ignoreUnrecognized);
1483
          if (result < 0)
1484
            return result;
1485
        }
1486
      else if (! strncmp (option_string, "-D", 2))
1487
        {
1488
          _Jv_Compiler_Properties = (const char**) _Jv_Realloc
1489
            (_Jv_Compiler_Properties,
1490
             (_Jv_Properties_Count + 1) * sizeof (char*));
1491
 
1492
          _Jv_Compiler_Properties[_Jv_Properties_Count++] =
1493
            strdup (option_string + 2);
1494
 
1495
          continue;
1496
        }
1497
#ifdef INTERPRETER
1498
      else if (! strncmp (option_string, "-agentlib", sizeof ("-agentlib") - 1))
1499
        {
1500
          char *strPtr;
1501
 
1502
          if (strlen(option_string) > (sizeof ("-agentlib:") - 1))
1503
            strPtr = &option_string[sizeof ("-agentlib:") - 1];
1504
          else
1505
            {
1506
              fprintf (stderr,
1507
                "libgcj: Malformed agentlib argument %s: expected lib name\n",
1508
                option_string);
1509
              return -1;
1510
            }
1511
 
1512
          // These are optional arguments to pass to the agent library.
1513
          jvmti_agent_opts = strchr (strPtr, '=');
1514
 
1515
          if (! strncmp (strPtr, "jdwp", 4))
1516
            {
1517
              // We want to run JDWP here so set the correct variables.
1518
              remoteDebug = true;
1519
              jdwpOptions = ++jvmti_agent_opts;
1520
            }
1521
          else
1522
            {
1523
              jint nameLength;
1524
 
1525
              if (jvmti_agent_opts == NULL)
1526
                nameLength = strlen (strPtr);
1527
              else
1528
                {
1529
                  nameLength = jvmti_agent_opts - strPtr;
1530
                  jvmti_agent_opts++;
1531
                }
1532
 
1533
              char lib_name[nameLength + 3 + 1];
1534
              strcpy (lib_name, "lib");
1535
              strncat (lib_name, strPtr, nameLength);
1536
 
1537
              jint result = load_jvmti_agent (lib_name);
1538
 
1539
              if (result < 0)
1540
                {
1541
                  return -1;
1542
                }
1543
 
1544
              // Mark JVMTI active
1545
              JVMTI::enabled = true;
1546
            }
1547
 
1548
          continue;
1549
        }
1550
      else if (! strncmp (option_string, "-agentpath:",
1551
                          sizeof ("-agentpath:") - 1))
1552
        {
1553
          char *strPtr;
1554
 
1555
          if (strlen(option_string) > 10)
1556
            strPtr = &option_string[10];
1557
          else
1558
            {
1559
              fprintf (stderr,
1560
                "libgcj: Malformed agentlib argument %s: expected lib path\n",
1561
                option_string);
1562
              return -1;
1563
            }
1564
 
1565
          // These are optional arguments to pass to the agent library.
1566
          jvmti_agent_opts = strchr (strPtr, '=');
1567
 
1568
          jint nameLength;
1569
 
1570
          if (jvmti_agent_opts == NULL)
1571
            nameLength = strlen (strPtr);
1572
          else
1573
            {
1574
              nameLength = jvmti_agent_opts - strPtr;
1575
              jvmti_agent_opts++;
1576
            }
1577
 
1578
          char lib_name[nameLength + 3 + 1];
1579
          strcpy (lib_name, "lib");
1580
          strncat (lib_name, strPtr, nameLength);
1581
          jint result = load_jvmti_agent (strPtr);
1582
 
1583
          if (result < 0)
1584
            {
1585
              return -1;
1586
            }
1587
 
1588
          // Mark JVMTI active
1589
          JVMTI::enabled = true;
1590
          continue;
1591
        }
1592
#endif // INTERPRETER
1593
      else
1594
        {
1595
          int r = -1;
1596
          if (option_string[0] == '_')
1597
            r = parse_x_arg (option_string + 1);
1598
          else if (! strncmp (option_string, "-X", 2))
1599
            r = parse_x_arg (option_string + 2);
1600
 
1601
          if (r == -1 && ! vm_args->ignoreUnrecognized)
1602
            {
1603
              fprintf (stderr, "libgcj: unknown option: %s\n", option_string);
1604
              return -1;
1605
            }
1606
        }
1607
    }
1608
  return 0;
1609
}
1610
 
1611
jint
1612
_Jv_CreateJavaVM (JvVMInitArgs* vm_args)
1613
{
1614
  using namespace gcj;
1615
 
1616
  if (runtimeInitialized)
1617
    return -1;
1618
 
1619
  runtimeInitialized = true;
1620
  startTime = _Jv_platform_gettimeofday();
1621
 
1622
  jint result = parse_init_args (vm_args);
1623
  if (result < 0)
1624
    return -1;
1625
 
1626
  PROCESS_GCJ_PROPERTIES;
1627
 
1628
  /* Threads must be initialized before the GC, so that it inherits the
1629
     signal mask.  */
1630
  _Jv_InitThreads ();
1631
  _Jv_InitGC ();
1632
  _Jv_InitializeSyncMutex ();
1633
 
1634
#ifdef INTERPRETER
1635
  _Jv_InitInterpreter ();
1636
#endif  
1637
 
1638
#ifdef HANDLE_SEGV
1639
  INIT_SEGV;
1640
#endif
1641
 
1642
#ifdef HANDLE_FPE
1643
  INIT_FPE;
1644
#endif
1645
 
1646
  /* Initialize Utf8 constants declared in jvm.h. */
1647
  void_signature = _Jv_makeUtf8Const ("()V", 3);
1648
  clinit_name = _Jv_makeUtf8Const ("<clinit>", 8);
1649
  init_name = _Jv_makeUtf8Const ("<init>", 6);
1650
  finit_name = _Jv_makeUtf8Const ("finit$", 6);
1651
 
1652
  /* Initialize built-in classes to represent primitive TYPEs. */
1653
  _Jv_InitPrimClass (&_Jv_byteClass,    "byte",    'B', 1);
1654
  _Jv_InitPrimClass (&_Jv_shortClass,   "short",   'S', 2);
1655
  _Jv_InitPrimClass (&_Jv_intClass,     "int",     'I', 4);
1656
  _Jv_InitPrimClass (&_Jv_longClass,    "long",    'J', 8);
1657
  _Jv_InitPrimClass (&_Jv_booleanClass, "boolean", 'Z', 1);
1658
  _Jv_InitPrimClass (&_Jv_charClass,    "char",    'C', 2);
1659
  _Jv_InitPrimClass (&_Jv_floatClass,   "float",   'F', 4);
1660
  _Jv_InitPrimClass (&_Jv_doubleClass,  "double",  'D', 8);
1661
  _Jv_InitPrimClass (&_Jv_voidClass,    "void",    'V', 0);
1662
 
1663
  // We have to initialize this fairly early, to avoid circular class
1664
  // initialization.  In particular we want to start the
1665
  // initialization of ClassLoader before we start the initialization
1666
  // of VMClassLoader.
1667
  _Jv_InitClass (&java::lang::ClassLoader::class$);
1668
 
1669
  // Set up the system class loader and the bootstrap class loader.
1670
  gnu::gcj::runtime::ExtensionClassLoader::initialize();
1671
  java::lang::VMClassLoader::initialize(JvNewStringLatin1(TOOLEXECLIBDIR));
1672
 
1673
  _Jv_RegisterBootstrapPackages();
1674
 
1675
  no_memory = new java::lang::OutOfMemoryError;
1676
 
1677
#ifdef USE_LTDL
1678
  LTDL_SET_PRELOADED_SYMBOLS ();
1679
#endif
1680
 
1681
  _Jv_platform_initialize ();
1682
 
1683
  _Jv_JNI_Init ();
1684
 
1685
#ifdef INTERPRETER
1686
  _Jv_JVMTI_Init ();
1687
#endif
1688
 
1689
  _Jv_GCInitializeFinalizers (&::gnu::gcj::runtime::FinalizerThread::finalizerReady);
1690
 
1691
  // Start the GC finalizer thread.  A VirtualMachineError can be
1692
  // thrown by the runtime if, say, threads aren't available.
1693
  try
1694
    {
1695
      using namespace gnu::gcj::runtime;
1696
      FinalizerThread *ft = new FinalizerThread ();
1697
      ft->start ();
1698
    }
1699
  catch (java::lang::VirtualMachineError *ignore)
1700
    {
1701
    }
1702
 
1703
  runtimeInitialized = true;
1704
 
1705
  return 0;
1706
}
1707
 
1708
void
1709
_Jv_RunMain (JvVMInitArgs *vm_args, jclass klass, const char *name, int argc,
1710
             const char **argv, bool is_jar)
1711
{
1712
#ifndef DISABLE_MAIN_ARGS
1713
  _Jv_SetArgs (argc, argv);
1714
#endif
1715
 
1716
  java::lang::Runtime *runtime = NULL;
1717
 
1718
  try
1719
    {
1720
      if (_Jv_CreateJavaVM (vm_args) < 0)
1721
        {
1722
          fprintf (stderr, "libgcj: couldn't create virtual machine\n");
1723
          exit (1);
1724
        }
1725
 
1726
      if (vm_args == NULL)
1727
        gcj::vmArgs = JvConvertArgv(0, NULL);
1728
      else
1729
        {
1730
          const char* vmArgs[vm_args->nOptions];
1731
          const char** vmPtr = vmArgs;
1732
          struct _Jv_VMOption* optionPtr = vm_args->options;
1733
          for (int i = 0; i < vm_args->nOptions; ++i)
1734
            *vmPtr++ = (*optionPtr++).optionString;
1735
          gcj::vmArgs = JvConvertArgv(vm_args->nOptions, vmArgs);
1736
        }
1737
 
1738
      // Get the Runtime here.  We want to initialize it before searching
1739
      // for `main'; that way it will be set up if `main' is a JNI method.
1740
      runtime = java::lang::Runtime::getRuntime ();
1741
 
1742
#ifdef DISABLE_MAIN_ARGS
1743
      arg_vec = JvConvertArgv (0, 0);
1744
#else      
1745
      arg_vec = JvConvertArgv (argc - 1, argv + 1);
1746
#endif
1747
 
1748
      using namespace gnu::java::lang;
1749
      if (klass)
1750
        main_thread = new MainThread (klass, arg_vec);
1751
      else
1752
        main_thread = new MainThread (JvNewStringUTF (name),
1753
                                      arg_vec, is_jar);
1754
      _Jv_AttachCurrentThread (main_thread);
1755
 
1756
#ifdef INTERPRETER
1757
      // Start JVMTI if an agent function has been found.
1758
      if (jvmti_agentonload)
1759
        (*jvmti_agentonload) (_Jv_GetJavaVM (), jvmti_agent_opts, NULL);
1760
 
1761
      // Start JDWP
1762
      if (remoteDebug)
1763
        {
1764
          using namespace gnu::classpath::jdwp;
1765
          VMVirtualMachine::initialize ();
1766
          Jdwp *jdwp = new Jdwp ();
1767
          jdwp->setDaemon (true);
1768
          jdwp->configure (JvNewStringLatin1 (jdwpOptions));
1769
          jdwp->start ();
1770
 
1771
          // Wait for JDWP to initialize and start
1772
          jdwp->join ();
1773
        }
1774
      // Send VMInit
1775
      if (JVMTI_REQUESTED_EVENT (VMInit))
1776
        _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_INIT, main_thread);
1777
#endif // INTERPRETER
1778
    }
1779
  catch (java::lang::Throwable *t)
1780
    {
1781
      java::lang::System::err->println (JvNewStringLatin1
1782
        ("Exception during runtime initialization"));
1783
      t->printStackTrace();
1784
      if (runtime)
1785
        java::lang::Runtime::exitNoChecksAccessor (1);
1786
      // In case the runtime creation failed.
1787
      ::exit (1);
1788
    }
1789
 
1790
  _Jv_ThreadRun (main_thread);
1791
 
1792
#ifdef INTERPRETER
1793
  // Send VMDeath
1794
  if (JVMTI_REQUESTED_EVENT (VMDeath))
1795
    {
1796
      java::lang::Thread *thread = java::lang::Thread::currentThread ();
1797
      JNIEnv *jni_env = _Jv_GetCurrentJNIEnv ();
1798
      _Jv_JVMTI_PostEvent (JVMTI_EVENT_VM_DEATH, thread, jni_env);
1799
    }
1800
 
1801
  // Run JVMTI AgentOnUnload if it exists and an agent is loaded.
1802
  if (jvmti_agentonunload)
1803
    (*jvmti_agentonunload) (_Jv_GetJavaVM ());
1804
#endif // INTERPRETER
1805
 
1806
  // If we got here then something went wrong, as MainThread is not
1807
  // supposed to terminate.
1808
  ::exit (1);
1809
}
1810
 
1811
void
1812
_Jv_RunMain (jclass klass, const char *name, int argc, const char **argv,
1813
             bool is_jar)
1814
{
1815
  _Jv_RunMain (NULL, klass, name, argc, argv, is_jar);
1816
}
1817
 
1818
void
1819
JvRunMain (jclass klass, int argc, const char **argv)
1820
{
1821
  _Jv_RunMain (klass, NULL, argc, argv, false);
1822
}
1823
 
1824
void
1825
JvRunMainName (const char *name, int argc, const char **argv)
1826
{
1827
  _Jv_RunMain (NULL, name, argc, argv, false);
1828
}
1829
 
1830
 
1831
 
1832
// Parse a string and return a heap size.
1833
static size_t
1834
parse_memory_size (const char *spec)
1835
{
1836
  char *end;
1837
  unsigned long val = strtoul (spec, &end, 10);
1838
  if (*end == 'k' || *end == 'K')
1839
    val *= 1024;
1840
  else if (*end == 'm' || *end == 'M')
1841
    val *= 1048576;
1842
  return (size_t) val;
1843
}
1844
 
1845
// Set the initial heap size.  This might be ignored by the GC layer.
1846
// This must be called before _Jv_RunMain.
1847
void
1848
_Jv_SetInitialHeapSize (const char *arg)
1849
{
1850
  size_t size = parse_memory_size (arg);
1851
  _Jv_GCSetInitialHeapSize (size);
1852
}
1853
 
1854
// Set the maximum heap size.  This might be ignored by the GC layer.
1855
// This must be called before _Jv_RunMain.
1856
void
1857
_Jv_SetMaximumHeapSize (const char *arg)
1858
{
1859
  size_t size = parse_memory_size (arg);
1860
  _Jv_GCSetMaximumHeapSize (size);
1861
}
1862
 
1863
void
1864
_Jv_SetStackSize (const char *arg)
1865
{
1866
  size_t size = parse_memory_size (arg);
1867
  gcj::stack_size = size;
1868
}
1869
 
1870
void *
1871
_Jv_Malloc (jsize size)
1872
{
1873
  if (__builtin_expect (size == 0, false))
1874
    size = 1;
1875
  void *ptr = malloc ((size_t) size);
1876
  if (__builtin_expect (ptr == NULL, false))
1877
    throw no_memory;
1878
  return ptr;
1879
}
1880
 
1881
void *
1882
_Jv_Realloc (void *ptr, jsize size)
1883
{
1884
  if (__builtin_expect (size == 0, false))
1885
    size = 1;
1886
  ptr = realloc (ptr, (size_t) size);
1887
  if (__builtin_expect (ptr == NULL, false))
1888
    throw no_memory;
1889
  return ptr;
1890
}
1891
 
1892
void *
1893
_Jv_MallocUnchecked (jsize size)
1894
{
1895
  if (__builtin_expect (size == 0, false))
1896
    size = 1;
1897
  return malloc ((size_t) size);
1898
}
1899
 
1900
void
1901
_Jv_Free (void* ptr)
1902
{
1903
  return free (ptr);
1904
}
1905
 
1906
 
1907
 
1908
// In theory, these routines can be #ifdef'd away on machines which
1909
// support divide overflow signals.  However, we never know if some
1910
// code might have been compiled with "-fuse-divide-subroutine", so we
1911
// always include them in libgcj.
1912
 
1913
jint
1914
_Jv_divI (jint dividend, jint divisor)
1915
{
1916
  if (__builtin_expect (divisor == 0, false))
1917
    {
1918
      java::lang::ArithmeticException *arithexception
1919
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
1920
      throw arithexception;
1921
    }
1922
 
1923
  if (dividend == (jint) 0x80000000L && divisor == -1)
1924
    return dividend;
1925
 
1926
  return dividend / divisor;
1927
}
1928
 
1929
jint
1930
_Jv_remI (jint dividend, jint divisor)
1931
{
1932
  if (__builtin_expect (divisor == 0, false))
1933
    {
1934
      java::lang::ArithmeticException *arithexception
1935
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
1936
      throw arithexception;
1937
    }
1938
 
1939
  if (dividend == (jint) 0x80000000L && divisor == -1)
1940
    return 0;
1941
 
1942
  return dividend % divisor;
1943
}
1944
 
1945
jlong
1946
_Jv_divJ (jlong dividend, jlong divisor)
1947
{
1948
  if (__builtin_expect (divisor == 0, false))
1949
    {
1950
      java::lang::ArithmeticException *arithexception
1951
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
1952
      throw arithexception;
1953
    }
1954
 
1955
  if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
1956
    return dividend;
1957
 
1958
  return dividend / divisor;
1959
}
1960
 
1961
jlong
1962
_Jv_remJ (jlong dividend, jlong divisor)
1963
{
1964
  if (__builtin_expect (divisor == 0, false))
1965
    {
1966
      java::lang::ArithmeticException *arithexception
1967
        = new java::lang::ArithmeticException (JvNewStringLatin1 ("/ by zero"));
1968
      throw arithexception;
1969
    }
1970
 
1971
  if (dividend == (jlong) 0x8000000000000000LL && divisor == -1)
1972
    return 0;
1973
 
1974
  return dividend % divisor;
1975
}
1976
 
1977
 
1978
 
1979
// Return true if SELF_KLASS can access a field or method in
1980
// OTHER_KLASS.  The field or method's access flags are specified in
1981
// FLAGS.
1982
jboolean
1983
_Jv_CheckAccess (jclass self_klass, jclass other_klass, jint flags)
1984
{
1985
  using namespace java::lang::reflect;
1986
  return ((self_klass == other_klass)
1987
          || ((flags & Modifier::PUBLIC) != 0)
1988
          || (((flags & Modifier::PROTECTED) != 0)
1989
              && _Jv_IsAssignableFromSlow (self_klass, other_klass))
1990
          || (((flags & Modifier::PRIVATE) == 0)
1991
              && _Jv_ClassNameSamePackage (self_klass->name,
1992
                                           other_klass->name)));
1993
}
1994
 
1995
// Prepend GCJ_VERSIONED_LIBDIR to a module search path stored in a C
1996
// char array, if the path is not already prefixed by
1997
// GCJ_VERSIONED_LIBDIR.  Return a newly JvMalloc'd char buffer.  The
1998
// result should be freed using JvFree.
1999
char*
2000
_Jv_PrependVersionedLibdir (char* libpath)
2001
{
2002
  char* retval = 0;
2003
 
2004
  if (libpath && libpath[0] != '\0')
2005
    {
2006
      if (! strncmp (libpath,
2007
                     GCJ_VERSIONED_LIBDIR,
2008
                     sizeof (GCJ_VERSIONED_LIBDIR) - 1))
2009
        {
2010
          // LD_LIBRARY_PATH is already prefixed with
2011
          // GCJ_VERSIONED_LIBDIR.
2012
          retval = (char*) _Jv_Malloc (strlen (libpath) + 1);
2013
          strcpy (retval, libpath);
2014
        }
2015
      else
2016
        {
2017
          // LD_LIBRARY_PATH is not prefixed with
2018
          // GCJ_VERSIONED_LIBDIR.
2019
          char path_sep[2];
2020
          path_sep[0] = (char) _Jv_platform_path_separator;
2021
          path_sep[1] = '\0';
2022
          jsize total = ((sizeof (GCJ_VERSIONED_LIBDIR) - 1)
2023
                         + 1 /* path separator */ + strlen (libpath) + 1);
2024
          retval = (char*) _Jv_Malloc (total);
2025
          strcpy (retval, GCJ_VERSIONED_LIBDIR);
2026
          strcat (retval, path_sep);
2027
          strcat (retval, libpath);
2028
        }
2029
    }
2030
  else
2031
    {
2032
      // LD_LIBRARY_PATH was not specified or is empty.
2033
      retval = (char*) _Jv_Malloc (sizeof (GCJ_VERSIONED_LIBDIR));
2034
      strcpy (retval, GCJ_VERSIONED_LIBDIR);
2035
    }
2036
 
2037
  return retval;
2038
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.