# HG changeset patch # User Doug Simon # Date 1366994201 -7200 # Node ID 0266549ff6e04b46c5e361b146a5ae69bb55efab # Parent e1200d5141fa0ee3bbf9316f1b533615b71da6e9 added support from compiled stubs to be installed as RuntimeStubs and to be able to directly call C/C++ runtime functions (GRAAL-81) replaced NewArraySlowStubCall with NewArrayRuntimeCall using this support diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Apr 26 18:36:41 2013 +0200 @@ -45,6 +45,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.StandardOp.ParametersOp; import com.oracle.graal.lir.LIRInstruction.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; @@ -161,28 +162,59 @@ Stub stub = runtime().asStub(lirGen.method()); if (stub != null) { - final Set definedRegisters = new HashSet<>(); - ValueProcedure defProc = new ValueProcedure() { + + List registerPreservations = new ArrayList<>(); + final Set definedRegisters = gatherDefinedRegisters(lir, registerPreservations); + stub.initDefinedRegisters(definedRegisters); + + // Eliminate unnecessary register preservation + for (AMD64RegisterPreservationOp op : registerPreservations) { + op.doNotPreserve(definedRegisters); + } + + // Record where preserved registers are saved + for (Map.Entry e : gen.calleeSaveInfo.entrySet()) { + e.getValue().describePreservation(e.getKey().debugInfo(), frameMap); + } + } + + return tasm; + } - @Override - public Value doValue(Value value) { - if (ValueUtil.isRegister(value)) { - final Register reg = ValueUtil.asRegister(value); - definedRegisters.add(reg); - } - return value; + /** + * Finds all the registers that are defined by some given LIR. + * + * @param lir the LIR to examine + * @param registerPreservations register preservation operations in {@code lir} are added to this list + * @return the registers that are defined by or used as temps for any instruction in {@code lir} + */ + private static Set gatherDefinedRegisters(LIR lir, List registerPreservations) { + final Set definedRegisters = new HashSet<>(); + ValueProcedure defProc = new ValueProcedure() { + + @Override + public Value doValue(Value value) { + if (ValueUtil.isRegister(value)) { + final Register reg = ValueUtil.asRegister(value); + definedRegisters.add(reg); } - }; - for (Block block : lir.codeEmittingOrder()) { - for (LIRInstruction op : lir.lir(block)) { + return value; + } + }; + for (Block block : lir.codeEmittingOrder()) { + for (LIRInstruction op : lir.lir(block)) { + if (op instanceof AMD64RegisterPreservationOp) { + // Don't consider these ops as definitions + registerPreservations.add((AMD64RegisterPreservationOp) op); + } else if (op instanceof ParametersOp) { + // Don't consider these ops as definitions + } else { op.forEachTemp(defProc); op.forEachOutput(defProc); } } - stub.initDefinedRegisters(definedRegisters); } - - return tasm; + return definedRegisters; } @Override diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallEpilogueOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +@Opcode("CRUNTIME_CALL_EPILOGUE") +final class AMD64HotSpotCRuntimeCallEpilogueOp extends AMD64LIRInstruction { + + @Use({REG, ILLEGAL}) protected Value thread; + + AMD64HotSpotCRuntimeCallEpilogueOp(Value thread) { + this.thread = thread; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + // reset last Java frame: + HotSpotVMConfig config = graalRuntime().getConfig(); + masm.movslq(new AMD64Address(asRegister(thread), config.threadLastJavaSpOffset), 0); + masm.movslq(new AMD64Address(asRegister(thread), config.threadLastJavaFpOffset), 0); + } +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotCRuntimeCallPrologueOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +@Opcode("CRUNTIME_CALL_PROLOGUE") +final class AMD64HotSpotCRuntimeCallPrologueOp extends AMD64LIRInstruction { + + @Use({REG, ILLEGAL}) protected Value thread; + + AMD64HotSpotCRuntimeCallPrologueOp(Value thread) { + this.thread = thread; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + + // save last Java frame + masm.movq(new AMD64Address(asRegister(thread), graalRuntime().getConfig().threadLastJavaSpOffset), rsp); + } +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotDeoptimizeCallerOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; +import static com.oracle.graal.api.code.ValueUtil.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; +import static com.oracle.graal.hotspot.amd64.AMD64DeoptimizeOp.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Removes the current frame and tail calls the uncommon trap routine. + */ +@Opcode("DEOPT_CALLER") +final class AMD64HotSpotDeoptimizeCallerOp extends AMD64HotSpotEpilogueOp { + + private final DeoptimizationAction action; + private final DeoptimizationReason reason; + + AMD64HotSpotDeoptimizeCallerOp(DeoptimizationAction action, DeoptimizationReason reason) { + this.action = action; + this.reason = reason; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + if (isStackSlot(savedRbp)) { + // Restoring RBP from the stack must be done before the frame is removed + masm.movq(rbp, (AMD64Address) tasm.asAddress(savedRbp)); + } else { + Register framePointer = asRegister(savedRbp); + if (framePointer != rbp) { + masm.movq(rbp, framePointer); + } + } + if (tasm.frameContext != null) { + tasm.frameContext.leave(tasm); + } + HotSpotGraalRuntime runtime = graalRuntime(); + Register thread = runtime.getRuntime().threadRegister(); + masm.movl(new AMD64Address(thread, runtime.getConfig().pendingDeoptimizationOffset), tasm.runtime.encodeDeoptActionAndReason(action, reason)); + AMD64Call.directJmp(tasm, masm, tasm.runtime.lookupRuntimeCall(DEOPTIMIZE)); + } +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLIRGenerator.java Fri Apr 26 18:36:41 2013 +0200 @@ -144,8 +144,8 @@ } } params[params.length - 1] = rbpParam; + ParametersOp paramsOp = new ParametersOp(params); - ParametersOp paramsOp = new ParametersOp(params); append(paramsOp); saveRbp = new SaveRbp(new PlaceholderOp(currentBlock, lir.lir(currentBlock).size())); @@ -171,6 +171,74 @@ return runtime().asStub(method) != null; } + /** + * Map from debug infos that need to be updated with callee save information to the operations + * that provide the information. + */ + Map calleeSaveInfo = new HashMap<>(); + + private LIRFrameState currentRuntimeCallInfo; + + @Override + protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, LIRFrameState info) { + boolean needsCalleeSave = callTarget.getDescriptor() == NewArrayRuntimeCall.NEW_ARRAY_RUNTIME; + if (needsCalleeSave) { + currentRuntimeCallInfo = info; + } + super.emitCall(callTarget, result, arguments, temps, info); + } + + @Override + public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, DeoptimizingNode info, Value... args) { + boolean needsCalleeSave = callTarget.getDescriptor() == NewArrayRuntimeCall.NEW_ARRAY_RUNTIME; + + RegisterValue[] savedRegisters = null; + StackSlot[] savedRegisterLocations = null; + if (needsCalleeSave) { + Register returnReg = isRegister(cc.getReturn()) ? asRegister(cc.getReturn()) : null; + Set registers = new HashSet<>(Arrays.asList(frameMap.registerConfig.getAllocatableRegisters())); + if (returnReg != null) { + registers.remove(returnReg); + } + + savedRegisters = new RegisterValue[registers.size()]; + savedRegisterLocations = new StackSlot[savedRegisters.length]; + int savedRegisterIndex = 0; + for (Register reg : registers) { + assert reg.isCpu() || reg.isFpu(); + savedRegisters[savedRegisterIndex++] = reg.asValue(reg.isCpu() ? Kind.Long : Kind.Double); + } + + append(new ParametersOp(savedRegisters)); + for (int i = 0; i < savedRegisters.length; i++) { + StackSlot spillSlot = frameMap.allocateSpillSlot(Kind.Long); + savedRegisterLocations[i] = spillSlot; + } + AMD64SaveRegistersOp save = new AMD64SaveRegistersOp(savedRegisters, savedRegisterLocations); + append(save); + + Value thread = args[0]; + AMD64HotSpotCRuntimeCallPrologueOp op = new AMD64HotSpotCRuntimeCallPrologueOp(thread); + append(op); + } + + Variable result = super.emitCall(callTarget, cc, info, args); + + if (needsCalleeSave) { + + Value thread = args[0]; + AMD64HotSpotCRuntimeCallEpilogueOp op = new AMD64HotSpotCRuntimeCallEpilogueOp(thread); + append(op); + + AMD64RestoreRegistersOp restore = new AMD64RestoreRegistersOp(savedRegisterLocations.clone(), savedRegisters.clone()); + AMD64RestoreRegistersOp oldValue = calleeSaveInfo.put(currentRuntimeCallInfo, restore); + assert oldValue == null; + append(restore); + } + + return result; + } + @Override protected CallingConvention createCallingConvention() { Stub stub = runtime().asStub(method); @@ -223,7 +291,6 @@ @Override public void emitTailcall(Value[] args, Value address) { append(new AMD64TailcallOp(args, address)); - } @Override @@ -263,6 +330,13 @@ } @Override + public void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason) { + AMD64HotSpotDeoptimizeCallerOp op = new AMD64HotSpotDeoptimizeCallerOp(action, reason); + epilogueOps.add(op); + append(op); + } + + @Override public void beforeRegisterAllocation() { boolean hasDebugInfo = lir.hasDebugInfo(); AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo); diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotReturnOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -33,7 +33,7 @@ import com.oracle.graal.lir.asm.*; /** - * Performs an unwind to throw an exception. + * Returns from a function. */ @Opcode("RETURN") final class AMD64HotSpotReturnOp extends AMD64HotSpotEpilogueOp { diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri Apr 26 18:36:41 2013 +0200 @@ -29,7 +29,7 @@ import static com.oracle.graal.hotspot.nodes.IdentityHashCodeStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; -import static com.oracle.graal.hotspot.nodes.NewArraySlowStubCall.*; +import static com.oracle.graal.hotspot.nodes.NewArrayRuntimeCall.*; import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceSlowStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; @@ -110,11 +110,12 @@ /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_ARRAY_SLOW, config.newArrayStub, + addRuntimeCall(NEW_ARRAY_RUNTIME, config.newArrayAddress, /* temps */ null, /* ret */ rax.asValue(Kind.Object), - /* arg0: hub */ rdx.asValue(word), - /* arg1: length */ rbx.asValue(Kind.Int)); + /* arg0: thread */ nativeCallingConvention(word, + /* arg1: hub */ word, + /* arg2: length */ Kind.Int)); addStubCall(NEW_INSTANCE, /* ret */ rax.asValue(Kind.Object), diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompilationResult.java Fri Apr 26 18:36:41 2013 +0200 @@ -22,11 +22,17 @@ */ package com.oracle.graal.hotspot; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + import java.util.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CompilationResult.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.api.code.CompilationResult.ExceptionHandler; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; +import com.oracle.graal.replacements.*; /** * Augments a {@link CompilationResult} with HotSpot-specific information. @@ -37,7 +43,12 @@ public final CompilationResult comp; public final HotSpotResolvedJavaMethod method; // used only for methods public final int entryBCI; // used only for methods - public final String name; // used only for stubs + + /** + * Name of the RuntimeStub to be installed for this compilation result. If null, then the + * compilation result will be installed as an nmethod. + */ + public final String stubName; public final Site[] sites; public final ExceptionHandler[] exceptionHandlers; @@ -46,7 +57,14 @@ this.method = method; this.comp = comp; this.entryBCI = entryBCI; - this.name = null; + + // Class stubClass = Stub.class; + Class stubClass = NewArrayStub.class; + if (graalRuntime().getRuntime().lookupJavaType(stubClass).isAssignableFrom(method.getDeclaringClass()) && method.getAnnotation(Snippet.class) != null) { + this.stubName = MetaUtil.format("%h.%n", method); + } else { + this.stubName = null; + } sites = getSortedSites(comp); if (comp.getExceptionHandlers() == null) { diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLIRGenerator.java Fri Apr 26 18:36:41 2013 +0200 @@ -42,6 +42,8 @@ */ void emitTailcall(Value[] args, Value address); + void emitDeoptimizeCaller(DeoptimizationAction action, DeoptimizationReason reason); + void visitDirectCompareAndSwap(DirectCompareAndSwapNode x); /** diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Apr 26 18:36:41 2013 +0200 @@ -179,6 +179,11 @@ public int uninitializedIdentityHashCodeValue; /** + * Offset of the pending exception field. + */ + public int pendingExceptionOffset; + + /** * Offset of the pending deoptimization field. */ public int pendingDeoptimizationOffset; @@ -302,6 +307,10 @@ public int threadTlabStartOffset; public int threadTlabSizeOffset; public int threadAllocatedBytesOffset; + public int threadLastJavaSpOffset; + public int threadLastJavaFpOffset; + public int threadLastJavaPcOffset; + public int threadObjectResultOffset; public int tlabRefillWasteLimitOffset; public int tlabRefillWasteIncrement; public int tlabAlignmentReserve; @@ -372,6 +381,8 @@ public long cipherBlockChainingEncryptAESCryptStub; public long cipherBlockChainingDecryptAESCryptStub; + public long newArrayAddress; + public int deoptReasonNullCheck; public int deoptReasonRangeCheck; public int deoptReasonClassCheck; diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Fri Apr 26 18:36:41 2013 +0200 @@ -194,20 +194,20 @@ long getMaxCallTargetOffset(long stub); - String disassembleNMethod(long nmethod); + String disassembleCodeBlob(long codeBlob); /** - * Gets a copy of the machine code for an nmethod. + * Gets a copy of the machine code for a CodeBlob. * - * @return the machine code for {@code nmethod} if it is valid, null otherwise + * @return the machine code for {@code codeBlob} if it is valid, null otherwise */ - byte[] getCode(long nmethod); + byte[] getCode(long codeBlob); StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); - Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException; + Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException; - Object executeCompiledMethodVarargs(Object[] args, long nativeMethod) throws InvalidInstalledCodeException; + Object executeCompiledMethodVarargs(Object[] args, long nmethod) throws InvalidInstalledCodeException; int getVtableEntryOffset(long metaspaceMethod); diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Fri Apr 26 18:36:41 2013 +0200 @@ -130,16 +130,16 @@ public native long getMaxCallTargetOffset(long stub); @Override - public native String disassembleNMethod(long nmethod); + public native String disassembleCodeBlob(long codeBlob); @Override - public native byte[] getCode(long nmethod); + public native byte[] getCode(long codeBlob); @Override public native StackTraceElement getStackTraceElement(long metaspaceMethod, int bci); @Override - public native Object executeCompiledMethodVarargs(Object[] args, long nativeMethod); + public native Object executeCompiledMethodVarargs(Object[] args, long nmethod); @Override public native int getVtableEntryOffset(long metaspaceMethod); @@ -172,16 +172,16 @@ public native boolean isInstalledCodeValid(long nativeMethod); @Override - public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nativeMethod) throws InvalidInstalledCodeException { - return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nativeMethod); + public Object executeCompiledMethod(Object arg1, Object arg2, Object arg3, long nmethod) throws InvalidInstalledCodeException { + return executeCompiledMethodIntrinsic(arg1, arg2, arg3, nmethod); } /** - * Direct call to the given nativeMethod with three object arguments and an object return value. - * This method does not have an implementation on the C++ side, but its entry points (from + * Direct call to the given nmethod with three object arguments and an object return value. This + * method does not have an implementation on the C++ side, but its entry points (from * interpreter and from compiled code) are directly pointing to a manually generated assembly * stub that does the necessary argument shuffling and a tail call via an indirect jump to the * verified entry point of the given native method. */ - private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nativeMethod); + private static native Object executeCompiledMethodIntrinsic(Object arg1, Object arg2, Object arg3, long nmethod); } diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Apr 26 18:36:41 2013 +0200 @@ -43,8 +43,9 @@ private final HotSpotResolvedJavaMethod method; private final boolean isDefault; private final Graph graph; - long nmethod; + long codeBlob; long start; + boolean isNmethod; public HotSpotInstalledCode(HotSpotResolvedJavaMethod method, Graph graph, boolean isDefault) { this.method = method; @@ -56,8 +57,8 @@ return isDefault; } - public long getMethodAddress() { - return nmethod; + public long getCodeBlob() { + return codeBlob; } public Graph getGraph() { @@ -71,26 +72,29 @@ @Override public boolean isValid() { - return graalRuntime().getCompilerToVM().isInstalledCodeValid(nmethod); + return !isNmethod || graalRuntime().getCompilerToVM().isInstalledCodeValid(codeBlob); } @Override public void invalidate() { - graalRuntime().getCompilerToVM().invalidateInstalledCode(nmethod); + if (isNmethod) { + graalRuntime().getCompilerToVM().invalidateInstalledCode(codeBlob); + } } @Override public String toString() { - return String.format("InstalledCode[method=%s, nmethod=0x%x]", method, nmethod); + return String.format("InstalledCode[method=%s, codeBlob=0x%x]", method, codeBlob); } @Override public Object execute(Object arg1, Object arg2, Object arg3) throws InvalidInstalledCodeException { + assert isNmethod; assert method.getSignature().getParameterCount(!Modifier.isStatic(method.getModifiers())) == 3; assert method.getSignature().getParameterKind(0) == Kind.Object; assert method.getSignature().getParameterKind(1) == Kind.Object; assert !Modifier.isStatic(method.getModifiers()) || method.getSignature().getParameterKind(2) == Kind.Object; - return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, nmethod); + return graalRuntime().getCompilerToVM().executeCompiledMethod(arg1, arg2, arg3, codeBlob); } private boolean checkArgs(Object... args) { @@ -109,8 +113,9 @@ @Override public Object executeVarargs(Object... args) throws InvalidInstalledCodeException { + assert isNmethod; assert checkArgs(args); - return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, nmethod); + return graalRuntime().getCompilerToVM().executeCompiledMethodVarargs(args, codeBlob); } @Override @@ -120,6 +125,6 @@ @Override public byte[] getCode() { - return graalRuntime().getCompilerToVM().getCode(nmethod); + return graalRuntime().getCompilerToVM().getCode(codeBlob); } } diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod.java Fri Apr 26 18:36:41 2013 +0200 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.meta; import static com.oracle.graal.api.meta.MetaUtil.*; -import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.graph.UnsafeAccess.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import java.lang.annotation.*; diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Apr 26 18:36:41 2013 +0200 @@ -33,6 +33,7 @@ import static com.oracle.graal.hotspot.nodes.NewArrayStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; import static com.oracle.graal.hotspot.replacements.SystemSubstitutions.*; +import static com.oracle.graal.hotspot.stubs.Stub.*; import static com.oracle.graal.java.GraphBuilderPhase.RuntimeCalls.*; import static com.oracle.graal.nodes.java.RegisterFinalizerNode.*; import static com.oracle.graal.replacements.Log.*; @@ -262,7 +263,7 @@ /* arg2: value */ Kind.Long, /* arg3: value */ Kind.Long)); - addRuntimeCall(Stub.STUB_PRINTF, config.stubPrintfStub, + addRuntimeCall(STUB_PRINTF, config.stubPrintfStub, /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: format */ javaCallingConvention(Kind.Long, @@ -951,8 +952,8 @@ public String disassemble(InstalledCode code) { if (code.isValid()) { - long nmethod = ((HotSpotInstalledCode) code).getMethodAddress(); - return graalRuntime.getCompilerToVM().disassembleNMethod(nmethod); + long codeBlob = ((HotSpotInstalledCode) code).getCodeBlob(); + return graalRuntime.getCompilerToVM().disassembleCodeBlob(codeBlob); } return null; } diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/DeoptimizeCallerNode.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.type.*; + +/** + * Removes the current frame and tail calls the uncommon trap routine. + */ +@NodeInfo(shortName = "DeoptCaller", nameTemplate = "DeoptCaller {p#reason/s}") +public class DeoptimizeCallerNode extends ControlSinkNode implements LIRLowerable { + + private final DeoptimizationAction action; + private final DeoptimizationReason reason; + + public DeoptimizeCallerNode(DeoptimizationAction action, DeoptimizationReason reason) { + super(StampFactory.forVoid()); + this.action = action; + this.reason = reason; + } + + @Override + public void generate(LIRGeneratorTool gen) { + ((HotSpotLIRGenerator) gen).emitDeoptimizeCaller(action, reason); + } + + @NodeIntrinsic + public static native void deopt(@ConstantNodeParameter DeoptimizationAction action, @ConstantNodeParameter DeoptimizationReason reason); +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/HotSpotInstalledCodeExecuteNode.java Fri Apr 26 18:36:41 2013 +0200 @@ -69,11 +69,11 @@ ResolvedJavaMethod method = null; ResolvedJavaField methodField = null; ResolvedJavaField metaspaceMethodField = null; - ResolvedJavaField nmethodField = null; + ResolvedJavaField codeBlobField = null; try { method = tool.lookupJavaMethod(HotSpotInstalledCodeExecuteNode.class.getMethod("placeholder", Object.class, Object.class, Object.class)); methodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("method")); - nmethodField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("nmethod")); + codeBlobField = tool.lookupJavaField(HotSpotInstalledCode.class.getDeclaredField("codeBlob")); metaspaceMethodField = tool.lookupJavaField(HotSpotResolvedJavaMethod.class.getDeclaredField("metaspaceMethod")); } catch (NoSuchMethodException | SecurityException | NoSuchFieldException e) { throw new IllegalStateException(e); @@ -86,8 +86,8 @@ StructuredGraph g = (StructuredGraph) graph(); - LoadFieldNode loadnmethod = g.add(new LoadFieldNode(code, nmethodField)); - UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadnmethod, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), graalRuntime().getTarget().wordKind)); + LoadFieldNode loadCodeBlob = g.add(new LoadFieldNode(code, codeBlobField)); + UnsafeLoadNode load = g.add(new UnsafeLoadNode(loadCodeBlob, verifiedEntryPointOffset, ConstantNode.forLong(0, graph()), graalRuntime().getTarget().wordKind)); LoadFieldNode loadMethod = g.add(new LoadFieldNode(code, methodField)); LoadFieldNode loadmetaspaceMethod = g.add(new LoadFieldNode(loadMethod, metaspaceMethodField)); @@ -102,7 +102,7 @@ g.addBeforeFixed(invoke, loadmetaspaceMethod); g.addBeforeFixed(loadmetaspaceMethod, loadMethod); g.addBeforeFixed(invoke, load); - g.addBeforeFixed(load, loadnmethod); + g.addBeforeFixed(load, loadCodeBlob); return invoke; } diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayRuntimeCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayRuntimeCall.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.nodes; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.word.*; + +/** + * Node implementing a call to the {@code new_array} stub. + */ +public class NewArrayRuntimeCall extends DeoptimizingStubCall implements LIRGenLowerable { + + private static final Stamp defaultStamp = StampFactory.objectNonNull(); + + @Input private final ValueNode thread; + @Input private final ValueNode hub; + @Input private final ValueNode length; + + public static final Descriptor NEW_ARRAY_RUNTIME = new Descriptor("new_array_runtime", false, Object.class, Word.class, Word.class, int.class); + + public NewArrayRuntimeCall(ValueNode thread, ValueNode hub, ValueNode length) { + super(defaultStamp); + this.thread = thread; + this.hub = hub; + this.length = length; + } + + @Override + public boolean inferStamp() { + if (stamp() == defaultStamp && hub.isConstant()) { + updateStamp(StampFactory.exactNonNull(HotSpotResolvedObjectType.fromMetaspaceKlass(hub.asConstant()))); + return true; + } + return false; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_RUNTIME); + Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(thread), gen.operand(hub), gen.operand(length)); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native Object call(Word thread, Word hub, int length); +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java Fri Apr 26 18:21:10 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.nodes; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; -import com.oracle.graal.compiler.gen.*; -import com.oracle.graal.compiler.target.*; -import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.lir.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.word.*; - -/** - * Node implementing a call to the {@code new_array} stub. - */ -public class NewArraySlowStubCall extends DeoptimizingStubCall implements LIRGenLowerable { - - private static final Stamp defaultStamp = StampFactory.objectNonNull(); - - @Input private final ValueNode hub; - @Input private final ValueNode length; - - public static final Descriptor NEW_ARRAY_SLOW = new Descriptor("new_array_slow", false, Object.class, Word.class, int.class); - - public NewArraySlowStubCall(ValueNode hub, ValueNode length) { - super(defaultStamp); - this.hub = hub; - this.length = length; - } - - @Override - public boolean inferStamp() { - if (stamp() == defaultStamp && hub.isConstant()) { - updateStamp(StampFactory.exactNonNull(HotSpotResolvedObjectType.fromMetaspaceKlass(hub.asConstant()))); - return true; - } - return false; - } - - @Override - public void generate(LIRGenerator gen) { - RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY_SLOW); - Variable result = gen.emitCall(stub, stub.getCallingConvention(), this, gen.operand(hub), gen.operand(length)); - gen.setResult(this, result); - } - - @NodeIntrinsic - public static native Object call(Word hub, int length); -} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/HotSpotSnippetUtils.java Fri Apr 26 18:36:41 2013 +0200 @@ -97,6 +97,20 @@ return config().threadTlabStartOffset; } + public static final Object PENDING_EXCEPTION_LOCATION = LocationNode.createLocation("PendingException"); + + @Fold + private static int threadPendingExceptionOffset() { + return config().pendingExceptionOffset; + } + + public static final Object OBJECT_RESULT_LOCATION = LocationNode.createLocation("ObjectResult"); + + @Fold + private static int objectResultOffset() { + return config().threadObjectResultOffset; + } + public static Object readExceptionOop(Word thread) { return thread.readObject(threadExceptionOopOffset(), EXCEPTION_OOP_LOCATION); } @@ -131,6 +145,28 @@ thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION); } + /** + * Clears the pending exception if for the given thread. + * + * @return {@code true} if there was a pending exception + */ + public static boolean clearPendingException(Word thread) { + boolean result = thread.readObject(threadPendingExceptionOffset(), PENDING_EXCEPTION_LOCATION) != null; + thread.writeObject(threadPendingExceptionOffset(), null); + return result; + } + + /** + * Gets and clears the object result from a runtime call stored in a thread local. + * + * @return the object that was in the thread local + */ + public static Object clearObjectResult(Word thread) { + Object result = thread.readObject(objectResultOffset(), OBJECT_RESULT_LOCATION); + thread.writeObject(objectResultOffset(), null); + return result; + } + @Fold public static int threadObjectOffset() { return config().threadObjectOffset; diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Fri Apr 26 18:36:41 2013 +0200 @@ -22,11 +22,15 @@ */ package com.oracle.graal.hotspot.stubs; +import static com.oracle.graal.api.code.DeoptimizationAction.*; +import static com.oracle.graal.api.meta.DeoptimizationReason.*; +import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import static com.oracle.graal.hotspot.replacements.HotSpotSnippetUtils.*; import static com.oracle.graal.hotspot.replacements.NewObjectSnippets.*; import static com.oracle.graal.hotspot.stubs.NewInstanceStub.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; @@ -42,7 +46,7 @@ * Stub implementing the fast path for TLAB refill during instance class allocation. This stub is * called from the {@linkplain NewObjectSnippets inline} allocation code when TLAB allocation fails. * If this stub fails to refill the TLAB or allocate the object, it calls out to the HotSpot C++ - * runtime for to complete the allocation. + * runtime to complete the allocation. */ public class NewArrayStub extends Stub { @@ -54,10 +58,16 @@ protected Arguments makeArguments(SnippetInfo stub) { HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); + // RuntimeStub cannot (currently) support oops or metadata embedded in the code so we + // convert the hub (i.e., Klass*) for int[] to be a naked word. This should be safe since + // the int[] class will never be unloaded. + Constant intArrayHub = intArrayType.klass(); + intArrayHub = Constant.forIntegerKind(graalRuntime().getTarget().wordKind, intArrayHub.asLong(), null); + Arguments args = new Arguments(stub); args.add("hub", null); args.add("length", null); - args.addConst("intArrayHub", intArrayType.klass()); + args.addConst("intArrayHub", intArrayHub); args.addConst("log", Boolean.getBoolean("graal.logNewArrayStub")); return args; } @@ -92,7 +102,15 @@ return verifyOop(memory.toObject()); } } - log(log, "newArray: calling new_array_slow", 0L); - return verifyOop(NewArraySlowStubCall.call(hub, length)); + log(log, "newArray: calling new_array_runtime", 0L); + + NewArrayRuntimeCall.call(thread(), hub, length); + + if (clearPendingException(thread())) { + log(log, "newArray: deoptimizing to caller", 0L); + clearObjectResult(thread()); + DeoptimizeCallerNode.deopt(InvalidateReprofile, RuntimeConstraint); + } + return verifyOop(clearObjectResult(thread())); } } diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Fri Apr 26 18:36:41 2013 +0200 @@ -28,6 +28,7 @@ import java.util.concurrent.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CompilationResult.DataPatch; import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.*; @@ -76,13 +77,13 @@ protected InstalledCode code; /** - * The registers defined by this stub. + * The registers/temporaries defined by this stub. */ private Set definedRegisters; public void initDefinedRegisters(Set registers) { assert registers != null; - assert definedRegisters == null : "cannot redefine"; + assert definedRegisters == null || registers.equals(definedRegisters) : "cannot redefine"; definedRegisters = registers; } @@ -123,6 +124,17 @@ return linkage; } + private boolean checkCompilationResult(CompilationResult compResult) { + if (this instanceof NewArrayStub) { + for (DataPatch data : compResult.getDataReferences()) { + Constant constant = data.constant; + assert constant.getKind() != Kind.Object : MetaUtil.format("%h.%n(%p): ", getMethod()) + "cannot have embedded oop: " + constant; + assert constant.getPrimitiveAnnotation() == null : MetaUtil.format("%h.%n(%p): ", getMethod()) + "cannot have embedded metadata: " + constant; + } + } + return true; + } + /** * Gets the code for this stub, compiling it first if necessary. */ @@ -143,6 +155,8 @@ final CompilationResult compResult = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, new SpeculationLog()); + assert checkCompilationResult(compResult); + assert definedRegisters != null; code = Debug.scope("CodeInstall", new Callable() { @@ -156,7 +170,6 @@ return installedCode; } }); - } }); assert code != null : "error installing stub " + getMethod(); diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegisterPreservationOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RegisterPreservationOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.amd64; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.asm.*; + +/** + * Base class for the operations that save or restore registers around another operation that may + * potentially destroy any register (e.g., a call). + */ +public abstract class AMD64RegisterPreservationOp extends AMD64LIRInstruction { + + protected static void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Value[] dst, Value[] src) { + for (int i = 0; i < dst.length; i++) { + if (dst[i] != null) { + AMD64Move.move(tasm, masm, dst[i], src[i]); + } else { + assert src[i] == null; + } + } + } + + protected static void doNotPreserve(Set registers, RegisterValue[] registerValues, StackSlot[] slots) { + for (int i = 0; i < slots.length; i++) { + if (registerValues[i] != null) { + if (registers.contains(registerValues[i].getRegister())) { + registerValues[i] = null; + slots[i] = null; + } + } + } + } + + /** + * Records that no registers in {@code registers} need to be preserved. + */ + public abstract void doNotPreserve(Set registers); +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64RestoreRegistersOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.amd64; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.asm.*; + +/** + * Restores registers from stack slots. + */ +@Opcode("RESTORE_REGISTER") +public final class AMD64RestoreRegistersOp extends AMD64RegisterPreservationOp { + + @Use(STACK) protected StackSlot[] src; + @Def(REG) protected RegisterValue[] dst; + + public AMD64RestoreRegistersOp(StackSlot[] src, RegisterValue[] dst) { + this.src = src; + this.dst = dst; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + emitCode(tasm, masm, dst, src); + } + + @Override + public void doNotPreserve(Set registers) { + doNotPreserve(registers, dst, src); + } + + /** + * Updates {@code debugInfo} with a description of where each preserved register is saved. + */ + public void describePreservation(DebugInfo debugInfo, FrameMap frameMap) { + int preserved = 0; + for (RegisterValue r : dst) { + if (r != null) { + preserved++; + } + } + if (preserved != 0) { + Register[] keys = new Register[preserved]; + int[] values = new int[keys.length]; + int mapIndex = 0; + for (int i = 0; i < src.length; i++) { + if (dst[i] != null) { + keys[mapIndex] = dst[i].getRegister(); + values[mapIndex] = frameMap.indexForStackSlot(src[i]); + mapIndex++; + } + } + assert mapIndex == preserved; + debugInfo.setCalleeSaveInfo(new RegisterSaveLayout(keys, values)); + } + } +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.amd64; + +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.asm.amd64.*; +import com.oracle.graal.lir.LIRInstruction.Opcode; +import com.oracle.graal.lir.asm.*; + +/** + * Saves registers to stack slots. + */ +@Opcode("SAVE_REGISTER") +public final class AMD64SaveRegistersOp extends AMD64RegisterPreservationOp { + + @Use(REG) protected RegisterValue[] src; + @Def(STACK) protected StackSlot[] dst; + + public AMD64SaveRegistersOp(RegisterValue[] src, StackSlot[] dst) { + this.src = src; + this.dst = dst; + } + + @Override + public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { + emitCode(tasm, masm, dst, src); + } + + @Override + public void doNotPreserve(Set registers) { + doNotPreserve(registers, src, dst); + } + +} diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Fri Apr 26 18:36:41 2013 +0200 @@ -210,8 +210,7 @@ } /** - * Computes the offset of a stack slot relative to the frame register. This is also the bit - * index of stack slots in the reference map. + * Computes the offset of a stack slot relative to the frame register. * * @param slot a stack slot * @return the offset of the stack slot @@ -226,6 +225,18 @@ } /** + * Computes the index of a stack slot relative to slot 0. This is also the bit index of stack + * slots in the reference map. + * + * @param slot a stack slot + * @return the index of the stack slot + */ + public int indexForStackSlot(StackSlot slot) { + assert offsetForStackSlot(slot) % target.wordSize == 0; + return offsetForStackSlot(slot) / target.wordSize; + } + + /** * Gets the offset to the stack area where callee-saved registers are stored. * * @return The offset to the callee save area (in bytes). @@ -285,7 +296,7 @@ return getSlot(kind, 0); } - private List freedSlots; + private Set freedSlots; /** * Frees a spill slot that was obtained via {@link #allocateSpillSlot(Kind)} such that it can be @@ -293,7 +304,7 @@ */ public void freeSpillSlot(StackSlot slot) { if (freedSlots == null) { - freedSlots = new ArrayList<>(); + freedSlots = new HashSet<>(); } freedSlots.add(slot); } @@ -329,11 +340,6 @@ } } - private int frameRefMapIndex(StackSlot slot) { - assert offsetForStackSlot(slot) % target.wordSize == 0; - return offsetForStackSlot(slot) / target.wordSize; - } - /** * Initializes a reference map that covers all registers of the target architecture. */ @@ -368,7 +374,7 @@ if (isRegister(location)) { registerRefMap.set(asRegister(location).number); } else if (isStackSlot(location)) { - int index = frameRefMapIndex(asStackSlot(location)); + int index = indexForStackSlot(asStackSlot(location)); frameRefMap.set(index); } else { assert isConstant(location); diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Fri Apr 26 18:36:41 2013 +0200 @@ -22,14 +22,14 @@ */ package com.oracle.graal.lir; +import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; + import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.graph.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.cfg.*; -import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; - /** * A collection of machine-independent LIR operations, as well as interfaces to be implemented for * specific kinds or LIR operations. diff -r e1200d5141fa -r 0266549ff6e0 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Fri Apr 26 18:21:10 2013 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/TargetMethodAssembler.java Fri Apr 26 18:36:41 2013 +0200 @@ -113,7 +113,7 @@ Debug.metric("TargetMethods").increment(); Debug.metric("CodeBytesEmitted").add(compilationResult.getTargetCodeSize()); - Debug.metric("SafepointsEmitted").add(compilationResult.getInfopoints().size()); + Debug.metric("InfopointsEmitted").add(compilationResult.getInfopoints().size()); Debug.metric("DataPatches").add(ldp.size()); Debug.metric("ExceptionHandlersEmitted").add(compilationResult.getExceptionHandlers().size()); } diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Fri Apr 26 18:36:41 2013 +0200 @@ -183,7 +183,7 @@ do_klass(Long_klass, java_lang_Long, Pre ) \ \ /* Support for Graal */ \ - do_klass(GraalBitMap_klass, java_util_BitSet, Opt) \ + do_klass(BitSet_klass, java_util_BitSet, Opt) \ /* graal.hotspot */ \ do_klass(HotSpotCompilationResult_klass, com_oracle_graal_hotspot_HotSpotCompilationResult, Opt) \ do_klass(HotSpotRuntimeCallTarget_klass, com_oracle_graal_hotspot_HotSpotRuntimeCallTarget, Opt) \ @@ -205,6 +205,7 @@ do_klass(Assumptions_CallSiteTargetValue_klass, com_oracle_graal_api_code_Assumptions_CallSiteTargetValue, Opt) \ do_klass(BytecodePosition_klass, com_oracle_graal_api_code_BytecodePosition, Opt) \ do_klass(DebugInfo_klass, com_oracle_graal_api_code_DebugInfo, Opt) \ + do_klass(RegisterSaveLayout_klass, com_oracle_graal_api_code_RegisterSaveLayout, Opt) \ do_klass(BytecodeFrame_klass, com_oracle_graal_api_code_BytecodeFrame, Opt) \ do_klass(CompilationResult_klass, com_oracle_graal_api_code_CompilationResult, Opt) \ do_klass(CompilationResult_Call_klass, com_oracle_graal_api_code_CompilationResult_Call, Opt) \ diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Apr 26 18:36:41 2013 +0200 @@ -341,6 +341,7 @@ template(com_oracle_graal_api_code_RegisterValue, "com/oracle/graal/api/code/RegisterValue") \ template(com_oracle_graal_api_code_StackSlot, "com/oracle/graal/api/code/StackSlot") \ template(com_oracle_graal_api_code_VirtualObject, "com/oracle/graal/api/code/VirtualObject") \ + template(com_oracle_graal_api_code_RegisterSaveLayout, "com/oracle/graal/api/code/RegisterSaveLayout") \ template(com_oracle_graal_api_code_InvalidInstalledCodeException, "com/oracle/graal/api/code/InvalidInstalledCodeException") \ template(startCompiler_name, "startCompiler") \ template(bootstrap_name, "bootstrap") \ diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Fri Apr 26 18:36:41 2013 +0200 @@ -68,41 +68,48 @@ const int MapWordBits = 64; -static bool is_bit_set(oop bit_map, int i) { - jint extra_idx = i / MapWordBits; - arrayOop extra = (arrayOop) GraalBitMap::words(bit_map); - assert(extra_idx >= 0 && extra_idx < extra->length(), "unexpected index"); - jlong word = ((jlong*) extra->base(T_LONG))[extra_idx]; +static bool is_bit_set(oop bitset, int i) { + jint words_idx = i / MapWordBits; + arrayOop words = (arrayOop) BitSet::words(bitset); + assert(words_idx >= 0 && words_idx < words->length(), "unexpected index"); + jlong word = ((jlong*) words->base(T_LONG))[words_idx]; return (word & (1LL << (i % MapWordBits))) != 0; } -static int bitmap_size(oop bit_map) { - arrayOop arr = (arrayOop) GraalBitMap::words(bit_map); +static int bitset_size(oop bitset) { + arrayOop arr = (arrayOop) BitSet::words(bitset); return arr->length() * MapWordBits; } +#ifdef _LP64 + #define SLOTS_PER_WORD 2 +#else + #define SLOTS_PER_WORD 1 +#endif // _LP64 + // creates a HotSpot oop map out of the byte arrays provided by DebugInfo static OopMap* create_oop_map(jint total_frame_size, jint parameter_count, oop debug_info) { OopMap* map = new OopMap(total_frame_size, parameter_count); oop register_map = (oop) DebugInfo::registerRefMap(debug_info); oop frame_map = (oop) DebugInfo::frameRefMap(debug_info); + oop callee_save_info = (oop) DebugInfo::calleeSaveInfo(debug_info); if (register_map != NULL) { for (jint i = 0; i < RegisterImpl::number_of_registers; i++) { bool is_oop = is_bit_set(register_map, i); - VMReg reg = get_hotspot_reg(i); + VMReg hotspot_reg = get_hotspot_reg(i); if (is_oop) { - map->set_oop(reg); + map->set_oop(hotspot_reg); } else { - map->set_value(reg); + map->set_value(hotspot_reg); } } } - for (jint i = 0; i < bitmap_size(frame_map); i++) { + for (jint i = 0; i < bitset_size(frame_map); i++) { bool is_oop = is_bit_set(frame_map, i); // HotSpot stack slots are 4 bytes - VMReg reg = VMRegImpl::stack2reg(i * 2); + VMReg reg = VMRegImpl::stack2reg(i * SLOTS_PER_WORD); if (is_oop) { map->set_oop(reg); } else { @@ -110,6 +117,26 @@ } } + if (callee_save_info != NULL) { + objArrayOop registers = (objArrayOop) RegisterSaveLayout::registers(callee_save_info); + arrayOop slots = (arrayOop) RegisterSaveLayout::slots(callee_save_info); + for (jint i = 0; i < slots->length(); i++) { + oop graal_reg = registers->obj_at(i); + jint graal_reg_number = code_Register::number(graal_reg); + VMReg hotspot_reg = get_hotspot_reg(graal_reg_number); + // HotSpot stack slots are 4 bytes + jint graal_slot = ((jint*) slots->base(T_INT))[i]; + jint hotspot_slot = graal_slot * SLOTS_PER_WORD; + VMReg hotspot_slot_as_reg = VMRegImpl::stack2reg(hotspot_slot); + map->set_callee_saved(hotspot_slot_as_reg, hotspot_reg); +#ifdef _LP64 + // (copied from generate_oop_map() in c1_Runtime1_x86.cpp) + VMReg hotspot_slot_hi_as_reg = VMRegImpl::stack2reg(hotspot_slot + 1); + map->set_callee_saved(hotspot_slot_hi_as_reg, hotspot_reg->next()); +#endif + } + } + return map; } @@ -330,7 +357,7 @@ } // constructor used to create a method -CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations) { +CodeInstaller::CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations) { GraalCompiler::initialize_buffer_blob(); CodeBuffer buffer(JavaThread::current()->get_buffer_blob()); jobject comp_result_obj = JNIHandles::make_local(comp_result()); @@ -347,8 +374,21 @@ int stack_slots = _total_frame_size / HeapWordSize; // conversion to words GrowableArray* leaf_graph_ids = get_leaf_graph_ids(comp_result); - result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, - GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, false, leaf_graph_ids, installed_code, triggered_deoptimizations); + if (_stubName != NULL) { + char* name = strdup(java_lang_String::as_utf8_string(_stubName)); + cb = RuntimeStub::new_runtime_stub(name, + &buffer, + CodeOffsets::frame_never_safe, + stack_slots, + _debug_recorder->_oopmaps, + false); + result = GraalEnv::ok; + } else { + nmethod* nm = NULL; + result = GraalEnv::register_method(method, nm, entry_bci, &_offsets, _custom_stack_area_offset, &buffer, stack_slots, _debug_recorder->_oopmaps, &_exception_handler_table, + GraalCompiler::instance(), _debug_recorder, _dependencies, NULL, -1, false, leaf_graph_ids, installed_code, triggered_deoptimizations); + cb = nm; + } } void CodeInstaller::initialize_fields(oop comp_result, methodHandle method) { @@ -357,7 +397,7 @@ _parameter_count = method->size_of_parameters(); TRACE_graal_1("installing code for %s", method->name_and_sig_as_C_string()); } - _name = HotSpotCompilationResult::name(comp_result); + _stubName = HotSpotCompilationResult::stubName(comp_result); _sites = (arrayOop) HotSpotCompilationResult::sites(comp_result); _exception_handlers = (arrayOop) HotSpotCompilationResult::exceptionHandlers(comp_result); @@ -640,8 +680,14 @@ if (target->is_a(SystemDictionary::HotSpotInstalledCode_klass())) { assert(inst->is_jump(), "jump expected"); - nmethod* nm = (nmethod*) HotSpotInstalledCode::nmethod(target); - nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); + CodeBlob* cb = (CodeBlob*) (address) HotSpotInstalledCode::codeBlob(target); + assert(cb != NULL, "npe"); + if (cb->is_nmethod()) { + nmethod* nm = (nmethod*) cb; + nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point()); + } else { + nativeJump_at((address)inst)->set_jump_destination(cb->code_begin()); + } _instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand); return; diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalCodeInstaller.hpp --- a/src/share/vm/graal/graalCodeInstaller.hpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.hpp Fri Apr 26 18:36:41 2013 +0200 @@ -51,7 +51,7 @@ Arena _arena; oop _comp_result; - oop _name; + oop _stubName; arrayOop _sites; arrayOop _exception_handlers; CodeOffsets _offsets; @@ -76,11 +76,7 @@ public: - // constructor used to create a method - CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, nmethod*& nm, Handle installed_code, Handle triggered_deoptimizations); - - // constructor used to create a stub - CodeInstaller(Handle& target_method, BufferBlob*& blob, jlong& id); + CodeInstaller(Handle& comp_result, methodHandle method, GraalEnv::CodeInstallResult& result, CodeBlob*& cb, Handle installed_code, Handle triggered_deoptimizations); static address runtime_call_target_address(oop runtime_call); diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Apr 26 18:36:41 2013 +0200 @@ -620,7 +620,7 @@ #define set_boolean(name, value) do { env->SetBooleanField(config, getFieldID(env, config, name, "Z"), value); } while (0) #define set_int(name, value) do { env->SetIntField(config, getFieldID(env, config, name, "I"), value); } while (0) #define set_long(name, value) do { env->SetLongField(config, getFieldID(env, config, name, "J"), value); } while (0) -#define set_stub(name, value) do { set_long(name, (jlong) value); } while (0) +#define set_address(name, value) do { set_long(name, (jlong) value); } while (0) #define set_object(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "Ljava/lang/Object;"), value); } while (0) #define set_int_array(name, value) do { env->SetObjectField(config, getFieldID(env, config, name, "[I"), value); } while (0) @@ -699,6 +699,7 @@ set_int("arrayKlassComponentMirrorOffset", in_bytes(ArrayKlass::component_mirror_offset())); + set_int("pendingExceptionOffset", in_bytes(ThreadShadow::pending_exception_offset())); set_int("pendingDeoptimizationOffset", in_bytes(ThreadShadow::pending_deoptimization_offset())); set_int("metaspaceArrayLengthOffset", Array::length_offset_in_bytes()); @@ -721,6 +722,10 @@ set_int("threadTlabStartOffset", in_bytes(JavaThread::tlab_start_offset())); set_int("threadTlabSizeOffset", in_bytes(JavaThread::tlab_size_offset())); set_int("threadAllocatedBytesOffset", in_bytes(JavaThread::allocated_bytes_offset())); + set_int("threadLastJavaSpOffset", in_bytes(JavaThread::last_Java_sp_offset())); + set_int("threadLastJavaFpOffset", in_bytes(JavaThread::last_Java_fp_offset())); + set_int("threadLastJavaPcOffset", in_bytes(JavaThread::last_Java_pc_offset())); + set_int("threadObjectResultOffset", in_bytes(JavaThread::vm_result_offset())); set_int("tlabSlowAllocationsOffset", in_bytes(JavaThread::tlab_slow_allocations_offset())); set_int("tlabFastRefillWasteOffset", in_bytes(JavaThread::tlab_fast_refill_waste_offset())); set_int("tlabNumberOfRefillsOffset", in_bytes(JavaThread::tlab_number_of_refills_offset())); @@ -742,42 +747,44 @@ set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); - set_stub("wbPreCallStub", GraalRuntime::entry_for(GraalRuntime::wb_pre_call_id)); - set_stub("wbPostCallStub", GraalRuntime::entry_for(GraalRuntime::wb_post_call_id)); + set_address("wbPreCallStub", GraalRuntime::entry_for(GraalRuntime::wb_pre_call_id)); + set_address("wbPostCallStub", GraalRuntime::entry_for(GraalRuntime::wb_post_call_id)); - set_stub("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id)); - set_stub("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id)); - set_stub("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id)); - set_stub("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id)); - set_stub("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id)); - set_stub("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub()); - set_stub("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id)); - set_stub("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); - set_stub("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id)); - set_stub("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id)); - set_stub("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id)); - set_stub("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id)); - set_stub("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap()); - set_stub("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id)); - set_stub("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id)); - set_stub("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id)); - set_stub("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id)); - set_stub("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id)); - set_stub("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis)); - set_stub("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos)); - set_stub("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id)); - set_stub("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id)); - set_stub("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); - set_stub("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); - set_stub("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); - set_stub("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); - set_stub("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); - set_stub("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); - set_stub("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id)); - set_stub("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); - set_stub("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); - set_stub("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); - set_stub("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt()); + set_address("newInstanceStub", GraalRuntime::entry_for(GraalRuntime::new_instance_id)); + set_address("newArrayStub", GraalRuntime::entry_for(GraalRuntime::new_array_id)); + set_address("newMultiArrayStub", GraalRuntime::entry_for(GraalRuntime::new_multi_array_id)); + set_address("identityHashCodeStub", GraalRuntime::entry_for(GraalRuntime::identity_hash_code_id)); + set_address("threadIsInterruptedStub", GraalRuntime::entry_for(GraalRuntime::thread_is_interrupted_id)); + set_address("inlineCacheMissStub", SharedRuntime::get_ic_miss_stub()); + set_address("handleExceptionStub", GraalRuntime::entry_for(GraalRuntime::handle_exception_nofpu_id)); + set_address("handleDeoptStub", SharedRuntime::deopt_blob()->unpack()); + set_address("monitorEnterStub", GraalRuntime::entry_for(GraalRuntime::monitorenter_id)); + set_address("monitorExitStub", GraalRuntime::entry_for(GraalRuntime::monitorexit_id)); + set_address("verifyOopStub", GraalRuntime::entry_for(GraalRuntime::verify_oop_id)); + set_address("vmErrorStub", GraalRuntime::entry_for(GraalRuntime::vm_error_id)); + set_address("deoptimizeStub", SharedRuntime::deopt_blob()->uncommon_trap()); + set_address("unwindExceptionStub", GraalRuntime::entry_for(GraalRuntime::unwind_exception_call_id)); + set_address("osrMigrationEndStub", GraalRuntime::entry_for(GraalRuntime::OSR_migration_end_id)); + set_address("registerFinalizerStub", GraalRuntime::entry_for(GraalRuntime::register_finalizer_id)); + set_address("createNullPointerExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_null_pointer_exception_id)); + set_address("createOutOfBoundsExceptionStub", GraalRuntime::entry_for(GraalRuntime::create_out_of_bounds_exception_id)); + set_address("javaTimeMillisStub", CAST_FROM_FN_PTR(address, os::javaTimeMillis)); + set_address("javaTimeNanosStub", CAST_FROM_FN_PTR(address, os::javaTimeNanos)); + set_address("arithmeticFremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_frem_id)); + set_address("arithmeticDremStub", GraalRuntime::entry_for(GraalRuntime::arithmetic_drem_id)); + set_address("arithmeticSinStub", CAST_FROM_FN_PTR(address, SharedRuntime::dsin)); + set_address("arithmeticCosStub", CAST_FROM_FN_PTR(address, SharedRuntime::dcos)); + set_address("arithmeticTanStub", CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); + set_address("logPrimitiveStub", GraalRuntime::entry_for(GraalRuntime::log_primitive_id)); + set_address("logObjectStub", GraalRuntime::entry_for(GraalRuntime::log_object_id)); + set_address("logPrintfStub", GraalRuntime::entry_for(GraalRuntime::log_printf_id)); + set_address("stubPrintfStub", GraalRuntime::entry_for(GraalRuntime::stub_printf_id)); + set_address("aescryptEncryptBlockStub", StubRoutines::aescrypt_encryptBlock()); + set_address("aescryptDecryptBlockStub", StubRoutines::aescrypt_decryptBlock()); + set_address("cipherBlockChainingEncryptAESCryptStub", StubRoutines::cipherBlockChaining_encryptAESCrypt()); + set_address("cipherBlockChainingDecryptAESCryptStub", StubRoutines::cipherBlockChaining_decryptAESCrypt()); + + set_address("newArrayAddress", GraalRuntime::new_array); set_int("deoptReasonNone", Deoptimization::Reason_none); set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check); @@ -849,12 +856,13 @@ ResourceMark rm; HandleMark hm; Handle compResultHandle = JNIHandles::resolve(compResult); - nmethod* nm = NULL; + CodeBlob* cb = NULL; methodHandle method = getMethodFromHotSpotMethod(HotSpotCompilationResult::method(compResult)); Handle installed_code_handle = JNIHandles::resolve(installed_code); Handle triggered_deoptimizations_handle = JNIHandles::resolve(triggered_deoptimizations); GraalEnv::CodeInstallResult result; - CodeInstaller installer(compResultHandle, method, result, nm, installed_code_handle, triggered_deoptimizations_handle); + + CodeInstaller installer(compResultHandle, method, result, cb, installed_code_handle, triggered_deoptimizations_handle); if (PrintCodeCacheOnCompilation) { stringStream s; @@ -868,13 +876,15 @@ } if (result != GraalEnv::ok) { - assert(nm == NULL, "should be"); + assert(cb == NULL, "should be"); } else { if (!installed_code_handle.is_null()) { assert(installed_code_handle->is_a(HotSpotInstalledCode::klass()), "wrong type"); - HotSpotInstalledCode::set_nmethod(installed_code_handle, (jlong) nm); + HotSpotInstalledCode::set_codeBlob(installed_code_handle, (jlong) cb); HotSpotInstalledCode::set_method(installed_code_handle, HotSpotCompilationResult::method(compResult)); - HotSpotInstalledCode::set_start(installed_code_handle, (jlong) nm->code_begin()); + HotSpotInstalledCode::set_start(installed_code_handle, (jlong) cb->code_begin()); + HotSpotInstalledCode::set_isNmethod(installed_code_handle, cb->is_nmethod()); + nmethod* nm = cb->as_nmethod_or_null(); assert(nm == NULL || !installed_code_handle->is_scavengable() || nm->on_scavenge_root_list(), "nm should be scavengable if installed_code is scavengable"); } } @@ -886,30 +896,53 @@ method->clear_queued_for_compilation(); C2V_END -C2V_VMENTRY(jobject, getCode, (JNIEnv *jniEnv, jobject, jlong metaspace_nmethod)) +C2V_VMENTRY(jobject, getCode, (JNIEnv *jniEnv, jobject, jlong codeBlob)) + ResourceMark rm; + HandleMark hm; + + CodeBlob* cb = (CodeBlob*) (address) codeBlob; + if (cb == NULL) { + return NULL; + } + if (cb->is_nmethod()) { + nmethod* nm = (nmethod*) cb; + if (!nm->is_alive()) { + return NULL; + } + } + int length = cb->code_size(); + arrayOop codeCopy = oopFactory::new_byteArray(length, CHECK_0); + memcpy(codeCopy->base(T_BYTE), cb->code_begin(), length); + return JNIHandles::make_local(codeCopy); +C2V_END + +C2V_VMENTRY(jobject, disassembleCodeBlob, (JNIEnv *jniEnv, jobject, jlong codeBlob)) ResourceMark rm; HandleMark hm; - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { + CodeBlob* cb = (CodeBlob*) (address) codeBlob; + if (cb == NULL) { return NULL; } - int length = nm->code_size(); - arrayOop codeCopy = oopFactory::new_byteArray(length, CHECK_0); - memcpy(codeCopy->base(T_BYTE), nm->code_begin(), length); - return JNIHandles::make_local(codeCopy); -C2V_END -C2V_VMENTRY(jobject, disassembleNMethod, (JNIEnv *jniEnv, jobject, jlong metaspace_nmethod)) - ResourceMark rm; - HandleMark hm; - - nmethod* nm = (nmethod*) (address) metaspace_nmethod; - if (nm == NULL || !nm->is_alive()) { - return NULL; + // We don't want the stringStream buffer to resize during disassembly as it + // uses scoped resource memory. If a nested function called during disassembly uses + // a ResourceMark and the buffer expands within the scope of the mark, + // the buffer becomes garbage when that scope is exited. Experience shows that + // the disassembled code is typically about 10x the code size so a fixed buffer + // sized to 20x code size should be sufficient. + int bufferSize = cb->code_size() * 20; + char* buffer = NEW_RESOURCE_ARRAY(char, bufferSize); + stringStream st(buffer, bufferSize); + if (cb->is_nmethod()) { + nmethod* nm = (nmethod*) cb; + if (!nm->is_alive()) { + return NULL; + } + Disassembler::decode(nm, &st); + } else { + Disassembler::decode(cb, &st); } - stringStream(st); - Disassembler::decode(nm, &st); Handle result = java_lang_String::create_from_platform_dependent_str(st.as_string(), CHECK_NULL); return JNIHandles::make_local(result()); @@ -924,11 +957,11 @@ return JNIHandles::make_local(element); C2V_END -C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nativeMethod)) +C2V_VMENTRY(jobject, executeCompiledMethodVarargs, (JNIEnv *env, jobject, jobject args, jlong nmethodValue)) ResourceMark rm; HandleMark hm; - nmethod* nm = (nmethod*) (address) nativeMethod; + nmethod* nm = (nmethod*) (address) nmethodValue; methodHandle mh = nm->method(); Symbol* signature = mh->signature(); JavaCallArguments jca(mh->size_of_parameters()); @@ -1150,7 +1183,7 @@ {CC"initializeConfiguration", CC"("HS_CONFIG")V", FN_PTR(initializeConfiguration)}, {CC"installCode0", CC"("HS_COMP_RESULT HS_INSTALLED_CODE"[Z)I", FN_PTR(installCode0)}, {CC"getCode", CC"(J)[B", FN_PTR(getCode)}, - {CC"disassembleNMethod", CC"(J)"STRING, FN_PTR(disassembleNMethod)}, + {CC"disassembleCodeBlob", CC"(J)"STRING, FN_PTR(disassembleCodeBlob)}, {CC"executeCompiledMethodVarargs", CC"(["OBJECT NMETHOD")"OBJECT, FN_PTR(executeCompiledMethodVarargs)}, {CC"getDeoptedLeafGraphIds", CC"()[J", FN_PTR(getDeoptedLeafGraphIds)}, {CC"getLineNumberTable", CC"("HS_RESOLVED_METHOD")[J", FN_PTR(getLineNumberTable)}, diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalJavaAccess.cpp --- a/src/share/vm/graal/graalJavaAccess.cpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.cpp Fri Apr 26 18:36:41 2013 +0200 @@ -32,7 +32,7 @@ Symbol* name_symbol = SymbolTable::probe(name, (int)strlen(name)); Symbol* signature_symbol = SymbolTable::probe(signature, (int)strlen(signature)); #ifndef PRODUCT - if (name_symbol == NULL) { + if (name_symbol == NULL || signature_symbol == NULL) { tty->print_cr("symbol with name %s was not found in symbol table (klass=%s)", name, klass->name()->as_C_string()); } #endif diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Fri Apr 26 18:36:41 2013 +0200 @@ -73,15 +73,16 @@ int_field(HotSpotResolvedJavaField, flags) \ end_class \ start_class(HotSpotInstalledCode) \ - long_field(HotSpotInstalledCode, nmethod) \ + long_field(HotSpotInstalledCode, codeBlob) \ oop_field(HotSpotInstalledCode, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ long_field(HotSpotInstalledCode, start) \ boolean_field(HotSpotInstalledCode, isDefault) \ + boolean_field(HotSpotInstalledCode, isNmethod) \ end_class \ start_class(HotSpotCompilationResult) \ oop_field(HotSpotCompilationResult, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \ oop_field(HotSpotCompilationResult, method, "Lcom/oracle/graal/hotspot/meta/HotSpotResolvedJavaMethod;") \ - oop_field(HotSpotCompilationResult, name, "Ljava/lang/String;") \ + oop_field(HotSpotCompilationResult, stubName, "Ljava/lang/String;") \ int_field(HotSpotCompilationResult, entryBCI) \ oop_field(HotSpotCompilationResult, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ oop_field(HotSpotCompilationResult, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ @@ -162,9 +163,14 @@ oop_field(DebugInfo, bytecodePosition, "Lcom/oracle/graal/api/code/BytecodePosition;") \ oop_field(DebugInfo, registerRefMap, "Ljava/util/BitSet;") \ oop_field(DebugInfo, frameRefMap, "Ljava/util/BitSet;") \ + oop_field(DebugInfo, calleeSaveInfo, "Lcom/oracle/graal/api/code/RegisterSaveLayout;") \ end_class \ - start_class(GraalBitMap) \ - oop_field(GraalBitMap, words, "[J") \ + start_class(RegisterSaveLayout) \ + oop_field(RegisterSaveLayout, registers, "[Lcom/oracle/graal/api/code/Register;") \ + oop_field(RegisterSaveLayout, slots, "[I") \ + end_class \ + start_class(BitSet) \ + oop_field(BitSet, words, "[J") \ end_class \ start_class(BytecodeFrame) \ oop_field(BytecodeFrame, values, "[Lcom/oracle/graal/api/meta/Value;") \ diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Fri Apr 26 18:36:41 2013 +0200 @@ -260,11 +260,16 @@ // This is pretty rare but this runtime patch is stressful to deoptimization // if we deoptimize here so force a deopt to stress the path. if (DeoptimizeALot) { - deopt_caller(); + static int deopts = 0; + // Alternate between deoptimizing and raising an error (which will also cause a deopt) + if (deopts++ % 2 == 0) { + ResourceMark rm(THREAD); + THROW(vmSymbols::java_lang_OutOfMemoryError()); + } else { + deopt_caller(); + } } - JRT_END - - +JRT_END JRT_ENTRY(void, GraalRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) assert(klass->is_klass(), "not a class"); diff -r e1200d5141fa -r 0266549ff6e0 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Fri Apr 26 18:21:10 2013 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Fri Apr 26 18:36:41 2013 +0200 @@ -134,7 +134,6 @@ // runtime entry points static void new_instance(JavaThread* thread, Klass* klass); - static void new_array(JavaThread* thread, Klass* klass, jint length); static void new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims); static void unimplemented_entry(JavaThread* thread, StubID id); @@ -164,6 +163,7 @@ static void log_object(JavaThread* thread, oop msg, jint flags); public: + static void new_array(JavaThread* thread, Klass* klass, jint length); // initialization static void initialize(BufferBlob* blob);