Search in sources :

Example 6 with RVMArray

use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.

the class MultianewarrayHelper method newArrayArray.

/**
 * Allocate something like {@code new Foo[cnt0][cnt1]...[cntN-1]},
 *                      or {@code new int[cnt0][cnt1]...[cntN-1]}.
 * @param methodId method id of caller
 * @param numDimensions number of array dimensions
 * @param typeId type id of type reference for array
 * @param argOffset position of word *above* `cnt0' argument within
 * caller's frame This is used to access the number of elements to
 * be allocated for each dimension.
 *
 * See also: bytecode 0xc5 ("multianewarray") in BaselineCompilerImpl
 *
 * @return newly allocated multidimensional array
 */
@Entrypoint
static Object newArrayArray(int methodId, int numDimensions, int typeId, int argOffset) throws NoClassDefFoundError, NegativeArraySizeException, OutOfMemoryError {
    if (numDimensions == 2) {
        int dim0, dim1;
        // fetch number of elements to be allocated for each array dimension
        VM.disableGC();
        Address argp = Magic.getFramePointer().plus(argOffset);
        argp = argp.minus(BYTES_IN_WORD);
        dim0 = argp.loadInt();
        argp = argp.minus(BYTES_IN_WORD);
        dim1 = argp.loadInt();
        VM.enableGC();
        // validate arguments
        if ((dim0 < 0) || (dim1 < 0))
            throw new NegativeArraySizeException();
        // create array
        TypeReference tRef = TypeReference.getTypeRef(typeId);
        RVMArray array = tRef.resolve().asArray();
        return RuntimeEntrypoints.buildTwoDimensionalArray(methodId, dim0, dim1, array);
    } else {
        // fetch number of elements to be allocated for each array dimension
        int[] numElements = new int[numDimensions];
        VM.disableGC();
        Address argp = Magic.getFramePointer().plus(argOffset);
        for (int i = 0; i < numDimensions; ++i) {
            argp = argp.minus(BYTES_IN_WORD);
            numElements[i] = argp.loadInt();
        }
        VM.enableGC();
        // validate arguments
        for (int elements : numElements) {
            if (elements < 0)
                throw new NegativeArraySizeException();
        }
        // create array
        TypeReference tRef = TypeReference.getTypeRef(typeId);
        RVMArray array = tRef.resolve().asArray();
        return RuntimeEntrypoints.buildMultiDimensionalArray(methodId, numElements, array);
    }
}
Also used : Address(org.vmmagic.unboxed.Address) RVMArray(org.jikesrvm.classloader.RVMArray) TypeReference(org.jikesrvm.classloader.TypeReference) Entrypoint(org.vmmagic.pragma.Entrypoint) Entrypoint(org.vmmagic.pragma.Entrypoint)

Example 7 with RVMArray

use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.

the class VMCommonLibrarySupport method createArray.

/* ---- Array Methods ---- */
/**
 * Dynamically create an array of objects.
 *
 * @param cls guaranteed to be a valid object type
 * @param length the length of the array
 * @return the new array
 * @throws NegativeArraySizeException if dim is negative
 * @throws OutOfMemoryError if memory allocation fails
 */
static Object createArray(Class<?> cls, int length) throws OutOfMemoryError, NegativeArraySizeException {
    if (cls == Void.TYPE)
        throwNewIllegalArgumentException("Cannot create new array instance for the specified arguments");
    // will raise NPE
    RVMArray arrayType = java.lang.JikesRVMSupport.getTypeForClass(cls).getArrayTypeForElementType();
    if (!arrayType.isInitialized()) {
        arrayType.resolve();
        arrayType.instantiate();
        arrayType.initialize();
    }
    // will check -ve array size
    return RuntimeEntrypoints.resolvedNewArray(length, arrayType);
}
Also used : RVMArray(org.jikesrvm.classloader.RVMArray)

Example 8 with RVMArray

use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.

the class MemoryManagerTest method allocateArrayTestPositive.

@Test
public void allocateArrayTestPositive() {
    int size = 20;
    RVMArray arrayType = RVMArray.IntArray;
    int headerSize = ObjectModel.computeArrayHeaderSize(arrayType);
    int align = ObjectModel.getAlignment(arrayType);
    int offset = ObjectModel.getOffsetForAlignment(arrayType, false);
    int width = arrayType.getLogElementSize();
    TIB arrayTib = arrayType.getTypeInformationBlock();
    int[] test = (int[]) MemoryManager.allocateArray(size, width, headerSize, arrayTib, ALLOC_NON_MOVING, align, offset, DEFAULT_SITE);
    assertEquals(test.length, 20);
}
Also used : RVMArray(org.jikesrvm.classloader.RVMArray) TIB(org.jikesrvm.objectmodel.TIB) Test(org.junit.Test)

Example 9 with RVMArray

use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.

the class MemoryManagerTest method allocateArrayTestOverflowToPositive.

@Test(expected = OutOfMemoryError.class)
public void allocateArrayTestOverflowToPositive() {
    int size = 1 << 30;
    RVMArray arrayType = RVMArray.IntArray;
    int headerSize = ObjectModel.computeArrayHeaderSize(arrayType);
    int align = ObjectModel.getAlignment(arrayType);
    int offset = ObjectModel.getOffsetForAlignment(arrayType, false);
    int width = arrayType.getLogElementSize();
    TIB arrayTib = arrayType.getTypeInformationBlock();
    int[] test = (int[]) MemoryManager.allocateArray(size, width, headerSize, arrayTib, ALLOC_NON_MOVING, align, offset, DEFAULT_SITE);
    fail("FAIL! Created array with length " + test.length);
}
Also used : RVMArray(org.jikesrvm.classloader.RVMArray) TIB(org.jikesrvm.objectmodel.TIB) Test(org.junit.Test)

Example 10 with RVMArray

use of org.jikesrvm.classloader.RVMArray in project JikesRVM by JikesRVM.

the class DynamicTypeCheckExpansion method generateBranchingTypeCheck.

/**
 * Generate a branching dynamic type check.
 * This routine assumes that the CFG and code order are already
 * correctly established.
 * This routine must either remove s or mutate it.
 *
 * @param s          The Instruction that is to be replaced by a
 *                   branching type check
 * @param ir         The IR containing the instruction to be expanded.
 * @param RHSobj     The RegisterOperand containing the rhs object.
 * @param LHStype    The TypeReference to be tested against.
 * @param RHStib     The Operand containing the TIB of the rhs.
 * @param trueBlock  The BasicBlock to continue at if the typecheck
 *                   evaluates to true
 * @param falseBlock The BasicBlock to continue at if the typecheck
 *                   evaluates to false.
 * @param oldGuard   A suitable guard operand (not necessarily related
 *                   the instruction that is to be replaced).
 * @param falseProb   The probability that typecheck will branch to the falseBlock
 * @return the opt instruction immediately before the instruction to
 *         continue expansion.
 */
private static Instruction generateBranchingTypeCheck(Instruction s, IR ir, Operand RHSobj, TypeReference LHStype, Operand RHStib, BasicBlock trueBlock, BasicBlock falseBlock, RegisterOperand oldGuard, BranchProfileOperand falseProb) {
    Instruction continueAt = Goto.create(GOTO, trueBlock.makeJumpTarget());
    continueAt.copyPosition(s);
    s.insertBefore(continueAt);
    s.remove();
    if (LHStype.isClassType()) {
        RVMClass LHSclass = (RVMClass) LHStype.peekType();
        if (LHSclass != null && LHSclass.isResolved()) {
            // class or interface
            if (LHSclass.isInterface()) {
                // A resolved interface (case 4)
                int interfaceIndex = LHSclass.getDoesImplementIndex();
                int interfaceMask = LHSclass.getDoesImplementBitMask();
                RegisterOperand doesImpl = InsertUnary(continueAt, ir, GET_DOES_IMPLEMENT_FROM_TIB, TypeReference.IntArray, RHStib);
                if (DynamicTypeCheck.MIN_DOES_IMPLEMENT_SIZE <= interfaceIndex) {
                    RegisterOperand doesImplLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, doesImpl.copyD2U(), TG());
                    Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, doesImplLength, IC(interfaceIndex), ConditionOperand.LESS_EQUAL(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
                    if (oldGuard != null) {
                        oldGuard = oldGuard.copyD2D();
                    }
                    continueAt.insertBefore(lengthCheck);
                    BasicBlock oldBlock = continueAt.getBasicBlock();
                    oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
                    // required due to splitNode!
                    oldBlock.insertOut(falseBlock);
                }
                RegisterOperand entry = InsertLoadOffset(continueAt, ir, INT_LOAD, TypeReference.Int, doesImpl, Offset.fromIntZeroExtend(interfaceIndex << 2), new LocationOperand(TypeReference.Int), TG());
                RegisterOperand bit = insertBinary(continueAt, ir, INT_AND, TypeReference.Int, entry, IC(interfaceMask));
                continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, bit, IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            } else {
                // A resolved class (cases 5 and 6 in DynamicTypeCheck)
                if (LHSclass.isFinal()) {
                    // For a final class, we can do a PTR compare of
                    // rhsTIB and the TIB of the class
                    Operand classTIB = getTIB(continueAt, ir, LHSclass);
                    continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                    return continueAt;
                } else {
                    // Do the full blown case 5 or 6 typecheck.
                    int LHSDepth = LHSclass.getTypeDepth();
                    int LHSId = LHSclass.getId();
                    RegisterOperand superclassIds = InsertUnary(continueAt, ir, GET_SUPERCLASS_IDS_FROM_TIB, TypeReference.ShortArray, RHStib);
                    if (DynamicTypeCheck.MIN_SUPERCLASS_IDS_SIZE <= LHSDepth) {
                        RegisterOperand superclassIdsLength = InsertGuardedUnary(continueAt, ir, ARRAYLENGTH, TypeReference.Int, superclassIds.copyD2U(), TG());
                        Instruction lengthCheck = IfCmp.create(INT_IFCMP, oldGuard, superclassIdsLength, IC(LHSDepth), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), BranchProfileOperand.unlikely());
                        if (oldGuard != null) {
                            oldGuard = oldGuard.copyD2D();
                        }
                        continueAt.insertBefore(lengthCheck);
                        BasicBlock oldBlock = continueAt.getBasicBlock();
                        oldBlock.splitNodeWithLinksAt(lengthCheck, ir);
                        // required due to splitNode!
                        oldBlock.insertOut(falseBlock);
                    }
                    RegisterOperand refCandidate = InsertLoadOffset(continueAt, ir, USHORT_LOAD, TypeReference.Short, superclassIds, Offset.fromIntZeroExtend(LHSDepth << 1), new LocationOperand(TypeReference.Short), TG());
                    continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, refCandidate, IC(LHSId), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                    return continueAt;
                }
            }
        } else {
            // A non-resolved class or interface. Case 3 of DynamicTypeCheck
            // Branch on the result of a call to
            // RuntimeEntrypoints.instance
            RegisterOperand result = ir.regpool.makeTempInt();
            RVMMethod target = Entrypoints.instanceOfMethod;
            Instruction call = Call.create2(CALL, result, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
            call.copyPosition(continueAt);
            continueAt.insertBefore(call);
            call = callHelper(call, ir);
            continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, result.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
            return continueAt;
        }
    }
    if (LHStype.isArrayType()) {
        // Case 2 of DynamicTypeCheck: LHS is an array.
        RVMArray LHSArray = (RVMArray) LHStype.peekType();
        if (LHSArray != null) {
            Operand classTIB = getTIB(continueAt, ir, LHSArray);
            RVMType innermostElementType = LHSArray.getInnermostElementType();
            if (innermostElementType.isPrimitiveType() || innermostElementType.isUnboxedType() || (innermostElementType.asClass().isResolved() && innermostElementType.asClass().isFinal())) {
                // [^k of primitive or [^k of final class. Just like final classes,
                // a PTR compare of rhsTIB and the TIB of the class gives the answer.
                continueAt.insertBefore(IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            }
            // TODO: branch probability calculation is somewhat bogus for this case.
            Instruction shortcircuit = IfCmp.create(REF_IFCMP, oldGuard, RHStib, classTIB, ConditionOperand.EQUAL(), trueBlock.makeJumpTarget(), new BranchProfileOperand());
            if (oldGuard != null) {
                oldGuard = oldGuard.copyD2D();
            }
            continueAt.insertBefore(shortcircuit);
            BasicBlock myBlock = shortcircuit.getBasicBlock();
            BasicBlock mainBlock = myBlock.splitNodeWithLinksAt(shortcircuit, ir);
            // must come after the splitNodeAt
            myBlock.insertOut(trueBlock);
            RegisterOperand rhsType = InsertUnary(continueAt, ir, GET_TYPE_FROM_TIB, TypeReference.Type, RHStib.copy());
            if (innermostElementType.isJavaLangObjectType()) {
                IntConstantOperand lhsDimension = IC(LHStype.getDimensionality());
                RegisterOperand rhsDimension = getField(continueAt, ir, rhsType, Entrypoints.dimensionField);
                Instruction dimTest = IfCmp2.create(INT_IFCMP2, oldGuard, rhsDimension, lhsDimension, ConditionOperand.GREATER(), trueBlock.makeJumpTarget(), ((BranchProfileOperand) falseProb.copy()).flip(), ConditionOperand.LESS(), falseBlock.makeJumpTarget(), (BranchProfileOperand) falseProb.copy());
                if (oldGuard != null) {
                    oldGuard = oldGuard.copyD2D();
                }
                continueAt.insertBefore(dimTest);
                // BasicBlock testBlock =
                mainBlock.splitNodeWithLinksAt(dimTest, ir);
                mainBlock.insertOut(trueBlock);
                mainBlock.insertOut(falseBlock);
                RegisterOperand rhsInnermostElementTypeDimension = getField(continueAt, ir, rhsType.copyU2U(), Entrypoints.innermostElementTypeDimensionField);
                continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, rhsInnermostElementTypeDimension, IC(0), ConditionOperand.NOT_EQUAL(), falseBlock.makeJumpTarget(), falseProb));
                return continueAt;
            }
        }
        // Not a case we want to handle inline
        RVMMethod target = Entrypoints.instanceOfMethod;
        RegisterOperand callResult = ir.regpool.makeTempInt();
        Instruction call = Call.create2(CALL, callResult, AC(target.getOffset()), MethodOperand.STATIC(target), RHSobj, IC(LHStype.getId()));
        call.copyPosition(continueAt);
        continueAt.insertBefore(call);
        call = callHelper(call, ir);
        continueAt.insertBefore(IfCmp.create(INT_IFCMP, oldGuard, callResult.copyD2U(), IC(0), ConditionOperand.EQUAL(), falseBlock.makeJumpTarget(), falseProb));
        return continueAt;
    }
    OptimizingCompilerException.UNREACHABLE();
    return null;
}
Also used : RVMMethod(org.jikesrvm.classloader.RVMMethod) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) MethodOperand(org.jikesrvm.compilers.opt.ir.operand.MethodOperand) RegisterOperand(org.jikesrvm.compilers.opt.ir.operand.RegisterOperand) TrueGuardOperand(org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand) ConditionOperand(org.jikesrvm.compilers.opt.ir.operand.ConditionOperand) Operand(org.jikesrvm.compilers.opt.ir.operand.Operand) NullConstantOperand(org.jikesrvm.compilers.opt.ir.operand.NullConstantOperand) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) TrapCodeOperand(org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand) LocationOperand(org.jikesrvm.compilers.opt.ir.operand.LocationOperand) IntConstantOperand(org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand) RVMArray(org.jikesrvm.classloader.RVMArray) RVMType(org.jikesrvm.classloader.RVMType) BasicBlock(org.jikesrvm.compilers.opt.ir.BasicBlock) BranchProfileOperand(org.jikesrvm.compilers.opt.ir.operand.BranchProfileOperand) Instruction(org.jikesrvm.compilers.opt.ir.Instruction) RVMClass(org.jikesrvm.classloader.RVMClass)

Aggregations

RVMArray (org.jikesrvm.classloader.RVMArray)32 TIB (org.jikesrvm.objectmodel.TIB)14 Entrypoint (org.vmmagic.pragma.Entrypoint)14 RVMType (org.jikesrvm.classloader.RVMType)11 RVMClass (org.jikesrvm.classloader.RVMClass)9 NoInline (org.vmmagic.pragma.NoInline)8 TypeReference (org.jikesrvm.classloader.TypeReference)7 Interruptible (org.vmmagic.pragma.Interruptible)7 RVMMethod (org.jikesrvm.classloader.RVMMethod)6 Address (org.vmmagic.unboxed.Address)6 Operand (org.jikesrvm.compilers.opt.ir.operand.Operand)4 RegisterOperand (org.jikesrvm.compilers.opt.ir.operand.RegisterOperand)4 Test (org.junit.Test)4 Instruction (org.jikesrvm.compilers.opt.ir.Instruction)3 ConditionOperand (org.jikesrvm.compilers.opt.ir.operand.ConditionOperand)3 IntConstantOperand (org.jikesrvm.compilers.opt.ir.operand.IntConstantOperand)3 LocationOperand (org.jikesrvm.compilers.opt.ir.operand.LocationOperand)3 MethodOperand (org.jikesrvm.compilers.opt.ir.operand.MethodOperand)3 TrapCodeOperand (org.jikesrvm.compilers.opt.ir.operand.TrapCodeOperand)3 TrueGuardOperand (org.jikesrvm.compilers.opt.ir.operand.TrueGuardOperand)3