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 */ 013 package org.jikesrvm.ia32; 014 015 import org.jikesrvm.VM; 016 import org.jikesrvm.classloader.RVMArray; 017 import org.jikesrvm.classloader.TypeReference; 018 import org.jikesrvm.runtime.Magic; 019 import org.jikesrvm.runtime.RuntimeEntrypoints; 020 import org.vmmagic.unboxed.Address; 021 022 /** 023 * Helper routine to pull the parameters to multianewarray off the 024 * Java expression stack maintained by the baseline compiler and 025 * pass them to RuntimeEntrypoints.buildMultiDimensionalArray.<p> 026 * 027 * TODO: There is only 1 line of platform dependent code here; refactor? 028 */ 029 public abstract class MultianewarrayHelper { 030 031 /** 032 * Allocate something like {@code new Foo[cnt0][cnt1]...[cntN-1]}, 033 * or {@code new int[cnt0][cnt1]...[cntN-1]}. 034 * @param methodId method id of caller 035 * @param numDimensions number of array dimensions 036 * @param typeId type id of type reference for array 037 * @param argOffset position of word *above* `cnt0' argument within 038 * caller's frame This is used to access the number of elements to 039 * be allocated for each dimension. 040 * 041 * See also: bytecode 0xc5 ("multianewarray") in BaselineCompilerImpl 042 */ 043 static Object newArrayArray(int methodId, int numDimensions, int typeId, int argOffset) 044 throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError { 045 if (numDimensions == 2) { 046 int dim0, dim1; 047 // fetch number of elements to be allocated for each array dimension 048 VM.disableGC(); 049 Address argp = Magic.getFramePointer().plus(argOffset); 050 argp = argp.minus(4); 051 dim0 = argp.loadInt(); 052 argp = argp.minus(4); 053 dim1 = argp.loadInt(); 054 VM.enableGC(); 055 // validate arguments 056 if ((dim0 < 0) || (dim1 < 0)) throw new NegativeArraySizeException(); 057 // create array 058 TypeReference tRef = TypeReference.getTypeRef(typeId); 059 RVMArray array = tRef.resolve().asArray(); 060 return RuntimeEntrypoints.buildTwoDimensionalArray(methodId, dim0, dim1, array); 061 } else { 062 // fetch number of elements to be allocated for each array dimension 063 int[] numElements = new int[numDimensions]; 064 VM.disableGC(); 065 Address argp = Magic.getFramePointer().plus(argOffset); 066 for (int i = 0; i < numDimensions; ++i) { 067 if (VM.BuildFor32Addr) { 068 argp = argp.minus(4); 069 } else { 070 argp = argp.minus(8); 071 } 072 numElements[i] = argp.loadInt(); 073 } 074 VM.enableGC(); 075 // validate arguments 076 for (int elements : numElements) { 077 if (elements < 0) throw new NegativeArraySizeException(); 078 } 079 // create array 080 TypeReference tRef = TypeReference.getTypeRef(typeId); 081 RVMArray array = tRef.resolve().asArray(); 082 return RuntimeEntrypoints.buildMultiDimensionalArray(methodId, numElements, array); 083 } 084 } 085 }