001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.ia32; 014 015import static org.jikesrvm.runtime.UnboxedSizeConstants.BYTES_IN_WORD; 016 017import org.jikesrvm.VM; 018import org.jikesrvm.classloader.RVMArray; 019import org.jikesrvm.classloader.TypeReference; 020import org.jikesrvm.runtime.Magic; 021import org.jikesrvm.runtime.RuntimeEntrypoints; 022import org.vmmagic.pragma.Entrypoint; 023import org.vmmagic.unboxed.Address; 024 025/** 026 * Helper routine to pull the parameters to multianewarray off the 027 * Java expression stack maintained by the baseline compiler and 028 * pass them to RuntimeEntrypoints.buildMultiDimensionalArray.<p> 029 * 030 * TODO: There is only 1 line of platform dependent code here; refactor? 031 */ 032public abstract class MultianewarrayHelper { 033 034 /** 035 * Allocate something like {@code new Foo[cnt0][cnt1]...[cntN-1]}, 036 * or {@code new int[cnt0][cnt1]...[cntN-1]}. 037 * @param methodId method id of caller 038 * @param numDimensions number of array dimensions 039 * @param typeId type id of type reference for array 040 * @param argOffset position of word *above* `cnt0' argument within 041 * caller's frame This is used to access the number of elements to 042 * be allocated for each dimension. 043 * 044 * See also: bytecode 0xc5 ("multianewarray") in BaselineCompilerImpl 045 * 046 * @return newly allocated multidimensional array 047 */ 048 @Entrypoint 049 static Object newArrayArray(int methodId, int numDimensions, int typeId, int argOffset) 050 throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError { 051 if (numDimensions == 2) { 052 int dim0, dim1; 053 // fetch number of elements to be allocated for each array dimension 054 VM.disableGC(); 055 Address argp = Magic.getFramePointer().plus(argOffset); 056 argp = argp.minus(BYTES_IN_WORD); 057 dim0 = argp.loadInt(); 058 argp = argp.minus(BYTES_IN_WORD); 059 dim1 = argp.loadInt(); 060 VM.enableGC(); 061 // validate arguments 062 if ((dim0 < 0) || (dim1 < 0)) throw new NegativeArraySizeException(); 063 // create array 064 TypeReference tRef = TypeReference.getTypeRef(typeId); 065 RVMArray array = tRef.resolve().asArray(); 066 return RuntimeEntrypoints.buildTwoDimensionalArray(methodId, dim0, dim1, array); 067 } else { 068 // fetch number of elements to be allocated for each array dimension 069 int[] numElements = new int[numDimensions]; 070 VM.disableGC(); 071 Address argp = Magic.getFramePointer().plus(argOffset); 072 for (int i = 0; i < numDimensions; ++i) { 073 argp = argp.minus(BYTES_IN_WORD); 074 numElements[i] = argp.loadInt(); 075 } 076 VM.enableGC(); 077 // validate arguments 078 for (int elements : numElements) { 079 if (elements < 0) throw new NegativeArraySizeException(); 080 } 081 // create array 082 TypeReference tRef = TypeReference.getTypeRef(typeId); 083 RVMArray array = tRef.resolve().asArray(); 084 return RuntimeEntrypoints.buildMultiDimensionalArray(methodId, numElements, array); 085 } 086 } 087}