====== Arrays ====== The following figure demonstrates how arrays are implemented in the memory. [{{ .:array1.png?250&direct | //Implementation of an array//}}] An array extends //java/lang/object//. The field //Tag// points to the type descriptor of this array (//[ClassA// for this example). The single array elements themselves are of type //ClassA// and have a //Tag// which points to the type descriptor of //ClassA//. For this reason arrays of base types like ([B, [S ...) need a class descritor as well. \\ The field //length// denotes the number of elements of the array (16 bit). //heap// is used for the garbage collection ([[..:rts:heap|Heap Manager and Garbage Collection]]). In between there is a byte which contains an array bit. This is used for type checking. The //P// bit is for garbage collection. It is set for arrays of primitive types\\ When accessing array elements the code generator inserts code to check if the element index is in the range 0 to //length//.\\ If the field //length// is used in Java the Bytecode instruktion //arraylength// is used. This instruktion has to be translated so that the //length// field is accessed. ===== Generating Arrays ===== The Java code static int[]a1 = new int[4]; will be translated into Bytecode 0 iconst_4 1 newarray int 3 putstatic Test.a1 : int[] When regular objects are created the constructor of the supertype is automatically inserted into the Bytecode. When arrays are created there is no such call. The constructor of //Object// has to be inserted by the code generator and the heap manager has to add the size of //java/lang/Object// to the size of the array. As long as //java/lang/Object// has no fields the size is 0 and we can also omit the call of the constructor.\\ In the Bytecode //newarray// has a type (here //int//). When generating the SSA the reference to this type //[I// has to be fetched from the object directory. \\ For static Object[] a1 = new ClassA[4]; the Bytecode looks like: 0 iconst_4 1 anewarray org/deepjava/junitTarget/comp/objects/ClassA 4 putstatic org/deepjava/junitTarget/comp/objects/InheritanceTest.a1: Ljava/lang/Object[]; Here, as well, the reference to //[ClassA// has to be fetched from the object directory when generating the SSA. There are cases when there is no entry for //[ClassA//. This is the case when there is never a type check for the type //[ClassA//. Then the SSA has a reference to null and the //Tag// can be 0 as well. ===== Multidimensional Arrays ===== Let us consider the following case: int[][] a = new int[2][3] The memory will look like [{{ .:array2.png?450&direct | //2-dimensional Array//}}] //[[I// and //[I// are the corresponding type descriptors. When accessing an element one has to access a reference in the first dimension followed by the element access in the second dimension. ==== Generating an Multidimensional Array of Basetypes ==== The following code short[][] a = new short[2][3] leads to the Bytecode 0 iconst_2 1 iconst_3 2 multianewarray short[][] 6 putstatic org/deepjava/runtime/mpc555/test/ArrayTest3.a1: short[][] If an array is immediately initialized short[][] a2 = {{1,2},{3,4}}; the Bytecode will be 9 iconst_2 10 anewarray [S 13 dup 14 iconst_0 15 iconst_2 16 newarray short 18 dup 19 iconst_0 20 iconst_1 21 sastore 22 dup 23 iconst_1 24 iconst_2 25 sastore 26 aastore 27 dup 28 iconst_1 29 iconst_2 30 newarray short etc. The problem with the first case is, that only the type descriptor //[[I// would be linked. However, //[I// must be created as well. In the method //multianewarray// of the heap manager the array must be allocated and the references to //[[I// and //[I// must be set. The reference to //[[I// is passed as a parameter. In //[[I// there is the reference to //[I//. This reference must be fetched and inserted into the object at the appropriate position. \\ Similar thoughts are true for arrays with higher dimensions. As well, the instruction //multianewarray// is used solely for special purposes. ==== Generating an Multidimensional Array of Objects ==== Here, the same conditions are true as described above. ClassA[][][] a1 = new ClassA[3][2][2]; This leads to Bytecode 0 iconst_3 1 iconst_2 2 iconst_2 3 multianewarray Lch/ntb/junitTarget/comp/arrays/A[][][]; 7 astore_1 [a1] The reference to //[[[ClassA;// can be found already in the SSA. The heap manager has to fetch the base types //[[ClassA;//, //[ClassA;// and //ClassA;// from the type descriptor recursively.