1 /*
   2  * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  *
  23  */
  24 
  25 #include "adlc.hpp"
  26 
  27 void* AllocateHeap(size_t size) {
  28   unsigned char* ptr = (unsigned char*) malloc(size);
  29   if (ptr == NULL && size != 0) {
  30     fprintf(stderr, "Error: Out of memory in ADLC\n"); // logging can cause crash!
  31     fflush(stderr);
  32     exit(1);
  33   }
  34   return ptr;
  35 }
  36 
  37 void* Chunk::operator new(size_t requested_size, size_t length) throw() {
  38   return CHeapObj::operator new(requested_size + length);
  39 }
  40 
  41 void  Chunk::operator delete(void* p, size_t length) {
  42   CHeapObj::operator delete(p);
  43 }
  44 
  45 Chunk::Chunk(size_t length) {
  46   _next = NULL;         // Chain on the linked list
  47   _len  = length;       // Save actual size
  48 }
  49 
  50 //------------------------------chop-------------------------------------------
  51 void Chunk::chop() {
  52   Chunk *k = this;
  53   while( k ) {
  54     Chunk *tmp = k->_next;
  55     // clear out this chunk (to detect allocation bugs)
  56     memset(k, 0xBE, k->_len);
  57     free(k);                    // Free chunk (was malloc'd)
  58     k = tmp;
  59   }
  60 }
  61 
  62 void Chunk::next_chop() {
  63   _next->chop();
  64   _next = NULL;
  65 }
  66 
  67 //------------------------------Arena------------------------------------------
  68 Arena::Arena( size_t init_size ) {
  69   init_size = (init_size+3) & ~3;
  70   _first = _chunk = new (init_size) Chunk(init_size);
  71   _hwm = _chunk->bottom();      // Save the cached hwm, max
  72   _max = _chunk->top();
  73   set_size_in_bytes(init_size);
  74 }
  75 
  76 Arena::Arena() {
  77   _first = _chunk = new (Chunk::init_size) Chunk(Chunk::init_size);
  78   _hwm = _chunk->bottom();      // Save the cached hwm, max
  79   _max = _chunk->top();
  80   set_size_in_bytes(Chunk::init_size);
  81 }
  82 
  83 Arena::Arena( Arena *a )
  84 : _chunk(a->_chunk), _hwm(a->_hwm), _max(a->_max), _first(a->_first) {
  85   set_size_in_bytes(a->size_in_bytes());
  86 }
  87 
  88 //------------------------------used-------------------------------------------
  89 // Total of all Chunks in arena
  90 size_t Arena::used() const {
  91   size_t sum = _chunk->_len - (_max-_hwm); // Size leftover in this Chunk
  92   Chunk *k = _first;
  93   while( k != _chunk) {         // Whilst have Chunks in a row
  94     sum += k->_len;             // Total size of this Chunk
  95     k = k->_next;               // Bump along to next Chunk
  96   }
  97   return sum;                   // Return total consumed space.
  98 }
  99 
 100 //------------------------------grow-------------------------------------------
 101 // Grow a new Chunk
 102 void* Arena::grow( size_t x ) {
 103   // Get minimal required size.  Either real big, or even bigger for giant objs
 104   size_t len = max(x, Chunk::size);
 105 
 106   Chunk *k = _chunk;            // Get filled-up chunk address
 107   _chunk = new (len) Chunk(len);
 108 
 109   if( k ) k->_next = _chunk;    // Append new chunk to end of linked list
 110   else _first = _chunk;
 111   _hwm  = _chunk->bottom();     // Save the cached hwm, max
 112   _max =  _chunk->top();
 113   set_size_in_bytes(size_in_bytes() + len);
 114   void* result = _hwm;
 115   _hwm += x;
 116   return result;
 117 }
 118 
 119 //------------------------------calloc-----------------------------------------
 120 // Allocate zeroed storage in Arena
 121 void *Arena::Acalloc( size_t items, size_t x ) {
 122   size_t z = items*x;   // Total size needed
 123   void *ptr = Amalloc(z);       // Get space
 124   memset( ptr, 0, z );          // Zap space
 125   return ptr;                   // Return space
 126 }
 127 
 128 //------------------------------realloc----------------------------------------
 129 // Reallocate storage in Arena.
 130 void *Arena::Arealloc( void *old_ptr, size_t old_size, size_t new_size ) {
 131   char *c_old = (char*)old_ptr; // Handy name
 132   // Stupid fast special case
 133   if( new_size <= old_size ) {  // Shrink in-place
 134     if( c_old+old_size == _hwm) // Attempt to free the excess bytes
 135       _hwm = c_old+new_size;    // Adjust hwm
 136     return c_old;
 137   }
 138 
 139   // See if we can resize in-place
 140   if( (c_old+old_size == _hwm) &&       // Adjusting recent thing
 141       (c_old+new_size <= _max) ) {      // Still fits where it sits
 142     _hwm = c_old+new_size;      // Adjust hwm
 143     return c_old;               // Return old pointer
 144   }
 145 
 146   // Oops, got to relocate guts
 147   void *new_ptr = Amalloc(new_size);
 148   memcpy( new_ptr, c_old, old_size );
 149   Afree(c_old,old_size);        // Mostly done to keep stats accurate
 150   return new_ptr;
 151 }
 152 
 153 //------------------------------reset------------------------------------------
 154 // Reset this Arena to empty, and return this Arenas guts in a new Arena.
 155 Arena *Arena::reset(void) {
 156   Arena *a = new Arena(this);   // New empty arena
 157   _first = _chunk = NULL;       // Normal, new-arena initialization
 158   _hwm = _max = NULL;
 159   return a;                     // Return Arena with guts
 160 }
 161 
 162 //------------------------------contains---------------------------------------
 163 // Determine if pointer belongs to this Arena or not.
 164 bool Arena::contains( const void *ptr ) const {
 165   if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm )
 166     return true;                // Check for in this chunk
 167   for( Chunk *c = _first; c; c = c->_next )
 168     if( (void*)c->bottom() <= ptr && ptr < (void*)c->top())
 169       return true;              // Check for every chunk in Arena
 170   return false;                 // Not in any Chunk, so not in Arena
 171 }
 172 
 173 //-----------------------------------------------------------------------------
 174 // CHeapObj
 175 
 176 void* CHeapObj::operator new(size_t size) throw() {
 177   return (void *) AllocateHeap(size);
 178 }
 179 
 180 void CHeapObj::operator delete(void* p){
 181  free(p);
 182 }