# HG changeset patch # User Christian Humer # Date 1366641654 -7200 # Node ID 7e3c7d55d538b3eba69ade5c0fc86b7ae70ce217 # Parent 76a6e7907b67417b7a117af1d06c0cb206daf5d1# Parent 898045a71791b42764ce53e7066dfd33dd660de7 Merge. diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/Register.java Mon Apr 22 16:40:54 2013 +0200 @@ -196,6 +196,16 @@ } /** + * Gets a hash code for this register. + * + * @return the value of {@link #number} + */ + @Override + public int hashCode() { + return number; + } + + /** * Categorizes a set of registers by {@link RegisterFlag}. * * @param registers a list of registers to be categorized diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/DeoptimizationReason.java Mon Apr 22 16:40:54 2013 +0200 @@ -25,7 +25,6 @@ /** * Enumeration of reasons for why a deoptimization is happening. */ -// @formatter:off public enum DeoptimizationReason { None, NullCheckException, diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java --- a/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.api.replacements/src/com/oracle/graal/api/replacements/MethodSubstitution.java Mon Apr 22 16:40:54 2013 +0200 @@ -59,7 +59,7 @@ * Determines if this method should be substituted in all cases, even if inlining thinks it is * not important. * - * Not that this is still depending on whether inlining sees the correct call target, so it's + * Note that this is still depending on whether inlining sees the correct call target, so it's * only a hard guarantee for static and special invocations. */ boolean forced() default false; diff -r 76a6e7907b67 -r 7e3c7d55d538 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 Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Mon Apr 22 16:40:54 2013 +0200 @@ -156,23 +156,15 @@ append(createMove(dst, src)); } - private AMD64AddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + private AMD64AddressValue prepareAddress(Kind kind, Value base, long displacement, Value index, int scale) { AllocatableValue baseRegister; - int finalDisp = displacement; + long finalDisp = displacement; if (isConstant(base)) { if (asConstant(base).isNull()) { baseRegister = AllocatableValue.UNUSED; - } else if (asConstant(base).getKind() != Kind.Object) { - long newDisplacement = displacement + asConstant(base).asLong(); - if (NumUtil.isInt(newDisplacement)) { - assert !runtime.needsDataPatch(asConstant(base)); - finalDisp = (int) newDisplacement; - baseRegister = AllocatableValue.UNUSED; - } else { - Variable newBase = newVariable(Kind.Long); - emitMove(newBase, base); - baseRegister = newBase; - } + } else if (asConstant(base).getKind() != Kind.Object && !runtime.needsDataPatch(asConstant(base))) { + finalDisp += asConstant(base).asLong(); + baseRegister = AllocatableValue.UNUSED; } else { baseRegister = load(base); } @@ -187,19 +179,8 @@ if (index != Value.ILLEGAL && scale != 0) { scaleEnum = Scale.fromInt(scale); if (isConstant(index)) { - long newDisplacement = finalDisp + asConstant(index).asLong() * scale; - // only use the constant index if the resulting displacement fits into a 32 bit - // offset - if (NumUtil.isInt(newDisplacement)) { - finalDisp = (int) newDisplacement; - indexRegister = AllocatableValue.UNUSED; - } else { - // create a temporary variable for the index, the pointer load cannot handle a - // constant index - Variable newIndex = newVariable(Kind.Long); - emitMove(newIndex, index); - indexRegister = newIndex; - } + finalDisp += asConstant(index).asLong() * scale; + indexRegister = AllocatableValue.UNUSED; } else { indexRegister = asAllocatable(index); } @@ -208,11 +189,27 @@ scaleEnum = Scale.Times1; } - return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, finalDisp); + int displacementInt; + if (NumUtil.isInt(finalDisp)) { + displacementInt = (int) finalDisp; + } else { + displacementInt = 0; + AllocatableValue displacementRegister = load(Constant.forLong(finalDisp)); + if (baseRegister == AllocatableValue.UNUSED) { + baseRegister = displacementRegister; + } else if (indexRegister == AllocatableValue.UNUSED) { + indexRegister = displacementRegister; + scaleEnum = Scale.Times1; + } else { + baseRegister = emitAdd(baseRegister, displacementRegister); + } + } + + return new AMD64AddressValue(kind, baseRegister, indexRegister, scaleEnum, displacementInt); } @Override - public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) { + public Variable emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting) { AMD64AddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null)); @@ -220,7 +217,7 @@ } @Override - public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { + public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { AMD64AddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); LIRFrameState state = deopting != null ? state(deopting) : null; @@ -237,7 +234,7 @@ } @Override - public Variable emitLea(Value base, int displacement, Value index, int scale) { + public Variable emitLea(Value base, long displacement, Value index, int scale) { Variable result = newVariable(target().wordKind); AMD64AddressValue address = prepareAddress(result.getKind(), base, displacement, index, scale); append(new LeaOp(result, address)); diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java --- a/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.compiler.ptx/src/com/oracle/graal/compiler/ptx/PTXLIRGenerator.java Mon Apr 22 16:40:54 2013 +0200 @@ -137,7 +137,7 @@ } } - private PTXAddressValue prepareAddress(Kind kind, Value base, int displacement, Value index, int scale) { + private PTXAddressValue prepareAddress(Kind kind, Value base, long displacement, Value index, int scale) { AllocatableValue baseRegister; long finalDisp = displacement; if (isConstant(base)) { @@ -181,7 +181,7 @@ } @Override - public Variable emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting) { + public Variable emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting) { PTXAddressValue loadAddress = prepareAddress(kind, base, displacement, index, scale); Variable result = newVariable(loadAddress.getKind()); append(new LoadOp(result, loadAddress, deopting != null ? state(deopting) : null)); @@ -189,14 +189,14 @@ } @Override - public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { + public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value inputVal, DeoptimizingNode deopting) { PTXAddressValue storeAddress = prepareAddress(kind, base, displacement, index, scale); Variable input = load(inputVal); append(new StoreOp(storeAddress, input, deopting != null ? state(deopting) : null)); } @Override - public Variable emitLea(Value base, int displacement, Value index, int scale) { + public Variable emitLea(Value base, long displacement, Value index, int scale) { throw new InternalError("NYI"); } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Mon Apr 22 16:40:54 2013 +0200 @@ -214,19 +214,19 @@ } @Override - public Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode canTrap) { + public Value emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode canTrap) { // SPARC: Auto-generated method stub return null; } @Override - public void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) { + public void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value input, DeoptimizingNode canTrap) { // SPARC: Auto-generated method stub } @Override - public Value emitLea(Value base, int displacement, Value index, int scale) { + public Value emitLea(Value base, long displacement, Value index, int scale) { // SPARC: Auto-generated method stub return null; } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/Debug.java Mon Apr 22 16:40:54 2013 +0200 @@ -76,9 +76,26 @@ return callable; } - public static void sandbox(String name, Runnable runnable) { + public static void sandbox(String name, DebugConfig config, Runnable runnable) { if (ENABLED) { - DebugScope.getInstance().scope(name, runnable, null, true, new Object[0]); + DebugScope.getInstance().scope(name, runnable, null, true, config, new Object[0]); + } else { + runnable.run(); + } + } + + /** + * Creates a new debug scope that is unrelated to the current scope and runs a given task in the + * new scope. + * + * @param name new scope name + * @param context the context objects of the new scope + * @param config the debug configuration to use for the new scope + * @param runnable the task to run in the new scope + */ + public static void sandbox(String name, Object[] context, DebugConfig config, Runnable runnable) { + if (ENABLED) { + DebugScope.getInstance().scope(name, runnable, null, true, config, context); } else { runnable.run(); } @@ -98,7 +115,7 @@ public static void scope(String name, Object[] context, Runnable runnable) { if (ENABLED) { - DebugScope.getInstance().scope(name, runnable, null, false, context); + DebugScope.getInstance().scope(name, runnable, null, false, null, context); } else { runnable.run(); } @@ -118,7 +135,7 @@ public static T scope(String name, Object[] context, Callable callable) { if (ENABLED) { - return DebugScope.getInstance().scope(name, null, callable, false, context); + return DebugScope.getInstance().scope(name, null, callable, false, null, context); } else { return DebugScope.call(callable); } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java --- a/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.debug/src/com/oracle/graal/debug/internal/DebugScope.java Mon Apr 22 16:40:54 2013 +0200 @@ -138,13 +138,26 @@ } } - public T scope(String newName, Runnable runnable, Callable callable, boolean sandbox, Object[] newContext) { + /** + * Runs a task in a new debug scope which is either a child of the current scope or a disjoint + * top level scope. + * + * @param newName the name of the new scope + * @param runnable the task to run (must be null iff {@code callable} is not null) + * @param callable the task to run (must be null iff {@code runnable} is not null) + * @param sandbox specifies if the scope is a child of the current scope or a top level scope + * @param sandboxConfig the config to use of a new top level scope (ignored if + * {@code sandbox == false}) + * @param newContext context objects of the new scope + * @return the value returned by the task + */ + public T scope(String newName, Runnable runnable, Callable callable, boolean sandbox, DebugConfig sandboxConfig, Object[] newContext) { DebugScope oldContext = getInstance(); DebugConfig oldConfig = getConfig(); DebugScope newChild = null; if (sandbox) { newChild = new DebugScope(newName, newName, null, newContext); - setConfig(null); + setConfig(sandboxConfig); } else { newChild = oldContext.createChild(newName, newContext); } @@ -215,7 +228,7 @@ return new RuntimeException("Exception while intercepting exception", t); } } - }, false, new Object[]{e}); + }, false, null, new Object[]{e}); } return null; } diff -r 76a6e7907b67 -r 7e3c7d55d538 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 Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Apr 22 16:40:54 2013 +0200 @@ -28,6 +28,7 @@ import static com.oracle.graal.phases.GraalOptions.*; import java.lang.reflect.*; +import java.util.*; import sun.misc.*; @@ -42,10 +43,13 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.cfg.*; import com.oracle.graal.phases.*; /** @@ -154,6 +158,30 @@ if (deoptimizationRescueSlot != null) { tasm.compilationResult.setCustomStackAreaOffset(frameMap.offsetForStackSlot(deoptimizationRescueSlot)); } + + Stub stub = runtime().asStub(lirGen.method()); + if (stub != null) { + final Set definedRegisters = new HashSet<>(); + ValueProcedure defProc = new ValueProcedure() { + + @Override + public Value doValue(Value value) { + if (ValueUtil.isRegister(value)) { + final Register reg = ValueUtil.asRegister(value); + definedRegisters.add(reg); + } + return value; + } + }; + for (Block block : lir.codeEmittingOrder()) { + for (LIRInstruction op : lir.lir(block)) { + op.forEachTemp(defProc); + op.forEachOutput(defProc); + } + } + stub.initDefinedRegisters(definedRegisters); + } + return tasm; } diff -r 76a6e7907b67 -r 7e3c7d55d538 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 Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Mon Apr 22 16:40:54 2013 +0200 @@ -105,8 +105,7 @@ /* arg0: object */ javaCallingConvention(Kind.Object, /* arg1: lock */ word)); - addRuntimeCall(NEW_ARRAY, 0L, - /* temps */ null, + addStubCall(NEW_ARRAY, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); @@ -117,8 +116,7 @@ /* arg0: hub */ rdx.asValue(word), /* arg1: length */ rbx.asValue(Kind.Int)); - addRuntimeCall(NEW_INSTANCE, 0L, - /* temps */ null, + addStubCall(NEW_INSTANCE, /* ret */ rax.asValue(Kind.Object), /* arg0: hub */ rdx.asValue(word)); diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotRuntimeCallTarget.java Mon Apr 22 16:40:54 2013 +0200 @@ -22,6 +22,8 @@ */ package com.oracle.graal.hotspot; +import java.util.*; + import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.target.*; @@ -51,7 +53,7 @@ /** * Where the stub gets its arguments and where it places its result. */ - public final CallingConvention cc; + private CallingConvention cc; private final CompilerToVM vm; @@ -87,12 +89,28 @@ public void finalizeAddress(Backend backend) { if (address == 0) { assert stub != null : "linkage without an address must be a stub"; - address = stub.getAddress(backend); + InstalledCode code = stub.getCode(backend); + + Value[] argumentLocations = new Value[cc.getArgumentCount()]; + for (int i = 0; i < argumentLocations.length; i++) { + argumentLocations[i] = cc.getArgument(i); + } + + Set definedRegisters = stub.getDefinedRegisters(); + Value[] temporaryLocations = new Value[definedRegisters.size()]; + int i = 0; + for (Register reg : definedRegisters) { + temporaryLocations[i++] = reg.asValue(); + } + // Update calling convention with temporaries + cc = new CallingConvention(temporaryLocations, cc.getStackSize(), cc.getReturn(), argumentLocations); + address = code.getStart(); } } @Override public boolean preservesRegisters() { - return stub == null; + assert address != 0; + return true; } } diff -r 76a6e7907b67 -r 7e3c7d55d538 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 Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Mon Apr 22 16:40:54 2013 +0200 @@ -271,6 +271,17 @@ } /** + * Registers the details for linking a call to a compiled {@link Stub}. + * + * @param descriptor name and signature of the call + * @param ret where the call returns its result + * @param args where arguments are passed to the call + */ + protected RuntimeCallTarget addStubCall(Descriptor descriptor, Value ret, Value... args) { + return addRuntimeCall(descriptor, 0L, null, ret, args); + } + + /** * Registers the details for linking a runtime call. * * @param descriptor name and signature of the call @@ -496,7 +507,7 @@ if (n instanceof ArrayLengthNode) { ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; ValueNode array = arrayLengthNode.array(); - ReadNode arrayLengthRead = graph.add(new ReadNode(array, LocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt())); + ReadNode arrayLengthRead = graph.add(new ReadNode(array, ConstantLocationNode.create(LocationNode.FINAL_LOCATION, Kind.Int, config.arrayLengthOffset, graph), StampFactory.positiveInt())); arrayLengthRead.dependencies().add(tool.createNullCheckGuard(array)); graph.replaceFixedWithFixed(arrayLengthNode, arrayLengthRead); } else if (n instanceof Invoke) { @@ -522,8 +533,9 @@ // as HotSpot does not guarantee they are final values. assert vtableEntryOffset > 0; LoadHubNode hub = graph.add(new LoadHubNode(receiver, wordKind)); - ReadNode metaspaceMethod = graph.add(new ReadNode(hub, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), StampFactory.forKind(wordKind()))); - ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, LocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), + ReadNode metaspaceMethod = graph.add(new ReadNode(hub, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, vtableEntryOffset, graph), + StampFactory.forKind(wordKind()))); + ReadNode compiledEntry = graph.add(new ReadNode(metaspaceMethod, ConstantLocationNode.create(LocationNode.ANY_LOCATION, wordKind, config.methodCompiledEntryOffset, graph), StampFactory.forKind(wordKind()))); loweredCallTarget = graph.add(new HotSpotIndirectCallTargetNode(metaspaceMethod, compiledEntry, parameters, invoke.asNode().stamp(), signature, callTarget.targetMethod(), @@ -547,7 +559,7 @@ HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) loadField.field(); ValueNode object = loadField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : loadField.object(); assert loadField.kind() != Kind.Illegal; - ReadNode memoryRead = graph.add(new ReadNode(object, LocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp())); + ReadNode memoryRead = graph.add(new ReadNode(object, ConstantLocationNode.create(field, field.getKind(), field.offset(), graph), loadField.stamp())); memoryRead.dependencies().add(tool.createNullCheckGuard(object)); graph.replaceFixedWithFixed(loadField, memoryRead); @@ -562,7 +574,7 @@ StoreFieldNode storeField = (StoreFieldNode) n; HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) storeField.field(); ValueNode object = storeField.isStatic() ? ConstantNode.forObject(field.getDeclaringClass().mirror(), this, graph) : storeField.object(); - LocationNode location = LocationNode.create(field, field.getKind(), field.offset(), graph); + LocationNode location = ConstantLocationNode.create(field, field.getKind(), field.offset(), graph); WriteBarrierType barrierType = getFieldStoreBarrierType(storeField); WriteNode memoryWrite = graph.add(new WriteNode(object, storeField.value(), location, barrierType)); memoryWrite.dependencies().add(tool.createNullCheckGuard(object)); @@ -610,7 +622,7 @@ } } else { LoadHubNode arrayClass = graph.add(new LoadHubNode(array, wordKind)); - LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); + LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.arrayClassElementOffset, graph); FloatingReadNode arrayElementKlass = graph.unique(new FloatingReadNode(arrayClass, location, null, StampFactory.forKind(wordKind()))); CheckCastDynamicNode checkcast = graph.add(new CheckCastDynamicNode(arrayElementKlass, value)); graph.addBeforeFixed(storeIndexed, checkcast); @@ -645,7 +657,7 @@ } else if (n instanceof LoadHubNode) { LoadHubNode loadHub = (LoadHubNode) n; assert loadHub.kind() == wordKind; - LocationNode location = LocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph); + LocationNode location = ConstantLocationNode.create(LocationNode.FINAL_LOCATION, wordKind, config.hubOffset, graph); ValueNode object = loadHub.object(); assert !object.isConstant() || object.asConstant().isNull(); ValueNode guard = tool.createNullCheckGuard(object); diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/Stub.java Mon Apr 22 16:40:54 2013 +0200 @@ -22,6 +22,7 @@ */ package com.oracle.graal.hotspot.stubs; +import java.util.*; import java.util.concurrent.*; import com.oracle.graal.api.code.*; @@ -29,6 +30,7 @@ import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.debug.*; +import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.java.*; @@ -64,11 +66,26 @@ /** * The code installed for the stub. */ - protected InstalledCode stubCode; + protected InstalledCode code; /** - * Creates a new stub container. The new stub still needs to be - * {@linkplain #getAddress(Backend) installed}. + * The registers defined by this stub. + */ + private Set definedRegisters; + + public void initDefinedRegisters(Set registers) { + assert registers != null; + assert definedRegisters == null : "cannot redefine"; + definedRegisters = registers; + } + + public Set getDefinedRegisters() { + assert definedRegisters != null : "not yet initialized"; + return definedRegisters; + } + + /** + * Creates a new stub container.. * * @param linkage linkage details for a call to the stub */ @@ -100,37 +117,43 @@ } /** - * Ensures the code for this stub is installed. - * - * @return the entry point address for calls to this stub + * Gets the code for this stub, compiling it first if necessary. */ - public synchronized long getAddress(Backend backend) { - if (stubCode == null) { - Arguments args = makeArguments(stubInfo); - SnippetTemplate template = template(args); - StructuredGraph 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 = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, OptimisticOptimizations.ALL, - new SpeculationLog()); - - stubCode = Debug.scope("CodeInstall", new Object[]{runtime(), getMethod()}, new Callable() { + public synchronized InstalledCode getCode(final Backend backend) { + if (code == null) { + Debug.sandbox("CompilingStub", new Object[]{runtime(), getMethod()}, DebugScope.getConfig(), new Runnable() { @Override - public InstalledCode call() { - InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); - assert installedCode != null : "error installing stub " + getMethod(); - if (Debug.isDumpEnabled()) { - Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); - } - return installedCode; + public void run() { + + Arguments args = makeArguments(stubInfo); + SnippetTemplate template = template(args); + StructuredGraph 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 = GraalCompiler.compileMethod(runtime(), replacements, backend, runtime().getTarget(), getMethod(), graph, null, phasePlan, + OptimisticOptimizations.ALL, new SpeculationLog()); + + assert definedRegisters != null; + code = Debug.scope("CodeInstall", new Callable() { + + @Override + public InstalledCode call() { + InstalledCode installedCode = runtime().addMethod(getMethod(), compResult); + assert installedCode != null : "error installing stub " + getMethod(); + if (Debug.isDumpEnabled()) { + Debug.dump(new Object[]{compResult, installedCode}, "After code installation"); + } + return installedCode; + } + }); + } }); - - assert stubCode != null : "error installing stub " + getMethod(); + assert code != null : "error installing stub " + getMethod(); } - return stubCode.getStart(); + return code; } } diff -r 76a6e7907b67 -r 7e3c7d55d538 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 Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Mon Apr 22 16:40:54 2013 +0200 @@ -285,7 +285,7 @@ ValueNode value; if (kind == Kind.Object) { value = frameState.xpop(); - // astore and astore_ may be used to store a returnAddress (jsr) see JVMS par. 6.5.astore + // astore and astore_ may be used to store a returnAddress (jsr) assert value.kind() == Kind.Object || value.kind() == Kind.Int; } else { value = frameState.pop(kind); @@ -1169,7 +1169,7 @@ createInvokeNode(callTarget, resultType); } - protected Invoke createInvokeNode(MethodCallTargetNode callTarget, Kind resultType) { + protected Invoke createInvokeNode(CallTargetNode callTarget, Kind resultType) { // be conservative if information was not recorded (could result in endless recompiles // otherwise) if (graphBuilderConfig.omitAllExceptionEdges() || (optimisticOpts.useExceptionProbability() && profilingInfo.getExceptionSeen(bci()) == TriState.FALSE)) { diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java --- a/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.jtt/src/com/oracle/graal/jtt/hotpath/HP_idea.java Mon Apr 22 16:40:54 2013 +0200 @@ -29,7 +29,6 @@ import com.oracle.graal.jtt.*; import org.junit.*; -//@formatter:off public class HP_idea extends JTTTest { public boolean test() { @@ -60,7 +59,7 @@ /* * buildTestData - * + * * Builds the data used for the test -- each time the test is run. */ @@ -115,10 +114,11 @@ /* * calcEncryptKey - * - * Builds the 52 16-bit encryption subkeys Z[] from the user key and stores in 32-bit int array. The routing - * corrects an error in the source code in the Schnier book. Basically, the sense of the 7- and 9-bit shifts are - * reversed. It still works reversed, but would encrypted code would not decrypt with someone else's IDEA code. + * + * Builds the 52 16-bit encryption subkeys Z[] from the user key and stores in 32-bit int array. + * The routing corrects an error in the source code in the Schnier book. Basically, the sense of + * the 7- and 9-bit shifts are reversed. It still works reversed, but would encrypted code would + * not decrypt with someone else's IDEA code. */ private void calcEncryptKey() { @@ -168,9 +168,9 @@ /* * calcDecryptKey - * - * Builds the 52 16-bit encryption subkeys DK[] from the encryption- subkeys Z[]. DK[] is a 32-bit int array holding - * 16-bit values as unsigned. + * + * Builds the 52 16-bit encryption subkeys DK[] from the encryption- subkeys Z[]. DK[] is a + * 32-bit int array holding 16-bit values as unsigned. */ private void calcDecryptKey() { @@ -215,12 +215,14 @@ /* * cipher_idea - * - * IDEA encryption/decryption algorithm. It processes plaintext in 64-bit blocks, one at a time, breaking the block - * into four 16-bit unsigned subblocks. It goes through eight rounds of processing using 6 new subkeys each time, - * plus four for last step. The source text is in array text1, the destination text goes into array text2 The - * routine represents 16-bit subblocks and subkeys as type int so that they can be treated more easily as unsigned. - * Multiplication modulo 0x10001 interprets a zero sub-block as 0x10000; it must to fit in 16 bits. + * + * IDEA encryption/decryption algorithm. It processes plaintext in 64-bit blocks, one at a time, + * breaking the block into four 16-bit unsigned subblocks. It goes through eight rounds of + * processing using 6 new subkeys each time, plus four for last step. The source text is in + * array text1, the destination text goes into array text2 The routine represents 16-bit + * subblocks and subkeys as type int so that they can be treated more easily as unsigned. + * Multiplication modulo 0x10001 interprets a zero sub-block as 0x10000; it must to fit in 16 + * bits. */ @SuppressWarnings("static-method") @@ -356,35 +358,40 @@ /* * mul - * - * Performs multiplication, modulo (2**16)+1. This code is structured on the assumption that untaken branches are - * cheaper than taken branches, and that the compiler doesn't schedule branches. Java: Must work with 32-bit int and - * one 64-bit long to keep 16-bit values and their products "unsigned." The routine assumes that both a and b could - * fit in 16 bits even though they come in as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit. - * Also, because the routine stores mod (2**16)+1 results in a 2**16 space, the result is truncated to zero whenever - * the result would zero, be 2**16. And if one of the multiplicands is 0, the result is not zero, but (2**16) + 1 - * minus the other multiplicand (sort of an additive inverse mod 0x10001). - * - * NOTE: The java conversion of this routine works correctly, but is half the speed of using Java's modulus division - * function (%) on the multiplication with a 16-bit masking of the result--running in the Symantec Caje IDE. So it's - * not called for now; the test uses Java % instead. + * + * Performs multiplication, modulo (2**16)+1. This code is structured on the assumption that + * untaken branches are cheaper than taken branches, and that the compiler doesn't schedule + * branches. Java: Must work with 32-bit int and one 64-bit long to keep 16-bit values and their + * products "unsigned." The routine assumes that both a and b could fit in 16 bits even though + * they come in as 32-bit ints. Lots of "& 0xFFFF" masks here to keep things 16-bit. Also, + * because the routine stores mod (2**16)+1 results in a 2**16 space, the result is truncated to + * zero whenever the result would zero, be 2**16. And if one of the multiplicands is 0, the + * result is not zero, but (2**16) + 1 minus the other multiplicand (sort of an additive inverse + * mod 0x10001). + * + * NOTE: The java conversion of this routine works correctly, but is half the speed of using + * Java's modulus division function (%) on the multiplication with a 16-bit masking of the + * result--running in the Symantec Caje IDE. So it's not called for now; the test uses Java % + * instead. */ /* - * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch 16-bit multiply // - * without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b = (int) p & 0xFFFF; // Lower 16 bits. a - * = (int) p >>> 16; // Upper 16 bits. - * - * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0, then same as // 0x10001 - * - a. } else // If a = 0, then return return((1 - b) & 0xFFFF); // same as 0x10001 - b. } + * private int mul(int a, int b) throws ArithmeticException { long p; // Large enough to catch + * 16-bit multiply // without hitting sign bit. if (a != 0) { if (b != 0) { p = (long) a * b; b + * = (int) p & 0xFFFF; // Lower 16 bits. a = (int) p >>> 16; // Upper 16 bits. + * + * return (b - a + (b < a ? 1 : 0) & 0xFFFF); } else return ((1 - a) & 0xFFFF); // If b = 0, + * then same as // 0x10001 - a. } else // If a = 0, then return return((1 - b) & 0xFFFF); // + * same as 0x10001 - b. } */ /* * inv - * - * Compute multiplicative inverse of x, modulo (2**16)+1 using extended Euclid's GCD (greatest common divisor) - * algorithm. It is unrolled twice to avoid swapping the meaning of the registers. And some subtracts are changed to - * adds. Java: Though it uses signed 32-bit ints, the interpretation of the bits within is strictly unsigned 16-bit. + * + * Compute multiplicative inverse of x, modulo (2**16)+1 using extended Euclid's GCD (greatest + * common divisor) algorithm. It is unrolled twice to avoid swapping the meaning of the + * registers. And some subtracts are changed to adds. Java: Though it uses signed 32-bit ints, + * the interpretation of the bits within is strictly unsigned 16-bit. */ @SuppressWarnings("static-method") @@ -432,7 +439,7 @@ /* * freeTestData - * + * * Nulls arrays and forces garbage collection to free up memory. */ diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.nodes.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Location node that is the sum of two other location nodes. Can represent locations in the form of + * [(base + x) + y] where base is a node and x and y are location nodes. + */ +@NodeInfo(nameTemplate = "AddLoc {p#locationIdentity/s}") +public final class AddLocationNode extends LocationNode implements Canonicalizable { + + @Input private ValueNode x; + @Input private ValueNode y; + + public LocationNode getX() { + return (LocationNode) x; + } + + public LocationNode getY() { + return (LocationNode) y; + } + + public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) { + assert x.getValueKind().equals(y.getValueKind()) && x.locationIdentity() == y.locationIdentity(); + return graph.unique(new AddLocationNode(x, y)); + } + + private AddLocationNode(LocationNode x, LocationNode y) { + super(x.locationIdentity(), x.getValueKind()); + this.x = x; + this.y = y; + } + + @Override + protected LocationNode addDisplacement(long displacement) { + LocationNode added = getX().addDisplacement(displacement); + return graph().unique(new AddLocationNode(added, getY())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool) { + if (x instanceof ConstantLocationNode) { + return getY().addDisplacement(((ConstantLocationNode) x).displacement()); + } + if (y instanceof ConstantLocationNode) { + return getX().addDisplacement(((ConstantLocationNode) y).displacement()); + } + + if (x instanceof IndexedLocationNode && y instanceof IndexedLocationNode) { + IndexedLocationNode xIdx = (IndexedLocationNode) x; + IndexedLocationNode yIdx = (IndexedLocationNode) y; + if (xIdx.indexScaling() == yIdx.indexScaling()) { + long displacement = xIdx.displacement() + yIdx.displacement(); + ValueNode index = IntegerArithmeticNode.add(xIdx.index(), yIdx.index()); + return IndexedLocationNode.create(locationIdentity(), getValueKind(), displacement, index, graph(), xIdx.indexScaling()); + } + } + + return this; + } + + @Override + public Value generateLea(LIRGeneratorTool gen, Value base) { + Value xAddr = getX().generateLea(gen, base); + return getY().generateLea(gen, xAddr); + } + + @Override + public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) { + Value xAddr = getX().generateLea(gen, base); + return getY().generateLoad(gen, xAddr, deopting); + } + + @Override + public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) { + Value xAddr = getX().generateLea(gen, base); + getY().generateStore(gen, xAddr, value, deopting); + } +} diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ComputeAddressNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -49,7 +49,7 @@ @Override public void generate(LIRGeneratorTool gen) { - Value addr = getLocation().generateLea(gen, getObject()); + Value addr = getLocation().generateLea(gen, gen.operand(getObject())); gen.setResult(this, addr); } } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2011, 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.nodes.extended; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +/** + * Location node that has a constant displacement. Can represent addresses of the form [base + disp] + * where base is a node and disp is a constant. + */ +@NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") +public class ConstantLocationNode extends LocationNode { + + private final long displacement; + + public long displacement() { + return displacement; + } + + public static ConstantLocationNode create(Object identity, Kind kind, long displacement, Graph graph) { + return graph.unique(new ConstantLocationNode(identity, kind, displacement)); + } + + protected ConstantLocationNode(Object identity, Kind kind, long displacement) { + super(identity, kind); + this.displacement = displacement; + } + + @Override + protected ConstantLocationNode addDisplacement(long x) { + return create(locationIdentity(), getValueKind(), displacement + x, graph()); + } + + @Override + public Value generateLea(LIRGeneratorTool gen, Value base) { + return gen.emitLea(base, displacement(), Value.ILLEGAL, 0); + } + + @Override + public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) { + return gen.emitLoad(getValueKind(), base, displacement(), Value.ILLEGAL, 0, deopting); + } + + @Override + public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) { + gen.emitStore(getValueKind(), base, displacement(), Value.ILLEGAL, 0, value, deopting); + } +} diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/FloatingReadNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -53,7 +53,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, location().generateLoad(gen, object(), this)); + gen.setResult(this, location().generateLoad(gen, gen.operand(object()), this)); } @Override diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -28,13 +28,15 @@ import com.oracle.graal.nodes.spi.*; /** - * Extension of a {@linkplain LocationNode location} to include a scaled index. Can represent - * locations in the form of [base + index * scale + disp] where base and index are nodes and scale - * and disp are integer constants. + * Location node that has a displacement and a scaled index. Can represent locations in the form of + * [base + index * scale + disp] where base and index are nodes and scale and disp are integer + * constants. */ +@NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}") public final class IndexedLocationNode extends LocationNode implements Canonicalizable { @Input private ValueNode index; + private final long displacement; private final int indexScaling; /** @@ -44,8 +46,8 @@ return index; } - public static Object getArrayLocation(Kind elementKind) { - return elementKind; + public long displacement() { + return displacement; } /** @@ -55,43 +57,46 @@ return indexScaling; } - public static IndexedLocationNode create(Object identity, Kind kind, int displacement, ValueNode index, Graph graph, int indexScaling) { + public static IndexedLocationNode create(Object identity, Kind kind, long displacement, ValueNode index, Graph graph, int indexScaling) { return graph.unique(new IndexedLocationNode(identity, kind, index, displacement, indexScaling)); } - private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int displacement, int indexScaling) { - super(identity, kind, displacement); + private IndexedLocationNode(Object identity, Kind kind, ValueNode index, long displacement, int indexScaling) { + super(identity, kind); this.index = index; + this.displacement = displacement; this.indexScaling = indexScaling; } @Override + protected LocationNode addDisplacement(long x) { + return create(locationIdentity(), getValueKind(), displacement + x, index, graph(), indexScaling); + } + + @Override public ValueNode canonical(CanonicalizerTool tool) { Constant constantIndex = index.asConstant(); if (constantIndex != null) { long constantIndexLong = constantIndex.asLong(); constantIndexLong *= indexScaling; - constantIndexLong += displacement(); - int constantIndexInt = (int) constantIndexLong; - if (constantIndexLong == constantIndexInt) { - return LocationNode.create(locationIdentity(), getValueKind(), constantIndexInt, graph()); - } + constantIndexLong += displacement; + return ConstantLocationNode.create(locationIdentity(), getValueKind(), constantIndexLong, graph()); } return this; } @Override - public Value generateLea(LIRGeneratorTool gen, ValueNode base) { - return gen.emitLea(gen.operand(base), displacement(), gen.operand(index()), indexScaling()); + public Value generateLea(LIRGeneratorTool gen, Value base) { + return gen.emitLea(base, displacement, gen.operand(index()), indexScaling()); } @Override - public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) { - return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), deopting); + public Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting) { + return gen.emitLoad(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), deopting); } @Override - public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) { - gen.emitStore(getValueKind(), gen.operand(base), displacement(), gen.operand(index()), indexScaling(), gen.operand(value), deopting); + public void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting) { + gen.emitStore(getValueKind(), base, displacement, gen.operand(index()), indexScaling(), value, deopting); } } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -23,7 +23,6 @@ package com.oracle.graal.nodes.extended; import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; import com.oracle.graal.graph.Node.ValueNumberable; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; @@ -31,20 +30,18 @@ import com.oracle.graal.nodes.type.*; /** - * A location for a memory access in terms of the kind of value accessed and how to access it. The - * base version can represent addresses of the form [base + disp] where base is a node and disp is a - * constant. + * A location for a memory access in terms of the kind of value accessed and how to access it. + * All locations have the form [base + location], where base is a node and location is defined + * by subclasses of the {@link LocationNode}. */ -@NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}") -public class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { +public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable { - private int displacement; private Kind valueKind; private Object locationIdentity; /** * Creates a new unique location identity for read and write operations. - * + * * @param name the name of the new location identity, for debugging purposes * @return the new location identity */ @@ -74,18 +71,9 @@ return elementKind; } - public int displacement() { - return displacement; - } - - public static LocationNode create(Object identity, Kind kind, int displacement, Graph graph) { - return graph.unique(new LocationNode(identity, kind, displacement)); - } - - protected LocationNode(Object identity, Kind kind, int displacement) { + protected LocationNode(Object identity, Kind kind) { super(StampFactory.extension()); assert kind != Kind.Illegal && kind != Kind.Void; - this.displacement = displacement; this.valueKind = kind; this.locationIdentity = identity; } @@ -98,20 +86,16 @@ return locationIdentity; } + protected abstract LocationNode addDisplacement(long displacement); + @Override public void generate(LIRGeneratorTool generator) { // nothing to do... } - public Value generateLea(LIRGeneratorTool gen, ValueNode base) { - return gen.emitLea(gen.operand(base), displacement(), Value.ILLEGAL, 0); - } + public abstract Value generateLea(LIRGeneratorTool gen, Value base); - public Value generateLoad(LIRGeneratorTool gen, ValueNode base, DeoptimizingNode deopting) { - return gen.emitLoad(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, deopting); - } + public abstract Value generateLoad(LIRGeneratorTool gen, Value base, DeoptimizingNode deopting); - public void generateStore(LIRGeneratorTool gen, ValueNode base, ValueNode value, DeoptimizingNode deopting) { - gen.emitStore(getValueKind(), gen.operand(base), displacement(), Value.ILLEGAL, 0, gen.operand(value), deopting); - } + public abstract void generateStore(LIRGeneratorTool gen, Value base, Value value, DeoptimizingNode deopting); } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ReadNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -44,7 +44,7 @@ } private ReadNode(ValueNode object, int displacement, Object locationIdentity, Kind kind) { - super(object, object.graph().add(new LocationNode(locationIdentity, kind, displacement)), StampFactory.forKind(kind)); + super(object, ConstantLocationNode.create(locationIdentity, kind, displacement, object.graph()), StampFactory.forKind(kind)); } private ReadNode(ValueNode object, ValueNode location, ValueNode dependency) { @@ -57,7 +57,7 @@ @Override public void generate(LIRGeneratorTool gen) { - gen.setResult(this, location().generateLoad(gen, object(), this)); + gen.setResult(this, location().generateLoad(gen, gen.operand(object()), this)); } @Override @@ -73,8 +73,8 @@ public static ValueNode canonicalizeRead(ValueNode read, LocationNode location, ValueNode object, CanonicalizerTool tool) { MetaAccessProvider runtime = tool.runtime(); if (runtime != null && object != null && object.isConstant()) { - if (location.locationIdentity() == LocationNode.FINAL_LOCATION && location.getClass() == LocationNode.class) { - long displacement = location.displacement(); + if (location.locationIdentity() == LocationNode.FINAL_LOCATION && location instanceof ConstantLocationNode) { + long displacement = ((ConstantLocationNode) location).displacement(); Kind kind = location.getValueKind(); if (object.kind() == Kind.Object) { Object base = object.asConstant().asObject(); diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/WriteNode.java Mon Apr 22 16:40:54 2013 +0200 @@ -84,7 +84,7 @@ @Override public void generate(LIRGeneratorTool gen) { - location().generateStore(gen, object(), value(), this); + location().generateStore(gen, gen.operand(object()), gen.operand(value()), this); } @NodeIntrinsic diff -r 76a6e7907b67 -r 7e3c7d55d538 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 Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/LIRGeneratorTool.java Mon Apr 22 16:40:54 2013 +0200 @@ -57,11 +57,11 @@ public abstract void emitMove(Value dst, Value src); - public abstract Value emitLoad(Kind kind, Value base, int displacement, Value index, int scale, DeoptimizingNode deopting); + public abstract Value emitLoad(Kind kind, Value base, long displacement, Value index, int scale, DeoptimizingNode deopting); - public abstract void emitStore(Kind kind, Value base, int displacement, Value index, int scale, Value input, DeoptimizingNode deopting); + public abstract void emitStore(Kind kind, Value base, long displacement, Value index, int scale, Value input, DeoptimizingNode deopting); - public abstract Value emitLea(Value base, int displacement, Value index, int scale); + public abstract Value emitLea(Value base, long displacement, Value index, int scale); public abstract Value emitLea(StackSlot slot); diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/spi/MacroSubstitution.java Mon Apr 22 16:40:54 2013 +0200 @@ -78,7 +78,7 @@ * Determines if this method should be substituted in all cases, even if inlining thinks it is * not important. * - * Not that this is still depending on whether inlining sees the correct call target, so it's + * Note that this is still depending on whether inlining sees the correct call target, so it's * only a hard guarantee for static and special invocations. */ boolean forced() default false; diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/GuardLoweringPhase.java Mon Apr 22 16:40:54 2013 +0200 @@ -218,6 +218,10 @@ } private boolean isImplicitNullCheck(LocationNode location) { - return !(location instanceof IndexedLocationNode) && location.displacement() < target.implicitNullCheckLimit; + if (location instanceof ConstantLocationNode) { + return ((ConstantLocationNode) location).displacement() < target.implicitNullCheckLimit; + } else { + return false; + } } } diff -r 76a6e7907b67 -r 7e3c7d55d538 graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java --- a/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Mon Apr 22 16:39:47 2013 +0200 +++ b/graal/com.oracle.graal.printer/src/com/oracle/graal/printer/GraphPrinterDumpHandler.java Mon Apr 22 16:40:54 2013 +0200 @@ -161,7 +161,7 @@ previousInlineContext = inlineContext; final SchedulePhase predefinedSchedule = getPredefinedSchedule(); - Debug.sandbox("PrintingGraph", new Runnable() { + Debug.sandbox("PrintingGraph", null, new Runnable() { @Override public void run() {