array.hpp revision 3465:d2a62e0f25eb
1/*
2 * Copyright (c) 2000, 2010, 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#ifndef SHARE_VM_UTILITIES_ARRAY_HPP
26#define SHARE_VM_UTILITIES_ARRAY_HPP
27
28#include "memory/allocation.hpp"
29#include "memory/allocation.inline.hpp"
30
31// correct linkage required to compile w/o warnings
32// (must be on file level - cannot be local)
33extern "C" { typedef int (*ftype)(const void*, const void*); }
34
35
36class ResourceArray: public ResourceObj {
37 protected:
38  int   _length;                                 // the number of array elements
39  void* _data;                                   // the array memory
40#ifdef ASSERT
41  int   _nesting;                                // the resource area nesting level
42#endif
43
44  // creation
45  ResourceArray() {
46    _length  = 0;
47    _data    = NULL;
48    DEBUG_ONLY(init_nesting();)
49    // client may call initialize, at most once
50  }
51
52
53  ResourceArray(size_t esize, int length) {
54    DEBUG_ONLY(_data = NULL);
55    initialize(esize, length);
56  }
57
58  void initialize(size_t esize, int length) {
59    assert(length >= 0, "illegal length");
60    assert(_data == NULL, "must be new object");
61    _length  = length;
62    _data    = resource_allocate_bytes(esize * length);
63    DEBUG_ONLY(init_nesting();)
64  }
65
66#ifdef ASSERT
67  void init_nesting();
68#endif
69
70  // helper functions
71  void sort     (size_t esize, ftype f);         // sort the array
72  void expand   (size_t esize, int i, int& size);// expand the array to include slot i
73  void remove_at(size_t esize, int i);           // remove the element in slot i
74
75 public:
76  // standard operations
77  int  length() const                            { return _length; }
78  bool is_empty() const                          { return length() == 0; }
79};
80
81
82template <MEMFLAGS F>class CHeapArray: public CHeapObj<F> {
83 protected:
84  int   _length;                                 // the number of array elements
85  void* _data;                                   // the array memory
86
87  // creation
88  CHeapArray() {
89    _length  = 0;
90    _data    = NULL;
91  }
92
93
94  CHeapArray(size_t esize, int length) {
95    assert(length >= 0, "illegal length");
96    _length  = length;
97    _data    = (void*) NEW_C_HEAP_ARRAY(char *, esize * length, F);
98  }
99
100#ifdef ASSERT
101  void init_nesting();
102#endif
103
104  // helper functions
105  void sort     (size_t esize, ftype f);         // sort the array
106  void expand   (size_t esize, int i, int& size);// expand the array to include slot i
107  void remove_at(size_t esize, int i);           // remove the element in slot i
108
109 public:
110  // standard operations
111  int  length() const                            { return _length; }
112  bool is_empty() const                          { return length() == 0; }
113};
114
115#define define_generic_array(array_name,element_type, base_class)                        \
116  class array_name: public base_class {                                                  \
117   protected:                                                                            \
118    typedef element_type etype;                                                          \
119    enum { esize = sizeof(etype) };                                                      \
120                                                                                         \
121    void base_remove_at(size_t size, int i) { base_class::remove_at(size, i); }          \
122                                                                                         \
123   public:                                                                               \
124    /* creation */                                                                       \
125    array_name() : base_class()                       {}                                 \
126    array_name(const int length) : base_class(esize, length) {}                          \
127    array_name(const int length, const etype fx)      { initialize(length, fx); }        \
128    void initialize(const int length)     { base_class::initialize(esize, length); }     \
129    void initialize(const int length, const etype fx) {                                  \
130      initialize(length);                                                                \
131      for (int i = 0; i < length; i++) ((etype*)_data)[i] = fx;                          \
132    }                                                                                    \
133                                                                                         \
134    /* standard operations */                                                            \
135    etype& operator [] (const int i) const {                                             \
136      assert(0 <= i && i < length(), "index out of bounds");                             \
137      return ((etype*)_data)[i];                                                         \
138    }                                                                                    \
139                                                                                         \
140    int index_of(const etype x) const {                                                  \
141      int i = length();                                                                  \
142      while (i-- > 0 && ((etype*)_data)[i] != x) ;                                       \
143      /* i < 0 || ((etype*)_data)_data[i] == x */                                        \
144      return i;                                                                          \
145    }                                                                                    \
146                                                                                         \
147    void sort(int f(etype*, etype*))             { base_class::sort(esize, (ftype)f); }  \
148    bool contains(const etype x) const           { return index_of(x) >= 0; }            \
149                                                                                         \
150    /* deprecated operations - for compatibility with GrowableArray only */              \
151    etype  at(const int i) const                 { return (*this)[i]; }                  \
152    void   at_put(const int i, const etype x)    { (*this)[i] = x; }                     \
153    etype* adr_at(const int i)                   { return &(*this)[i]; }                 \
154    int    find(const etype x)                   { return index_of(x); }                 \
155  };                                                                                     \
156
157
158#define define_array(array_name,element_type)                                            \
159  define_generic_array(array_name, element_type, ResourceArray)
160
161
162#define define_stack(stack_name,array_name)                                              \
163  class stack_name: public array_name {                                                  \
164   protected:                                                                            \
165    int _size;                                                                           \
166                                                                                         \
167    void grow(const int i, const etype fx) {                                             \
168      assert(i >= length(), "index too small");                                          \
169      if (i >= size()) expand(esize, i, _size);                                          \
170      for (int j = length(); j <= i; j++) ((etype*)_data)[j] = fx;                       \
171      _length = i+1;                                                                     \
172    }                                                                                    \
173                                                                                         \
174   public:                                                                               \
175    /* creation */                                                                       \
176    stack_name() : array_name()                     { _size = 0; }                       \
177    stack_name(const int size)                      { initialize(size); }                \
178    stack_name(const int size, const etype fx)      { initialize(size, fx); }            \
179    void initialize(const int size, const etype fx) {                                    \
180      _size = size;                                                                      \
181      array_name::initialize(size, fx);                                                  \
182      /* _length == size, allocation and size are the same */                            \
183    }                                                                                    \
184    void initialize(const int size) {                                                    \
185      _size = size;                                                                      \
186      array_name::initialize(size);                                                      \
187      _length = 0;          /* reset length to zero; _size records the allocation */     \
188    }                                                                                    \
189                                                                                         \
190    /* standard operations */                                                            \
191    int size() const                             { return _size; }                       \
192                                                                                         \
193    int push(const etype x) {                                                            \
194      int len = length();                                                                \
195      if (len >= size()) expand(esize, len, _size);                                      \
196      ((etype*)_data)[len] = x;                                                          \
197      _length = len+1;                                                                   \
198      return len;                                                                        \
199    }                                                                                    \
200                                                                                         \
201    etype pop() {                                                                        \
202      assert(!is_empty(), "stack is empty");                                             \
203      return ((etype*)_data)[--_length];                                                 \
204    }                                                                                    \
205                                                                                         \
206    etype top() const {                                                                  \
207      assert(!is_empty(), "stack is empty");                                             \
208      return ((etype*)_data)[length() - 1];                                              \
209    }                                                                                    \
210                                                                                         \
211    void push_all(const stack_name* stack) {                                             \
212      const int l = stack->length();                                                     \
213      for (int i = 0; i < l; i++) push(((etype*)(stack->_data))[i]);                     \
214    }                                                                                    \
215                                                                                         \
216    etype at_grow(const int i, const etype fx) {                                         \
217      if (i >= length()) grow(i, fx);                                                    \
218      return ((etype*)_data)[i];                                                         \
219    }                                                                                    \
220                                                                                         \
221    void at_put_grow(const int i, const etype x, const etype fx) {                       \
222      if (i >= length()) grow(i, fx);                                                    \
223      ((etype*)_data)[i] = x;                                                            \
224    }                                                                                    \
225                                                                                         \
226    void truncate(const int length) {                                                    \
227      assert(0 <= length && length <= this->length(), "illegal length");                 \
228      _length = length;                                                                  \
229    }                                                                                    \
230                                                                                         \
231    void remove_at(int i)                        { base_remove_at(esize, i); }           \
232    void remove(etype x)                         { remove_at(index_of(x)); }             \
233                                                                                         \
234    /* inserts the given element before the element at index i */                        \
235    void insert_before(const int i, const etype el)  {                                   \
236      int len = length();                                                                \
237      int new_length = len + 1;                                                          \
238      if (new_length >= size()) expand(esize, new_length, _size);                        \
239      for (int j = len - 1; j >= i; j--) {                                               \
240        ((etype*)_data)[j + 1] = ((etype*)_data)[j];                                     \
241      }                                                                                  \
242      _length = new_length;                                                              \
243      at_put(i, el);                                                                     \
244    }                                                                                    \
245                                                                                         \
246    /* inserts contents of the given stack before the element at index i */              \
247    void insert_before(const int i, const stack_name *st) {                              \
248      if (st->length() == 0) return;                                                     \
249      int len = length();                                                                \
250      int st_len = st->length();                                                         \
251      int new_length = len + st_len;                                                     \
252      if (new_length >= size()) expand(esize, new_length, _size);                        \
253      int j;                                                                             \
254      for (j = len - 1; j >= i; j--) {                                                   \
255        ((etype*)_data)[j + st_len] = ((etype*)_data)[j];                                \
256      }                                                                                  \
257      for (j = 0; j < st_len; j++) {                                                     \
258        ((etype*)_data)[i + j] = ((etype*)st->_data)[j];                                 \
259      }                                                                                  \
260      _length = new_length;                                                              \
261    }                                                                                    \
262                                                                                         \
263    /* deprecated operations - for compatibility with GrowableArray only */              \
264    int  capacity() const                        { return size(); }                      \
265    void clear()                                 { truncate(0); }                        \
266    void trunc_to(const int length)              { truncate(length); }                   \
267    int  append(const etype x)                   { return push(x); }                     \
268    void appendAll(const stack_name* stack)      { push_all(stack); }                    \
269    etype last() const                           { return top(); }                       \
270  };                                                                                     \
271
272
273#define define_resource_list(element_type)                                               \
274  define_generic_array(element_type##Array, element_type, ResourceArray)                 \
275  define_stack(element_type##List, element_type##Array)
276
277#define define_resource_pointer_list(element_type)                                       \
278  define_generic_array(element_type##Array, element_type *, ResourceArray)               \
279  define_stack(element_type##List, element_type##Array)
280
281#define define_c_heap_list(element_type)                                                 \
282  define_generic_array(element_type##Array, element_type, CHeapArray)                    \
283  define_stack(element_type##List, element_type##Array)
284
285#define define_c_heap_pointer_list(element_type)                                         \
286  define_generic_array(element_type##Array, element_type *, CHeapArray)                  \
287  define_stack(element_type##List, element_type##Array)
288
289
290// Arrays for basic types
291
292define_array(boolArray, bool)          define_stack(boolStack, boolArray)
293define_array(intArray , int )          define_stack(intStack , intArray )
294
295#endif // SHARE_VM_UTILITIES_ARRAY_HPP
296