# HG changeset patch # User Doug Simon # Date 1354889525 -3600 # Node ID 445193cc2a7d174db576b799ae9e3beb9b9e88f0 # Parent 283fe237085b5d09a1608007e26bc847101d2836 added support for writing stubs in Java and wrote the TLAB fast refill stub diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CodeCacheProvider.java Fri Dec 07 15:12:05 2012 +0100 @@ -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,7 +81,7 @@ /** * 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. diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Fri Dec 07 15:12:05 2012 +0100 @@ -571,11 +571,11 @@ } @Override - protected void emitCall(Object targetMethod, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info) { + protected void emitCall(RuntimeCall 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/LIRGenerator.java Fri Dec 07 15:12:05 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 callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info); + protected abstract void emitCall(RuntimeCall callTarget, Value result, Value[] arguments, Value[] temps, Value targetAddress, LIRFrameState info); private static Value toStackKind(Value value) { if (value.getKind().getStackKind() != value.getKind()) { diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64DirectCallOp.java Fri Dec 07 15:12:05 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 283fe237085b -r 445193cc2a7d graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Fri Dec 07 15:12:05 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 283fe237085b -r 445193cc2a7d graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Fri Dec 07 15:12:05 2012 +0100 @@ -28,6 +28,7 @@ import static com.oracle.graal.hotspot.nodes.MonitorEnterStubCall.*; import static com.oracle.graal.hotspot.nodes.MonitorExitStubCall.*; 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.*; @@ -96,7 +97,12 @@ /* 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64IndirectCallOp.java Fri Dec 07 15:12:05 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCall.java Fri Dec 07 15:12:05 2012 +0100 @@ -23,7 +23,9 @@ 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. @@ -38,7 +40,12 @@ /** * The entry point address of the stub. */ - public final long address; + 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. @@ -56,7 +63,7 @@ @Override public String toString() { - return descriptor + "@0x" + Long.toHexString(address) + ":" + cc; + return (stub == null ? descriptor.toString() : MetaUtil.format("%h.%n", stub.getMethod())) + "@0x" + Long.toHexString(address) + ":" + cc; } public CallingConvention getCallingConvention() { @@ -70,4 +77,19 @@ 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 283fe237085b -r 445193cc2a7d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Fri Dec 07 15:12:05 2012 +0100 @@ -222,6 +222,21 @@ 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; // methodData information public int methodDataOopDataOffset; diff -r 283fe237085b -r 445193cc2a7d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotInstalledCode.java Fri Dec 07 15:12:05 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotResolvedObjectType.java Fri Dec 07 15:12:05 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; diff -r 283fe237085b -r 445193cc2a7d graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Fri Dec 07 15:12:05 2012 +0100 @@ -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,18 @@ private NewObjectSnippets.Templates newObjectSnippets; private MonitorSnippets.Templates monitorSnippets; - private final Map runtimeCalls = new HashMap<>(); + private NewInstanceStub newInstanceStub; + + 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. @@ -264,6 +276,19 @@ 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 HotSpotRuntimeCall registerStub(Descriptor descriptor, Stub stub) { + HotSpotRuntimeCall 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) { @@ -275,14 +300,17 @@ installer.install(InstanceOfSnippets.class); installer.install(NewObjectSnippets.class); installer.install(MonitorSnippets.class); + installer.install(NewInstanceStub.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()); + newInstanceStub.install(graalRuntime.getCompiler()); } - public HotSpotGraalRuntime getGraalRuntime() { return graalRuntime; } @@ -411,7 +439,7 @@ } @Override - public RegisterConfig lookupRegisterConfig(JavaMethod method) { + public RegisterConfig lookupRegisterConfig(ResolvedJavaMethod method) { return regConfig; } @@ -727,14 +755,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 HotSpotRuntimeCall) { + return ((HotSpotRuntimeCall) 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 HotSpotRuntimeCall lookupRuntimeCall(Descriptor descriptor) { assert runtimeCalls.containsKey(descriptor) : descriptor; return runtimeCalls.get(descriptor); } @@ -830,4 +868,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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 15:12:05 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.RuntimeCall.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) { + RuntimeCall 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/NewInstanceStubCall.java Fri Dec 07 15:12:05 2012 +0100 @@ -30,13 +30,14 @@ 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); + RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(NEW_INSTANCE); Variable result = gen.emitCall(stub, stub.getCallingConvention(), true, gen.operand(hub)); gen.setResult(this, result); } diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/nodes/VMErrorNode.java Fri Dec 07 15:12:05 2012 +0100 @@ -27,6 +27,7 @@ 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()); } + 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); + } + RuntimeCall stub = gen.getRuntime().lookupRuntimeCall(VMErrorNode.VM_ERROR); - gen.emitCall(stub, stub.getCallingConvention(), false, Constant.forObject(where), gen.operand(format), gen.operand(value)); + gen.emitCall(stub, stub.getCallingConvention(), false, whereArg, formatArg, gen.operand(value)); } @NodeIntrinsic diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/HotSpotSnippetUtils.java Fri Dec 07 15:12:05 2012 +0100 @@ -40,59 +40,63 @@ */ 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 int markOffset() { + return config().markOffset; } @Fold - static int unlockedMask() { - return HotSpotGraalRuntime.getInstance().getConfig().unlockedMask; + public static int unlockedMask() { + return config().unlockedMask; } /** @@ -105,13 +109,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 +128,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 +219,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()); } diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/MonitorSnippets.java Fri Dec 07 15:12:05 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/NewObjectSnippets.java Fri Dec 07 15:12:05 2012 +0100 @@ -225,10 +225,11 @@ /** * 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 size, 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()) { storeWord(memory, 0, offset, Word.zero()); diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 15:12:05 2012 +0100 @@ -0,0 +1,316 @@ +/* + * 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.Fold; +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) { + logf("newInstance: hub=%p\n", hub.toLong()); + if (inlineContiguousAllocationSupported()) { + if (loadIntFromWord(hub, klassStateOffset()) == klassStateFullyInitialized()) { + int sizeInBytes = loadIntFromWord(hub, klassInstanceSizeOffset()); + 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 + */ + private 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 + */ + private 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); + } + } + + @Fold + static int log2WordSize() { + return CodeUtil.log2(wordSize()); + } + + @Fold + static int klassStateOffset() { + return config().klassStateOffset; + } + + @Fold + static int klassInstanceSizeOffset() { + return config().klassInstanceSizeOffset; + } + + @Fold + static long heapTopAddress() { + return config().heapTopAddress; + } + + @Fold + static long heapEndAddress() { + return config().heapEndAddress; + } + + @Fold + static int threadTlabStartOffset() { + return config().threadTlabStartOffset; + } + + @Fold + static long tlabIntArrayMarkWord() { + return config().tlabIntArrayMarkWord; + } + + @Fold + static boolean inlineContiguousAllocationSupported() { + return config().inlineContiguousAllocationSupported; + } + + @Fold + static int tlabAlignmentReserveInHeapWords() { + return config().tlabAlignmentReserve; + } + + @Fold + static int threadTlabSizeOffset() { + return config().threadTlabSizeOffset; + } + + @Fold + static int threadAllocatedBytesOffset() { + return config().threadAllocatedBytesOffset; + } + + @Fold + static int klassStateFullyInitialized() { + return config().klassStateFullyInitialized; + } + + @Fold + static int tlabRefillWasteLimitOffset() { + return config().tlabRefillWasteLimitOffset; + } + + @Fold + static int tlabNumberOfRefillsOffset() { + return config().tlabNumberOfRefillsOffset; + } + + @Fold + static int tlabFastRefillWasteOffset() { + return config().tlabFastRefillWasteOffset; + } + + @Fold + static int tlabSlowAllocationsOffset() { + return config().tlabSlowAllocationsOffset; + } + + @Fold + static int tlabRefillWasteIncrement() { + return config().tlabRefillWasteIncrement; + } + + @Fold + static boolean tlabStats() { + return config().tlabStats; + } +} diff -r 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 15:12:05 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.RuntimeCall.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 HotSpotRuntimeCall 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 HotSpotRuntimeCall 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 283fe237085b -r 445193cc2a7d 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 Fri Dec 07 11:14:12 2012 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64Call.java Fri Dec 07 15:12:05 2012 +0100 @@ -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 RuntimeCall) { + long maxOffset = ((RuntimeCall) 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 283fe237085b -r 445193cc2a7d src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Fri Dec 07 11:14:12 2012 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Fri Dec 07 15:12:05 2012 +0100 @@ -585,120 +585,131 @@ 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("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("newTypeArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_type_array_id))); + set_long("newObjectArrayStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_new_object_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 +718,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 +737,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))