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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [gnu/] [gcj/] [util/] [natGCInfo.cc] - Blame information for rev 756

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 756 jeremybenn
/* natGCInfo.cc -- Native portion of support for creating heap dumps.
2
   Copyright (C) 2007  Free Software Foundation
3
 
4
   This file is part of libgcj.
5
 
6
   This software is copyrighted work licensed under the terms of the
7
   Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
8
   details.  */
9
 
10
 
11
#include <config.h>
12
 
13
#include <gcj/cni.h>
14
 
15
#include <gnu/gcj/util/GCInfo.h>
16
 
17
#ifdef HAVE_PROC_SELF_MAPS
18
//
19
// If /proc/self/maps does not exist we assume we are doomed and do nothing.
20
//
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <fcntl.h>
24
#include <unistd.h>
25
#include <string.h>
26
#include <errno.h>
27
 
28
//
29
// Boehm GC includes.
30
//
31
#ifdef PACKAGE_NAME
32
#undef PACKAGE_NAME
33
#endif
34
 
35
#ifdef PACKAGE_STRING
36
#undef PACKAGE_STRING
37
#endif
38
 
39
#ifdef PACKAGE_TARNAME
40
#undef PACKAGE_TARNAME
41
#endif
42
 
43
#ifdef PACKAGE_VERSION
44
#undef PACKAGE_VERSION
45
#endif
46
 
47
#ifdef TRUE
48
#undef TRUE
49
#endif
50
 
51
#ifdef FALSE
52
#undef FALSE
53
#endif
54
 
55
extern "C" {
56
#include "private/dbg_mlc.h"
57
  int GC_n_set_marks(hdr* hhdr);
58
  ptr_t GC_clear_stack(ptr_t p);
59
  extern int GC_gcj_kind;
60
  extern int GC_gcj_debug_kind;
61
}
62
 
63
#endif
64
 
65
#ifdef HAVE_PROC_SELF_MAPS
66
 
67
static int gc_ok = 1;
68
 
69
struct gc_debug_info
70
{
71
  int used;
72
  int free;
73
  int wasted;
74
  int blocks;
75
  FILE* fp;
76
};
77
 
78
static void
79
GC_print_debug_callback(hblk *h, word user_data)
80
{
81
  hdr *hhdr = HDR(h);
82
  size_t bytes = WORDS_TO_BYTES(hhdr -> hb_sz);
83
 
84
  gc_debug_info *pinfo = (gc_debug_info *)user_data;
85
 
86
  fprintf(pinfo->fp, "ptr = %#lx, kind = %d, size = %zd, marks = %d\n",
87
          (unsigned long)h, hhdr->hb_obj_kind, bytes, GC_n_set_marks(hhdr));
88
}
89
 
90
/*
91
  this next section of definitions shouldn't really be here.
92
  copied from boehmgc/allchblk.c
93
*/
94
 
95
# define UNIQUE_THRESHOLD 32
96
# define HUGE_THRESHOLD 256
97
# define FL_COMPRESSION 8
98
# define N_HBLK_FLS (HUGE_THRESHOLD - UNIQUE_THRESHOLD)/FL_COMPRESSION \
99
                         + UNIQUE_THRESHOLD
100
#ifndef USE_MUNMAP
101
extern "C" {
102
  extern word GC_free_bytes[N_HBLK_FLS+1];
103
}
104
#endif
105
 
106
# ifdef USE_MUNMAP
107
#   define IS_MAPPED(hhdr) (((hhdr) -> hb_flags & WAS_UNMAPPED) == 0)
108
# else  /* !USE_MMAP */
109
#   define IS_MAPPED(hhdr) 1
110
# endif /* USE_MUNMAP */
111
 
112
static void
113
GC_print_hblkfreelist_file(FILE *fp)
114
{
115
  struct hblk * h;
116
  word total_free = 0;
117
  hdr * hhdr;
118
  word sz;
119
  int i;
120
 
121
  fprintf(fp, "---------- Begin free map ----------\n");
122
  for (i = 0; i <= N_HBLK_FLS; ++i)
123
    {
124
      h = GC_hblkfreelist[i];
125
#ifdef USE_MUNMAP
126
      if (0 != h)
127
        fprintf (fp, "Free list %ld:\n", (unsigned long)i);
128
#else
129
      if (0 != h)
130
        fprintf (fp, "Free list %ld (Total size %ld):\n",
131
                 (unsigned long)i,
132
                 (unsigned long)GC_free_bytes[i]);
133
#endif
134
      while (h != 0)
135
        {
136
          hhdr = HDR(h);
137
          sz = hhdr -> hb_sz;
138
          fprintf (fp, "\t0x%lx size %lu ", (unsigned long)h,
139
                   (unsigned long)sz);
140
          total_free += sz;
141
 
142
          if (GC_is_black_listed (h, HBLKSIZE) != 0)
143
            fprintf (fp, "start black listed\n");
144
          else if (GC_is_black_listed(h, hhdr -> hb_sz) != 0)
145
            fprintf (fp, "partially black listed\n");
146
          else
147
            fprintf (fp, "not black listed\n");
148
 
149
          h = hhdr -> hb_next;
150
        }
151
    }
152
#ifndef USE_MUNMAP
153
  if (total_free != GC_large_free_bytes)
154
    {
155
      fprintf (fp, "GC_large_free_bytes = %lu (INCONSISTENT!!)\n",
156
               (unsigned long) GC_large_free_bytes);
157
    }
158
#endif
159
  fprintf (fp, "Total of %lu bytes on free list\n", (unsigned long)total_free);
160
  fprintf (fp, "---------- End free map ----------\n");
161
}
162
 
163
static int GC_dump_count = 1;
164
 
165
static void
166
GC_print_debug_info_file(FILE* fp)
167
{
168
  gc_debug_info info;
169
 
170
  memset(&info, 0, sizeof info);
171
  info.fp = fp;
172
 
173
  if (gc_ok)
174
    GC_gcollect();
175
  fprintf(info.fp, "---------- Begin block map ----------\n");
176
  GC_apply_to_all_blocks(GC_print_debug_callback, (word)(void*)(&info));
177
  //fprintf(fp, "#Total used %d free %d wasted %d\n", info.used, info.free, info.wasted);
178
  //fprintf(fp, "#Total blocks %d; %dK bytes\n", info.blocks, info.blocks*4);
179
  fprintf(info.fp, "---------- End block map ----------\n");
180
 
181
  //fprintf(fp, "\n***Free blocks:\n");
182
  //GC_print_hblkfreelist();
183
}
184
 
185
namespace
186
{
187
  class  __attribute__ ((visibility ("hidden"))) GC_enumerator
188
  {
189
  public:
190
    GC_enumerator(const char *name);
191
    void enumerate();
192
  private:
193
    FILE* fp;
194
    int bytes_fd;
195
 
196
    void print_address_map();
197
    void enumerate_callback(struct hblk *h);
198
    static void enumerate_callback_adaptor(struct hblk *h, word dummy);
199
  };
200
}
201
 
202
GC_enumerator::GC_enumerator(const char *name)
203
{
204
  bytes_fd = -1;
205
  fp = fopen (name, "w");
206
  if (!fp)
207
    {
208
      printf ("GC_enumerator failed to open [%s]\n", name);
209
      return;
210
    }
211
  printf ("GC_enumerator saving summary to [%s]\n", name);
212
 
213
  // open heap file
214
  char bytes_name[strlen(name) + 10];
215
  sprintf (bytes_name, "%s.bytes", name);
216
  bytes_fd = open (bytes_name, O_CREAT|O_TRUNC|O_WRONLY, 0666);
217
  if (bytes_fd <= 0)
218
    {
219
      printf ("GC_enumerator failed to open [%s]\n", bytes_name);
220
      return;
221
    }
222
  printf ("GC_enumerator saving heap contents to [%s]\n", bytes_name);
223
}
224
 
225
/*
226
  sample format of /proc/self/maps
227
 
228
  0063b000-00686000 rw-p 001fb000 03:01 81993      /avtrex/bin/dumppropapp
229
  00686000-0072e000 rwxp 00000000 00:00 0
230
 
231
  These are parsed below as:
232
  start   -end      xxxx xxxxxxxx  a:b xxxxxxxxxxxxxxx
233
 
234
*/
235
 
236
 
237
void
238
GC_enumerator::print_address_map()
239
{
240
  FILE* fm;
241
  char buffer[128];
242
 
243
  fprintf(fp, "---------- Begin address map ----------\n");
244
 
245
  fm = fopen("/proc/self/maps", "r");
246
  if (fm == NULL)
247
    {
248
#ifdef HAVE_STRERROR_R
249
      if (0 == strerror_r (errno, buffer, sizeof buffer))
250
        fputs (buffer, fp);
251
#else
252
      fputs (strerror (errno), fp);
253
#endif
254
    }
255
  else
256
    {
257
      while (fgets (buffer, sizeof buffer, fm) != NULL)
258
        {
259
          fputs (buffer, fp);
260
          char *dash = strchr(buffer, '-');
261
          char *colon = strchr(buffer, ':');
262
          if (dash && colon && ((ptrdiff_t)strlen(buffer) > (colon - buffer) + 2))
263
            {
264
              char *endp;
265
              unsigned long start = strtoul(buffer, NULL, 16);
266
              unsigned long end   = strtoul(dash + 1, &endp, 16);
267
              unsigned long a     = strtoul(colon - 2, NULL, 16);
268
              unsigned long b     = strtoul(colon + 1, NULL, 16);
269
              // If it is an anonymous mapping 00:00 and both readable
270
              // and writeable then dump the contents of the mapping
271
              // to the bytes file.  Each block has a header of three
272
              // unsigned longs:
273
              // 0 - The number sizeof(unsigned long) to detect endianness and
274
              //     structure layout.
275
              // 1 - The offset in VM.
276
              // 2 - The Length in bytes.
277
              // Followed by the bytes.
278
              if (!a && !b && endp < colon && 'r' == endp[1] && 'w' == endp[2])
279
                {
280
                  unsigned long t = sizeof(unsigned long);
281
                  write(bytes_fd, (void*)&t, sizeof(t));
282
                  write(bytes_fd, (void*)&start, sizeof(start));
283
                  t = end - start;
284
                  write(bytes_fd, (void*)&t, sizeof(t));
285
                  write(bytes_fd, (void*)start, (end - start));
286
                }
287
            }
288
        }
289
      fclose(fm);
290
    }
291
  fprintf(fp, "---------- End address map ----------\n");
292
  fflush(fp);
293
}
294
 
295
void
296
GC_enumerator::enumerate()
297
{
298
  print_address_map();
299
  fprintf(fp, "---------- Begin object map ----------\n");
300
  if (gc_ok)
301
    GC_gcollect();
302
  GC_apply_to_all_blocks(enumerate_callback_adaptor,
303
                         (word)(void*)(this));
304
  fprintf(fp, "---------- End object map ----------\n");
305
  fflush(fp);
306
 
307
  GC_print_debug_info_file(fp);
308
  fflush(fp);
309
  GC_print_hblkfreelist_file(fp);
310
  fflush(fp);
311
 
312
  close(bytes_fd);
313
  fclose(fp);
314
 
315
  GC_clear_stack(0);
316
}
317
 
318
void
319
GC_enumerator::enumerate_callback_adaptor(struct hblk *h,
320
                                          word dummy)
321
{
322
  GC_enumerator* pinfo = (GC_enumerator*)dummy;
323
  pinfo->enumerate_callback(h);
324
}
325
 
326
void
327
GC_enumerator::enumerate_callback(struct hblk *h)
328
{
329
  hdr * hhdr = HDR(h);
330
  size_t bytes = WORDS_TO_BYTES(hhdr->hb_sz);
331
  int i;
332
 
333
  for (i = 0; i == 0 || (i + bytes <= HBLKSIZE); i += bytes)
334
    {
335
      int inUse = mark_bit_from_hdr(hhdr,BYTES_TO_WORDS(i));  // in use
336
      char *ptr = (char*)h+i;                                 // address
337
      int kind = hhdr->hb_obj_kind;                           // kind
338
      void *klass = 0;
339
      void *data = 0;
340
      if (kind == GC_gcj_kind
341
          || kind == GC_gcj_debug_kind
342
          || kind == GC_gcj_debug_kind+1)
343
        {
344
          void* v = *(void **)ptr;
345
          if (v)
346
            {
347
              klass = *(void **)v;
348
              data = *(void **)(ptr + sizeof(void*));
349
            }
350
        }
351
      if (inUse)
352
        fprintf (fp, "used = %d, ptr = %#lx, size = %zd, kind = %d, "
353
                 "klass = %#lx, data = %#lx\n",
354
                 inUse, (unsigned long)ptr, bytes, kind,
355
                 (unsigned long)klass, (unsigned long)data);
356
    }
357
}
358
 
359
/*
360
 * Fill in a char[] with low bytes of the string characters.  These
361
 * methods may be called while an OutOfMemoryError is being thrown, so
362
 * we cannot call nice java methods to get the encoding of the string.
363
 */
364
static void
365
J2A(::java::lang::String* str, char *dst)
366
{
367
  jchar * pchars = JvGetStringChars(str);
368
  jint len = str->length();
369
  int i;
370
  for (i=0; i<len; i++)
371
    dst[i] = (char)pchars[i];
372
  dst[i] = 0;
373
}
374
 
375
void
376
::gnu::gcj::util::GCInfo::dump0 (::java::lang::String * name)
377
{
378
  char n[name->length() + 1];
379
  J2A(name, n);
380
 
381
  char temp[name->length() + 20];
382
  sprintf(temp, "%s%03d", n, GC_dump_count++);
383
  FILE* fp = fopen(temp, "w");
384
 
385
  GC_print_debug_info_file(fp);
386
 
387
  fclose(fp);
388
}
389
 
390
void
391
::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String * name)
392
{
393
  char n[name->length() + 1];
394
  J2A(name, n);
395
  char temp[name->length() + 20];
396
  sprintf(temp, "%s%03d", n, GC_dump_count++);
397
 
398
  GC_enumerator x(temp);
399
  x.enumerate();
400
}
401
 
402
static char *oomDumpName = NULL;
403
 
404
static void *
405
nomem_handler(size_t size)
406
{
407
  if (oomDumpName)
408
    {
409
      char temp[strlen(oomDumpName) + 20];
410
      sprintf(temp, "%s%03d", oomDumpName, GC_dump_count++);
411
      printf("nomem_handler(%zd) called\n", size);
412
      gc_ok--;
413
      GC_enumerator x(temp);
414
      x.enumerate();
415
      gc_ok++;
416
    }
417
  return (void*)0;
418
}
419
 
420
void
421
::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String * name)
422
{
423
  char *oldName = oomDumpName;
424
  oomDumpName = NULL;
425
  free (oldName);
426
 
427
  if (NULL == name)
428
    return;
429
 
430
  char *n = (char *)malloc(name->length() + 1);
431
 
432
  J2A(name, n);
433
  oomDumpName = n;
434
  GC_oom_fn = nomem_handler;
435
}
436
 
437
#else  // HAVE_PROC_SELF_MAPS
438
 
439
void
440
::gnu::gcj::util::GCInfo::dump0 (::java::lang::String * name)
441
{
442
  // Do nothing if dumping not supported.
443
}
444
 
445
void
446
::gnu::gcj::util::GCInfo::enumerate0 (::java::lang::String * name)
447
{
448
  // Do nothing if dumping not supported.
449
}
450
 
451
void
452
::gnu::gcj::util::GCInfo::setOOMDump0 (::java::lang::String * name)
453
{
454
  // Do nothing if dumping not supported.
455
}
456
 
457
#endif // HAVE_PROC_SELF_MAPS
458
 

powered by: WebSVN 2.1.0

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