LCOV - code coverage report
Current view: top level - vm - array.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 82 122 67.2 %
Date: 2015-06-10 18:10:59 Functions: 65 144 45.1 %

          Line data    Source code
       1             : /* src/vm/array.hpp - Java array functions
       2             : 
       3             :    Copyright (C) 1996-2014
       4             :    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
       5             :    Copyright (C) 2008 Theobroma Systems Ltd.
       6             : 
       7             :    This file is part of CACAO.
       8             : 
       9             :    This program is free software; you can redistribute it and/or
      10             :    modify it under the terms of the GNU General Public License as
      11             :    published by the Free Software Foundation; either version 2, or (at
      12             :    your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful, but
      15             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :    General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program; if not, write to the Free Software
      21             :    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      22             :    02110-1301, USA.
      23             : 
      24             : */
      25             : 
      26             : 
      27             : #ifndef ARRAY_HPP_
      28             : #define ARRAY_HPP_ 1
      29             : 
      30             : #include "config.h"
      31             : #include <cassert>                      // for assert
      32             : #include <cstdio>                       // for NULL, printf
      33             : #include <stdint.h>                     // for int32_t, int8_t, int16_t, etc
      34             : #include "mm/gc.hpp"                    // for GCCriticalSection, etc
      35             : #include "threads/lockword.hpp"         // for Lockword
      36             : #include "vm/class.hpp"                 // for classinfo
      37             : #include "vm/exceptions.hpp"
      38             : #include "vm/global.hpp"                // for java_handle_t, java_array_t, etc
      39             : #include "vm/jit/builtin.hpp"           // for builtin_canstore
      40             : #include "vm/os.hpp"                    // for os
      41             : #include "vm/primitive.hpp"             // for primitivetypeinfo, etc
      42             : #include "vm/types.hpp"                 // for s4, s2
      43             : #include "vm/vftbl.hpp"                 // for vftbl_t
      44             : 
      45             : /* array types ****************************************************************/
      46             : 
      47             : /* CAUTION: Don't change the numerical values! These constants (with
      48             :    the exception of ARRAYTYPE_OBJECT) are used as indices in the
      49             :    primitive type table. */
      50             : 
      51             : enum ArrayType {
      52             :         ARRAYTYPE_INT     = PRIMITIVETYPE_INT,
      53             :         ARRAYTYPE_LONG    = PRIMITIVETYPE_LONG,
      54             :         ARRAYTYPE_FLOAT   = PRIMITIVETYPE_FLOAT,
      55             :         ARRAYTYPE_DOUBLE  = PRIMITIVETYPE_DOUBLE,
      56             :         ARRAYTYPE_BYTE    = PRIMITIVETYPE_BYTE,
      57             :         ARRAYTYPE_CHAR    = PRIMITIVETYPE_CHAR,
      58             :         ARRAYTYPE_SHORT   = PRIMITIVETYPE_SHORT,
      59             :         ARRAYTYPE_BOOLEAN = PRIMITIVETYPE_BOOLEAN,
      60             :         ARRAYTYPE_OBJECT  = PRIMITIVETYPE_VOID     // don't use as index!
      61             : };
      62             : 
      63             : 
      64             : /* arraydescriptor *************************************************************
      65             : 
      66             :    For every array class an arraydescriptor is allocated which
      67             :    describes the array class. The arraydescriptor is referenced from
      68             :    the vftbl of the array class.
      69             : 
      70             : *******************************************************************************/
      71             : 
      72             : struct arraydescriptor {
      73             :         vftbl_t   *componentvftbl; /* vftbl of the component type, NULL for primit. */
      74             :         vftbl_t   *elementvftbl;   /* vftbl of the element type, NULL for primitive */
      75             :         ArrayType  arraytype;      /* ARRAYTYPE_* constant                          */
      76             :         ArrayType  elementtype;    /* ARRAYTYPE_* constant                          */
      77             :         s4         dataoffset;     /* offset of the array data from object pointer  */
      78             :         s4         componentsize;  /* size of a component in bytes                  */
      79             :         s2         dimension;      /* dimension of the array (always >= 1)          */
      80             : };
      81             : 
      82             : 
      83             : /**
      84             :  * This is a generic accessor class for Java arrays (of unspecified type),
      85             :  * which can be used to safely operate on Java arrays in native code.
      86             :  */
      87         271 : class Array {
      88             : protected:
      89             :         // Handle of Java array.
      90             :         java_handle_array_t* _handle;
      91             : 
      92             : private:
      93             :         // We don't want a Java arrays to be copied.
      94             :         Array(Array* a) {}
      95             :         Array(Array& a) {}
      96             : 
      97             : public:
      98             :         Array(java_handle_t* h);
      99             :         Array(int32_t length, classinfo* arrayclass);
     100     2621635 :         virtual ~Array() {}
     101             : 
     102             :         // Getters.
     103    22785913 :         virtual java_handle_array_t* get_handle() const { return _handle; }
     104             :         int32_t                      get_length() const;
     105             : 
     106             :         // Null checks.
     107             :         bool is_null    () const;
     108             :         bool is_non_null() const;
     109             : 
     110             :         // Safe element modification functions for primitive values
     111             :         imm_union get_primitive_element(int32_t index);
     112             :         void      set_primitive_element(int32_t index, imm_union value);
     113             : 
     114             :         // Safe element modification functions for boxed values
     115             :         java_handle_t* get_boxed_element(int32_t index);
     116             :         void           set_boxed_element(int32_t index, java_handle_t *o);
     117             : };
     118             : 
     119             : 
     120             : /**
     121             :  * Constructor checks if passed handle really is a Java array.
     122             :  */
     123     1789643 : inline Array::Array(java_handle_t* h)
     124             : {
     125     1789643 :         if (h == NULL) {
     126      337653 :                 _handle = NULL;
     127      337653 :                 return;
     128             :         }
     129             : 
     130             : #if 0
     131             :         classinfo* c;
     132             :         LLNI_class_get(h, c);
     133             :         if (!class_is_array(c)) {
     134             :                 printf("Array::Array(): WARNING, passed handle is not an array\n");
     135             :                 //exceptions_throw_illegalargumentexception("Argument is not an array");
     136             :                 exceptions_throw_illegalargumentexception();
     137             :                 _handle = NULL;
     138             :                 return;
     139             :         }
     140             : #endif
     141             : 
     142     1451990 :         _handle = h;
     143             : }
     144             : 
     145             : /**
     146             :  * Creates an array of the given array type on the heap.
     147             :  * The handle pointer to the array can be NULL in case of an exception.
     148             :  */
     149      832133 : inline Array::Array(int32_t size, classinfo* arrayclass)
     150             : {
     151             :         // Sanity check.
     152      832133 :         assert(class_is_array(arrayclass));
     153             : 
     154      832133 :         if (size < 0) {
     155           3 :                 exceptions_throw_negativearraysizeexception();
     156           3 :                 _handle = NULL;
     157           3 :                 return;
     158             :         }
     159             : 
     160      832130 :         arraydescriptor* desc          = arrayclass->vftbl->arraydesc;
     161      832130 :         int32_t          dataoffset    = desc->dataoffset;
     162      832130 :         int32_t          componentsize = desc->componentsize;
     163      832130 :         int32_t          actualsize    = dataoffset + size * componentsize;
     164             : 
     165             :         // Check for overflow.
     166             : 
     167      832130 :         if (((u4) actualsize) < ((u4) size)) {
     168           0 :                 exceptions_throw_outofmemoryerror();
     169           0 :                 _handle = NULL;
     170           0 :                 return;
     171             :         }
     172             : 
     173      832130 :         java_array_t* a = (java_array_t*) heap_alloc(actualsize, (desc->arraytype == ARRAYTYPE_OBJECT), NULL, true);
     174             : 
     175      832130 :         if (a == NULL) {
     176           2 :                 _handle = NULL;
     177           2 :                 return;
     178             :         }
     179             : 
     180      832128 :         LLNI_vftbl_direct(a) = arrayclass->vftbl;
     181             : 
     182      832128 :         Lockword(a->objheader.lockword).init();
     183             : 
     184      832128 :         a->size = size;
     185             : 
     186      832128 :         _handle = (java_handle_array_t*) a;
     187             : }
     188             : 
     189     8119101 : inline int32_t Array::get_length() const
     190             : {
     191     8119101 :         if (is_null()) {
     192           0 :                 printf("Array::get_length(): WARNING, got null-pointer\n");
     193           0 :                 exceptions_throw_nullpointerexception();
     194           0 :                 return -1;
     195             :         }
     196             : 
     197             :         // XXX Fix me!
     198     8119101 :         int32_t length = ((java_array_t*) _handle)->size;
     199             : 
     200     8119101 :         return length;
     201             : }
     202             : 
     203    15544904 : inline bool Array::is_null() const
     204             : {
     205    15544904 :         return (_handle == NULL);
     206             : }
     207             : 
     208         271 : inline bool Array::is_non_null() const
     209             : {
     210         271 :         return (_handle != NULL);
     211             : }
     212             : 
     213             : 
     214             : /**
     215             :  * This is a template of an accessor class for Java arrays
     216             :  * of a specific type.
     217             :  */
     218     1316329 : template<class T> class ArrayTemplate : public Array {
     219             : protected:
     220      484569 :         ArrayTemplate(int32_t length, classinfo* arrayclass) : Array(length, arrayclass) {}
     221             : 
     222             : public:
     223      831630 :         ArrayTemplate(java_handle_array_t* h) : Array(h) {}
     224             : 
     225             :         // XXX This should be protected or private!
     226             :         virtual T* get_raw_data_ptr() = 0;
     227             : 
     228             :         // Safe element modification functions
     229             :         T    get_element(int32_t index);
     230             :         void set_element(int32_t index, T value);
     231             : 
     232             :         // Region copy functions
     233             :         void get_region(int32_t offset, int32_t count, T* buffer);
     234             :         void set_region(int32_t offset, int32_t count, const T* buffer);
     235             : };
     236             : 
     237             : 
     238       12885 : template<class T> inline T ArrayTemplate<T>::get_element(int32_t index)
     239             : {
     240       12885 :         if (is_null()) {
     241           0 :                 exceptions_throw_nullpointerexception();
     242           0 :                 return 0;
     243             :         }
     244             : 
     245       12885 :         if ((index < 0) || (index >= get_length())) {
     246           0 :                 exceptions_throw_arrayindexoutofboundsexception();
     247           0 :                 return 0;
     248             :         }
     249             : 
     250       12885 :         T* ptr = get_raw_data_ptr();
     251             : 
     252       12885 :         return ptr[index];
     253             : }
     254             : 
     255         687 : template<class T> inline void ArrayTemplate<T>::set_element(int32_t index, T value)
     256             : {
     257         687 :         if (is_null()) {
     258           0 :                 exceptions_throw_nullpointerexception();
     259           0 :                 return;
     260             :         }
     261             : 
     262         687 :         if ((index < 0) || (index >= get_length())) {
     263           0 :                 exceptions_throw_arrayindexoutofboundsexception();
     264           0 :                 return;
     265             :         }
     266             : 
     267         687 :         T* ptr = get_raw_data_ptr();
     268             : 
     269         687 :         ptr[index] = value;
     270             : }
     271             : 
     272     7057689 : template<> inline void ArrayTemplate<java_handle_t*>::set_element(int32_t index, java_handle_t* value)
     273             : {
     274     7057689 :         if (is_null()) {
     275           0 :                 exceptions_throw_nullpointerexception();
     276           0 :                 return;
     277             :         }
     278             : 
     279             :         // Sanity check.
     280     7057689 :         assert(((java_array_t*) get_handle())->objheader.vftbl->arraydesc->arraytype == ARRAYTYPE_OBJECT);
     281             : 
     282             :         // Check if value can be stored
     283     7057689 :         if (!builtin_canstore(get_handle(), value)) {
     284           0 :                 exceptions_throw_illegalargumentexception();
     285           0 :                 return;
     286             :         }
     287             : 
     288     7057689 :         if ((index < 0) || (index >= get_length())) {
     289           0 :                 exceptions_throw_arrayindexoutofboundsexception();
     290           0 :                 return;
     291             :         }
     292             : 
     293     7057689 :         java_handle_t** ptr = get_raw_data_ptr();
     294             : 
     295     7057689 :         ptr[index] = value;
     296             : }
     297             : 
     298           0 : template<class T> inline void ArrayTemplate<T>::get_region(int32_t offset, int32_t count, T* buffer)
     299             : {
     300             :         // Copy the array region inside a GC critical section.
     301           0 :         GCCriticalSection cs;
     302             : 
     303           0 :         const T* ptr = get_raw_data_ptr();
     304             : 
     305           0 :         os::memcpy(buffer, ptr + offset, sizeof(T) * count);
     306           0 : }
     307             : 
     308           0 : template<class T> inline void ArrayTemplate<T>::set_region(int32_t offset, int32_t count, const T* buffer)
     309             : {
     310             :         // Copy the array region inside a GC critical section.
     311           0 :         GCCriticalSection cs;
     312             : 
     313           0 :         T* ptr = get_raw_data_ptr();
     314             : 
     315           0 :         os::memcpy(ptr + offset, buffer, sizeof(T) * count);
     316           0 : }
     317             : 
     318             : 
     319             : /**
     320             :  * Actual implementations of common Java array access classes.
     321             :  */
     322           0 : class BooleanArray : public ArrayTemplate<uint8_t> {
     323             : public:
     324           0 :         BooleanArray(java_handle_booleanarray_t* h) : ArrayTemplate<uint8_t>(h) {}
     325           0 :         BooleanArray(int32_t length) : ArrayTemplate<uint8_t>(length, primitivetype_table[ARRAYTYPE_BOOLEAN].arrayclass) {}
     326           0 :         uint8_t* get_raw_data_ptr() { return ((java_booleanarray_t*) get_handle())->data; }
     327             : };
     328             : 
     329      402529 : class ByteArray : public ArrayTemplate<int8_t> {
     330             : public:
     331      190522 :         ByteArray(java_handle_bytearray_t* h) : ArrayTemplate<int8_t>(h) {}
     332      212007 :         ByteArray(int32_t length) : ArrayTemplate<int8_t>(length, primitivetype_table[ARRAYTYPE_BYTE].arrayclass) {}
     333      211884 :         int8_t* get_raw_data_ptr() { return (int8_t*) ((java_bytearray_t*) get_handle())->data; }
     334             : };
     335             : 
     336      562428 : class CharArray : public ArrayTemplate<uint16_t> {
     337             : public:
     338      294322 :         CharArray(java_handle_chararray_t* h) : ArrayTemplate<uint16_t>(h) {}
     339      268106 :         CharArray(int32_t length) : ArrayTemplate<uint16_t>(length, primitivetype_table[ARRAYTYPE_CHAR].arrayclass) {}
     340      229624 :         uint16_t* get_raw_data_ptr() { return ((java_chararray_t*) get_handle())->data; }
     341             : };
     342             : 
     343        2540 : class ShortArray : public ArrayTemplate<int16_t> {
     344             : public:
     345           0 :         ShortArray(java_handle_shortarray_t* h) : ArrayTemplate<int16_t>(h) {}
     346        2540 :         ShortArray(int32_t length) : ArrayTemplate<int16_t>(length, primitivetype_table[ARRAYTYPE_SHORT].arrayclass) {}
     347           0 :         int16_t* get_raw_data_ptr() { return ((java_shortarray_t*) get_handle())->data; }
     348             : };
     349             : 
     350        1852 : class IntArray : public ArrayTemplate<int32_t> {
     351             : public:
     352           2 :         IntArray(java_handle_intarray_t* h) : ArrayTemplate<int32_t>(h) {}
     353        1850 :         IntArray(int32_t length) : ArrayTemplate<int32_t>(length, primitivetype_table[ARRAYTYPE_INT].arrayclass) {}
     354           2 :         int32_t* get_raw_data_ptr() { return ((java_intarray_t*) get_handle())->data; }
     355             : };
     356             : 
     357          50 : class LongArray : public ArrayTemplate<int64_t> {
     358             : public:
     359           2 :         LongArray(java_handle_longarray_t* h) : ArrayTemplate<int64_t>(h) {}
     360          48 :         LongArray(int32_t length) : ArrayTemplate<int64_t>(length, primitivetype_table[ARRAYTYPE_LONG].arrayclass) {}
     361           2 :         int64_t* get_raw_data_ptr() { return ((java_longarray_t*) get_handle())->data; }
     362             : };
     363             : 
     364           9 : class FloatArray : public ArrayTemplate<float> {
     365             : public:
     366           0 :         FloatArray(java_handle_floatarray_t* h) : ArrayTemplate<float>(h) {}
     367           9 :         FloatArray(int32_t length) : ArrayTemplate<float>(length, primitivetype_table[ARRAYTYPE_FLOAT].arrayclass) {}
     368           0 :         float* get_raw_data_ptr() { return ((java_floatarray_t*) get_handle())->data; }
     369             : };
     370             : 
     371           9 : class DoubleArray : public ArrayTemplate<double> {
     372             : public:
     373           0 :         DoubleArray(java_handle_doublearray_t* h) : ArrayTemplate<double>(h) {}
     374           9 :         DoubleArray(int32_t length) : ArrayTemplate<double>(length, primitivetype_table[ARRAYTYPE_DOUBLE].arrayclass) {}
     375           0 :         double* get_raw_data_ptr() { return ((java_doublearray_t*) get_handle())->data; }
     376             : };
     377             : 
     378             : /**
     379             :  * Actual implementation of access class for Java Object arrays.
     380             :  */
     381      345013 : class ObjectArray : public ArrayTemplate<java_handle_t*> {
     382             : public:
     383       32814 :         ObjectArray(java_handle_objectarray_t* h) : ArrayTemplate<java_handle_t*>(h) {}
     384             :         ObjectArray(int32_t length, classinfo* componentclass);
     385     7070748 :         java_handle_t** get_raw_data_ptr() { return ((java_objectarray_t*) get_handle())->data; }
     386             : };
     387             : 
     388             : /**
     389             :  * Actual implementation of access class for java.lang.Class arrays.
     390             :  */
     391        1899 : class ClassArray : public ArrayTemplate<classinfo*> {
     392             : public:
     393             :         ClassArray(int32_t length);
     394         687 :         classinfo** get_raw_data_ptr() { return (classinfo**) ((java_objectarray_t*) get_handle())->data; }
     395             : };
     396             : 
     397             : #endif // ARRAY_HPP_
     398             : 
     399             : 
     400             : /*
     401             :  * These are local overrides for various environment variables in Emacs.
     402             :  * Please do not remove this and leave it at the end of the file, where
     403             :  * Emacs will automagically detect them.
     404             :  * ---------------------------------------------------------------------
     405             :  * Local variables:
     406             :  * mode: c++
     407             :  * indent-tabs-mode: t
     408             :  * c-basic-offset: 4
     409             :  * tab-width: 4
     410             :  * End:
     411             :  * vim:noexpandtab:sw=4:ts=4:
     412             :  */

Generated by: LCOV version 1.11