1*c05d8e5dSAndroid Build Coastguard Worker //===-------------------------- cxa_vector.cpp ---------------------------===//
2*c05d8e5dSAndroid Build Coastguard Worker //
3*c05d8e5dSAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*c05d8e5dSAndroid Build Coastguard Worker //
5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open
6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details.
7*c05d8e5dSAndroid Build Coastguard Worker //
8*c05d8e5dSAndroid Build Coastguard Worker //
9*c05d8e5dSAndroid Build Coastguard Worker // This file implements the "Array Construction and Destruction APIs"
10*c05d8e5dSAndroid Build Coastguard Worker // http://mentorembedded.github.io/cxx-abi/abi.html#array-ctor
11*c05d8e5dSAndroid Build Coastguard Worker //
12*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*c05d8e5dSAndroid Build Coastguard Worker
14*c05d8e5dSAndroid Build Coastguard Worker #include "cxxabi.h"
15*c05d8e5dSAndroid Build Coastguard Worker
16*c05d8e5dSAndroid Build Coastguard Worker #include <exception> // for std::terminate
17*c05d8e5dSAndroid Build Coastguard Worker
18*c05d8e5dSAndroid Build Coastguard Worker namespace __cxxabiv1 {
19*c05d8e5dSAndroid Build Coastguard Worker
20*c05d8e5dSAndroid Build Coastguard Worker #if 0
21*c05d8e5dSAndroid Build Coastguard Worker #pragma mark --Helper routines and classes --
22*c05d8e5dSAndroid Build Coastguard Worker #endif
23*c05d8e5dSAndroid Build Coastguard Worker
24*c05d8e5dSAndroid Build Coastguard Worker namespace {
__get_element_count(void * p)25*c05d8e5dSAndroid Build Coastguard Worker inline static size_t __get_element_count ( void *p ) {
26*c05d8e5dSAndroid Build Coastguard Worker return static_cast <size_t *> (p)[-1];
27*c05d8e5dSAndroid Build Coastguard Worker }
28*c05d8e5dSAndroid Build Coastguard Worker
__set_element_count(void * p,size_t element_count)29*c05d8e5dSAndroid Build Coastguard Worker inline static void __set_element_count ( void *p, size_t element_count ) {
30*c05d8e5dSAndroid Build Coastguard Worker static_cast <size_t *> (p)[-1] = element_count;
31*c05d8e5dSAndroid Build Coastguard Worker }
32*c05d8e5dSAndroid Build Coastguard Worker
33*c05d8e5dSAndroid Build Coastguard Worker
34*c05d8e5dSAndroid Build Coastguard Worker // A pair of classes to simplify exception handling and control flow.
35*c05d8e5dSAndroid Build Coastguard Worker // They get passed a block of memory in the constructor, and unless the
36*c05d8e5dSAndroid Build Coastguard Worker // 'release' method is called, they deallocate the memory in the destructor.
37*c05d8e5dSAndroid Build Coastguard Worker // Preferred usage is to allocate some memory, attach it to one of these objects,
38*c05d8e5dSAndroid Build Coastguard Worker // and then, when all the operations to set up the memory block have succeeded,
39*c05d8e5dSAndroid Build Coastguard Worker // call 'release'. If any of the setup operations fail, or an exception is
40*c05d8e5dSAndroid Build Coastguard Worker // thrown, then the block is automatically deallocated.
41*c05d8e5dSAndroid Build Coastguard Worker //
42*c05d8e5dSAndroid Build Coastguard Worker // The only difference between these two classes is the signature for the
43*c05d8e5dSAndroid Build Coastguard Worker // deallocation function (to match new2/new3 and delete2/delete3.
44*c05d8e5dSAndroid Build Coastguard Worker class st_heap_block2 {
45*c05d8e5dSAndroid Build Coastguard Worker public:
46*c05d8e5dSAndroid Build Coastguard Worker typedef void (*dealloc_f)(void *);
47*c05d8e5dSAndroid Build Coastguard Worker
st_heap_block2(dealloc_f dealloc,void * ptr)48*c05d8e5dSAndroid Build Coastguard Worker st_heap_block2 ( dealloc_f dealloc, void *ptr )
49*c05d8e5dSAndroid Build Coastguard Worker : dealloc_ ( dealloc ), ptr_ ( ptr ), enabled_ ( true ) {}
~st_heap_block2()50*c05d8e5dSAndroid Build Coastguard Worker ~st_heap_block2 () { if ( enabled_ ) dealloc_ ( ptr_ ) ; }
release()51*c05d8e5dSAndroid Build Coastguard Worker void release () { enabled_ = false; }
52*c05d8e5dSAndroid Build Coastguard Worker
53*c05d8e5dSAndroid Build Coastguard Worker private:
54*c05d8e5dSAndroid Build Coastguard Worker dealloc_f dealloc_;
55*c05d8e5dSAndroid Build Coastguard Worker void *ptr_;
56*c05d8e5dSAndroid Build Coastguard Worker bool enabled_;
57*c05d8e5dSAndroid Build Coastguard Worker };
58*c05d8e5dSAndroid Build Coastguard Worker
59*c05d8e5dSAndroid Build Coastguard Worker class st_heap_block3 {
60*c05d8e5dSAndroid Build Coastguard Worker public:
61*c05d8e5dSAndroid Build Coastguard Worker typedef void (*dealloc_f)(void *, size_t);
62*c05d8e5dSAndroid Build Coastguard Worker
st_heap_block3(dealloc_f dealloc,void * ptr,size_t size)63*c05d8e5dSAndroid Build Coastguard Worker st_heap_block3 ( dealloc_f dealloc, void *ptr, size_t size )
64*c05d8e5dSAndroid Build Coastguard Worker : dealloc_ ( dealloc ), ptr_ ( ptr ), size_ ( size ), enabled_ ( true ) {}
~st_heap_block3()65*c05d8e5dSAndroid Build Coastguard Worker ~st_heap_block3 () { if ( enabled_ ) dealloc_ ( ptr_, size_ ) ; }
release()66*c05d8e5dSAndroid Build Coastguard Worker void release () { enabled_ = false; }
67*c05d8e5dSAndroid Build Coastguard Worker
68*c05d8e5dSAndroid Build Coastguard Worker private:
69*c05d8e5dSAndroid Build Coastguard Worker dealloc_f dealloc_;
70*c05d8e5dSAndroid Build Coastguard Worker void *ptr_;
71*c05d8e5dSAndroid Build Coastguard Worker size_t size_;
72*c05d8e5dSAndroid Build Coastguard Worker bool enabled_;
73*c05d8e5dSAndroid Build Coastguard Worker };
74*c05d8e5dSAndroid Build Coastguard Worker
75*c05d8e5dSAndroid Build Coastguard Worker class st_cxa_cleanup {
76*c05d8e5dSAndroid Build Coastguard Worker public:
77*c05d8e5dSAndroid Build Coastguard Worker typedef void (*destruct_f)(void *);
78*c05d8e5dSAndroid Build Coastguard Worker
st_cxa_cleanup(void * ptr,size_t & idx,size_t element_size,destruct_f destructor)79*c05d8e5dSAndroid Build Coastguard Worker st_cxa_cleanup ( void *ptr, size_t &idx, size_t element_size, destruct_f destructor )
80*c05d8e5dSAndroid Build Coastguard Worker : ptr_ ( ptr ), idx_ ( idx ), element_size_ ( element_size ),
81*c05d8e5dSAndroid Build Coastguard Worker destructor_ ( destructor ), enabled_ ( true ) {}
~st_cxa_cleanup()82*c05d8e5dSAndroid Build Coastguard Worker ~st_cxa_cleanup () {
83*c05d8e5dSAndroid Build Coastguard Worker if ( enabled_ )
84*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_cleanup ( ptr_, idx_, element_size_, destructor_ );
85*c05d8e5dSAndroid Build Coastguard Worker }
86*c05d8e5dSAndroid Build Coastguard Worker
release()87*c05d8e5dSAndroid Build Coastguard Worker void release () { enabled_ = false; }
88*c05d8e5dSAndroid Build Coastguard Worker
89*c05d8e5dSAndroid Build Coastguard Worker private:
90*c05d8e5dSAndroid Build Coastguard Worker void *ptr_;
91*c05d8e5dSAndroid Build Coastguard Worker size_t &idx_;
92*c05d8e5dSAndroid Build Coastguard Worker size_t element_size_;
93*c05d8e5dSAndroid Build Coastguard Worker destruct_f destructor_;
94*c05d8e5dSAndroid Build Coastguard Worker bool enabled_;
95*c05d8e5dSAndroid Build Coastguard Worker };
96*c05d8e5dSAndroid Build Coastguard Worker
97*c05d8e5dSAndroid Build Coastguard Worker class st_terminate {
98*c05d8e5dSAndroid Build Coastguard Worker public:
st_terminate(bool enabled=true)99*c05d8e5dSAndroid Build Coastguard Worker st_terminate ( bool enabled = true ) : enabled_ ( enabled ) {}
~st_terminate()100*c05d8e5dSAndroid Build Coastguard Worker ~st_terminate () { if ( enabled_ ) std::terminate (); }
release()101*c05d8e5dSAndroid Build Coastguard Worker void release () { enabled_ = false; }
102*c05d8e5dSAndroid Build Coastguard Worker private:
103*c05d8e5dSAndroid Build Coastguard Worker bool enabled_ ;
104*c05d8e5dSAndroid Build Coastguard Worker };
105*c05d8e5dSAndroid Build Coastguard Worker }
106*c05d8e5dSAndroid Build Coastguard Worker
107*c05d8e5dSAndroid Build Coastguard Worker #if 0
108*c05d8e5dSAndroid Build Coastguard Worker #pragma mark --Externally visible routines--
109*c05d8e5dSAndroid Build Coastguard Worker #endif
110*c05d8e5dSAndroid Build Coastguard Worker
111*c05d8e5dSAndroid Build Coastguard Worker extern "C" {
112*c05d8e5dSAndroid Build Coastguard Worker
113*c05d8e5dSAndroid Build Coastguard Worker // Equivalent to
114*c05d8e5dSAndroid Build Coastguard Worker //
115*c05d8e5dSAndroid Build Coastguard Worker // __cxa_vec_new2(element_count, element_size, padding_size, constructor,
116*c05d8e5dSAndroid Build Coastguard Worker // destructor, &::operator new[], &::operator delete[])
117*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void *
__cxa_vec_new(size_t element_count,size_t element_size,size_t padding_size,void (* constructor)(void *),void (* destructor)(void *))118*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size,
119*c05d8e5dSAndroid Build Coastguard Worker void (*constructor)(void *), void (*destructor)(void *)) {
120*c05d8e5dSAndroid Build Coastguard Worker return __cxa_vec_new2 ( element_count, element_size, padding_size,
121*c05d8e5dSAndroid Build Coastguard Worker constructor, destructor, &::operator new [], &::operator delete [] );
122*c05d8e5dSAndroid Build Coastguard Worker }
123*c05d8e5dSAndroid Build Coastguard Worker
124*c05d8e5dSAndroid Build Coastguard Worker
125*c05d8e5dSAndroid Build Coastguard Worker
126*c05d8e5dSAndroid Build Coastguard Worker // Given the number and size of elements for an array and the non-negative
127*c05d8e5dSAndroid Build Coastguard Worker // size of prefix padding for a cookie, allocate space (using alloc) for
128*c05d8e5dSAndroid Build Coastguard Worker // the array preceded by the specified padding, initialize the cookie if
129*c05d8e5dSAndroid Build Coastguard Worker // the padding is non-zero, and call the given constructor on each element.
130*c05d8e5dSAndroid Build Coastguard Worker // Return the address of the array proper, after the padding.
131*c05d8e5dSAndroid Build Coastguard Worker //
132*c05d8e5dSAndroid Build Coastguard Worker // If alloc throws an exception, rethrow the exception. If alloc returns
133*c05d8e5dSAndroid Build Coastguard Worker // NULL, return NULL. If the constructor throws an exception, call
134*c05d8e5dSAndroid Build Coastguard Worker // destructor for any already constructed elements, and rethrow the
135*c05d8e5dSAndroid Build Coastguard Worker // exception. If the destructor throws an exception, call std::terminate.
136*c05d8e5dSAndroid Build Coastguard Worker //
137*c05d8e5dSAndroid Build Coastguard Worker // The constructor may be NULL, in which case it must not be called. If the
138*c05d8e5dSAndroid Build Coastguard Worker // padding_size is zero, the destructor may be NULL; in that case it must
139*c05d8e5dSAndroid Build Coastguard Worker // not be called.
140*c05d8e5dSAndroid Build Coastguard Worker //
141*c05d8e5dSAndroid Build Coastguard Worker // Neither alloc nor dealloc may be NULL.
142*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void *
__cxa_vec_new2(size_t element_count,size_t element_size,size_t padding_size,void (* constructor)(void *),void (* destructor)(void *),void * (* alloc)(size_t),void (* dealloc)(void *))143*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size,
144*c05d8e5dSAndroid Build Coastguard Worker void (*constructor)(void *), void (*destructor)(void *),
145*c05d8e5dSAndroid Build Coastguard Worker void *(*alloc)(size_t), void (*dealloc)(void *)) {
146*c05d8e5dSAndroid Build Coastguard Worker const size_t heap_size = element_count * element_size + padding_size;
147*c05d8e5dSAndroid Build Coastguard Worker char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
148*c05d8e5dSAndroid Build Coastguard Worker char *vec_base = heap_block;
149*c05d8e5dSAndroid Build Coastguard Worker
150*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != vec_base ) {
151*c05d8e5dSAndroid Build Coastguard Worker st_heap_block2 heap ( dealloc, heap_block );
152*c05d8e5dSAndroid Build Coastguard Worker
153*c05d8e5dSAndroid Build Coastguard Worker // put the padding before the array elements
154*c05d8e5dSAndroid Build Coastguard Worker if ( 0 != padding_size ) {
155*c05d8e5dSAndroid Build Coastguard Worker vec_base += padding_size;
156*c05d8e5dSAndroid Build Coastguard Worker __set_element_count ( vec_base, element_count );
157*c05d8e5dSAndroid Build Coastguard Worker }
158*c05d8e5dSAndroid Build Coastguard Worker
159*c05d8e5dSAndroid Build Coastguard Worker // Construct the elements
160*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor );
161*c05d8e5dSAndroid Build Coastguard Worker heap.release (); // We're good!
162*c05d8e5dSAndroid Build Coastguard Worker }
163*c05d8e5dSAndroid Build Coastguard Worker
164*c05d8e5dSAndroid Build Coastguard Worker return vec_base;
165*c05d8e5dSAndroid Build Coastguard Worker }
166*c05d8e5dSAndroid Build Coastguard Worker
167*c05d8e5dSAndroid Build Coastguard Worker
168*c05d8e5dSAndroid Build Coastguard Worker // Same as __cxa_vec_new2 except that the deallocation function takes both
169*c05d8e5dSAndroid Build Coastguard Worker // the object address and its size.
170*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void *
__cxa_vec_new3(size_t element_count,size_t element_size,size_t padding_size,void (* constructor)(void *),void (* destructor)(void *),void * (* alloc)(size_t),void (* dealloc)(void *,size_t))171*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size,
172*c05d8e5dSAndroid Build Coastguard Worker void (*constructor)(void *), void (*destructor)(void *),
173*c05d8e5dSAndroid Build Coastguard Worker void *(*alloc)(size_t), void (*dealloc)(void *, size_t)) {
174*c05d8e5dSAndroid Build Coastguard Worker const size_t heap_size = element_count * element_size + padding_size;
175*c05d8e5dSAndroid Build Coastguard Worker char * const heap_block = static_cast<char *> ( alloc ( heap_size ));
176*c05d8e5dSAndroid Build Coastguard Worker char *vec_base = heap_block;
177*c05d8e5dSAndroid Build Coastguard Worker
178*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != vec_base ) {
179*c05d8e5dSAndroid Build Coastguard Worker st_heap_block3 heap ( dealloc, heap_block, heap_size );
180*c05d8e5dSAndroid Build Coastguard Worker
181*c05d8e5dSAndroid Build Coastguard Worker // put the padding before the array elements
182*c05d8e5dSAndroid Build Coastguard Worker if ( 0 != padding_size ) {
183*c05d8e5dSAndroid Build Coastguard Worker vec_base += padding_size;
184*c05d8e5dSAndroid Build Coastguard Worker __set_element_count ( vec_base, element_count );
185*c05d8e5dSAndroid Build Coastguard Worker }
186*c05d8e5dSAndroid Build Coastguard Worker
187*c05d8e5dSAndroid Build Coastguard Worker // Construct the elements
188*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_ctor ( vec_base, element_count, element_size, constructor, destructor );
189*c05d8e5dSAndroid Build Coastguard Worker heap.release (); // We're good!
190*c05d8e5dSAndroid Build Coastguard Worker }
191*c05d8e5dSAndroid Build Coastguard Worker
192*c05d8e5dSAndroid Build Coastguard Worker return vec_base;
193*c05d8e5dSAndroid Build Coastguard Worker }
194*c05d8e5dSAndroid Build Coastguard Worker
195*c05d8e5dSAndroid Build Coastguard Worker
196*c05d8e5dSAndroid Build Coastguard Worker // Given the (data) addresses of a destination and a source array, an
197*c05d8e5dSAndroid Build Coastguard Worker // element count and an element size, call the given copy constructor to
198*c05d8e5dSAndroid Build Coastguard Worker // copy each element from the source array to the destination array. The
199*c05d8e5dSAndroid Build Coastguard Worker // copy constructor's arguments are the destination address and source
200*c05d8e5dSAndroid Build Coastguard Worker // address, respectively. If an exception occurs, call the given destructor
201*c05d8e5dSAndroid Build Coastguard Worker // (if non-NULL) on each copied element and rethrow. If the destructor
202*c05d8e5dSAndroid Build Coastguard Worker // throws an exception, call terminate(). The constructor and or destructor
203*c05d8e5dSAndroid Build Coastguard Worker // pointers may be NULL. If either is NULL, no action is taken when it
204*c05d8e5dSAndroid Build Coastguard Worker // would have been called.
205*c05d8e5dSAndroid Build Coastguard Worker
__cxa_vec_cctor(void * dest_array,void * src_array,size_t element_count,size_t element_size,void (* constructor)(void *,void *),void (* destructor)(void *))206*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void __cxa_vec_cctor(void *dest_array, void *src_array,
207*c05d8e5dSAndroid Build Coastguard Worker size_t element_count,
208*c05d8e5dSAndroid Build Coastguard Worker size_t element_size,
209*c05d8e5dSAndroid Build Coastguard Worker void (*constructor)(void *, void *),
210*c05d8e5dSAndroid Build Coastguard Worker void (*destructor)(void *)) {
211*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != constructor ) {
212*c05d8e5dSAndroid Build Coastguard Worker size_t idx = 0;
213*c05d8e5dSAndroid Build Coastguard Worker char *src_ptr = static_cast<char *>(src_array);
214*c05d8e5dSAndroid Build Coastguard Worker char *dest_ptr = static_cast<char *>(dest_array);
215*c05d8e5dSAndroid Build Coastguard Worker st_cxa_cleanup cleanup ( dest_array, idx, element_size, destructor );
216*c05d8e5dSAndroid Build Coastguard Worker
217*c05d8e5dSAndroid Build Coastguard Worker for ( idx = 0; idx < element_count;
218*c05d8e5dSAndroid Build Coastguard Worker ++idx, src_ptr += element_size, dest_ptr += element_size )
219*c05d8e5dSAndroid Build Coastguard Worker constructor ( dest_ptr, src_ptr );
220*c05d8e5dSAndroid Build Coastguard Worker cleanup.release (); // We're good!
221*c05d8e5dSAndroid Build Coastguard Worker }
222*c05d8e5dSAndroid Build Coastguard Worker }
223*c05d8e5dSAndroid Build Coastguard Worker
224*c05d8e5dSAndroid Build Coastguard Worker
225*c05d8e5dSAndroid Build Coastguard Worker // Given the (data) address of an array, not including any cookie padding,
226*c05d8e5dSAndroid Build Coastguard Worker // and the number and size of its elements, call the given constructor on
227*c05d8e5dSAndroid Build Coastguard Worker // each element. If the constructor throws an exception, call the given
228*c05d8e5dSAndroid Build Coastguard Worker // destructor for any already-constructed elements, and rethrow the
229*c05d8e5dSAndroid Build Coastguard Worker // exception. If the destructor throws an exception, call terminate(). The
230*c05d8e5dSAndroid Build Coastguard Worker // constructor and/or destructor pointers may be NULL. If either is NULL,
231*c05d8e5dSAndroid Build Coastguard Worker // no action is taken when it would have been called.
232*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void
__cxa_vec_ctor(void * array_address,size_t element_count,size_t element_size,void (* constructor)(void *),void (* destructor)(void *))233*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_ctor(void *array_address, size_t element_count, size_t element_size,
234*c05d8e5dSAndroid Build Coastguard Worker void (*constructor)(void *), void (*destructor)(void *)) {
235*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != constructor ) {
236*c05d8e5dSAndroid Build Coastguard Worker size_t idx;
237*c05d8e5dSAndroid Build Coastguard Worker char *ptr = static_cast <char *> ( array_address );
238*c05d8e5dSAndroid Build Coastguard Worker st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor );
239*c05d8e5dSAndroid Build Coastguard Worker
240*c05d8e5dSAndroid Build Coastguard Worker // Construct the elements
241*c05d8e5dSAndroid Build Coastguard Worker for ( idx = 0; idx < element_count; ++idx, ptr += element_size )
242*c05d8e5dSAndroid Build Coastguard Worker constructor ( ptr );
243*c05d8e5dSAndroid Build Coastguard Worker cleanup.release (); // We're good!
244*c05d8e5dSAndroid Build Coastguard Worker }
245*c05d8e5dSAndroid Build Coastguard Worker }
246*c05d8e5dSAndroid Build Coastguard Worker
247*c05d8e5dSAndroid Build Coastguard Worker // Given the (data) address of an array, the number of elements, and the
248*c05d8e5dSAndroid Build Coastguard Worker // size of its elements, call the given destructor on each element. If the
249*c05d8e5dSAndroid Build Coastguard Worker // destructor throws an exception, rethrow after destroying the remaining
250*c05d8e5dSAndroid Build Coastguard Worker // elements if possible. If the destructor throws a second exception, call
251*c05d8e5dSAndroid Build Coastguard Worker // terminate(). The destructor pointer may be NULL, in which case this
252*c05d8e5dSAndroid Build Coastguard Worker // routine does nothing.
__cxa_vec_dtor(void * array_address,size_t element_count,size_t element_size,void (* destructor)(void *))253*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void __cxa_vec_dtor(void *array_address,
254*c05d8e5dSAndroid Build Coastguard Worker size_t element_count,
255*c05d8e5dSAndroid Build Coastguard Worker size_t element_size,
256*c05d8e5dSAndroid Build Coastguard Worker void (*destructor)(void *)) {
257*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != destructor ) {
258*c05d8e5dSAndroid Build Coastguard Worker char *ptr = static_cast <char *> (array_address);
259*c05d8e5dSAndroid Build Coastguard Worker size_t idx = element_count;
260*c05d8e5dSAndroid Build Coastguard Worker st_cxa_cleanup cleanup ( array_address, idx, element_size, destructor );
261*c05d8e5dSAndroid Build Coastguard Worker {
262*c05d8e5dSAndroid Build Coastguard Worker st_terminate exception_guard (__cxa_uncaught_exception ());
263*c05d8e5dSAndroid Build Coastguard Worker ptr += element_count * element_size; // one past the last element
264*c05d8e5dSAndroid Build Coastguard Worker
265*c05d8e5dSAndroid Build Coastguard Worker while ( idx-- > 0 ) {
266*c05d8e5dSAndroid Build Coastguard Worker ptr -= element_size;
267*c05d8e5dSAndroid Build Coastguard Worker destructor ( ptr );
268*c05d8e5dSAndroid Build Coastguard Worker }
269*c05d8e5dSAndroid Build Coastguard Worker exception_guard.release (); // We're good !
270*c05d8e5dSAndroid Build Coastguard Worker }
271*c05d8e5dSAndroid Build Coastguard Worker cleanup.release (); // We're still good!
272*c05d8e5dSAndroid Build Coastguard Worker }
273*c05d8e5dSAndroid Build Coastguard Worker }
274*c05d8e5dSAndroid Build Coastguard Worker
275*c05d8e5dSAndroid Build Coastguard Worker // Given the (data) address of an array, the number of elements, and the
276*c05d8e5dSAndroid Build Coastguard Worker // size of its elements, call the given destructor on each element. If the
277*c05d8e5dSAndroid Build Coastguard Worker // destructor throws an exception, call terminate(). The destructor pointer
278*c05d8e5dSAndroid Build Coastguard Worker // may be NULL, in which case this routine does nothing.
__cxa_vec_cleanup(void * array_address,size_t element_count,size_t element_size,void (* destructor)(void *))279*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void __cxa_vec_cleanup(void *array_address,
280*c05d8e5dSAndroid Build Coastguard Worker size_t element_count,
281*c05d8e5dSAndroid Build Coastguard Worker size_t element_size,
282*c05d8e5dSAndroid Build Coastguard Worker void (*destructor)(void *)) {
283*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != destructor ) {
284*c05d8e5dSAndroid Build Coastguard Worker char *ptr = static_cast <char *> (array_address);
285*c05d8e5dSAndroid Build Coastguard Worker size_t idx = element_count;
286*c05d8e5dSAndroid Build Coastguard Worker st_terminate exception_guard;
287*c05d8e5dSAndroid Build Coastguard Worker
288*c05d8e5dSAndroid Build Coastguard Worker ptr += element_count * element_size; // one past the last element
289*c05d8e5dSAndroid Build Coastguard Worker while ( idx-- > 0 ) {
290*c05d8e5dSAndroid Build Coastguard Worker ptr -= element_size;
291*c05d8e5dSAndroid Build Coastguard Worker destructor ( ptr );
292*c05d8e5dSAndroid Build Coastguard Worker }
293*c05d8e5dSAndroid Build Coastguard Worker exception_guard.release (); // We're done!
294*c05d8e5dSAndroid Build Coastguard Worker }
295*c05d8e5dSAndroid Build Coastguard Worker }
296*c05d8e5dSAndroid Build Coastguard Worker
297*c05d8e5dSAndroid Build Coastguard Worker
298*c05d8e5dSAndroid Build Coastguard Worker // If the array_address is NULL, return immediately. Otherwise, given the
299*c05d8e5dSAndroid Build Coastguard Worker // (data) address of an array, the non-negative size of prefix padding for
300*c05d8e5dSAndroid Build Coastguard Worker // the cookie, and the size of its elements, call the given destructor on
301*c05d8e5dSAndroid Build Coastguard Worker // each element, using the cookie to determine the number of elements, and
302*c05d8e5dSAndroid Build Coastguard Worker // then delete the space by calling ::operator delete[](void *). If the
303*c05d8e5dSAndroid Build Coastguard Worker // destructor throws an exception, rethrow after (a) destroying the
304*c05d8e5dSAndroid Build Coastguard Worker // remaining elements, and (b) deallocating the storage. If the destructor
305*c05d8e5dSAndroid Build Coastguard Worker // throws a second exception, call terminate(). If padding_size is 0, the
306*c05d8e5dSAndroid Build Coastguard Worker // destructor pointer must be NULL. If the destructor pointer is NULL, no
307*c05d8e5dSAndroid Build Coastguard Worker // destructor call is to be made.
308*c05d8e5dSAndroid Build Coastguard Worker //
309*c05d8e5dSAndroid Build Coastguard Worker // The intent of this function is to permit an implementation to call this
310*c05d8e5dSAndroid Build Coastguard Worker // function when confronted with an expression of the form delete[] p in
311*c05d8e5dSAndroid Build Coastguard Worker // the source code, provided that the default deallocation function can be
312*c05d8e5dSAndroid Build Coastguard Worker // used. Therefore, the semantics of this function are consistent with
313*c05d8e5dSAndroid Build Coastguard Worker // those required by the standard. The requirement that the deallocation
314*c05d8e5dSAndroid Build Coastguard Worker // function be called even if the destructor throws an exception derives
315*c05d8e5dSAndroid Build Coastguard Worker // from the resolution to DR 353 to the C++ standard, which was adopted in
316*c05d8e5dSAndroid Build Coastguard Worker // April, 2003.
__cxa_vec_delete(void * array_address,size_t element_size,size_t padding_size,void (* destructor)(void *))317*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void __cxa_vec_delete(void *array_address,
318*c05d8e5dSAndroid Build Coastguard Worker size_t element_size,
319*c05d8e5dSAndroid Build Coastguard Worker size_t padding_size,
320*c05d8e5dSAndroid Build Coastguard Worker void (*destructor)(void *)) {
321*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_delete2 ( array_address, element_size, padding_size,
322*c05d8e5dSAndroid Build Coastguard Worker destructor, &::operator delete [] );
323*c05d8e5dSAndroid Build Coastguard Worker }
324*c05d8e5dSAndroid Build Coastguard Worker
325*c05d8e5dSAndroid Build Coastguard Worker // Same as __cxa_vec_delete, except that the given function is used for
326*c05d8e5dSAndroid Build Coastguard Worker // deallocation instead of the default delete function. If dealloc throws
327*c05d8e5dSAndroid Build Coastguard Worker // an exception, the result is undefined. The dealloc pointer may not be
328*c05d8e5dSAndroid Build Coastguard Worker // NULL.
329*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void
__cxa_vec_delete2(void * array_address,size_t element_size,size_t padding_size,void (* destructor)(void *),void (* dealloc)(void *))330*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_delete2(void *array_address, size_t element_size, size_t padding_size,
331*c05d8e5dSAndroid Build Coastguard Worker void (*destructor)(void *), void (*dealloc)(void *)) {
332*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != array_address ) {
333*c05d8e5dSAndroid Build Coastguard Worker char *vec_base = static_cast <char *> (array_address);
334*c05d8e5dSAndroid Build Coastguard Worker char *heap_block = vec_base - padding_size;
335*c05d8e5dSAndroid Build Coastguard Worker st_heap_block2 heap ( dealloc, heap_block );
336*c05d8e5dSAndroid Build Coastguard Worker
337*c05d8e5dSAndroid Build Coastguard Worker if ( 0 != padding_size && NULL != destructor ) // call the destructors
338*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_dtor ( array_address, __get_element_count ( vec_base ),
339*c05d8e5dSAndroid Build Coastguard Worker element_size, destructor );
340*c05d8e5dSAndroid Build Coastguard Worker }
341*c05d8e5dSAndroid Build Coastguard Worker }
342*c05d8e5dSAndroid Build Coastguard Worker
343*c05d8e5dSAndroid Build Coastguard Worker
344*c05d8e5dSAndroid Build Coastguard Worker // Same as __cxa_vec_delete, except that the given function is used for
345*c05d8e5dSAndroid Build Coastguard Worker // deallocation instead of the default delete function. The deallocation
346*c05d8e5dSAndroid Build Coastguard Worker // function takes both the object address and its size. If dealloc throws
347*c05d8e5dSAndroid Build Coastguard Worker // an exception, the result is undefined. The dealloc pointer may not be
348*c05d8e5dSAndroid Build Coastguard Worker // NULL.
349*c05d8e5dSAndroid Build Coastguard Worker _LIBCXXABI_FUNC_VIS void
__cxa_vec_delete3(void * array_address,size_t element_size,size_t padding_size,void (* destructor)(void *),void (* dealloc)(void *,size_t))350*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_delete3(void *array_address, size_t element_size, size_t padding_size,
351*c05d8e5dSAndroid Build Coastguard Worker void (*destructor)(void *), void (*dealloc)(void *, size_t)) {
352*c05d8e5dSAndroid Build Coastguard Worker if ( NULL != array_address ) {
353*c05d8e5dSAndroid Build Coastguard Worker char *vec_base = static_cast <char *> (array_address);
354*c05d8e5dSAndroid Build Coastguard Worker char *heap_block = vec_base - padding_size;
355*c05d8e5dSAndroid Build Coastguard Worker const size_t element_count = padding_size ? __get_element_count ( vec_base ) : 0;
356*c05d8e5dSAndroid Build Coastguard Worker const size_t heap_block_size = element_size * element_count + padding_size;
357*c05d8e5dSAndroid Build Coastguard Worker st_heap_block3 heap ( dealloc, heap_block, heap_block_size );
358*c05d8e5dSAndroid Build Coastguard Worker
359*c05d8e5dSAndroid Build Coastguard Worker if ( 0 != padding_size && NULL != destructor ) // call the destructors
360*c05d8e5dSAndroid Build Coastguard Worker __cxa_vec_dtor ( array_address, element_count, element_size, destructor );
361*c05d8e5dSAndroid Build Coastguard Worker }
362*c05d8e5dSAndroid Build Coastguard Worker }
363*c05d8e5dSAndroid Build Coastguard Worker
364*c05d8e5dSAndroid Build Coastguard Worker
365*c05d8e5dSAndroid Build Coastguard Worker } // extern "C"
366*c05d8e5dSAndroid Build Coastguard Worker
367*c05d8e5dSAndroid Build Coastguard Worker } // abi
368