# HG changeset patch # User Doug Simon # Date 1355210965 -3600 # Node ID ff6df8b7ce81c1bc2ae1d379f75f89a3b4c367d0 # Parent 807bf592eb90e5876545305557a1777f2a143a71# Parent 6a8b22829e369f92f20837314d5fd83c53bb386d Merge. diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Tue Dec 11 08:29:25 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.api.code; import com.oracle.graal.api.code.CompilationResult.DataPatch; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; /** @@ -39,7 +39,7 @@ * @param compResult the compilation result to be added * @param info the object into which details of the installed code will be written. Ignored if null, otherwise the * info is written to index 0 of this array. - * @return a reference to the compiled and ready-to-run code + * @return a reference to the compiled and ready-to-run code or null if the code installation failed */ InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, CodeInfo[] info); @@ -61,7 +61,7 @@ * * @param method the top level method of a compilation */ - RegisterConfig lookupRegisterConfig(JavaMethod method); + RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method); /** * Custom area on the stack of each compiled method that the VM can use for its own purposes. @@ -81,12 +81,12 @@ /** * Performs any runtime-specific conversion on the object used to describe the target of a call. */ - Object lookupCallTarget(Object target); + Object lookupCallTarget(Object callTarget); /** * Gets the signature and linkage information for a runtime call. */ - RuntimeCall lookupRuntimeCall(Descriptor descriptor); + RuntimeCallTarget lookupRuntimeCall(Descriptor descriptor); /** * Encodes a deoptimization action and a deoptimization reason in an integer value. diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCall.java Tue Dec 11 08:27:01 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2009, 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.api.code; - -import java.util.*; - -import com.oracle.graal.api.meta.*; - -/** - * The name, signature and calling convention of a call from compiled code to the runtime. - * The target of such a call may be a leaf stub or a call into the runtime code proper. - */ -public interface RuntimeCall { - - /** - * The name and signature of a runtime call. - */ - public static class Descriptor { - private final String name; - private final boolean hasSideEffect; - private final Kind resultKind; - private final Kind[] argumentKinds; - - public Descriptor(String name, boolean hasSideEffect, Kind resultKind, Kind... args) { - this.name = name; - this.hasSideEffect = hasSideEffect; - this.resultKind = resultKind; - this.argumentKinds = args; - } - - /** - * Gets the name of this runtime call. - */ - public String getName() { - return name; - } - - /** - * Determines if this call changes state visible to other threads. - * Such calls denote boundaries across which deoptimization - * points cannot be moved. - */ - public boolean hasSideEffect() { - return hasSideEffect; - } - - /** - * Gets the return kind of this runtime call. - */ - public Kind getResultKind() { - return resultKind; - } - - /** - * Gets the argument kinds of this runtime call. - */ - public Kind[] getArgumentKinds() { - return argumentKinds.clone(); - } - - @Override - public int hashCode() { - return name.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Descriptor) { - Descriptor nas = (Descriptor) obj; - return nas.name.equals(name) && nas.resultKind.equals(resultKind) && Arrays.equals(nas.argumentKinds, argumentKinds); - } - return false; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(name).append('('); - String sep = ""; - for (Kind arg : argumentKinds) { - sb.append(sep).append(arg); - sep = ","; - } - return sb.append(')').append(resultKind).toString(); - } - } - - CallingConvention getCallingConvention(); - - /** - * Returns the maximum absolute offset of PC relative call to this stub from any position in the code cache or -1 - * when not applicable. Intended for determining the required size of address/offset fields. - */ - long getMaxCallTargetOffset(); - - Descriptor getDescriptor(); -} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/RuntimeCallTarget.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2009, 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.api.code; + +import java.util.*; + +import com.oracle.graal.api.meta.*; + +/** + * The name, signature and calling convention of a call from compiled code to the runtime. + * The target of such a call may be a leaf stub or a call into the runtime code proper. + */ +public interface RuntimeCallTarget { + + /** + * The name and signature of a runtime call. + */ + public static class Descriptor { + private final String name; + private final boolean hasSideEffect; + private final Kind resultKind; + private final Kind[] argumentKinds; + + public Descriptor(String name, boolean hasSideEffect, Kind resultKind, Kind... args) { + this.name = name; + this.hasSideEffect = hasSideEffect; + this.resultKind = resultKind; + this.argumentKinds = args; + } + + /** + * Gets the name of this runtime call. + */ + public String getName() { + return name; + } + + /** + * Determines if this call changes state visible to other threads. + * Such calls denote boundaries across which deoptimization + * points cannot be moved. + */ + public boolean hasSideEffect() { + return hasSideEffect; + } + + /** + * Gets the return kind of this runtime call. + */ + public Kind getResultKind() { + return resultKind; + } + + /** + * Gets the argument kinds of this runtime call. + */ + public Kind[] getArgumentKinds() { + return argumentKinds.clone(); + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Descriptor) { + Descriptor nas = (Descriptor) obj; + return nas.name.equals(name) && nas.resultKind.equals(resultKind) && Arrays.equals(nas.argumentKinds, argumentKinds); + } + return false; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(name).append('('); + String sep = ""; + for (Kind arg : argumentKinds) { + sb.append(sep).append(arg); + sep = ","; + } + return sb.append(')').append(resultKind).toString(); + } + } + + CallingConvention getCallingConvention(); + + /** + * Returns the maximum absolute offset of PC relative call to this stub from any position in the code cache or -1 + * when not applicable. Intended for determining the required size of address/offset fields. + */ + long getMaxCallTargetOffset(); + + Descriptor getDescriptor(); +} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/ResolvedJavaType.java Tue Dec 11 08:29:25 2012 +0100 @@ -215,9 +215,12 @@ /** * Returns the instance fields of this class, including {@linkplain ResolvedJavaField#isInternal() internal} fields. * A zero-length array is returned for array and primitive types. The order of fields returned by this method is - * stable. That is, for a single JVM execution the same order is returned each time this method is called. + * stable. That is, for a single JVM execution the same order is returned each time this method is called. It is + * also the "natural" order, which means that the JVM would expect the fields in this order if no specific order is + * given. * - * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this type are included in the result + * @param includeSuperclasses if true, then instance fields for the complete hierarchy of this type are included in + * the result * @return an array of instance fields */ ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64DeoptimizationStub.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,7 +25,7 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.code.RuntimeCallTarget.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Tue Dec 11 08:29:25 2012 +0100 @@ -29,7 +29,7 @@ import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; @@ -382,11 +382,11 @@ append(new DivOp(LREM, RDX_L, RAX_L, load(b), state())); return emitMove(RDX_L); case Float: { - RuntimeCall stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM); + RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_FREM); return emitCall(stub, stub.getCallingConvention(), false, a, b); } case Double: { - RuntimeCall stub = runtime.lookupRuntimeCall(ARITHMETIC_DREM); + RuntimeCallTarget stub = runtime.lookupRuntimeCall(ARITHMETIC_DREM); return emitCall(stub, stub.getCallingConvention(), false, a, b); } default: @@ -571,11 +571,11 @@ } @Override - protected void emitCall(Object targetMethod, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { + protected void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { if (isConstant(targetAddress)) { - append(new DirectCallOp(targetMethod, result, arguments, temps, info)); + append(new DirectCallOp(callTarget, result, arguments, temps, info)); } else { - append(new IndirectCallOp(targetMethod, result, arguments, temps, targetAddress, info)); + append(new IndirectCallOp(callTarget, result, arguments, temps, targetAddress, info)); } } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Tue Dec 11 08:29:25 2012 +0100 @@ -216,13 +216,20 @@ return LabelRef.forSuccessor(lir, currentBlock, suxIndex); } + /** + * Determines if only oop maps are required for the code generated from the LIR. + */ + protected boolean needOnlyOopMaps() { + return false; + } + public LIRFrameState state() { - assert lastState != null : "must have state before instruction"; + assert lastState != null || needOnlyOopMaps() : "must have state before instruction"; return stateFor(lastState, StructuredGraph.INVALID_GRAPH_ID); } public LIRFrameState state(long leafGraphId) { - assert lastState != null : "must have state before instruction"; + assert lastState != null || needOnlyOopMaps() : "must have state before instruction"; return stateFor(lastState, leafGraphId); } @@ -231,6 +238,9 @@ } public LIRFrameState stateFor(FrameState state, List pointerSlots, LabelRef exceptionEdge, long leafGraphId) { + if (needOnlyOopMaps()) { + return new LIRFrameState(null, null, null, null); + } return debugInfoBuilder.build(state, lockDataSlots.subList(0, currentLockCount), pointerSlots, exceptionEdge, leafGraphId); } @@ -731,7 +741,7 @@ protected abstract void emitIndirectCall(IndirectCallTargetNode callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState callState); - protected abstract void emitCall(Object targetMethod, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info); + protected abstract void emitCall(RuntimeCallTarget callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info); private static Value toStackKind(Value value) { if (value.getKind().getStackKind() != value.getKind()) { @@ -768,7 +778,7 @@ protected abstract LabelRef createDeoptStub(DeoptimizationAction action, DeoptimizationReason reason, LIRFrameState info, Object deoptInfo); @Override - public Variable emitCall(@SuppressWarnings("hiding") Object target, CallingConvention cc, boolean canTrap, Value... args) { + public Variable emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args) { LIRFrameState info = canTrap ? state() : null; // move the arguments into the correct location @@ -781,7 +791,7 @@ emitMove(arg, loc); argLocations[i] = loc; } - emitCall(target, cc.getReturn(), argLocations, cc.getTemporaries(), Constant.forLong(0), info); + emitCall(callTarget, cc.getReturn(), argLocations, cc.getTemporaries(), Constant.forLong(0), info); if (isLegal(cc.getReturn())) { return emitMove(cc.getReturn()); @@ -792,7 +802,7 @@ @Override public void visitRuntimeCall(RuntimeCallNode x) { - RuntimeCall call = runtime.lookupRuntimeCall(x.getDescriptor()); + RuntimeCallTarget call = runtime.lookupRuntimeCall(x.getDescriptor()); CallingConvention cc = call.getCallingConvention(); frameMap.callsMethod(cc); Value resultOperand = cc.getReturn(); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Tue Dec 11 08:29:25 2012 +0100 @@ -74,8 +74,8 @@ private final InvokeKind invokeKind; - AMD64DirectCallOp(Object targetMethod, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) { - super(targetMethod, result, parameters, temps, state); + AMD64DirectCallOp(Object target, Value result, Value[] parameters, Value[] temps, LIRFrameState state, InvokeKind invokeKind, LIR lir) { + super(target, result, parameters, temps, state); this.invokeKind = invokeKind; if (invokeKind == Static || invokeKind == Special) { @@ -116,6 +116,6 @@ callsiteMark = tasm.recordMark(null); } - AMD64Call.directCall(tasm, masm, targetMethod, state); + AMD64Call.directCall(tasm, masm, callTarget, state); } } diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Tue Dec 11 08:29:25 2012 +0100 @@ -40,6 +40,7 @@ import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.amd64.AMD64Move.CompareAndSwapOp; @@ -73,7 +74,18 @@ } @Override + protected boolean needOnlyOopMaps() { + // Stubs only need oop maps + return runtime().asStub(method) != null; + } + + @Override protected CallingConvention createCallingConvention() { + Stub stub = runtime().asStub(method); + if (stub != null) { + return stub.getLinkage().getCallingConvention(); + } + if (graph.getEntryBCI() == StructuredGraph.INVOCATION_ENTRY_BCI) { return super.createCallingConvention(); } else { @@ -219,14 +231,14 @@ // - has no callee-saved registers // - has no incoming arguments passed on the stack // - has no instructions with debug info - boolean canOmitFrame = GraalOptions.CanOmitFrame && + boolean omitFrame = GraalOptions.CanOmitFrame && frameMap.frameSize() == frameMap.initialFrameSize && frameMap.registerConfig.getCalleeSaveLayout().registers.length == 0 && !lir.hasArgInCallerFrame() && !lir.hasDebugInfo(); AbstractAssembler masm = new AMD64MacroAssembler(target, frameMap.registerConfig); - HotSpotFrameContext frameContext = canOmitFrame ? null : new HotSpotFrameContext(); + HotSpotFrameContext frameContext = omitFrame ? null : new HotSpotFrameContext(); TargetMethodAssembler tasm = new TargetMethodAssembler(target, runtime(), frameMap, masm, frameContext, lir.stubs); tasm.setFrameSize(frameMap.frameSize()); tasm.targetMethod.setCustomStackAreaOffset(frameMap.offsetToCustomArea()); @@ -239,11 +251,11 @@ FrameMap frameMap = tasm.frameMap; RegisterConfig regConfig = frameMap.registerConfig; HotSpotVMConfig config = runtime().config; - Label unverifiedStub = new Label(); + boolean isStatic = Modifier.isStatic(method.getModifiers()); + Label unverifiedStub = isStatic ? null : new Label(); // Emit the prefix - boolean isStatic = Modifier.isStatic(method.getModifiers()); if (!isStatic) { tasm.recordMark(Marks.MARK_UNVERIFIED_ENTRY); CallingConvention cc = regConfig.getCallingConvention(JavaCallee, Kind.Void, new Kind[] {Kind.Object}, target, false); @@ -277,7 +289,7 @@ assert !frameMap.accessesCallerFrame(); } - if (!isStatic) { + if (unverifiedStub != null) { asm.bind(unverifiedStub); AMD64Call.directJmp(tasm, asm, config.inlineCacheMissStub); } @@ -285,5 +297,6 @@ for (int i = 0; i < GraalOptions.MethodEndBreakpointGuards; ++i) { asm.int3(); } + } } diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Dec 11 08:29:25 2012 +0100 @@ -27,7 +27,9 @@ import static com.oracle.graal.compiler.amd64.AMD64LIRGenerator.*; 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.NewArrayStubCall.*; +import static com.oracle.graal.hotspot.nodes.NewInstanceSlowStubCall.*; import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; import static com.oracle.graal.hotspot.nodes.NewMultiArrayStubCall.*; import static com.oracle.graal.hotspot.nodes.VMErrorNode.*; @@ -73,30 +75,35 @@ /* arg1: b */ arg(1, Kind.Double)); addRuntimeCall(MONITORENTER, config.monitorEnterStub, - /* temps */ new Register[] {rax, rbx}, + /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: object */ arg(0, Kind.Object), /* arg1: lock */ arg(1, word)); addRuntimeCall(MONITOREXIT, c.monitorExitStub, - /* temps */ new Register[] {rax, rbx}, + /* temps */ null, /* ret */ ret(Kind.Void), /* arg0: object */ arg(0, Kind.Object), /* arg1: lock */ arg(1, word)); - addRuntimeCall(NEW_OBJECT_ARRAY, c.newObjectArrayStub, - /* temps */ new Register[] {rcx, rdi, rsi}, + addRuntimeCall(NEW_ARRAY, 0L, + /* temps */ null, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_TYPE_ARRAY, c.newTypeArrayStub, - /* temps */ new Register[] {rcx, rdi, rsi}, + addRuntimeCall(NEW_ARRAY_SLOW, c.newArrayStub, + /* temps */ null, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_INSTANCE, c.newInstanceStub, + addRuntimeCall(NEW_INSTANCE, 0L, + /* temps */ null, + /* ret */ rax.asValue(Kind.Object), + /* arg0: hub */ rdx.asValue(word)); + + addRuntimeCall(NEW_INSTANCE_SLOW, c.newInstanceStub, /* temps */ null, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word)); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Tue Dec 11 08:29:25 2012 +0100 @@ -62,7 +62,7 @@ tasm.recordMark(Marks.MARK_INLINE_INVOKEVIRTUAL); Register callReg = asRegister(targetAddress); assert callReg != METHOD; - AMD64Call.indirectCall(tasm, masm, callReg, targetMethod, state); + AMD64Call.indirectCall(tasm, masm, callReg, callTarget, state); } @Override diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCall.java Tue Dec 11 08:27:01 2012 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +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; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.hotspot.bridge.*; - -/** - * The details required to link a HotSpot runtime or stub call. - */ -public class HotSpotRuntimeCall implements RuntimeCall { - - /** - * The descriptor of the stub. This is for informational purposes only. - */ - public final Descriptor descriptor; - - /** - * The entry point address of the stub. - */ - public final long address; - - /** - * Where the stub gets its arguments and where it places its result. - */ - public final CallingConvention cc; - - private final CompilerToVM vm; - - public HotSpotRuntimeCall(Descriptor descriptor, long address, CallingConvention cc, CompilerToVM vm) { - this.address = address; - this.descriptor = descriptor; - this.cc = cc; - this.vm = vm; - } - - @Override - public String toString() { - return descriptor + "@0x" + Long.toHexString(address) + ":" + cc; - } - - public CallingConvention getCallingConvention() { - return cc; - } - - public long getMaxCallTargetOffset() { - return vm.getMaxCallTargetOffset(address); - } - - public Descriptor getDescriptor() { - return descriptor; - } -} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,95 @@ +/* + * 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; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.stubs.*; + +/** + * The details required to link a HotSpot runtime or stub call. + */ +public class HotSpotRuntimeCallTarget implements RuntimeCallTarget { + + /** + * The descriptor of the stub. This is for informational purposes only. + */ + public final Descriptor descriptor; + + /** + * The entry point address of the stub. + */ + private long address; + + /** + * Non-null (eventually) iff this is a call to a snippet-based {@linkplain Stub stub}. + */ + private Stub stub; + + /** + * Where the stub gets its arguments and where it places its result. + */ + public final CallingConvention cc; + + private final CompilerToVM vm; + + public HotSpotRuntimeCallTarget(Descriptor descriptor, long address, CallingConvention cc, CompilerToVM vm) { + this.address = address; + this.descriptor = descriptor; + this.cc = cc; + this.vm = vm; + } + + @Override + public String toString() { + return (stub == null ? descriptor.toString() : MetaUtil.format("%h.%n", stub.getMethod())) + "@0x" + Long.toHexString(address) + ":" + cc; + } + + public CallingConvention getCallingConvention() { + return cc; + } + + public long getMaxCallTargetOffset() { + return vm.getMaxCallTargetOffset(address); + } + + public Descriptor getDescriptor() { + return descriptor; + } + + public void setStub(Stub stub) { + assert address == 0L : "cannot stub for linkage that already has an address: " + this; + this.stub = stub; + } + + public void setAddress(long address) { + assert this.address == 0L : "cannot re-initialize address of " + this; + this.address = address; + } + + public long getAddress() { + assert address != 0L : "address not yet initialized for " + this; + return address; + } +} diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Dec 11 08:29:25 2012 +0100 @@ -222,6 +222,29 @@ public int methodCompiledEntryOffset; public int basicLockSize; public int basicLockDisplacedHeaderOffset; + public long tlabIntArrayMarkWord; + public long heapEndAddress; + public long heapTopAddress; + public int threadTlabStartOffset; + public int threadTlabSizeOffset; + public int threadAllocatedBytesOffset; + public int tlabRefillWasteLimitOffset; + public int tlabRefillWasteIncrement; + public int tlabAlignmentReserve; + public int tlabSlowAllocationsOffset; + public int tlabFastRefillWasteOffset; + public int tlabNumberOfRefillsOffset; + public boolean tlabStats; + public int klassInstanceSizeOffset; + public boolean inlineContiguousAllocationSupported; + public long arrayPrototypeMarkWord; + public int layoutHelperLog2ElementSizeShift; + public int layoutHelperLog2ElementSizeMask; + public int layoutHelperElementTypeShift; + public int layoutHelperElementTypeMask; + public int layoutHelperHeaderSizeShift; + public int layoutHelperHeaderSizeMask; + public int layoutHelperOffset; // methodData information public int methodDataOopDataOffset; @@ -239,8 +262,7 @@ public long debugStub; public long instanceofStub; public long newInstanceStub; - public long newTypeArrayStub; - public long newObjectArrayStub; + public long newArrayStub; public long newMultiArrayStub; public long inlineCacheMissStub; public long handleExceptionStub; diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVM.java Tue Dec 11 08:29:25 2012 +0100 @@ -192,6 +192,4 @@ long[] getDeoptedLeafGraphIds(); String decodePC(long pc); - - long getPrototypeMarkWord(HotSpotResolvedObjectType hotSpotResolvedJavaType); } diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/CompilerToVMImpl.java Tue Dec 11 08:29:25 2012 +0100 @@ -139,7 +139,4 @@ @Override public native String decodePC(long pc); - - @Override - public native long getPrototypeMarkWord(HotSpotResolvedObjectType type); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Dec 11 08:29:25 2012 +0100 @@ -136,7 +136,8 @@ @Override public void run() { - Assumptions assumptions = new Assumptions(GraalOptions.OptAssumptions); + // Snippets cannot have speculative optimizations since they have to be valid for the entire run of the VM. + Assumptions assumptions = new Assumptions(false); VMToCompilerImpl.this.intrinsifyArrayCopy = new IntrinsifyArrayCopyPhase(runtime, assumptions); SnippetInstaller installer = new SnippetInstaller(runtime, assumptions, runtime.getGraalRuntime().getTarget()); GraalIntrinsics.installIntrinsics(installer); diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Tue Dec 11 08:29:25 2012 +0100 @@ -57,7 +57,7 @@ @Override public String toString() { - return "compiled method " + method + " @" + nmethod; + return String.format("InstalledCode[method=%s, nmethod=0x%x]", method, nmethod); } @Override diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Tue Dec 11 08:29:25 2012 +0100 @@ -63,7 +63,7 @@ private final boolean hasFinalizableSubclass; /** - * The instance size for an instance type, {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} denoting + * The instance size (in bytes) for an instance type, {@link HotSpotResolvedObjectType#INTERFACE_SPECIES_VALUE} denoting * an interface type or {@link HotSpotResolvedObjectType#ARRAY_SPECIES_VALUE} denoting an array type. */ private final int sizeOrSpecies; @@ -106,6 +106,7 @@ * @return the {@link HotSpotResolvedObjectType} corresponding to {@code javaClass} */ public static ResolvedJavaType fromClass(Class javaClass) { + assert javaClass != null; ResolvedJavaType type = (ResolvedJavaType) unsafe.getObject(javaClass, (long) HotSpotGraalRuntime.getInstance().getConfig().graalMirrorInClassOffset); if (type == null) { type = HotSpotGraalRuntime.getInstance().getCompilerToVM().getResolvedType(javaClass); @@ -395,6 +396,13 @@ return ((HotSpotResolvedJavaMethod) method).uniqueConcreteMethod(); } + private static class OffsetComparator implements Comparator { + @Override + public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) { + return o1.offset() - o2.offset(); + } + } + @Override public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { if (instanceFields == null) { @@ -402,6 +410,7 @@ instanceFields = new HotSpotResolvedJavaField[0]; } else { HotSpotResolvedJavaField[] myFields = HotSpotGraalRuntime.getInstance().getCompilerToVM().getInstanceFields(this); + Arrays.sort(myFields, new OffsetComparator()); if (javaMirror != Object.class) { HotSpotResolvedJavaField[] superFields = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true); HotSpotResolvedJavaField[] fields = Arrays.copyOf(superFields, superFields.length + myFields.length); @@ -461,7 +470,12 @@ } public long prototypeMarkWord() { - return HotSpotGraalRuntime.getInstance().getCompilerToVM().getPrototypeMarkWord(this); + HotSpotVMConfig config = HotSpotGraalRuntime.getInstance().getConfig(); + if (isArray()) { + return config.arrayPrototypeMarkWord; + } else { + return unsafeReadWord(metaspaceKlass + config.prototypeMarkWordOffset); + } } @Override diff -r 807bf592eb90 -r ff6df8b7ce81 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 Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Dec 11 08:29:25 2012 +0100 @@ -47,7 +47,7 @@ import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.code.CompilationResult.Safepoint; import com.oracle.graal.api.code.Register.RegisterFlag; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; @@ -56,6 +56,7 @@ import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.hotspot.phases.*; import com.oracle.graal.hotspot.snippets.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.extended.*; @@ -82,7 +83,19 @@ private NewObjectSnippets.Templates newObjectSnippets; private MonitorSnippets.Templates monitorSnippets; - private final Map runtimeCalls = new HashMap<>(); + private NewInstanceStub newInstanceStub; + private NewArrayStub newArrayStub; + + private final Map runtimeCalls = new HashMap<>(); + private final Map stubs = new HashMap<>(); + + /** + * Holds onto objects that will be embedded in compiled code. HotSpot treats oops + * embedded in code as weak references so without an external strong root, such + * an embedded oop will quickly die. This in turn will cause the nmethod to + * be unloaded. + */ + private final Map gcRoots = new HashMap<>(); /** * The offset from the origin of an array to the first element. @@ -260,10 +273,23 @@ for (int i = 0; i < argKinds.length; i++) { assert argKinds[i].equals(args[i].getKind()) : descriptor + " incompatible with argument location " + i + ": " + args[i]; } - HotSpotRuntimeCall runtimeCall = new HotSpotRuntimeCall(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM()); + HotSpotRuntimeCallTarget runtimeCall = new HotSpotRuntimeCallTarget(descriptor, address, new CallingConvention(temps, 0, ret, args), graalRuntime.getCompilerToVM()); runtimeCalls.put(descriptor, runtimeCall); } + /** + * Binds a snippet-base {@link Stub} to a runtime call descriptor. + * + * @return the linkage information for a call to the stub + */ + public HotSpotRuntimeCallTarget registerStub(Descriptor descriptor, Stub stub) { + HotSpotRuntimeCallTarget linkage = runtimeCalls.get(descriptor); + assert linkage != null; + linkage.setStub(stub); + stubs.put(stub.getMethod(), stub); + return linkage; + } + protected abstract RegisterConfig createRegisterConfig(boolean globalStubConfig); public void installSnippets(SnippetInstaller installer, Assumptions assumptions) { @@ -276,13 +302,20 @@ installer.install(NewObjectSnippets.class); installer.install(MonitorSnippets.class); + installer.install(NewInstanceStub.class); + installer.install(NewArrayStub.class); + checkcastSnippets = new CheckCastSnippets.Templates(this, assumptions, graalRuntime.getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(this, assumptions, graalRuntime.getTarget()); newObjectSnippets = new NewObjectSnippets.Templates(this, assumptions, graalRuntime.getTarget(), config.useTLAB); monitorSnippets = new MonitorSnippets.Templates(this, assumptions, graalRuntime.getTarget(), config.useFastLocking); + + newInstanceStub = new NewInstanceStub(this, assumptions, graalRuntime.getTarget()); + newArrayStub = new NewArrayStub(this, assumptions, graalRuntime.getTarget()); + newInstanceStub.install(graalRuntime.getCompiler()); + newArrayStub.install(graalRuntime.getCompiler()); } - public HotSpotGraalRuntime getGraalRuntime() { return graalRuntime; } @@ -411,7 +444,7 @@ } @Override - public RegisterConfig lookupRegisterConfig(JavaMethod method) { + public RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method) { return regConfig; } @@ -617,6 +650,10 @@ ReadNode hub = graph.add(new ReadNode(object, location, StampFactory.forKind(wordKind()))); hub.dependencies().add(guard); graph.replaceFixed(loadHub, hub); + } else if (n instanceof FixedGuardNode) { + FixedGuardNode node = (FixedGuardNode) n; + ValueAnchorNode newAnchor = graph.add(new ValueAnchorNode(tool.createGuard(node.condition(), node.getReason(), node.getAction(), node.isNegated(), node.getLeafGraphId()))); + graph.replaceFixedWithFixed(node, newAnchor); } else if (n instanceof CheckCastNode) { checkcastSnippets.lower((CheckCastNode) n, tool); } else if (n instanceof CheckCastDynamicNode) { @@ -723,14 +760,24 @@ return HotSpotResolvedObjectType.fromClass(clazz); } - public Object lookupCallTarget(Object target) { - if (target instanceof HotSpotRuntimeCall) { - return ((HotSpotRuntimeCall) target).address; + public Object lookupCallTarget(Object callTarget) { + if (callTarget instanceof HotSpotRuntimeCallTarget) { + return ((HotSpotRuntimeCallTarget) callTarget).getAddress(); } - return target; + return callTarget; } - public RuntimeCall lookupRuntimeCall(Descriptor descriptor) { + /** + * Gets the stub corresponding to a given method. + * + * @return the stub {@linkplain Stub#getMethod() implemented} by {@code method} or null if {@code method} does not + * implement a stub + */ + public Stub asStub(ResolvedJavaMethod method) { + return stubs.get(method); + } + + public HotSpotRuntimeCallTarget lookupRuntimeCall(Descriptor descriptor) { assert runtimeCalls.containsKey(descriptor) : descriptor; return runtimeCalls.get(descriptor); } @@ -826,4 +873,18 @@ public boolean needsDataPatch(Constant constant) { return constant.getPrimitiveAnnotation() instanceof HotSpotResolvedObjectType; } + + /** + * Registers an object created by the compiler and referenced by some generated code. + * HotSpot treats oops embedded in code as weak references so without an external strong root, such + * an embedded oop will quickly die. This in turn will cause the nmethod to be unloaded. + */ + public synchronized Object registerGCRoot(Object object) { + Object existing = gcRoots.get(object); + if (existing != null) { + return existing; + } + gcRoots.put(object, object); + return object; + } } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/InitializeArrayNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -37,17 +37,17 @@ @Input private final ValueNode memory; @Input private final ValueNode length; - @Input private final ValueNode size; + @Input private final ValueNode allocationSize; private final ResolvedJavaType type; private final boolean fillContents; private final boolean locked; - public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode size, ResolvedJavaType type, boolean fillContents, boolean locked) { + public InitializeArrayNode(ValueNode memory, ValueNode length, ValueNode allocationSize, ResolvedJavaType type, boolean fillContents, boolean locked) { super(StampFactory.exactNonNull(type)); this.memory = memory; this.type = type; this.length = length; - this.size = size; + this.allocationSize = allocationSize; this.fillContents = fillContents; this.locked = locked; } @@ -61,8 +61,11 @@ return length; } - public ValueNode size() { - return size; + /** + * Gets the size (in bytes) of the memory chunk allocated for the array. + */ + public ValueNode allocationSize() { + return allocationSize; } public ResolvedJavaType type() { @@ -83,5 +86,5 @@ } @NodeIntrinsic - public static native Object initialize(Object memory, int length, int size, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter boolean locked); + public static native Object initialize(Object memory, int length, int allocationSize, @ConstantNodeParameter ResolvedJavaType type, @ConstantNodeParameter boolean fillContents, @ConstantNodeParameter boolean locked); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorEnterStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,7 +25,7 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -50,7 +50,7 @@ @Override public void generate(LIRGenerator gen) { - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(MonitorEnterStubCall.MONITORENTER); + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorEnterStubCall.MONITORENTER); gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.operand(lock)); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/MonitorExitStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,7 +25,7 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -47,7 +47,7 @@ @Override public void generate(LIRGenerator gen) { - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(MonitorExitStubCall.MONITOREXIT); + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(MonitorExitStubCall.MONITOREXIT); gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object), gen.emitLea(gen.peekLock())); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArraySlowStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,74 @@ +/* + * 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 static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +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.snippets.*; + +/** + * Node implementing a call to the {@code new_array} stub. + */ +public class NewArraySlowStubCall extends FixedWithNextNode 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, Kind.Object, wordKind(), Kind.Int); + + 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(), true, gen.operand(hub), gen.operand(length)); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native Object call(Word hub, int length); +} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewArrayStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,18 +25,19 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.snippets.*; /** - * Node implementing a call to HotSpot's {@code new_[object|type]_array} stub. + * A call to the {@link NewArrayStub}. */ public class NewArrayStubCall extends FixedWithNextNode implements LIRGenLowerable { @@ -44,15 +45,11 @@ @Input private final ValueNode hub; @Input private final ValueNode length; - private final boolean isObjectArray; - public static final Descriptor NEW_OBJECT_ARRAY = new Descriptor("new_object_array", false, Kind.Object, wordKind(), Kind.Int); + public static final Descriptor NEW_ARRAY = new Descriptor("new_array", false, Kind.Object, wordKind(), Kind.Int); - public static final Descriptor NEW_TYPE_ARRAY = new Descriptor("new_type_array", false, Kind.Object, wordKind(), Kind.Int); - - public NewArrayStubCall(boolean isObjectArray, ValueNode hub, ValueNode length) { + public NewArrayStubCall(ValueNode hub, ValueNode length) { super(defaultStamp); - this.isObjectArray = isObjectArray; this.hub = hub; this.length = length; } @@ -68,11 +65,11 @@ @Override public void generate(LIRGenerator gen) { - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(isObjectArray ? NewArrayStubCall.NEW_OBJECT_ARRAY : NewArrayStubCall.NEW_TYPE_ARRAY); + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_ARRAY); Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), gen.operand(length)); gen.setResult(this, result); } @NodeIntrinsic - public static native Object call(@ConstantNodeParameter boolean isObjectArray, Word hub, int length); + public static native Object call(Word hub, int length); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceSlowStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,72 @@ +/* + * 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 static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +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.snippets.*; + +/** + * Node implementing a call to HotSpot's {@code new_instance} stub. + */ +public class NewInstanceSlowStubCall extends FixedWithNextNode implements LIRGenLowerable { + + private static final Stamp defaultStamp = StampFactory.objectNonNull(); + + @Input private final ValueNode hub; + + public static final Descriptor NEW_INSTANCE_SLOW = new Descriptor("new_instance_slow", false, Kind.Object, wordKind()); + + public NewInstanceSlowStubCall(ValueNode hub) { + super(defaultStamp); + this.hub = hub; + } + + @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_INSTANCE_SLOW); + Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub)); + gen.setResult(this, result); + } + + @NodeIntrinsic + public static native Object call(Word hub); +} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,18 +25,19 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.type.*; import com.oracle.graal.snippets.*; /** - * Node implementing a call to HotSpot's {@code new_instance} stub. + * A call to the {@link NewInstanceStub}. */ public class NewInstanceStubCall extends FixedWithNextNode implements LIRGenLowerable { @@ -62,7 +63,7 @@ @Override public void generate(LIRGenerator gen) { - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(NewInstanceStubCall.NEW_INSTANCE); + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NEW_INSTANCE); Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub)); gen.setResult(this, result); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewMultiArrayStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,7 +25,7 @@ import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -66,7 +66,7 @@ @Override public void generate(LIRGenerator gen) { - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(NewMultiArrayStubCall.NEW_MULTI_ARRAY); + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(NewMultiArrayStubCall.NEW_MULTI_ARRAY); Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub), Constant.forInt(rank), gen.operand(dims)); gen.setResult(this, result); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -23,10 +23,11 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; 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.*; @@ -60,8 +61,17 @@ where = "in compiled code for " + MetaUtil.format("%H.%n(%p)", gen.method()); } - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(VMErrorNode.VM_ERROR); - gen.emitCall(stub, stub.getCallingConvention(), false, Constant.forObject(where), gen.operand(format), gen.operand(value)); + HotSpotRuntime runtime = (HotSpotRuntime) gen.getRuntime(); + Constant whereArg = Constant.forObject(runtime.registerGCRoot(where)); + Value formatArg; + if (format.isConstant() && format.kind() == Kind.Object) { + formatArg = Constant.forObject(runtime.registerGCRoot(format.asConstant().asObject())); + } else { + formatArg = gen.operand(format); + } + + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(VMErrorNode.VM_ERROR); + gen.emitCall(stub, stub.getCallingConvention(), false, whereArg, formatArg, gen.operand(value)); } @NodeIntrinsic diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VerifyOopStubCall.java Tue Dec 11 08:29:25 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.nodes; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; @@ -45,7 +45,7 @@ @Override public void generate(LIRGenerator gen) { - RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(VerifyOopStubCall.VERIFY_OOP); + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(VerifyOopStubCall.VERIFY_OOP); gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(object)); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/phases/OnStackReplacementPhase.java Tue Dec 11 08:29:25 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.phases; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.code.RuntimeCallTarget.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.debug.*; import com.oracle.graal.graph.*; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Tue Dec 11 08:29:25 2012 +0100 @@ -40,59 +40,68 @@ */ public class HotSpotSnippetUtils { + public static HotSpotVMConfig config() { + return HotSpotGraalRuntime.getInstance().getConfig(); + } + @Fold - static boolean verifyOops() { - return HotSpotGraalRuntime.getInstance().getConfig().verifyOops; + public static boolean verifyOops() { + return config().verifyOops; } @Fold - static int threadTlabTopOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().threadTlabTopOffset; + public static int threadTlabTopOffset() { + return config().threadTlabTopOffset; } @Fold - static int threadTlabEndOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().threadTlabEndOffset; + public static int threadTlabEndOffset() { + return config().threadTlabEndOffset; } @Fold - static Kind wordKind() { + public static Kind wordKind() { return HotSpotGraalRuntime.getInstance().getTarget().wordKind; } @Fold - static Register threadRegister() { + public static Register threadRegister() { return HotSpotGraalRuntime.getInstance().getRuntime().threadRegister(); } @Fold - static Register stackPointerRegister() { + public static Register stackPointerRegister() { return HotSpotGraalRuntime.getInstance().getRuntime().stackPointerRegister(); } @Fold - static int wordSize() { + public static int wordSize() { return HotSpotGraalRuntime.getInstance().getTarget().wordSize; } @Fold - static int pageSize() { + public static int pageSize() { return HotSpotGraalRuntime.getInstance().getTarget().pageSize; } @Fold - static int prototypeMarkWordOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().prototypeMarkWordOffset; + public static int prototypeMarkWordOffset() { + return config().prototypeMarkWordOffset; } @Fold - static int markOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().markOffset; + public static long arrayPrototypeMarkWord() { + return config().arrayPrototypeMarkWord; } @Fold - static int unlockedMask() { - return HotSpotGraalRuntime.getInstance().getConfig().unlockedMask; + public static int markOffset() { + return config().markOffset; + } + + @Fold + public static int unlockedMask() { + return config().unlockedMask; } /** @@ -105,13 +114,13 @@ * */ @Fold - static int biasedLockMaskInPlace() { - return HotSpotGraalRuntime.getInstance().getConfig().biasedLockMaskInPlace; + public static int biasedLockMaskInPlace() { + return config().biasedLockMaskInPlace; } @Fold - static int epochMaskInPlace() { - return HotSpotGraalRuntime.getInstance().getConfig().epochMaskInPlace; + public static int epochMaskInPlace() { + return config().epochMaskInPlace; } /** @@ -124,88 +133,88 @@ * */ @Fold - static int biasedLockPattern() { - return HotSpotGraalRuntime.getInstance().getConfig().biasedLockPattern; + public static int biasedLockPattern() { + return config().biasedLockPattern; } @Fold - static int ageMaskInPlace() { - return HotSpotGraalRuntime.getInstance().getConfig().ageMaskInPlace; + public static int ageMaskInPlace() { + return config().ageMaskInPlace; } @Fold - static int hubOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().hubOffset; + public static int hubOffset() { + return config().hubOffset; } @Fold - static int metaspaceArrayLengthOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().metaspaceArrayLengthOffset; + public static int metaspaceArrayLengthOffset() { + return config().metaspaceArrayLengthOffset; } @Fold - static int metaspaceArrayBaseOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().metaspaceArrayBaseOffset; + public static int metaspaceArrayBaseOffset() { + return config().metaspaceArrayBaseOffset; } @Fold - static int arrayLengthOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().arrayLengthOffset; + public static int arrayLengthOffset() { + return config().arrayLengthOffset; } @Fold - static int arrayBaseOffset(Kind elementKind) { + public static int arrayBaseOffset(Kind elementKind) { return HotSpotRuntime.getArrayBaseOffset(elementKind); } @Fold - static int arrayIndexScale(Kind elementKind) { + public static int arrayIndexScale(Kind elementKind) { return HotSpotRuntime.getArrayIndexScale(elementKind); } @Fold - static int cardTableShift() { - return HotSpotGraalRuntime.getInstance().getConfig().cardtableShift; + public static int cardTableShift() { + return config().cardtableShift; } @Fold - static long cardTableStart() { - return HotSpotGraalRuntime.getInstance().getConfig().cardtableStartAddress; + public static long cardTableStart() { + return config().cardtableStartAddress; } @Fold - static int superCheckOffsetOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().superCheckOffsetOffset; + public static int superCheckOffsetOffset() { + return config().superCheckOffsetOffset; } @Fold - static int secondarySuperCacheOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().secondarySuperCacheOffset; + public static int secondarySuperCacheOffset() { + return config().secondarySuperCacheOffset; } @Fold - static int secondarySupersOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().secondarySupersOffset; + public static int secondarySupersOffset() { + return config().secondarySupersOffset; } @Fold - static int lockDisplacedMarkOffset() { - return HotSpotGraalRuntime.getInstance().getConfig().basicLockDisplacedHeaderOffset; + public static int lockDisplacedMarkOffset() { + return config().basicLockDisplacedHeaderOffset; } @Fold - static boolean useBiasedLocking() { - return HotSpotGraalRuntime.getInstance().getConfig().useBiasedLocking; + public static boolean useBiasedLocking() { + return config().useBiasedLocking; } /** * Loads the hub from a object, null checking it first. */ - static Word loadHub(Object object) { + public static Word loadHub(Object object) { return loadHubIntrinsic(object, wordKind()); } - static Object verifyOop(Object object) { + public static Object verifyOop(Object object) { if (verifyOops()) { VerifyOopStubCall.call(object); } @@ -215,27 +224,27 @@ /** * Gets the value of the stack pointer register as a Word. */ - static Word stackPointer() { + public static Word stackPointer() { return HotSpotSnippetUtils.registerAsWord(stackPointerRegister()); } /** * Gets the value of the thread register as a Word. */ - static Word thread() { + public static Word thread() { return HotSpotSnippetUtils.registerAsWord(threadRegister()); } - static int loadIntFromWord(Word address, int offset) { + public static int loadIntFromWord(Word address, int offset) { Integer value = UnsafeLoadNode.load(address, 0, offset, Kind.Int); return value; } - static Word loadWordFromWord(Word address, int offset) { + public static Word loadWordFromWord(Word address, int offset) { return loadWordFromWordIntrinsic(address, 0, offset, wordKind()); } - static Word loadWordFromObject(Object object, int offset) { + public static Word loadWordFromObject(Object object, int offset) { return loadWordFromObjectIntrinsic(object, 0, offset, wordKind()); } @@ -251,6 +260,149 @@ @NodeIntrinsic(value = LoadHubNode.class, setStampFromReturnType = true) static native Word loadHubIntrinsic(Object object, @ConstantNodeParameter Kind word); + @Fold + public + static int log2WordSize() { + return CodeUtil.log2(wordSize()); + } + + @Fold + public + static int klassStateOffset() { + return config().klassStateOffset; + } + + @Fold + public + static int klassInstanceSizeOffset() { + return config().klassInstanceSizeOffset; + } + + @Fold + public + static long heapTopAddress() { + return config().heapTopAddress; + } + + @Fold + public + static long heapEndAddress() { + return config().heapEndAddress; + } + + @Fold + public + static int threadTlabStartOffset() { + return config().threadTlabStartOffset; + } + + @Fold + public + static long tlabIntArrayMarkWord() { + return config().tlabIntArrayMarkWord; + } + + @Fold + public + static boolean inlineContiguousAllocationSupported() { + return config().inlineContiguousAllocationSupported; + } + + @Fold + public + static int tlabAlignmentReserveInHeapWords() { + return config().tlabAlignmentReserve; + } + + @Fold + public + static int threadTlabSizeOffset() { + return config().threadTlabSizeOffset; + } + + @Fold + public + static int threadAllocatedBytesOffset() { + return config().threadAllocatedBytesOffset; + } + + @Fold + public + static int klassStateFullyInitialized() { + return config().klassStateFullyInitialized; + } + + @Fold + public + static int tlabRefillWasteLimitOffset() { + return config().tlabRefillWasteLimitOffset; + } + + @Fold + public + static int tlabNumberOfRefillsOffset() { + return config().tlabNumberOfRefillsOffset; + } + + @Fold + public + static int tlabFastRefillWasteOffset() { + return config().tlabFastRefillWasteOffset; + } + + @Fold + public + static int tlabSlowAllocationsOffset() { + return config().tlabSlowAllocationsOffset; + } + + @Fold + public + static int tlabRefillWasteIncrement() { + return config().tlabRefillWasteIncrement; + } + + @Fold + public + static boolean tlabStats() { + return config().tlabStats; + } + + @Fold + public static int layoutHelperOffset() { + return config().layoutHelperOffset; + } + + @Fold + public static int layoutHelperHeaderSizeShift() { + return config().layoutHelperHeaderSizeShift; + } + + @Fold + public static int layoutHelperHeaderSizeMask() { + return config().layoutHelperHeaderSizeMask; + } + + @Fold + public static int layoutHelperLog2ElementSizeShift() { + return config().layoutHelperLog2ElementSizeShift; + } + + @Fold + public static int layoutHelperLog2ElementSizeMask() { + return config().layoutHelperLog2ElementSizeMask; + } + + @Fold + public static int layoutHelperElementTypeShift() { + return config().layoutHelperElementTypeShift; + } + + @Fold + public static int layoutHelperElementTypeMask() { + return config().layoutHelperElementTypeMask; + } + static { assert arrayIndexScale(Kind.Byte) == 1; assert arrayIndexScale(Kind.Boolean) == 1; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Tue Dec 11 08:29:25 2012 +0100 @@ -37,6 +37,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.NodeIntrinsic; import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.nodes.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.extended.*; @@ -520,7 +521,8 @@ List rets = graph.getNodes().filter(ReturnNode.class).snapshot(); for (ReturnNode ret : rets) { returnType = checkCounter.getSignature().getReturnType(checkCounter.getDeclaringClass()); - ConstantNode errMsg = ConstantNode.forObject("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d", runtime, graph); + Object msg = ((HotSpotRuntime) runtime).registerGCRoot("unbalanced monitors in " + MetaUtil.format("%H.%n(%p)", graph.method()) + ", count = %d"); + ConstantNode errMsg = ConstantNode.forObject(msg, runtime, graph); callTarget = graph.add(new MethodCallTargetNode(InvokeKind.Static, checkCounter, new ValueNode[] {errMsg}, returnType)); invoke = graph.add(new InvokeNode(callTarget, 0, -1)); List stack = Collections.emptyList(); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Tue Dec 11 08:29:25 2012 +0100 @@ -95,55 +95,30 @@ } @Snippet - public static Object initializeObjectArray( + public static Object initializeArray( @Parameter("memory") Word memory, @Parameter("hub") Word hub, @Parameter("length") int length, - @Parameter("size") int size, + @Parameter("allocationSize") int allocationSize, @Parameter("prototypeMarkWord") Word prototypeMarkWord, @ConstantParameter("headerSize") int headerSize, @ConstantParameter("fillContents") boolean fillContents, @ConstantParameter("locked") boolean locked) { if (locked) { - return initializeArray(memory, hub, length, size, thread().or(biasedLockPattern()), headerSize, true, fillContents); + return initializeArray(memory, hub, length, allocationSize, thread().or(biasedLockPattern()), headerSize, fillContents); } else { - return initializeArray(memory, hub, length, size, prototypeMarkWord, headerSize, true, fillContents); + return initializeArray(memory, hub, length, allocationSize, prototypeMarkWord, headerSize, fillContents); } } - @Snippet - public static Object initializePrimitiveArray( - @Parameter("memory") Word memory, - @Parameter("hub") Word hub, - @Parameter("length") int length, - @Parameter("size") int size, - @Parameter("prototypeMarkWord") Word prototypeMarkWord, - @ConstantParameter("headerSize") int headerSize, - @ConstantParameter("fillContents") boolean fillContents, - @ConstantParameter("locked") boolean locked) { - if (locked) { - return initializeArray(memory, hub, length, size, thread().or(biasedLockPattern()), headerSize, false, fillContents); - } else { - return initializeArray(memory, hub, length, size, prototypeMarkWord, headerSize, false, fillContents); - } - } - - private static Object initializeArray(Word memory, Word hub, int length, int size, Word prototypeMarkWord, int headerSize, boolean isObjectArray, boolean fillContents) { + private static Object initializeArray(Word memory, Word hub, int length, int allocationSize, Word prototypeMarkWord, int headerSize, boolean fillContents) { Object result; if (memory == Word.zero()) { - if (isObjectArray) { - anewarray_stub.inc(); - } else { - newarray_stub.inc(); - } - result = NewArrayStubCall.call(isObjectArray, hub, length); + newarray_stub.inc(); + result = NewArrayStubCall.call(hub, length); } else { - if (isObjectArray) { - anewarray_loopInit.inc(); - } else { - newarray_loopInit.inc(); - } - formatArray(hub, size, length, headerSize, memory, prototypeMarkWord, fillContents); + newarray_loopInit.inc(); + formatArray(hub, allocationSize, length, headerSize, memory, prototypeMarkWord, fillContents); result = memory.toObject(); } return unsafeArrayCast(verifyOop(result), length, StampFactory.forNodeIntrinsic()); @@ -152,7 +127,7 @@ /** * Maximum array length for which fast path allocation is used. */ - private static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; + public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet public static Object allocateArrayAndInitialize( @@ -165,12 +140,21 @@ // This handles both negative array sizes and very large array sizes DeoptimizeNode.deopt(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.RuntimeConstraint); } - int size = getArraySize(length, alignment, headerSize, log2ElementSize); - Word memory = TLABAllocateNode.allocateVariableSize(size); - return InitializeArrayNode.initialize(memory, length, size, type, true, false); + int allocationSize = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); + Word memory = TLABAllocateNode.allocateVariableSize(allocationSize); + return InitializeArrayNode.initialize(memory, length, allocationSize, type, true, false); } - public static int getArraySize(int length, int alignment, int headerSize, int log2ElementSize) { + /** + * Computes the size of the memory chunk allocated for an array. This size accounts for the array + * header size, boy size and any padding after the last element to satisfy object alignment requirements. + * + * @param length the number of elements in the array + * @param alignment the object alignment requirement + * @param headerSize the size of the array header + * @param log2ElementSize log2 of the size of an element in the array + */ + public static int computeArrayAllocationSize(int length, int alignment, int headerSize, int log2ElementSize) { int size = (length << log2ElementSize) + headerSize + (alignment - 1); int mask = ~(alignment - 1); return size & mask; @@ -225,12 +209,13 @@ /** * Formats some allocated memory with an object header zeroes out the rest. */ - private static void formatArray(Word hub, int size, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { + public static void formatArray(Word hub, int allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents) { storeWord(memory, 0, markOffset(), prototypeMarkWord); + storeInt(memory, 0, arrayLengthOffset(), length); + // store hub last as the concurrent garbage collectors assume length is valid if hub field is not null storeWord(memory, 0, hubOffset(), hub); - storeInt(memory, 0, arrayLengthOffset(), length); if (fillContents) { - for (int offset = headerSize; offset < size; offset += wordSize()) { + for (int offset = headerSize; offset < allocationSize; offset += wordSize()) { storeWord(memory, 0, offset, Word.zero()); } } @@ -240,8 +225,7 @@ private final ResolvedJavaMethod allocate; private final ResolvedJavaMethod initializeObject; - private final ResolvedJavaMethod initializeObjectArray; - private final ResolvedJavaMethod initializePrimitiveArray; + private final ResolvedJavaMethod initializeArray; private final ResolvedJavaMethod allocateArrayAndInitialize; private final ResolvedJavaMethod newmultiarray; private final TargetDescription target; @@ -253,8 +237,7 @@ this.useTLAB = useTLAB; allocate = snippet("allocate", int.class); initializeObject = snippet("initializeObject", Word.class, Word.class, Word.class, int.class, boolean.class, boolean.class); - initializeObjectArray = snippet("initializeObjectArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); - initializePrimitiveArray = snippet("initializePrimitiveArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); + initializeArray = snippet("initializeArray", Word.class, Word.class, int.class, int.class, Word.class, int.class, boolean.class, boolean.class); allocateArrayAndInitialize = snippet("allocateArrayAndInitialize", int.class, int.class, int.class, int.class, ResolvedJavaType.class); newmultiarray = snippet("newmultiarray", Word.class, int.class, int[].class); } @@ -308,7 +291,7 @@ graph.replaceFixedWithFixed(newArrayNode, initializeNode); } else if (length != null && belowThan(length, MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH)) { // Calculate aligned size - int size = getArraySize(length, alignment, headerSize, log2ElementSize); + int size = computeArrayAllocationSize(length, alignment, headerSize, log2ElementSize); ConstantNode sizeNode = ConstantNode.forInt(size, graph); tlabAllocateNode = graph.add(new TLABAllocateNode(sizeNode)); graph.addBeforeFixed(newArrayNode, tlabAllocateNode); @@ -364,11 +347,11 @@ ConstantNode hub = ConstantNode.forConstant(type.klass(), runtime, graph); Kind elementKind = elementType.getKind(); final int headerSize = HotSpotRuntime.getArrayBaseOffset(elementKind); - Key key = new Key(elementKind == Kind.Object ? initializeObjectArray : initializePrimitiveArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); + Key key = new Key(initializeArray).add("headerSize", headerSize).add("fillContents", initializeNode.fillContents()).add("locked", initializeNode.locked()); ValueNode memory = initializeNode.memory(); - Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("size", initializeNode.size()).add("length", initializeNode.length()); + Arguments arguments = arguments("memory", memory).add("hub", hub).add("prototypeMarkWord", type.prototypeMarkWord()).add("allocationSize", initializeNode.allocationSize()).add("length", initializeNode.length()); SnippetTemplate template = cache.get(key, assumptions); - Debug.log("Lowering initializeObjectArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); + Debug.log("Lowering initializeArray in %s: node=%s, template=%s, arguments=%s", graph, initializeNode, template, arguments); template.instantiate(runtime, initializeNode, DEFAULT_REPLACER, arguments); } @@ -394,11 +377,7 @@ private static final SnippetCounter new_loopInit = new SnippetCounter(countersNew, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); private static final SnippetCounter new_stub = new SnippetCounter(countersNew, "stub", "alloc and zeroing via stub"); - private static final SnippetCounter.Group countersNewPrimitiveArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewPrimitiveArray") : null; - private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewPrimitiveArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewPrimitiveArray, "stub", "alloc and zeroing via stub"); - - private static final SnippetCounter.Group countersNewObjectArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewObjectArray") : null; - private static final SnippetCounter anewarray_loopInit = new SnippetCounter(countersNewObjectArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); - private static final SnippetCounter anewarray_stub = new SnippetCounter(countersNewObjectArray, "stub", "alloc and zeroing via stub"); + private static final SnippetCounter.Group countersNewArray = GraalOptions.SnippetCounters ? new SnippetCounter.Group("NewArray") : null; + private static final SnippetCounter newarray_loopInit = new SnippetCounter(countersNewArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + private static final SnippetCounter newarray_stub = new SnippetCounter(countersNewArray, "stub", "alloc and zeroing via stub"); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/SystemSnippets.java Tue Dec 11 08:29:25 2012 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.hotspot.snippets; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewArrayStub.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,104 @@ +/* + * 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.stubs; + +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.hotspot.snippets.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.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.snippets.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.ConstantParameter; +import com.oracle.graal.snippets.Snippet.Parameter; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * 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. + */ +public class NewArrayStub extends Stub { + + public NewArrayStub(final HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) { + super(runtime, assumptions, target, NewArrayStubCall.NEW_ARRAY); + } + + @Override + protected void populateKey(Key key) { + HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); + Constant intArrayHub = intArrayType.klass(); + key.add("intArrayHub", intArrayHub); + } + + /** + * Re-attempts allocation after an initial TLAB allocation failed or was skipped (e.g., due to -XX:-UseTLAB). + * + * @param hub the hub of the object to be allocated + * @param length the length of the array + * @param intArrayHub the hub for {@code int[].class} + */ + @Snippet + private static Object newArray(@Parameter("hub") Word hub, @Parameter("length") int length, @ConstantParameter("intArrayHub") Word intArrayHub) { + int layoutHelper = loadIntFromWord(hub, layoutHelperOffset()); + int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift()) & layoutHelperLog2ElementSizeMask(); + int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift()) & layoutHelperHeaderSizeMask(); + int elementKind = (layoutHelper >> layoutHelperElementTypeShift()) & layoutHelperElementTypeMask(); + int sizeInBytes = computeArrayAllocationSize(length, wordSize(), headerSize, log2ElementSize); + logf("newArray: element kind %d\n", elementKind); + logf("newArray: array length %d\n", length); + logf("newArray: array size %d\n", sizeInBytes); + logf("newArray: hub=%p\n", hub.toLong()); + + // check that array length is small enough for fast path. + if (length <= MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH) { + Word memory; + if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize())) { + memory = allocate(sizeInBytes); + } else { + logf("newArray: allocating directly in eden\n", 0L); + memory = edenAllocate(Word.fromInt(sizeInBytes)); + } + if (memory != Word.zero()) { + logf("newArray: allocated new array at %p\n", memory.toLong()); + formatArray(hub, sizeInBytes, length, headerSize, memory, Word.fromLong(arrayPrototypeMarkWord()), true); + return verifyOop(memory.toObject()); + } + } + logf("newArray: calling new_array_slow", 0L); + return verifyOop(NewArraySlowStubCall.call(hub, length)); + } + + private static final boolean LOGGING_ENABLED = Boolean.getBoolean("graal.logNewArrayStub"); + + private static void logf(String format, long value) { + if (LOGGING_ENABLED) { + Log.printf(format, value); + } + } +} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/NewInstanceStub.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,225 @@ +/* + * 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.stubs; + +import static com.oracle.graal.hotspot.nodes.DirectCompareAndSwapNode.*; +import static com.oracle.graal.hotspot.nodes.NewInstanceStubCall.*; +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; +import static com.oracle.graal.hotspot.snippets.NewObjectSnippets.*; +import static com.oracle.graal.snippets.nodes.DirectObjectStoreNode.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.hotspot.snippets.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.ConstantParameter; +import com.oracle.graal.snippets.Snippet.Parameter; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * 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. + */ +public class NewInstanceStub extends Stub { + + public NewInstanceStub(final HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target) { + super(runtime, assumptions, target, NEW_INSTANCE); + } + + @Override + protected void populateKey(Key key) { + HotSpotResolvedObjectType intArrayType = (HotSpotResolvedObjectType) runtime.lookupJavaType(int[].class); + Constant intArrayHub = intArrayType.klass(); + key.add("intArrayHub", intArrayHub); + } + + /** + * Re-attempts allocation after an initial TLAB allocation failed or was skipped (e.g., due to -XX:-UseTLAB). + * + * @param hub the hub of the object to be allocated + * @param intArrayHub the hub for {@code int[].class} + */ + @Snippet + private static Object newInstance(@Parameter("hub") Word hub, @ConstantParameter("intArrayHub") Word intArrayHub) { + int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset()); + logf("newInstance: size %d\n", sizeInBytes); + if (inlineContiguousAllocationSupported()) { + if (loadIntFromWord(hub, klassStateOffset()) == klassStateFullyInitialized()) { + Word memory; + if (refillTLAB(intArrayHub, Word.fromLong(tlabIntArrayMarkWord()), tlabAlignmentReserveInHeapWords() * wordSize())) { + memory = allocate(sizeInBytes); + } else { + logf("newInstance: allocating directly in eden\n", 0L); + memory = edenAllocate(Word.fromInt(sizeInBytes)); + } + if (memory != Word.zero()) { + logf("newInstance: allocated new object at %p\n", memory.toLong()); + Word prototypeMarkWord = loadWordFromWord(hub, prototypeMarkWordOffset()); + storeWord(memory, 0, markOffset(), prototypeMarkWord); + storeWord(memory, 0, hubOffset(), hub); + for (int offset = 2 * wordSize(); offset < sizeInBytes; offset += wordSize()) { + storeWord(memory, 0, offset, Word.zero()); + } + return verifyOop(memory.toObject()); + } + } + } + logf("newInstance: calling new_instance_slow", 0L); + return verifyOop(NewInstanceSlowStubCall.call(hub)); + } + + /** + * Attempts to refill the current thread's TLAB. + * + * @param intArrayHub the hub for {@code int[].class} + * @param intArrayMarkWord the mark word for the int array placed in the left over TLAB space + * @param alignmentReserveInBytes the amount of extra bytes to reserve in a new TLAB + * @return whether or not a new TLAB was allocated + */ + static boolean refillTLAB(Word intArrayHub, Word intArrayMarkWord, int alignmentReserveInBytes) { + + Word thread = thread(); + Word top = loadWordFromWord(thread, threadTlabTopOffset()); + Word end = loadWordFromWord(thread, threadTlabEndOffset()); + + // calculate amount of free space + Word tlabFreeSpaceInBytes = end.minus(top); + + logf("refillTLAB: thread=%p\n", thread.toLong()); + logf("refillTLAB: top=%p\n", top.toLong()); + logf("refillTLAB: end=%p\n", end.toLong()); + logf("refillTLAB: tlabFreeSpaceInBytes=%d\n", tlabFreeSpaceInBytes.toLong()); + + // a DIV or SHR operations on Words would be handy here... + Word tlabFreeSpaceInWords = Word.fromLong(tlabFreeSpaceInBytes.toLong() >>> log2WordSize()); + + // Retain TLAB and allocate object in shared space if + // the amount free in the TLAB is too large to discard. + if (tlabFreeSpaceInWords.belowOrEqual(loadWordFromWord(thread, tlabRefillWasteLimitOffset()))) { + logf("refillTLAB: discarding TLAB\n", 0L); + + if (tlabStats()) { + // increment number of refills + storeInt(thread, 0, tlabNumberOfRefillsOffset(), loadIntFromWord(thread, tlabNumberOfRefillsOffset()) + 1); + // accumulate wastage + storeWord(thread, 0, tlabFastRefillWasteOffset(), loadWordFromWord(thread, tlabFastRefillWasteOffset()).plus(tlabFreeSpaceInWords)); + } + + // if TLAB is currently allocated (top or end != null) then + // fill [top, end + alignment_reserve) with array object + if (top != Word.zero()) { + int headerSize = arrayBaseOffset(Kind.Int); + // just like the HotSpot assembler stubs, assumes that tlabFreeSpaceInInts fits in an int + int tlabFreeSpaceInInts = (int) tlabFreeSpaceInBytes.toLong() >>> 2; + int length = ((alignmentReserveInBytes - headerSize) >>> 2) + tlabFreeSpaceInInts; + logf("refillTLAB: alignmentReserveInBytes %d\n", alignmentReserveInBytes); + logf("refillTLAB: headerSize %d\n", headerSize); + logf("refillTLAB: filler.length %d\n", length); + NewObjectSnippets.formatArray(intArrayHub, -1, length, headerSize, top, intArrayMarkWord, false); + + Word allocated = loadWordFromWord(thread, threadAllocatedBytesOffset()); + allocated = allocated.plus(top.minus(loadWordFromWord(thread, threadTlabStartOffset()))); + storeWord(thread, 0, threadAllocatedBytesOffset(), allocated); + } + + // refill the TLAB with an eden allocation + Word tlabRefillSizeInWords = loadWordFromWord(thread, threadTlabSizeOffset()); + Word tlabRefillSizeInBytes = Word.fromLong(tlabRefillSizeInWords.toLong() * wordSize()); + // allocate new TLAB, address returned in top + top = edenAllocate(tlabRefillSizeInBytes); + if (top != Word.zero()) { + storeWord(thread, 0, threadTlabStartOffset(), top); + storeWord(thread, 0, threadTlabTopOffset(), top); + + end = top.plus(tlabRefillSizeInBytes.minus(alignmentReserveInBytes)); + storeWord(thread, 0, threadTlabEndOffset(), end); + logf("refillTLAB: top'=%p\n", top.toLong()); + logf("refillTLAB: start'=%p\n", top.toLong()); + logf("refillTLAB: end'=%p\n", end.toLong()); + return true; + } else { + return false; + } + } else { + // Retain TLAB + Word newRefillWasteLimit = loadWordFromWord(thread, tlabRefillWasteLimitOffset()).plus(tlabRefillWasteIncrement()); + storeWord(thread, 0, tlabRefillWasteLimitOffset(), newRefillWasteLimit); + logf("refillTLAB: retaining TLAB - newRefillWasteLimit=%p\n", newRefillWasteLimit.toLong()); + + if (tlabStats()) { + storeInt(thread, 0, tlabSlowAllocationsOffset(), loadIntFromWord(thread, tlabSlowAllocationsOffset()) + 1); + } + + return false; + } + } + + /** + * Attempts to allocate a chunk of memory from Eden space. + * + * @param sizeInBytes the size of the chunk to allocate + * @return the allocated chunk or {@link Word#zero()} if allocation fails + */ + static Word edenAllocate(Word sizeInBytes) { + Word heapTopAddress = Word.fromLong(heapTopAddress()); + Word heapEndAddress = Word.fromLong(heapEndAddress()); + logf("edenAllocate: heapTopAddress %p\n", heapTopAddress.toLong()); + logf("edenAllocate: heapEndAddress %p\n", heapEndAddress.toLong()); + + while (true) { + Word heapTop = loadWordFromWord(heapTopAddress, 0); + Word newHeapTop = heapTop.plus(sizeInBytes); + logf("edenAllocate: heapTop %p\n", heapTop.toLong()); + logf("edenAllocate: newHeapTop %p\n", newHeapTop.toLong()); + if (newHeapTop.belowOrEqual(heapTop)) { + logf("edenAllocate: fail 1\n", 0L); + return Word.zero(); + } + + Word heapEnd = loadWordFromWord(heapEndAddress, 0); + logf("edenAllocate: heapEnd %p\n", heapEnd.toLong()); + if (newHeapTop.above(heapEnd)) { + logf("edenAllocate: fail 2\n", 0L); + return Word.zero(); + } + + if (compareAndSwap(heapTopAddress, 0, heapTop, newHeapTop) == heapTop) { + logf("edenAllocate: success %p\n", heapTop.toLong()); + return heapTop; + } + } + } + + private static final boolean LOGGING_ENABLED = Boolean.getBoolean("graal.logNewInstanceStub"); + + private static void logf(String format, long value) { + if (LOGGING_ENABLED) { + Log.printf(format, value); + } + } +} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Tue Dec 11 08:29:25 2012 +0100 @@ -0,0 +1,151 @@ +/* + * 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.stubs; + +import static java.lang.reflect.Modifier.*; + +import java.lang.reflect.*; +import java.util.concurrent.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.PhasePlan.PhasePosition; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.Snippet.ConstantParameter; +import com.oracle.graal.snippets.SnippetTemplate.AbstractTemplates; +import com.oracle.graal.snippets.SnippetTemplate.Key; + +/** + * Base class for implementing some low level code providing the out-of-line slow path for a snippet. + * A concrete stub is defined a subclass of this class. + *

+ * Implementation detail: The stub classes re-use some of the functionality for {@link Snippet}s + * purely for convenience (e.g., can re-use the {@link SnippetInstaller}). + */ +public abstract class Stub extends AbstractTemplates implements SnippetsInterface { + + /** + * The method implementing the stub. + */ + protected final HotSpotResolvedJavaMethod stubMethod; + + /** + * The linkage information for the stub. + */ + protected final HotSpotRuntimeCallTarget linkage; + + /** + * The code installed for the stub. + */ + protected InstalledCode stubCode; + + /** + * Creates a new stub container. The new stub still needs to be {@linkplain #install(GraalCompiler) installed}. + * + * @param descriptor linkage details for a call to the stub + */ + @SuppressWarnings("unchecked") + public Stub(HotSpotRuntime runtime, Assumptions assumptions, TargetDescription target, Descriptor descriptor) { + super(runtime, assumptions, target, null); + stubMethod = findStubMethod(runtime, getClass()); + linkage = runtime.registerStub(descriptor, this); + assert linkage != null; + } + + /** + * Adds the {@linkplain ConstantParameter constant} arguments of this stub. + */ + protected abstract void populateKey(Key key); + + protected HotSpotRuntime runtime() { + return (HotSpotRuntime) runtime; + } + + /** + * Gets the method implementing this stub. + */ + public ResolvedJavaMethod getMethod() { + return stubMethod; + } + + public HotSpotRuntimeCallTarget getLinkage() { + return linkage; + } + + /** + * Compiles the code for this stub, installs it and initializes the address used for calls to it. + */ + public void install(GraalCompiler compiler) { + StructuredGraph graph = (StructuredGraph) stubMethod.getCompilerStorage().get(Graph.class); + + Key key = new Key(stubMethod); + populateKey(key); + SnippetTemplate template = cache.get(key, assumptions); + graph = template.copySpecializedGraph(); + + PhasePlan phasePlan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(runtime, GraphBuilderConfiguration.getDefault(), OptimisticOptimizations.ALL); + phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + final CompilationResult compResult = compiler.compileMethod(stubMethod, graph, null, phasePlan, OptimisticOptimizations.ALL); + + final CodeInfo[] info = new CodeInfo[1]; + stubCode = Debug.scope("CodeInstall", new Object[] {compiler, stubMethod}, new Callable() { + @Override + public InstalledCode call() { + InstalledCode installedCode = runtime().addMethod(stubMethod, compResult, info); + assert installedCode != null : "error installing stub " + stubMethod; + if (Debug.isDumpEnabled()) { + Debug.dump(new Object[] {compResult, info[0]}, "After code installation"); + } + return installedCode; + } + }); + + assert stubCode != null : "error installing stub " + stubMethod; + linkage.setAddress(info[0].getStart()); + } + + /** + * Finds the static method annotated with {@link Snippet} in a given class of which there must be exactly one. + */ + private static HotSpotResolvedJavaMethod findStubMethod(HotSpotRuntime runtime, Class stubClass) { + HotSpotResolvedJavaMethod m = null; + for (Method candidate : stubClass.getDeclaredMethods()) { + if (isStatic(candidate.getModifiers()) && candidate.getAnnotation(Snippet.class) != null) { + assert m == null : "more than one method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; + m = (HotSpotResolvedJavaMethod) runtime.lookupJavaMethod(candidate); + } + } + assert m != null : "no static method annotated with @" + Snippet.class.getSimpleName() + " in " + stubClass; + return m; + } +} diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Tue Dec 11 08:29:25 2012 +0100 @@ -29,7 +29,7 @@ import java.util.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.api.meta.JavaTypeProfile.ProfiledType; import com.oracle.graal.api.meta.ProfilingInfo.ExceptionSeen; @@ -775,7 +775,7 @@ lastInstr = falseSucc; if (GraalOptions.OmitHotExceptionStacktrace) { - ValueNode exception = ConstantNode.forObject(new NullPointerException(), runtime, currentGraph); + ValueNode exception = ConstantNode.forObject(cachedNullPointerException, runtime, currentGraph); trueSucc.setNext(handleException(exception, bci())); } else { RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(CREATE_NULL_POINTER_EXCEPTION)); @@ -785,6 +785,14 @@ } } + private static final ArrayIndexOutOfBoundsException cachedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException(); + private static final NullPointerException cachedNullPointerException = new NullPointerException(); + static { + cachedArrayIndexOutOfBoundsException.setStackTrace(new StackTraceElement[0]); + cachedNullPointerException.setStackTrace(new StackTraceElement[0]); + } + + private void emitBoundsCheck(ValueNode index, ValueNode length) { BlockPlaceholderNode trueSucc = currentGraph.add(new BlockPlaceholderNode()); BlockPlaceholderNode falseSucc = currentGraph.add(new BlockPlaceholderNode()); @@ -794,7 +802,7 @@ lastInstr = trueSucc; if (GraalOptions.OmitHotExceptionStacktrace) { - ValueNode exception = ConstantNode.forObject(new ArrayIndexOutOfBoundsException(), runtime, currentGraph); + ValueNode exception = ConstantNode.forObject(cachedArrayIndexOutOfBoundsException, runtime, currentGraph); falseSucc.setNext(handleException(exception, bci())); } else { RuntimeCallNode call = currentGraph.add(new RuntimeCallNode(CREATE_OUT_OF_BOUNDS_EXCEPTION, index)); @@ -963,7 +971,7 @@ Kind resultType = targetMethod.getSignature().getReturnKind(); if (GraalOptions.DeoptALot) { DeoptimizeNode deoptimize = currentGraph.add(new DeoptimizeNode(DeoptimizationAction.None, DeoptimizationReason.RuntimeConstraint, graphId)); - deoptimize.setMessage("invoke " + targetMethod.getName()); + deoptimize.setMessage(targetMethod.getName()); append(deoptimize); frameState.pushReturn(resultType, ConstantNode.defaultForKind(resultType, currentGraph)); return; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java --- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Tue Dec 11 08:29:25 2012 +0100 @@ -26,7 +26,7 @@ import static com.oracle.graal.lir.LIRInstruction.OperandFlag.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.lir.*; @@ -44,10 +44,10 @@ @Temp protected Value[] temps; @State protected LIRFrameState state; - protected final Object targetMethod; + protected final Object callTarget; - public DirectCallOp(Object targetMethod, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { - this.targetMethod = targetMethod; + public DirectCallOp(Object callTarget, Value result, Value[] parameters, Value[] temps, LIRFrameState state) { + this.callTarget = callTarget; this.result = result; this.parameters = parameters; this.state = state; @@ -58,7 +58,7 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { emitAlignmentForDirectCall(tasm, masm); - directCall(tasm, masm, targetMethod, state); + directCall(tasm, masm, callTarget, state); } protected void emitAlignmentForDirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { @@ -79,10 +79,10 @@ @Temp protected Value[] temps; @State protected LIRFrameState state; - protected final Object targetMethod; + protected final Object callTarget; - public IndirectCallOp(Object targetMethod, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { - this.targetMethod = targetMethod; + public IndirectCallOp(Object callTarget, Value result, Value[] parameters, Value[] temps, Value targetAddress, LIRFrameState state) { + this.callTarget = callTarget; this.result = result; this.parameters = parameters; this.targetAddress = targetAddress; @@ -93,7 +93,7 @@ @Override public void emitCode(TargetMethodAssembler tasm, AMD64MacroAssembler masm) { - indirectCall(tasm, masm, asRegister(targetAddress), targetMethod, state); + indirectCall(tasm, masm, asRegister(targetAddress), callTarget, state); } @Override @@ -103,10 +103,10 @@ } } - public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object target, LIRFrameState info) { + public static void directCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Object callTarget, LIRFrameState info) { int before = masm.codeBuffer.position(); - if (target instanceof RuntimeCall) { - long maxOffset = ((RuntimeCall) target).getMaxCallTargetOffset(); + if (callTarget instanceof RuntimeCallTarget) { + long maxOffset = ((RuntimeCallTarget) callTarget).getMaxCallTargetOffset(); if (maxOffset != (int) maxOffset) { // offset might not fit a 32-bit immediate, generate an // indirect call with a 64-bit immediate @@ -122,7 +122,7 @@ masm.call(); } int after = masm.codeBuffer.position(); - tasm.recordDirectCall(before, after, tasm.runtime.lookupCallTarget(target), info); + tasm.recordDirectCall(before, after, tasm.runtime.lookupCallTarget(callTarget), info); tasm.recordExceptionHandlers(after, info); masm.ensureUniquePC(); } @@ -135,11 +135,11 @@ masm.ensureUniquePC(); } - public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object target, LIRFrameState info) { + public static void indirectCall(TargetMethodAssembler tasm, AMD64MacroAssembler masm, Register dst, Object callTarget, LIRFrameState info) { int before = masm.codeBuffer.position(); masm.call(dst); int after = masm.codeBuffer.position(); - tasm.recordIndirectCall(before, after, tasm.runtime.lookupCallTarget(target), info); + tasm.recordIndirectCall(before, after, tasm.runtime.lookupCallTarget(callTarget), info); tasm.recordExceptionHandlers(after, info); masm.ensureUniquePC(); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/FixedGuardNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -25,7 +25,6 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; -import com.oracle.graal.nodes.extended.*; import com.oracle.graal.nodes.spi.*; import com.oracle.graal.nodes.type.*; @@ -60,6 +59,22 @@ this.reason = deoptReason; } + public DeoptimizationReason getReason() { + return reason; + } + + public DeoptimizationAction getAction() { + return action; + } + + public boolean isNegated() { + return negated; + } + + public long getLeafGraphId() { + return leafGraphId; + } + @Override public String toString(Verbosity verbosity) { if (verbosity == Verbosity.Name && negated) { @@ -93,8 +108,7 @@ @Override public void lower(LoweringTool tool) { - ValueAnchorNode newAnchor = graph().add(new ValueAnchorNode(tool.createGuard(condition, reason, action, negated, leafGraphId))); - ((StructuredGraph) graph()).replaceFixedWithFixed(this, newAnchor); + tool.getRuntime().lower(this, tool); } @Override diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/UnwindNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.spi.*; @@ -50,7 +50,7 @@ @Override public void generate(LIRGeneratorTool gen) { - RuntimeCall call = gen.getRuntime().lookupRuntimeCall(UNWIND_EXCEPTION); + RuntimeCallTarget call = gen.getRuntime().lookupRuntimeCall(UNWIND_EXCEPTION); gen.emitCall(call, call.getCallingConvention(), false, gen.operand(exception())); } } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LoadHubNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -40,7 +40,7 @@ } public LoadHubNode(ValueNode object, Kind kind) { - super(StampFactory.forKind(kind)); + super(kind == Kind.Object ? StampFactory.objectNonNull() : StampFactory.forKind(kind)); this.object = object; } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/RuntimeCallNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.nodes.extended; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.graph.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/NewMultiArrayNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -45,6 +45,10 @@ return dimensions.size(); } + public NodeList dimensions() { + return dimensions; + } + /** * Constructs a new NewMultiArrayNode. * @param type the element type of the array diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/java/RegisterFinalizerNode.java Tue Dec 11 08:29:25 2012 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.nodes.java; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.RuntimeCall.*; +import com.oracle.graal.api.code.RuntimeCallTarget.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -49,7 +49,7 @@ @Override public void generate(LIRGeneratorTool gen) { - RuntimeCall call = gen.getRuntime().lookupRuntimeCall(REGISTER_FINALIZER); + RuntimeCallTarget call = gen.getRuntime().lookupRuntimeCall(REGISTER_FINALIZER); gen.emitCall(call, call.getCallingConvention(), true, gen.operand(object())); } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Tue Dec 11 08:29:25 2012 +0100 @@ -85,7 +85,7 @@ public abstract void emitMembar(int barriers); public abstract void emitDeoptimizeOnOverflow(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo); public abstract void emitDeoptimize(DeoptimizationAction action, DeoptimizationReason reason, Object deoptInfo, long leafGraphId); - public abstract Value emitCall(Object target, CallingConvention cc, boolean canTrap, Value... args); + public abstract Value emitCall(RuntimeCallTarget callTarget, CallingConvention cc, boolean canTrap, Value... args); public abstract void emitIf(IfNode i); public abstract void emitConditional(ConditionalNode i); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/InliningUtil.java Tue Dec 11 08:29:25 2012 +0100 @@ -987,7 +987,7 @@ return getIntrinsicGraph(invoke, target, runtime) != null; } - private static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) { + public static StructuredGraph getIntrinsicGraph(Invoke invoke, ResolvedJavaMethod target, GraalCodeCacheProvider runtime) { assert invoke.node().isAlive(); StructuredGraph intrinsicGraph = (StructuredGraph) target.getCompilerStorage().get(Graph.class); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/LoweringPhase.java Tue Dec 11 08:29:25 2012 +0100 @@ -104,6 +104,8 @@ private final GraalCodeCacheProvider runtime; private final Assumptions assumptions; + private boolean deferred; + public LoweringPhase(GraalCodeCacheProvider runtime, Assumptions assumptions) { this.runtime = runtime; this.assumptions = assumptions; @@ -127,11 +129,12 @@ final SchedulePhase schedule = new SchedulePhase(); schedule.apply(graph, false); + deferred = false; processBlock(schedule.getCFG().getStartBlock(), graph.createNodeBitMap(), null, schedule, processed); Debug.dump(graph, "Lowering iteration %d", i++); new CanonicalizerPhase(null, runtime, assumptions, mark).apply(graph); - if (!containsLowerable(graph.getNewNodes(mark))) { + if (!deferred && !containsLowerable(graph.getNewNodes(mark))) { // No new lowerable nodes - done! break; } @@ -184,9 +187,14 @@ loweringTool.lastFixedNode = fixed; } - if (node.isAlive() && !processed.isMarked(node)) { - processed.mark(node); - if (node instanceof Lowerable) { + if (node.isAlive() && !processed.isMarked(node) && node instanceof Lowerable) { + if (loweringTool.lastFixedNode == null) { + // We cannot lower the node now because we don't have a fixed node to anchor the replacements. + // This can happen when previous lowerings in this lowering iteration deleted the BeginNode of this block. + // In the next iteration, we will have the new BeginNode available, and we can lower this node. + deferred = true; + } else { + processed.mark(node); ((Lowerable) node).lower(loweringTool); } } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java --- a/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets.test/src/com/oracle/graal/snippets/WordTest.java Tue Dec 11 08:29:25 2012 +0100 @@ -116,7 +116,7 @@ @Test public void test_fromObject() { - inliningPolicy.set(new DefaultSnippetInliningPolicy(new BoxingMethodPool(runtime())) { + inliningPolicy.set(new DefaultSnippetInliningPolicy(runtime(), new BoxingMethodPool(runtime())) { @Override public boolean shouldInline(ResolvedJavaMethod method, ResolvedJavaMethod caller) { return super.shouldInline(method, caller) && !method.getName().equals("hashCode"); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Log.java Tue Dec 11 08:29:25 2012 +0100 @@ -24,7 +24,7 @@ import java.io.*; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/MathSnippetsX86.java Tue Dec 11 08:29:25 2012 +0100 @@ -22,7 +22,7 @@ */ package com.oracle.graal.snippets; -import com.oracle.graal.api.code.RuntimeCall.Descriptor; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; import com.oracle.graal.api.meta.*; import com.oracle.graal.graph.Node.ConstantNodeParameter; import com.oracle.graal.graph.Node.NodeIntrinsic; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/Snippet.java Tue Dec 11 08:29:25 2012 +0100 @@ -22,8 +22,6 @@ */ package com.oracle.graal.snippets; -import static com.oracle.graal.api.meta.MetaUtil.*; - import java.lang.annotation.*; import java.lang.reflect.*; @@ -73,9 +71,11 @@ * */ public static class DefaultSnippetInliningPolicy implements SnippetInliningPolicy { + private final MetaAccessProvider metaAccess; private final BoxingMethodPool pool; - public DefaultSnippetInliningPolicy(BoxingMethodPool pool) { + public DefaultSnippetInliningPolicy(MetaAccessProvider metaAccess, BoxingMethodPool pool) { + this.metaAccess = metaAccess; this.pool = pool; } @@ -90,7 +90,7 @@ if (method.getAnnotation(NodeIntrinsic.class) != null) { return false; } - if (Throwable.class.isAssignableFrom(getMirrorOrFail(method.getDeclaringClass(), null))) { + if (metaAccess.lookupJavaType(Throwable.class).isAssignableFrom(method.getDeclaringClass())) { if (method.getName().equals("")) { return false; } diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetInstaller.java Tue Dec 11 08:29:25 2012 +0100 @@ -130,7 +130,7 @@ policyClass = snippet.inlining(); } if (policyClass == SnippetInliningPolicy.class) { - return new DefaultSnippetInliningPolicy(pool); + return new DefaultSnippetInliningPolicy(runtime, pool); } try { return policyClass.getConstructor().newInstance(); diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetIntrinsificationPhase.java Tue Dec 11 08:29:25 2012 +0100 @@ -85,7 +85,7 @@ int count = signature.getParameterCount(false); Class[] result = new Class< ? >[count]; for (int i = 0; i < result.length; ++i) { - result[i] = getMirrorOrFail(signature.getParameterType(i, accessingClass).resolve(accessingClass), null); + result[i] = getMirrorOrFail(signature.getParameterType(i, accessingClass).resolve(accessingClass), Thread.currentThread().getContextClassLoader()); } return result; } @@ -126,7 +126,7 @@ } // Call the method - Constant constant = callMethod(target.getSignature().getReturnKind(), getMirrorOrFail(declaringClass, null), target.getName(), parameterTypes, receiver, arguments); + Constant constant = callMethod(target.getSignature().getReturnKind(), getMirrorOrFail(declaringClass, Thread.currentThread().getContextClassLoader()), target.getName(), parameterTypes, receiver, arguments); if (constant != null) { // Replace the invoke with the result of the call @@ -191,7 +191,7 @@ private static Class< ? > getNodeClass(ResolvedJavaMethod target, NodeIntrinsic intrinsic) { Class< ? > result = intrinsic.value(); if (result == NodeIntrinsic.class) { - return getMirrorOrFail(target.getDeclaringClass(), null); + return getMirrorOrFail(target.getDeclaringClass(), Thread.currentThread().getContextClassLoader()); } assert Node.class.isAssignableFrom(result); return result; diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/SnippetTemplate.java Tue Dec 11 08:29:25 2012 +0100 @@ -185,12 +185,17 @@ protected final Cache cache; protected final MetaAccessProvider runtime; protected final Assumptions assumptions; - protected Class snippetsClass; + protected Class snippetsClass; public AbstractTemplates(MetaAccessProvider runtime, Assumptions assumptions, TargetDescription target, Class snippetsClass) { this.runtime = runtime; this.assumptions = assumptions; - this.snippetsClass = snippetsClass; + if (snippetsClass == null) { + assert this instanceof SnippetsInterface; + this.snippetsClass = getClass(); + } else { + this.snippetsClass = snippetsClass; + } this.cache = new Cache(runtime, target); } @@ -243,7 +248,13 @@ String name = c.value(); Object arg = key.get(name); Kind kind = signature.getParameterKind(i); - replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(Constant.forBoxed(kind, arg), runtime, snippetCopy)); + Constant constantArg; + if (arg instanceof Constant) { + constantArg = (Constant) arg; + } else { + constantArg = Constant.forBoxed(kind, arg); + } + replacements.put(snippetGraph.getLocal(i), ConstantNode.forConstant(constantArg, runtime, snippetCopy)); } else { VarargsParameter vp = MetaUtil.getParameterAnnotation(VarargsParameter.class, i, method); if (vp != null) { @@ -390,8 +401,12 @@ } private static boolean checkConstantArgument(final ResolvedJavaMethod method, Signature signature, int i, String name, Object arg, Kind kind) { + ResolvedJavaType type = signature.getParameterType(i, method.getDeclaringClass()).resolve(method.getDeclaringClass()); + if (WordTypeRewriterPhase.isWord(type)) { + assert arg instanceof Constant : method + ": word constant parameters must be passed boxed in a Constant value: " + arg; + return true; + } if (kind == Kind.Object) { - ResolvedJavaType type = signature.getParameterType(i, method.getDeclaringClass()).resolve(method.getDeclaringClass()); assert arg == null || type.isInstance(Constant.forObject(arg)) : method + ": wrong value type for " + name + ": expected " + type.getName() + ", got " + arg.getClass().getName(); } else { @@ -581,6 +596,13 @@ } /** + * Gets a copy of the specialized graph. + */ + public StructuredGraph copySpecializedGraph() { + return snippet.copy(); + } + + /** * Replaces a given floating node with this specialized snippet. * * @param runtime diff -r 807bf592eb90 -r ff6df8b7ce81 graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java --- a/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Tue Dec 11 08:27:01 2012 +0100 +++ b/graal/com.oracle.graal.snippets/src/com/oracle/graal/snippets/WordTypeRewriterPhase.java Tue Dec 11 08:29:25 2012 +0100 @@ -43,7 +43,7 @@ */ public class WordTypeRewriterPhase extends Phase { - private static final String WordClassName = MetaUtil.toInternalName(Word.class.getName()); + public static final String WordClassName = MetaUtil.toInternalName(Word.class.getName()); private final Kind wordKind; @@ -290,6 +290,7 @@ } public static boolean isWord(ValueNode node) { + node.inferStamp(); if (node.stamp() == StampFactory.forWord()) { return true; } @@ -310,7 +311,7 @@ } private void changeToWord(ValueNode valueNode) { - assert !(valueNode instanceof ConstantNode); + assert !(valueNode instanceof ConstantNode) : "boxed Word constants should not appear in a snippet graph: " + valueNode + ", stamp: " + valueNode.stamp(); valueNode.setStamp(StampFactory.forKind(wordKind)); // Propagate word kind. diff -r 807bf592eb90 -r ff6df8b7ce81 src/cpu/x86/vm/graalRuntime_x86.cpp --- a/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/cpu/x86/vm/graalRuntime_x86.cpp Tue Dec 11 08:29:25 2012 +0100 @@ -804,44 +804,18 @@ break; - case graal_new_type_array_id: - case graal_new_object_array_id: + case graal_new_array_id: { Register length = rbx; // Incoming Register klass = rdx; // Incoming Register obj = rax; // Result - if (id == graal_new_type_array_id) { - __ set_info("new_type_array", dont_gc_arguments); - } else { - __ set_info("new_object_array", dont_gc_arguments); - } + __ set_info("new_array", dont_gc_arguments); -#ifdef ASSERT - // assert object type is really an array of the proper kind - { - Label ok; - Register t0 = obj; - __ movl(t0, Address(klass, Klass::layout_helper_offset())); - __ sarl(t0, Klass::_lh_array_tag_shift); - int tag = ((id == graal_new_type_array_id) - ? Klass::_lh_array_tag_type_value - : Klass::_lh_array_tag_obj_value); - __ cmpl(t0, tag); - __ jcc(Assembler::equal, ok); - __ stop("assert(is an array klass)"); - __ should_not_reach_here(); - __ bind(ok); - } -#endif // ASSERT __ enter(); OopMap* map = save_live_registers(sasm, 3); int call_offset; - if (id == graal_new_type_array_id) { - call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_type_array), klass, length); - } else { - call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_object_array), klass, length); - } + call_offset = __ call_RT(obj, noreg, CAST_FROM_FN_PTR(address, new_array), klass, length); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, map); diff -r 807bf592eb90 -r ff6df8b7ce81 src/share/vm/compiler/abstractCompiler.hpp --- a/src/share/vm/compiler/abstractCompiler.hpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/share/vm/compiler/abstractCompiler.hpp Tue Dec 11 08:29:25 2012 +0100 @@ -47,8 +47,11 @@ // Name of this compiler virtual const char* name() = 0; - // Missing feature tests + // Should a native wrapper be generated by the runtime. This method + // does *not* answer the question "can this compiler generate code for + // a native method". virtual bool supports_native() { return true; } + virtual bool supports_osr () { return true; } #if defined(TIERED) || ( !defined(COMPILER1) && !defined(COMPILER2) && !defined(SHARK) && !defined(GRAAL)) virtual bool is_c1 () { return false; } diff -r 807bf592eb90 -r ff6df8b7ce81 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Tue Dec 11 08:29:25 2012 +0100 @@ -538,8 +538,12 @@ // jint next_pc_offset = Assembler::locate_next_instruction(instruction) - _instructions->start(); _debug_recorder->add_safepoint(pc_offset, -1, create_oop_map(_total_frame_size, _parameter_count, debug_info)); - oop code_pos = DebugInfo::bytecodePosition(debug_info); - record_scope(pc_offset, code_pos, new GrowableArray()); + oop frame = DebugInfo::bytecodePosition(debug_info); + if (frame != NULL) { + record_scope(pc_offset, frame, new GrowableArray()); + } else { + // Stubs do not record scope info, just oop maps + } _debug_recorder->end_safepoint(pc_offset); } @@ -595,8 +599,13 @@ if (debug_info != NULL) { oop frame = DebugInfo::bytecodePosition(debug_info); - _debug_recorder->add_safepoint(next_pc_offset, BytecodeFrame::leafGraphId(frame), create_oop_map(_total_frame_size, _parameter_count, debug_info)); - record_scope(next_pc_offset, frame, new GrowableArray()); + jlong leaf_graph_id = frame == NULL ? -1 : BytecodeFrame::leafGraphId(frame); + _debug_recorder->add_safepoint(next_pc_offset, leaf_graph_id, create_oop_map(_total_frame_size, _parameter_count, debug_info)); + if (frame != NULL) { + record_scope(next_pc_offset, frame, new GrowableArray()); + } else { + // Stubs do not record scope info, just oop maps + } } if (global_stub != NULL) { diff -r 807bf592eb90 -r ff6df8b7ce81 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Dec 11 08:29:25 2012 +0100 @@ -514,15 +514,6 @@ return JNIHandles::make_local(THREAD, VMToCompiler::createResolvedJavaMethod(holder, method(), THREAD)); C2V_END -C2V_VMENTRY(jlong, getPrototypeMarkWord, (JNIEnv *, jobject, jobject klass)) - KlassHandle klass_handle(java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(klass))); - if (klass_handle->oop_is_array()) { - return (int32_t)(intptr_t) markOopDesc::prototype(); - } else { - return (jlong) (intptr_t) klass_handle->prototype_header(); - } -C2V_END - C2V_VMENTRY(jboolean, isTypeInitialized,(JNIEnv *, jobject, jobject hotspot_klass)) Klass* klass = java_lang_Class::as_Klass(HotSpotResolvedObjectType::javaMirror(hotspot_klass)); assert(klass != NULL, "method must not be called for primitive types"); @@ -585,120 +576,139 @@ return id; } -void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } -void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } -void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } -void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } -void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } - -jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } -jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } -jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } -jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } -jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } - - BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); C2V_ENTRY(void, initializeConfiguration, (JNIEnv *env, jobject, jobject config)) + +#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_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) + + guarantee(HeapWordSize == sizeof(char*), "Graal assumption that HeadWordSize == machine word size is wrong"); #ifdef _WIN64 set_boolean(env, config, "windowsOs", true); #else - set_boolean(env, config, "windowsOs", false); + set_boolean("windowsOs", false); #endif - set_boolean(env, config, "verifyOops", VerifyOops); - set_boolean(env, config, "useFastLocking", UseFastLocking); - set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); - set_boolean(env, config, "useBiasedLocking", UseBiasedLocking); - set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); - set_boolean(env, config, "useTLAB", UseTLAB); - set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); - set_int(env, config, "vmPageSize", os::vm_page_size()); - set_int(env, config, "stackShadowPages", StackShadowPages); - set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); - set_int(env, config, "markOffset", oopDesc::mark_offset_in_bytes()); - set_int(env, config, "prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset())); - set_int(env, config, "superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); - set_int(env, config, "secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); - set_int(env, config, "secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); - set_int(env, config, "subklassOffset", in_bytes(Klass::subklass_offset())); - set_int(env, config, "nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); - set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); - set_int(env, config, "klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); - set_int(env, config, "klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); - set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); - set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); - set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); - set_int(env, config, "unlockedMask", (int) markOopDesc::unlocked_value); - set_int(env, config, "biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); - set_int(env, config, "ageMaskInPlace", (int) markOopDesc::age_mask_in_place); - set_int(env, config, "epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place); - set_int(env, config, "biasedLockPattern", (int) markOopDesc::biased_lock_pattern); - set_int(env, config, "methodMaxLocalsOffset", in_bytes(Method::size_of_locals_offset())); - set_int(env, config, "methodMaxStackOffset", in_bytes(Method::max_stack_offset())); - set_int(env, config, "extraStackEntries", Method::extra_stack_entries()); - set_int(env, config, "methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); - set_int(env, config, "klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); - set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); - set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); - set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); - set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); - set_int(env, config, "classMirrorOffset", in_bytes(Klass::java_mirror_offset())); - set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); - set_int(env, config, "klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); - set_int(env, config, "klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); - set_int(env, config, "klassOffset", java_lang_Class::klass_offset_in_bytes()); - set_int(env, config, "graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); - set_int(env, config, "methodDataOffset", in_bytes(Method::method_data_offset())); - set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset()); - set_int(env, config, "methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); - set_int(env, config, "basicLockSize", sizeof(BasicLock)); - set_int(env, config, "basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); + set_boolean("verifyOops", VerifyOops); + set_boolean("useFastLocking", UseFastLocking); + set_boolean("useFastNewObjectArray", UseFastNewObjectArray); + set_boolean("useBiasedLocking", UseBiasedLocking); + set_boolean("useFastNewTypeArray", UseFastNewTypeArray); + set_boolean("useTLAB", UseTLAB); + set_int("codeEntryAlignment", CodeEntryAlignment); + set_int("vmPageSize", os::vm_page_size()); + set_int("stackShadowPages", StackShadowPages); + set_int("hubOffset", oopDesc::klass_offset_in_bytes()); + set_int("markOffset", oopDesc::mark_offset_in_bytes()); + set_int("prototypeMarkWordOffset", in_bytes(Klass::prototype_header_offset())); + set_int("superCheckOffsetOffset", in_bytes(Klass::super_check_offset_offset())); + set_int("secondarySuperCacheOffset", in_bytes(Klass::secondary_super_cache_offset())); + set_int("secondarySupersOffset", in_bytes(Klass::secondary_supers_offset())); + set_int("subklassOffset", in_bytes(Klass::subklass_offset())); + set_int("nextSiblingOffset", in_bytes(Klass::next_sibling_offset())); + set_int("arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); + set_int("klassStateOffset", in_bytes(InstanceKlass::init_state_offset())); + set_int("klassStateFullyInitialized", (int)InstanceKlass::fully_initialized); + set_int("threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); + set_int("threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); + set_int("threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); + set_int("unlockedMask", (int) markOopDesc::unlocked_value); + set_int("biasedLockMaskInPlace", (int) markOopDesc::biased_lock_mask_in_place); + set_int("ageMaskInPlace", (int) markOopDesc::age_mask_in_place); + set_int("epochMaskInPlace", (int) markOopDesc::epoch_mask_in_place); + set_int("biasedLockPattern", (int) markOopDesc::biased_lock_pattern); + set_int("methodMaxLocalsOffset", in_bytes(Method::size_of_locals_offset())); + set_int("methodMaxStackOffset", in_bytes(Method::max_stack_offset())); + set_int("extraStackEntries", Method::extra_stack_entries()); + set_int("methodAccessFlagsOffset", in_bytes(Method::access_flags_offset())); + set_int("klassHasFinalizerFlag", JVM_ACC_HAS_FINALIZER); + set_int("threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); + set_int("threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); + set_long("safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); + set_boolean("isPollingPageFar", Assembler::is_polling_page_far()); + set_int("classMirrorOffset", in_bytes(Klass::java_mirror_offset())); + set_int("runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); + set_int("klassModifierFlagsOffset", in_bytes(Klass::modifier_flags_offset())); + set_int("klassAccessFlagsOffset", in_bytes(Klass::access_flags_offset())); + set_int("klassOffset", java_lang_Class::klass_offset_in_bytes()); + set_int("graalMirrorInClassOffset", java_lang_Class::graal_mirror_offset_in_bytes()); + set_int("methodDataOffset", in_bytes(Method::method_data_offset())); + set_int("nmethodEntryOffset", nmethod::verified_entry_point_offset()); + set_int("methodCompiledEntryOffset", in_bytes(Method::from_compiled_offset())); + set_int("basicLockSize", sizeof(BasicLock)); + set_int("basicLockDisplacedHeaderOffset", BasicLock::displaced_header_offset_in_bytes()); - set_int(env, config, "metaspaceArrayLengthOffset", Array::length_offset_in_bytes()); - set_int(env, config, "metaspaceArrayBaseOffset", Array::base_offset_in_bytes()); - set_int(env, config, "methodDataOopDataOffset", in_bytes(MethodData::data_offset())); - set_int(env, config, "methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset())); - set_int(env, config, "dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); - set_int(env, config, "dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); - set_int(env, config, "dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); - set_int(env, config, "dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset())); - set_int(env, config, "dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0))); - set_int(env, config, "dataLayoutCellSize", DataLayout::cell_size); - set_int(env, config, "bciProfileWidth", BciProfileWidth); - set_int(env, config, "typeProfileWidth", TypeProfileWidth); + set_int("metaspaceArrayLengthOffset", Array::length_offset_in_bytes()); + set_int("metaspaceArrayBaseOffset", Array::base_offset_in_bytes()); + set_int("methodDataOopDataOffset", in_bytes(MethodData::data_offset())); + set_int("methodDataOopTrapHistoryOffset", in_bytes(MethodData::trap_history_offset())); + set_int("dataLayoutHeaderSize", DataLayout::header_size_in_bytes()); + set_int("dataLayoutTagOffset", in_bytes(DataLayout::tag_offset())); + set_int("dataLayoutFlagsOffset", in_bytes(DataLayout::flags_offset())); + set_int("dataLayoutBCIOffset", in_bytes(DataLayout::bci_offset())); + set_int("dataLayoutCellsOffset", in_bytes(DataLayout::cell_offset(0))); + set_int("dataLayoutCellSize", DataLayout::cell_size); + set_int("bciProfileWidth", BciProfileWidth); + set_int("typeProfileWidth", TypeProfileWidth); + + set_int("tlabAlignmentReserve", (int32_t)ThreadLocalAllocBuffer::alignment_reserve()); + set_long("tlabIntArrayMarkWord", (intptr_t)markOopDesc::prototype()->copy_set_hash(0x2)); + set_long("heapTopAddress", (jlong)(address) Universe::heap()->top_addr()); + set_long("heapEndAddress", (jlong)(address) Universe::heap()->end_addr()); + 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("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())); + set_int("tlabRefillWasteLimitOffset", in_bytes(JavaThread::tlab_refill_waste_limit_offset())); + set_int("tlabRefillWasteIncrement", (int32_t) ThreadLocalAllocBuffer::refill_waste_limit_increment()); + set_int("klassInstanceSizeOffset", in_bytes(Klass::layout_helper_offset())); + set_boolean("tlabStats", TLABStats); + set_boolean("inlineContiguousAllocationSupported", !CMSIncrementalMode && Universe::heap()->supports_inline_contig_alloc()); - set_long(env, config, "debugStub", VmIds::addStub((address)warning)); - set_long(env, config, "instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id))); - set_long(env, config, "newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id))); - set_long(env, config, "newTypeArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_type_array_id))); - set_long(env, config, "newObjectArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_object_array_id))); - set_long(env, config, "newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id))); - set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); - set_long(env, config, "handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id))); - set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); - set_long(env, config, "monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id))); - set_long(env, config, "monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id))); - set_long(env, config, "verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id))); - set_long(env, config, "vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id))); - set_long(env, config, "deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); - set_long(env, config, "unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id))); - set_long(env, config, "osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id))); - set_long(env, config, "registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id))); - set_long(env, config, "setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id))); - set_long(env, config, "createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id))); - set_long(env, config, "createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id))); - set_long(env, config, "javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis))); - set_long(env, config, "javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos))); - set_long(env, config, "arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id))); - set_long(env, config, "arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id))); - set_long(env, config, "arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); - set_long(env, config, "arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); - set_long(env, config, "arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); - set_long(env, config, "logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); - set_long(env, config, "logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); - set_long(env, config, "logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); + set_long("arrayPrototypeMarkWord", (intptr_t)markOopDesc::prototype()); + set_int("layoutHelperLog2ElementSizeShift", Klass::_lh_log2_element_size_shift); + set_int("layoutHelperLog2ElementSizeMask", Klass::_lh_log2_element_size_mask); + set_int("layoutHelperElementTypeShift", Klass::_lh_element_type_shift); + set_int("layoutHelperElementTypeMask", Klass::_lh_element_type_mask); + set_int("layoutHelperHeaderSizeShift", Klass::_lh_header_size_shift); + set_int("layoutHelperHeaderSizeMask", Klass::_lh_header_size_mask); + set_int("layoutHelperOffset", in_bytes(Klass::layout_helper_offset())); + + set_long("debugStub", VmIds::addStub((address)warning)); + set_long("instanceofStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_slow_subtype_check_id))); + set_long("newInstanceStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_instance_id))); + set_long("newArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_array_id))); + set_long("newMultiArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_multi_array_id))); + set_long("inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); + set_long("handleExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_handle_exception_nofpu_id))); + set_long("handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); + set_long("monitorEnterStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorenter_id))); + set_long("monitorExitStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_monitorexit_id))); + set_long("verifyOopStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_verify_oop_id))); + set_long("vmErrorStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_vm_error_id))); + set_long("deoptimizeStub", VmIds::addStub(SharedRuntime::deopt_blob()->uncommon_trap())); + set_long("unwindExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_unwind_exception_call_id))); + set_long("osrMigrationEndStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_OSR_migration_end_id))); + set_long("registerFinalizerStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_register_finalizer_id))); + set_long("setDeoptInfoStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_set_deopt_info_id))); + set_long("createNullPointerExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_null_pointer_exception_id))); + set_long("createOutOfBoundsExceptionStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_create_out_of_bounds_exception_id))); + set_long("javaTimeMillisStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeMillis))); + set_long("javaTimeNanosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, os::javaTimeNanos))); + set_long("arithmeticFremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_frem_id))); + set_long("arithmeticDremStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_arithmetic_drem_id))); + set_long("arithmeticSinStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dsin))); + set_long("arithmeticCosStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dcos))); + set_long("arithmeticTanStub", VmIds::addStub(CAST_FROM_FN_PTR(address, SharedRuntime::dtan))); + set_long("logPrimitiveStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_primitive_id))); + set_long("logObjectStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_object_id))); + set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); BarrierSet* bs = Universe::heap()->barrier_set(); @@ -707,14 +717,14 @@ case BarrierSet::CardTableExtension: { jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; assert(base != 0, "unexpected byte_map_base"); - set_long(env, config, "cardtableStartAddress", base); - set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift); + set_long("cardtableStartAddress", base); + set_int("cardtableShift", CardTableModRefBS::card_shift); break; } case BarrierSet::ModRef: case BarrierSet::Other: - set_long(env, config, "cardtableStartAddress", 0); - set_int(env, config, "cardtableShift", 0); + set_long("cardtableStartAddress", 0); + set_int("cardtableShift", 0); // No post barriers break; #ifndef SERIALGC @@ -726,7 +736,14 @@ break; } - set_int(env, config, "arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset())); + set_int("arrayClassElementOffset", in_bytes(ObjArrayKlass::element_klass_offset())); + +#undef set_boolean +#undef set_int +#undef set_long +#undef set_object +#undef set_int_array + C2V_END C2V_VMENTRY(jint, installCode0, (JNIEnv *jniEnv, jobject, jobject compResult, jobject installed_code, jobject info)) @@ -932,7 +949,6 @@ {CC"lookupReferencedTypeInPool", CC"("HS_RESOLVED_TYPE"IB)V", FN_PTR(lookupReferencedTypeInPool)}, {CC"lookupFieldInPool", CC"("HS_RESOLVED_TYPE"IB)"FIELD, FN_PTR(lookupFieldInPool)}, {CC"resolveMethod", CC"("HS_RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(resolveMethod)}, - {CC"getPrototypeMarkWord", CC"("HS_RESOLVED_TYPE")J", FN_PTR(getPrototypeMarkWord)}, {CC"getInstanceFields", CC"("HS_RESOLVED_TYPE")["HS_RESOLVED_FIELD, FN_PTR(getInstanceFields)}, {CC"isTypeInitialized", CC"("HS_RESOLVED_TYPE")Z", FN_PTR(isTypeInitialized)}, {CC"initializeType", CC"("HS_RESOLVED_TYPE")V", FN_PTR(initializeType)}, diff -r 807bf592eb90 -r ff6df8b7ce81 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Tue Dec 11 08:29:25 2012 +0100 @@ -244,31 +244,19 @@ thread->set_vm_result(obj); JRT_END - -JRT_ENTRY(void, GraalRuntime::new_type_array(JavaThread* thread, Klass* klass, jint length)) - // Note: no handle for klass needed since they are not used - // anymore after new_typeArray() and no GC can happen before. - // (This may have to change if this code changes!) - assert(klass->is_klass(), "not a class"); - BasicType elt_type = TypeArrayKlass::cast(klass)->element_type(); - oop obj = oopFactory::new_typeArray(elt_type, length, CHECK); - thread->set_vm_result(obj); - // 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(); - } - -JRT_END - - -JRT_ENTRY(void, GraalRuntime::new_object_array(JavaThread* thread, Klass* array_klass, jint length)) +JRT_ENTRY(void, GraalRuntime::new_array(JavaThread* thread, Klass* array_klass, jint length)) // Note: no handle for klass needed since they are not used // anymore after new_objArray() and no GC can happen before. // (This may have to change if this code changes!) assert(array_klass->is_klass(), "not a class"); - Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); - objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK); + oop obj; + if (array_klass->oop_is_typeArray()) { + BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); + obj = oopFactory::new_typeArray(elt_type, length, CHECK); + } else { + Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); + obj = oopFactory::new_objArray(elem_klass, length, CHECK); + } thread->set_vm_result(obj); // This is pretty rare but this runtime patch is stressful to deoptimization // if we deoptimize here so force a deopt to stress the path. diff -r 807bf592eb90 -r ff6df8b7ce81 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Tue Dec 11 08:29:25 2012 +0100 @@ -80,8 +80,7 @@ #define GRAAL_STUBS(stub, last_entry) \ stub(graal_register_finalizer) \ stub(graal_new_instance) \ - stub(graal_new_type_array) \ - stub(graal_new_object_array) \ + stub(graal_new_array) \ stub(graal_new_multi_array) \ stub(graal_handle_exception_nofpu) /* optimized version that does not preserve fpu registers */ \ stub(graal_slow_subtype_check) \ @@ -128,12 +127,11 @@ Register arg1 = noreg, Register arg2 = noreg, Register arg3 = noreg); // runtime entry points - static void new_instance (JavaThread* thread, Klass* klass); - static void new_type_array (JavaThread* thread, Klass* klass, jint length); - static void new_object_array(JavaThread* thread, Klass* klass, jint length); - static void new_multi_array (JavaThread* thread, Klass* klass, int rank, jint* dims); + 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); + static void unimplemented_entry(JavaThread* thread, StubID id); static address exception_handler_for_pc(JavaThread* thread); diff -r 807bf592eb90 -r ff6df8b7ce81 src/share/vm/runtime/deoptimization.cpp --- a/src/share/vm/runtime/deoptimization.cpp Tue Dec 11 08:27:01 2012 +0100 +++ b/src/share/vm/runtime/deoptimization.cpp Tue Dec 11 08:29:25 2012 +0100 @@ -36,9 +36,7 @@ #include "memory/resourceArea.hpp" #include "oops/method.hpp" #include "oops/oop.inline.hpp" -#ifdef GRAAL #include "oops/fieldStreams.hpp" -#endif #include "prims/jvmtiThreadState.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/compilationPolicy.hpp" @@ -809,77 +807,6 @@ return true; } -// This assumes that the fields are stored in ObjectValue in the same order -// they are yielded by do_nonstatic_fields. -class FieldReassigner: public FieldClosure { - frame* _fr; - RegisterMap* _reg_map; - ObjectValue* _sv; - InstanceKlass* _ik; - oop _obj; - - int _i; -public: - FieldReassigner(frame* fr, RegisterMap* reg_map, ObjectValue* sv, oop obj) : - _fr(fr), _reg_map(reg_map), _sv(sv), _obj(obj), _i(0) {} - - int i() const { return _i; } - - - void do_field(fieldDescriptor* fd) { - intptr_t val; - StackValue* value = - StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(i())); - int offset = fd->offset(); - switch (fd->field_type()) { - case T_OBJECT: case T_ARRAY: - assert(value->type() == T_OBJECT, "Agreement."); - _obj->obj_field_put(offset, value->get_obj()()); - break; - - case T_LONG: case T_DOUBLE: { - assert(value->type() == T_INT, "Agreement."); - StackValue* low = - StackValue::create_stack_value(_fr, _reg_map, _sv->field_at(++_i)); -#ifdef _LP64 - jlong res = (jlong)low->get_int(); -#else -#ifdef SPARC - // For SPARC we have to swap high and low words. - jlong res = jlong_from((jint)low->get_int(), (jint)value->get_int()); -#else - jlong res = jlong_from((jint)value->get_int(), (jint)low->get_int()); -#endif //SPARC -#endif - _obj->long_field_put(offset, res); - break; - } - // Have to cast to INT (32 bits) pointer to avoid little/big-endian problem. - case T_INT: case T_FLOAT: // 4 bytes. - assert(value->type() == T_INT, "Agreement."); - val = value->get_int(); - _obj->int_field_put(offset, (jint)*((jint*)&val)); - break; - - case T_SHORT: case T_CHAR: // 2 bytes - assert(value->type() == T_INT, "Agreement."); - val = value->get_int(); - _obj->short_field_put(offset, (jshort)*((jint*)&val)); - break; - - case T_BOOLEAN: case T_BYTE: // 1 byte - assert(value->type() == T_INT, "Agreement."); - val = value->get_int(); - _obj->bool_field_put(offset, (jboolean)*((jint*)&val)); - break; - - default: - ShouldNotReachHere(); - } - _i++; - } -}; - // restore elements of an eliminated type array void Deoptimization::reassign_type_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, typeArrayOop obj, BasicType type) { int index = 0; @@ -932,7 +859,6 @@ } } - // restore fields of an eliminated object array void Deoptimization::reassign_object_array_elements(frame* fr, RegisterMap* reg_map, ObjectValue* sv, objArrayOop obj) { for (int i = 0; i < sv->field_size(); i++) { @@ -942,7 +868,15 @@ } } -#ifdef GRAAL +typedef struct { + int offset; + BasicType type; +} ReassignedField; + +int compare(ReassignedField* left, ReassignedField* right) { + return left->offset - right->offset; +} + // Restore fields of an eliminated instance object using the same field order // returned by HotSpotResolvedObjectType.getInstanceFields(true) static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj) { @@ -950,14 +884,21 @@ svIndex = reassign_fields_by_klass(klass->superklass(), fr, reg_map, sv, svIndex, obj); } + GrowableArray* fields = new GrowableArray(); for (AllFieldStream fs(klass); !fs.done(); fs.next()) { - if (fs.access_flags().is_static()) { - continue; + if (!fs.access_flags().is_static()) { + ReassignedField field; + field.offset = fs.offset(); + field.type = FieldType::basic_type(fs.signature()); + fields->append(field); } + } + fields->sort(compare); + for (int i = 0; i < fields->length(); i++) { intptr_t val; StackValue* value = StackValue::create_stack_value(fr, reg_map, sv->field_at(svIndex)); - int offset = fs.offset(); - BasicType type = FieldType::basic_type(fs.signature()); + int offset = fields->at(i).offset; + BasicType type = fields->at(i).type; switch (type) { case T_OBJECT: case T_ARRAY: assert(value->type() == T_OBJECT, "Agreement."); @@ -1006,8 +947,6 @@ } return svIndex; } -#endif - // restore fields of all eliminated objects and arrays void Deoptimization::reassign_fields(frame* fr, RegisterMap* reg_map, GrowableArray* objects) { @@ -1022,12 +961,7 @@ if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k()); -#ifndef GRAAL - FieldReassigner reassign(fr, reg_map, sv, obj()); - ik->do_nonstatic_fields(&reassign); -#else reassign_fields_by_klass(ik, fr, reg_map, sv, 0, obj()); -#endif } else if (k->oop_is_typeArray()) { TypeArrayKlass* ak = TypeArrayKlass::cast(k()); reassign_type_array_elements(fr, reg_map, sv, (typeArrayOop) obj(), ak->element_type());