# HG changeset patch # User Thomas Wuerthinger # Date 1417981413 -3600 # Node ID e22a21b2703694397335d707352b772a8df8581c # Parent 02b5114b74c1331e9e32be42c2aebff4d1a34a0c# Parent 56f806632622a8c6650276504ae11d468f6f0ca2 Merge. diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/ReferenceMap.java Sun Dec 07 20:43:33 2014 +0100 @@ -25,12 +25,16 @@ import com.oracle.graal.api.code.CodeUtil.RefMapFormatter; import com.oracle.graal.api.meta.*; -public interface ReferenceMap { +public interface ReferenceMap extends Cloneable { void setRegister(int idx, LIRKind kind); + void clearRegister(int idx, LIRKind kind); + void setStackSlot(int offset, LIRKind kind); + void clearStackSlot(int offset, LIRKind kind); + boolean hasRegisterRefMap(); boolean hasFrameRefMap(); @@ -38,4 +42,11 @@ void appendRegisterMap(StringBuilder sb, RefMapFormatter formatterArg); void appendFrameMap(StringBuilder sb, RefMapFormatter formatterArg); + + ReferenceMap clone(); + + /** + * Updates this map with all references marked in {@code other}. + */ + void updateUnion(ReferenceMap other); } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java --- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Sun Dec 07 20:43:33 2014 +0100 @@ -158,13 +158,27 @@ } try (Scope s = Debug.scope("Allocator")) { - if (backend.shouldAllocateRegisters()) { LinearScan.allocate(target, lirGenRes); + } else if (!LocationMarker.Options.UseLocationMarker.getValue()) { + // build frame map for targets that do not allocate registers + lirGenRes.buildFrameMap(); } - } catch (Throwable e) { - throw Debug.handle(e); } + if (LocationMarker.Options.UseLocationMarker.getValue()) { + try (Scope s1 = Debug.scope("BuildFrameMap")) { + // build frame map + lirGenRes.buildFrameMap(); + Debug.dump(lir, "After FrameMap building"); + } + try (Scope s1 = Debug.scope("MarkLocations")) { + if (backend.shouldAllocateRegisters()) { + // currently we mark locations only if we do register allocation + LocationMarker.markLocations(lir, lirGenRes.getFrameMap()); + } + } + } + } catch (Throwable e) { throw Debug.handle(e); } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Sun Dec 07 20:43:33 2014 +0100 @@ -351,7 +351,7 @@ try (Scope s = Debug.scope("Allocator", nodeLirGen)) { if (backend.shouldAllocateRegisters()) { LinearScan.allocate(target, lirGenRes); - } else { + } else if (!LocationMarker.Options.UseLocationMarker.getValue()) { // build frame map for targets that do not allocate registers lirGenRes.buildFrameMap(); } @@ -359,6 +359,20 @@ throw Debug.handle(e); } + if (LocationMarker.Options.UseLocationMarker.getValue()) { + try (Scope s1 = Debug.scope("BuildFrameMap")) { + // build frame map + lirGenRes.buildFrameMap(); + Debug.dump(lir, "After FrameMap building"); + } + try (Scope s1 = Debug.scope("MarkLocations")) { + if (backend.shouldAllocateRegisters()) { + // currently we mark locations only if we do register allocation + LocationMarker.markLocations(lir, lirGenRes.getFrameMap()); + } + } + } + try (Scope s = Debug.scope("ControlFlowOptimizations")) { EdgeMoveOptimizer.optimize(lir); ControlFlowOptimizer.optimize(lir, codeEmittingOrder); diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Sun Dec 07 20:43:33 2014 +0100 @@ -1713,6 +1713,9 @@ * @see InstructionValueProcedure#doValue(LIRInstruction, Value, OperandMode, EnumSet) */ private Value debugInfoProcedure(LIRInstruction op, Value operand, OperandMode valueMode, EnumSet flags) { + if (isVirtualStackSlot(operand)) { + return operand; + } int tempOpId = op.id(); OperandMode mode = OperandMode.USE; AbstractBlock block = blockForId(tempOpId); @@ -1742,12 +1745,16 @@ } private void computeDebugInfo(IntervalWalker iw, final LIRInstruction op, LIRFrameState info) { - FrameMap frameMap = res.getFrameMap(); - info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !callKillsRegisters); - markFrameLocations(iw, op, info, frameMap); + if (!LocationMarker.Options.UseLocationMarker.getValue()) { + FrameMap frameMap = res.getFrameMap(); + info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !callKillsRegisters); + markFrameLocations(iw, op, info, frameMap); + } info.forEachState(op, this::debugInfoProcedure); - info.finish(op, frameMap); + if (!LocationMarker.Options.UseLocationMarker.getValue()) { + info.finish(op, res.getFrameMap()); + } } private void assignLocations(List instructions, final IntervalWalker iw) { @@ -1887,8 +1894,11 @@ // register interval mapper frameMapBuilder.requireMapping(new Mapper()); - // build frame map - res.buildFrameMap(); + + if (!LocationMarker.Options.UseLocationMarker.getValue()) { + // build frame map + res.buildFrameMap(); + } printLir("After FrameMap building", true); diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LocationMarker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LocationMarker.java Sun Dec 07 20:43:33 2014 +0100 @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2014, 2014, 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.compiler.alloc; + +import static com.oracle.graal.api.code.ValueUtil.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.LIRInstruction.OperandFlag; +import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.framemap.*; +import com.oracle.graal.options.*; + +public final class LocationMarker { + + public static class Options { + // @formatter:off + @Option(help = "Use decoupled pass for location marking (instead of using LSRA marking)") + public static final OptionValue UseLocationMarker = new OptionValue<>(true); + // @formatter:on + } + + /** + * Mark all live references for a frame state. The frame state use this information to build the + * OOP maps. + */ + public static void markLocations(LIR lir, FrameMap frameMap) { + new LocationMarker(lir, frameMap).build(); + } + + private final LIR lir; + private final FrameMap frameMap; + private final RegisterAttributes[] registerAttributes; + private final BlockMap liveInMap; + private final BlockMap liveOutMap; + + private LocationMarker(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + this.registerAttributes = frameMap.getRegisterConfig().getAttributesMap(); + liveInMap = new BlockMap<>(lir.getControlFlowGraph()); + liveOutMap = new BlockMap<>(lir.getControlFlowGraph()); + } + + private void build() { + Deque> worklist = new ArrayDeque<>(); + for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) { + worklist.add(lir.getControlFlowGraph().getBlocks().get(i)); + } + for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + liveInMap.put(block, frameMap.initReferenceMap(true)); + } + while (!worklist.isEmpty()) { + AbstractBlock block = worklist.poll(); + processBlock(block, worklist); + } + // finish states + for (AbstractBlock block : lir.getControlFlowGraph().getBlocks()) { + List instructions = lir.getLIRforBlock(block); + for (int i = instructions.size() - 1; i >= 0; i--) { + LIRInstruction inst = instructions.get(i); + inst.forEachState((op, info) -> info.finish(op, frameMap)); + } + + } + } + + /** + * Merge outSet with in-set of successors. + */ + private boolean updateOutBlock(AbstractBlock block) { + ReferenceMap union = frameMap.initReferenceMap(true); + block.getSuccessors().forEach(succ -> union.updateUnion(liveInMap.get(succ))); + ReferenceMap outSet = liveOutMap.get(block); + // check if changed + if (outSet == null || !union.equals(outSet)) { + liveOutMap.put(block, union); + return true; + } + return false; + } + + private void processBlock(AbstractBlock block, Deque> worklist) { + if (updateOutBlock(block)) { + try (Indent indent = Debug.logAndIndent("handle block %s", block)) { + BlockClosure closure = new BlockClosure(liveOutMap.get(block).clone()); + List instructions = lir.getLIRforBlock(block); + for (int i = instructions.size() - 1; i >= 0; i--) { + LIRInstruction inst = instructions.get(i); + closure.processInstructionBottomUp(inst); + } + liveInMap.put(block, closure.getCurrentSet()); + worklist.addAll(block.getPredecessors()); + } + } + } + + private static final EnumSet REGISTER_FLAG_SET = EnumSet.of(OperandFlag.REG); + private static final LIRKind REFERENCE_KIND = LIRKind.reference(Kind.Object); + + private void forEachDestroyedCallerSavedRegister(LIRInstruction op, ValueConsumer consumer) { + if (op.destroysCallerSavedRegisters()) { + for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { + consumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); + } + } + } + + private final class BlockClosure { + private final ReferenceMap currentSet; + + private BlockClosure(ReferenceMap set) { + currentSet = set; + } + + private ReferenceMap getCurrentSet() { + return currentSet; + } + + /** + * Process all values of an instruction bottom-up, i.e. definitions before usages. Values + * that start or end at the current operation are not included. + */ + private void processInstructionBottomUp(LIRInstruction op) { + try (Indent indent = Debug.logAndIndent("handle op %d, %s", op.id(), op)) { + // kills + op.visitEachTemp(this::defConsumer); + op.visitEachOutput(this::defConsumer); + forEachDestroyedCallerSavedRegister(op, this::defConsumer); + + // gen - values that are considered alive for this state + op.visitEachAlive(this::useConsumer); + op.visitEachState(this::useConsumer); + // mark locations + op.forEachState((inst, info) -> markLocation(inst, info, this.getCurrentSet())); + // gen + op.visitEachInput(this::useConsumer); + } + } + + /** + * @see InstructionValueConsumer + * @param operand + * @param mode + * @param flags + */ + private void useConsumer(Value operand, OperandMode mode, EnumSet flags) { + LIRKind kind = operand.getLIRKind(); + if (shouldProcessValue(operand) && !kind.isValue() && !kind.isDerivedReference()) { + // no need to insert values and derived reference + Debug.log("set operand: %s", operand); + frameMap.setReference(operand, currentSet); + } + } + + /** + * @see InstructionValueConsumer + * @param operand + * @param mode + * @param flags + */ + private void defConsumer(Value operand, OperandMode mode, EnumSet flags) { + if (shouldProcessValue(operand)) { + Debug.log("clear operand: %s", operand); + frameMap.clearReference(operand, currentSet); + } + } + + protected boolean shouldProcessValue(Value operand) { + return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getKind() != Kind.Illegal; + } + } + + /** + * This method does the actual marking. + */ + private void markLocation(LIRInstruction op, LIRFrameState info, ReferenceMap refMap) { + if (!info.hasDebugInfo()) { + info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved()); + } + info.updateUnion(refMap); + } + + /** + * Gets an object describing the attributes of a given register according to this register + * configuration. + * + * @see LinearScan#attributes + */ + private RegisterAttributes attributes(Register reg) { + return registerAttributes[reg.number]; + } +} diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterConfig.java Sun Dec 07 20:43:33 2014 +0100 @@ -26,6 +26,7 @@ import static com.oracle.graal.compiler.common.GraalOptions.*; import java.util.*; +import java.util.concurrent.*; import com.oracle.graal.amd64.*; import com.oracle.graal.api.code.*; @@ -51,7 +52,7 @@ private final boolean allAllocatableAreCallerSaved; - private final HashMap categorized = new HashMap<>(); + private final Map categorized = new ConcurrentHashMap<>(); private final RegisterAttributes[] attributesMap; diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java --- a/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Sun Dec 07 20:43:33 2014 +0100 @@ -26,19 +26,31 @@ import java.net.*; /** - * Utility to create a separate class loader for loading classes in {@code graal.jar} and - * {@code graal-truffle.jar}. + * Utility to create and register a separate class loader for loading Graal classes (i.e., those in + * {@code graal.jar} and {@code graal-truffle.jar}). */ public class Factory { /** + * Copy of the {@code UseGraalClassLoader} VM option. Set by the VM before the static + * initializer is called. + */ + private static boolean useGraalClassLoader; + + /** + * Registers the Graal class loader in the VM. + */ + private static native void init(ClassLoader loader); + + static { + init(useGraalClassLoader ? newClassLoader() : null); + } + + /** * Creates a new class loader for loading classes in {@code graal.jar} and - * {@code graal-truffle.jar} - * - * Called from the VM. + * {@code graal-truffle.jar}. */ - @SuppressWarnings("unused") - private static ClassLoader newClassLoader() throws MalformedURLException { + private static ClassLoader newClassLoader() { URL[] urls = {getGraalJarUrl("graal"), getGraalJarUrl("graal-truffle")}; ClassLoader parent = null; return URLClassLoader.newInstance(urls, parent); @@ -47,7 +59,7 @@ /** * Gets the URL for {@code base.jar}. */ - private static URL getGraalJarUrl(String base) throws MalformedURLException { + private static URL getGraalJarUrl(String base) { File file = new File(System.getProperty("java.home")); for (String name : new String[]{"lib", base + ".jar"}) { file = new File(file, name); @@ -57,6 +69,10 @@ throw new InternalError(file + " does not exist"); } - return file.toURI().toURL(); + try { + return file.toURI().toURL(); + } catch (MalformedURLException e) { + throw new InternalError(e); + } } } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Sun Dec 07 20:43:33 2014 +0100 @@ -26,6 +26,7 @@ import static com.oracle.graal.sparc.SPARC.*; import java.util.*; +import java.util.concurrent.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.code.CallingConvention.Type; @@ -42,7 +43,7 @@ private final Register[] allocatable; - private final HashMap categorized = new HashMap<>(); + private final Map categorized = new ConcurrentHashMap<>(20); private final RegisterAttributes[] attributesMap; diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotReferenceMap.java Sun Dec 07 20:43:33 2014 +0100 @@ -79,6 +79,19 @@ this.target = target; } + private HotSpotReferenceMap(HotSpotReferenceMap other) { + this.registerRefMap = (BitSet) other.registerRefMap.clone(); + this.frameRefMap = (BitSet) other.frameRefMap.clone(); + this.target = other.target; + } + + @Override + public ReferenceMap clone() { + return new HotSpotReferenceMap(this); + } + + // setters + private static void setOop(BitSet map, int startIdx, LIRKind kind) { int length = kind.getPlatformKind().getVectorLength(); map.clear(BITS_PER_WORD * startIdx, BITS_PER_WORD * (startIdx + length) - 1); @@ -154,6 +167,194 @@ } } + // clear + + private static void clearOop(BitSet map, int startIdx, LIRKind kind) { + int length = kind.getPlatformKind().getVectorLength(); + map.clear(BITS_PER_WORD * startIdx, BITS_PER_WORD * (startIdx + length) - 1); + } + + private static void clearNarrowOop(BitSet map, int idx, LIRKind kind) { + int length = kind.getPlatformKind().getVectorLength(); + int nextIdx = idx + (length + 1) / 2; + map.clear(BITS_PER_WORD * idx, BITS_PER_WORD * nextIdx - 1); + } + + public void clearRegister(int idx, LIRKind kind) { + + PlatformKind platformKind = kind.getPlatformKind(); + int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); + + if (bytesPerElement == target.wordSize) { + clearOop(registerRefMap, idx, kind); + } else if (bytesPerElement == target.wordSize / 2) { + clearNarrowOop(registerRefMap, idx, kind); + } else { + assert kind.isValue() : "unsupported reference kind " + kind; + } + } + + public void clearStackSlot(int offset, LIRKind kind) { + + PlatformKind platformKind = kind.getPlatformKind(); + int bytesPerElement = target.getSizeInBytes(platformKind) / platformKind.getVectorLength(); + assert offset % bytesPerElement == 0 : "unaligned value in ReferenceMap"; + + if (bytesPerElement == target.wordSize) { + clearOop(frameRefMap, offset / target.wordSize, kind); + } else if (bytesPerElement == target.wordSize / 2) { + if (platformKind.getVectorLength() > 1) { + clearNarrowOop(frameRefMap, offset / target.wordSize, kind); + } else { + // in this case, offset / target.wordSize may not divide evenly + // so setNarrowOop won't work correctly + int idx = offset / target.wordSize; + if (kind.isReference(0)) { + if (offset % target.wordSize == 0) { + frameRefMap.clear(BITS_PER_WORD * idx + 1); + if (!frameRefMap.get(BITS_PER_WORD * idx + 2)) { + // only reset the first bit if there is no other narrow oop + frameRefMap.clear(BITS_PER_WORD * idx); + } + } else { + frameRefMap.clear(BITS_PER_WORD * idx + 2); + if (!frameRefMap.get(BITS_PER_WORD * idx + 1)) { + // only reset the first bit if there is no other narrow oop + frameRefMap.clear(BITS_PER_WORD * idx); + } + } + } + } + } else { + assert kind.isValue() : "unknown reference kind " + kind; + } + } + + public void updateUnion(ReferenceMap otherArg) { + HotSpotReferenceMap other = (HotSpotReferenceMap) otherArg; + if (registerRefMap != null) { + assert other.registerRefMap != null; + updateUnionBitSetRaw(registerRefMap, other.registerRefMap); + } else { + assert other.registerRefMap == null || other.registerRefMap.cardinality() == 0 : "Target register reference map is empty but the source is not: " + other.registerRefMap; + } + updateUnionBitSetRaw(frameRefMap, other.frameRefMap); + } + + /** + * Update {@code src} with the union of {@code src} and {@code dst}. + * + * @see HotSpotReferenceMap#registerRefMap + * @see HotSpotReferenceMap#frameRefMap + */ + private static void updateUnionBitSetRaw(BitSet dst, BitSet src) { + assert dst.size() == src.size(); + assert UpdateUnionVerifier.verifyUpate(dst, src); + dst.or(src); + } + + private enum UpdateUnionVerifier { + NoReference, + WideOop, + NarrowOopLowerHalf, + NarrowOopUpperHalf, + TwoNarrowOops, + Illegal; + + /** + * Create enum values from BitSet. + *

+ * These bits can have the following values (LSB first): + * + *

+         * 000 - contains no references
+         * 100 - contains a wide oop
+         * 110 - contains a narrow oop in the lower half
+         * 101 - contains a narrow oop in the upper half
+         * 111 - contains two narrow oops
+         * 
+ * + * @see HotSpotReferenceMap#registerRefMap + * @see HotSpotReferenceMap#frameRefMap + */ + static UpdateUnionVerifier getFromBits(int idx, BitSet set) { + int n = (set.get(idx) ? 1 : 0) << 0 | (set.get(idx + 1) ? 1 : 0) << 1 | (set.get(idx + 2) ? 1 : 0) << 2; + switch (n) { + case 0: + return NoReference; + case 1: + return WideOop; + case 3: + return NarrowOopLowerHalf; + case 5: + return NarrowOopUpperHalf; + case 7: + return TwoNarrowOops; + default: + return Illegal; + } + } + + String toBitString() { + int bits = toBit(this); + if (bits == -1) { + return "---"; + } + return String.format("%3s", Integer.toBinaryString(bits)).replace(' ', '0'); + } + + static int toBit(UpdateUnionVerifier type) { + switch (type) { + case NoReference: + return 0; + case WideOop: + return 1; + case NarrowOopLowerHalf: + return 3; + case NarrowOopUpperHalf: + return 5; + case TwoNarrowOops: + return 7; + default: + return -1; + } + } + + private static boolean verifyUpate(BitSet dst, BitSet src) { + for (int idx = 0; idx < dst.size(); idx += BITS_PER_WORD) { + if (!verifyUpdateEntry(idx, dst, src)) { + return false; + } + } + return true; + } + + private static boolean verifyUpdateEntry(int idx, BitSet dst, BitSet src) { + UpdateUnionVerifier dstType = UpdateUnionVerifier.getFromBits(idx, dst); + UpdateUnionVerifier srcType = UpdateUnionVerifier.getFromBits(idx, src); + + if (dstType == UpdateUnionVerifier.Illegal || srcType == UpdateUnionVerifier.Illegal) { + assert false : String.format("Illegal RefMap bit pattern: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); + return false; + } + switch (dstType) { + case NoReference: + return true; + case WideOop: + switch (srcType) { + case NoReference: + case WideOop: + return true; + default: + assert false : String.format("Illegal RefMap combination: %s (0b%s), %s (0b%s)", dstType, dstType.toBitString(), srcType, srcType.toBitString()); + return false; + } + default: + return true; + } + } + } + @Override public int hashCode() { throw new UnsupportedOperationException(); diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/replacements/arraycopy/ArrayCopySnippets.java Sun Dec 07 20:43:33 2014 +0100 @@ -191,7 +191,8 @@ Object nonNullDest = guardingNonNull(dest); checkLimits(nonNullSrc, srcPos, nonNullDest, destPos, length); if (probability(SLOW_PATH_PROBABILITY, nonNullSrc == nonNullDest)) { - System.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length); + // no storecheck required. + ArrayCopyCallNode.arraycopy(nonNullSrc, srcPos, nonNullDest, destPos, length, Kind.Object, false, false); } else { KlassPointer destElemKlass = loadHub(nonNullDest); checkcastArraycopyHelper(srcPos, destPos, length, nonNullSrc, nonNullDest, destElemKlass); diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Sun Dec 07 20:43:33 2014 +0100 @@ -134,6 +134,13 @@ } /** + * Updates this reference map with all references that are marked in {@code refMap}. + */ + public void updateUnion(ReferenceMap refMap) { + debugInfo.getReferenceMap().updateUnion(refMap); + } + + /** * Called by the register allocator after all locations are marked. * * @param op The instruction to which this frame state belongs. diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java Sun Dec 07 20:43:33 2014 +0100 @@ -337,4 +337,16 @@ assert isConstant(location); } } + + public void clearReference(Value location, ReferenceMap refMap) { + LIRKind kind = location.getLIRKind(); + if (isRegister(location)) { + refMap.clearRegister(asRegister(location).getReferenceMapIndex(), kind); + } else if (isStackSlot(location)) { + int offset = offsetForStackSlot(asStackSlot(location)); + refMap.clearStackSlot(offset, kind); + } else { + assert isConstant(location); + } + } } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/ReplacementsImpl.java Sun Dec 07 20:43:33 2014 +0100 @@ -315,10 +315,10 @@ try { Object[] args = new Object[constructor.getParameterCount()]; for (int i = 0; i < args.length; i++) { - Object arg = snippetReflection.getSubstitutionGuardParameter(paramTypes[0]); + Object arg = snippetReflection.getSubstitutionGuardParameter(paramTypes[i]); if (arg != null) { args[i] = arg; - } else if (paramTypes[0].isInstance(target.arch)) { + } else if (paramTypes[i].isInstance(target.arch)) { args[i] = target.arch; } else { throw new GraalInternalError("Unsupported type %s in substitution guard constructor: %s", paramTypes[i].getName(), constructor); diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARCScratchRegister.java --- a/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARCScratchRegister.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.graal.sparc/src/com/oracle/graal/sparc/SPARCScratchRegister.java Sun Dec 07 20:43:33 2014 +0100 @@ -30,6 +30,7 @@ private final Register register; private static final SPARCScratchRegister scratch1 = new SPARCScratchRegister(SPARC.g3); private static final SPARCScratchRegister scratch2 = new SPARCScratchRegister(SPARC.g1); + private static final boolean LOG_REQUEST_STACK = false; private SPARCScratchRegister(Register register) { super(); @@ -42,10 +43,14 @@ } boolean isLocked = locked.get(); if (isLocked) { - where.get().printStackTrace(); + if (LOG_REQUEST_STACK) { + where.get().printStackTrace(); + } throw new RuntimeException("Temp Register is already taken!"); } else { - where.set(new Exception()); + if (LOG_REQUEST_STACK) { + where.set(new Exception()); + } locked.set(true); return register; } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/ArrayTest.java Sun Dec 07 20:43:33 2014 +0100 @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2014, 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.truffle.api.dsl.test; + +import org.junit.*; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.dsl.*; +import com.oracle.truffle.api.dsl.test.ArrayTestFactory.TestNode1Factory; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.nodes.*; + +public class ArrayTest { + + @Test + public void testNode1() { + final TestNode1 node = TestNode1Factory.create(null); + RootNode root = new RootNode() { + @Child TestNode1 test = node; + + @Override + public Object execute(VirtualFrame frame) { + return test.executeWith(frame, frame.getArguments()[0]); + } + }; + CallTarget target = Truffle.getRuntime().createCallTarget(root); + + Assert.assertEquals(1, (int) target.call(1)); + Assert.assertArrayEquals(new double[0], (double[]) target.call(new int[0]), 0.0d); + Assert.assertArrayEquals(new double[0], (double[]) target.call(new double[0]), 0.0d); + Assert.assertArrayEquals(new String[0], (String[]) target.call((Object) new String[0])); + } + + @TypeSystemReference(ArrayTypeSystem.class) + abstract static class BaseNode extends Node { + + abstract Object execute(VirtualFrame frame); + + int executeInt(VirtualFrame frame) throws UnexpectedResultException { + return ArrayTypeSystemGen.ARRAYTYPESYSTEM.expectInteger(execute(frame)); + } + + int[] executeIntArray(VirtualFrame frame) throws UnexpectedResultException { + return ArrayTypeSystemGen.ARRAYTYPESYSTEM.expectIntArray(execute(frame)); + } + + String[] executeStringArray(VirtualFrame frame) throws UnexpectedResultException { + return ArrayTypeSystemGen.ARRAYTYPESYSTEM.expectStringArray(execute(frame)); + } + + double[] executeDoubleArray(VirtualFrame frame) throws UnexpectedResultException { + return ArrayTypeSystemGen.ARRAYTYPESYSTEM.expectDoubleArray(execute(frame)); + } + } + + @NodeChild + abstract static class TestNode1 extends BaseNode { + + abstract Object executeWith(VirtualFrame frame, Object operand); + + @Specialization + int doInt(int value) { + return value; + } + + @Specialization + double[] doDoubleArray(double[] value) { + return value; + } + + @Specialization + String[] doStringArray(String[] value) { + return value; + } + + } + + @TypeSystem({int.class, int[].class, double[].class, String[].class, Object[].class}) + public static class ArrayTypeSystem { + + @ImplicitCast + public double[] castFromInt(int[] array) { + double[] newArray = new double[array.length]; + for (int i = 0; i < array.length; i++) { + newArray[i] = array[i]; + } + return newArray; + } + + @TypeCheck + public boolean isIntArray(Object array) { + return array instanceof int[]; + } + + @TypeCast + public int[] asIntArray(Object array) { + return (int[]) array; + } + + } + +} diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java Sun Dec 07 20:43:33 2014 +0100 @@ -322,12 +322,12 @@ /** *
      * variant1 $condition != null
-     * 
+     *
      * $type $name = defaultValue($type);
      * if ($condition) {
      *     $name = $value;
      * }
-     * 
+     *
      * variant2 $condition != null
      * $type $name = $value;
      * 
@@ -1993,7 +1993,7 @@ } String prefix = expect ? "expect" : "execute"; String suffix = execution.getIndex() > -1 ? String.valueOf(execution.getIndex()) : ""; - return prefix + ElementUtils.firstLetterUpperCase(child.getName()) + ElementUtils.firstLetterUpperCase(ElementUtils.getSimpleName(param.getType())) + suffix; + return prefix + ElementUtils.firstLetterUpperCase(child.getName()) + ElementUtils.firstLetterUpperCase(ElementUtils.getTypeId(param.getType())) + suffix; } private List createExecuteChilds(Parameter param, Set expectTypes) { diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/model/CodeTreeBuilder.java Sun Dec 07 20:43:33 2014 +0100 @@ -672,10 +672,6 @@ } public CodeTreeBuilder instanceOf(String var, TypeMirror type) { - TypeElement element = ElementUtils.fromTypeMirror(type); - if (element == null) { - throw new IllegalArgumentException("Cannot call instanceof for a non supported type: " + type.getKind()); - } return instanceOf(singleString(var), singleType(type)); } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/TypeSystemData.java Sun Dec 07 20:43:33 2014 +0100 @@ -139,7 +139,7 @@ public TypeData findType(String simpleName) { for (TypeData type : types) { - if (ElementUtils.getSimpleName(type.getBoxedType()).equals(simpleName)) { + if (ElementUtils.getTypeId(type.getBoxedType()).equals(simpleName)) { return type; } } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java --- a/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/TypeSystemParser.java Sun Dec 07 20:43:33 2014 +0100 @@ -216,7 +216,11 @@ typeData.addError("Invalid type order. The type(s) %s are inherited from a earlier defined type %s.", invalidTypes.get(ElementUtils.getQualifiedName(type)), ElementUtils.getQualifiedName(type)); } - List nextInvalidTypes = ElementUtils.getQualifiedSuperTypeNames(ElementUtils.fromTypeMirror(type)); + TypeElement element = ElementUtils.fromTypeMirror(type); + List nextInvalidTypes = new ArrayList<>(); + if (element != null) { + nextInvalidTypes.addAll(ElementUtils.getQualifiedSuperTypeNames(element)); + } nextInvalidTypes.add(getQualifiedName(type)); for (String qualifiedName : nextInvalidTypes) { diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java --- a/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.object.basic/src/com/oracle/truffle/object/basic/ShapeBasic.java Sun Dec 07 20:43:33 2014 +0100 @@ -30,13 +30,13 @@ super(layout, operations, sharedData, id); } - public ShapeBasic(Layout layout, Object sharedData, ShapeImpl parent, ObjectType operations, PropertyMap propertyMap, Allocator allocator, int id) { - super(layout, parent, operations, sharedData, propertyMap, allocator, id); + public ShapeBasic(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) { + super(layout, parent, objectType, sharedData, propertyMap, transition, allocator, id); } @SuppressWarnings("hiding") @Override - protected ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType operations, PropertyMap propertyMap, Allocator allocator, int id) { - return new ShapeBasic(layout, sharedData, parent, operations, propertyMap, allocator, id); + protected ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType objectType, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) { + return new ShapeBasic(layout, sharedData, parent, objectType, propertyMap, transition, allocator, id); } } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java --- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/ShapeImpl.java Sun Dec 07 20:43:33 2014 +0100 @@ -29,16 +29,18 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.object.*; +import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.object.LocationImpl.InternalLongLocation; import com.oracle.truffle.object.Locations.ConstantLocation; import com.oracle.truffle.object.Locations.DeclaredDualLocation; import com.oracle.truffle.object.Locations.DeclaredLocation; import com.oracle.truffle.object.Locations.DualLocation; import com.oracle.truffle.object.Locations.ValueLocation; -import com.oracle.truffle.object.Transition.AddTransition; -import com.oracle.truffle.object.Transition.OperationsTransition; +import com.oracle.truffle.object.Transition.AddPropertyTransition; +import com.oracle.truffle.object.Transition.ObjectTypeTransition; import com.oracle.truffle.object.Transition.PropertyTransition; -import com.oracle.truffle.object.Transition.RemoveTransition; +import com.oracle.truffle.object.Transition.RemovePropertyTransition; +import com.oracle.truffle.object.Transition.ReservePrimitiveArrayTransition; /** * Shape objects create a mapping of Property objects to indexes. The mapping of those indexes to an @@ -77,7 +79,7 @@ protected Property[] propertyArray; protected final Assumption validAssumption; - protected final Assumption leafAssumption; + @CompilationFinal protected volatile Assumption leafAssumption; /** * Shape transition map; lazily initialized. @@ -87,18 +89,24 @@ */ private HashMap transitionMap; + private final Transition transitionFromParent; + /** * Private constructor. * - * @see #ShapeImpl(Layout, ShapeImpl, ObjectType, Object, PropertyMap, BaseAllocator, int) + * @param parent predecessor shape + * @param transitionFromParent direct transition from parent shape + * @see #ShapeImpl(Layout, ShapeImpl, ObjectType, Object, PropertyMap, Transition, + * BaseAllocator, int) */ - private ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, int objectArraySize, int objectFieldSize, int primitiveFieldSize, - int primitiveArraySize, boolean hasPrimitiveArray, int id) { + private ShapeImpl(Layout layout, ShapeImpl parent, ObjectType objectType, Object sharedData, PropertyMap propertyMap, Transition transitionFromParent, int objectArraySize, int objectFieldSize, + int primitiveFieldSize, int primitiveArraySize, boolean hasPrimitiveArray, int id) { this.layout = (LayoutImpl) layout; - this.objectType = Objects.requireNonNull(operations); + this.objectType = Objects.requireNonNull(objectType); this.propertyMap = Objects.requireNonNull(propertyMap); this.root = parent != null ? parent.getRoot() : this; this.parent = parent; + this.transitionFromParent = transitionFromParent; this.objectArraySize = objectArraySize; this.objectArrayCapacity = capacityFromSize(objectArraySize); this.objectFieldSize = objectFieldSize; @@ -118,27 +126,26 @@ } this.validAssumption = createValidAssumption(); - this.leafAssumption = createLeafAssumption(); this.id = id; shapeCount.inc(); this.sharedData = sharedData; - this.extraData = operations.createShapeData(this); + this.extraData = objectType.createShapeData(this); debugRegisterShape(this); } - protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Allocator allocator, int id) { - this(layout, parent, operations, sharedData, propertyMap, ((BaseAllocator) allocator).objectArraySize, ((BaseAllocator) allocator).objectFieldSize, + protected ShapeImpl(Layout layout, ShapeImpl parent, ObjectType operations, Object sharedData, PropertyMap propertyMap, Transition transition, Allocator allocator, int id) { + this(layout, parent, operations, sharedData, propertyMap, transition, ((BaseAllocator) allocator).objectArraySize, ((BaseAllocator) allocator).objectFieldSize, ((BaseAllocator) allocator).primitiveFieldSize, ((BaseAllocator) allocator).primitiveArraySize, ((BaseAllocator) allocator).hasPrimitiveArray, id); } @SuppressWarnings("hiding") - protected abstract ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType operations, PropertyMap propertyMap, Allocator allocator, int id); + protected abstract ShapeImpl createShape(Layout layout, Object sharedData, ShapeImpl parent, ObjectType operations, PropertyMap propertyMap, Transition transition, Allocator allocator, int id); protected ShapeImpl(Layout layout, ObjectType operations, Object sharedData, int id) { - this(layout, null, operations, sharedData, PropertyMap.empty(), layout.createAllocator(), id); + this(layout, null, operations, sharedData, PropertyMap.empty(), null, layout.createAllocator(), id); } private static int makePropertyCount(ShapeImpl parent, PropertyMap propertyMap) { @@ -235,7 +242,7 @@ public final ShapeImpl getShapeFromProperty(Object propertyName) { ShapeImpl current = this; while (current != getRoot()) { - if (current.getLastProperty().getKey().equals(propertyName)) { + if (current.getTransitionFromParent() instanceof AddPropertyTransition && ((AddPropertyTransition) current.getTransitionFromParent()).getProperty().getKey().equals(propertyName)) { return current; } current = current.getParent(); @@ -250,7 +257,7 @@ public final ShapeImpl getShapeFromProperty(Property prop) { ShapeImpl current = this; while (current != getRoot()) { - if (current.getLastProperty().equals(prop)) { + if (current.getTransitionFromParent() instanceof AddPropertyTransition && ((AddPropertyTransition) current.getTransitionFromParent()).getProperty().equals(prop)) { return current; } current = current.parent; @@ -280,13 +287,13 @@ return null; } - protected final void addTransition(Transition transition, ShapeImpl next) { - assert next.getParent() == this; + protected final void addDirectTransition(Transition transition, ShapeImpl next) { + assert next.getParent() == this && transition.isDirect(); addTransitionInternal(transition, next); } - public final void addNonlinearTransition(Transition transition, ShapeImpl next) { - assert next.getParent() != this; + public final void addIndirectTransition(Transition transition, ShapeImpl next) { + assert next.getParent() != this && !transition.isDirect(); addTransitionInternal(transition, next); } @@ -311,6 +318,17 @@ return propertyMap; } + private ShapeImpl queryTransition(Transition transition) { + ShapeImpl cachedShape = this.getTransitionMapForRead().get(transition); + if (cachedShape != null) { // Shape already exists? + shapeCacheHitCount.inc(); + return (ShapeImpl) layout.getStrategy().returnCached(cachedShape); + } + shapeCacheMissCount.inc(); + + return null; + } + /** * Add a new property in the map, yielding a new or cached Shape object. * @@ -340,24 +358,21 @@ assert !getPropertyListInternal(false).contains(prop); // invalidatePropertyAssumption(prop.getName()); - Transition.AddTransition key = new Transition.AddTransition(prop); - Map transitionMapForRead = this.getTransitionMapForRead(); - ShapeImpl cachedShape = transitionMapForRead.get(key); - if (cachedShape != null) { // Shape already exists? - shapeCacheHitCount.inc(); - return (ShapeImpl) layout.getStrategy().returnCached(cachedShape); + AddPropertyTransition addTransition = new AddPropertyTransition(prop); + ShapeImpl cachedShape = queryTransition(addTransition); + if (cachedShape != null) { + return cachedShape; } - shapeCacheMissCount.inc(); ShapeImpl oldShape = (ShapeImpl) layout.getStrategy().ensureSpace(this, prop.getLocation()); - ShapeImpl newShape = makeShapeWithAddedProperty(oldShape, key); - oldShape.addTransition(key, newShape); + ShapeImpl newShape = makeShapeWithAddedProperty(oldShape, addTransition); + oldShape.addDirectTransition(addTransition, newShape); return newShape; } protected ShapeImpl cloneRoot(ShapeImpl from, Object newSharedData) { - return createShape(from.layout, newSharedData, null, from.objectType, from.propertyMap, from.allocator(), from.id); + return createShape(from.layout, newSharedData, null, from.objectType, from.propertyMap, null, from.allocator(), from.id); } /** @@ -367,34 +382,29 @@ */ protected final ShapeImpl cloneOnto(ShapeImpl newParent) { ShapeImpl from = this; - ShapeImpl newShape = createShape(newParent.layout, newParent.sharedData, newParent, from.objectType, from.propertyMap, from.allocator(), newParent.id); + ShapeImpl newShape = createShape(newParent.layout, newParent.sharedData, newParent, from.objectType, from.propertyMap, from.transitionFromParent, from.allocator(), newParent.id); shapeCloneCount.inc(); // (aw) need to have this transition for obsolescence - newParent.addTransition(getTransitionFromParent(), newShape); + newParent.addDirectTransition(from.transitionFromParent, newShape); return newShape; } - private Transition getTransitionFromParent() { - for (Map.Entry property : parent.getTransitionMapForRead().entrySet()) { - if (property.getValue() == this) { - return property.getKey(); - } - } - throw new NoSuchElementException(); + public final Transition getTransitionFromParent() { + return transitionFromParent; } /** * Create a new shape that adds a property to the parent shape. */ - private static ShapeImpl makeShapeWithAddedProperty(ShapeImpl parent, AddTransition addTransition) { + private static ShapeImpl makeShapeWithAddedProperty(ShapeImpl parent, AddPropertyTransition addTransition) { Property addend = addTransition.getProperty(); BaseAllocator allocator = parent.allocator().addLocation(addend.getLocation()); PropertyMap newPropertyMap = parent.propertyMap.putCopy(addend); - ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, newPropertyMap, allocator, parent.id); + ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, newPropertyMap, addTransition, allocator, parent.id); assert ((LocationImpl) addend.getLocation()).primitiveArrayCount() == 0 || newShape.hasPrimitiveArray; assert newShape.depth == allocator.depth; return newShape; @@ -403,11 +413,11 @@ /** * Create a new shape that reserves the primitive extension array field. */ - private static ShapeImpl makeShapeWithPrimitiveExtensionArray(ShapeImpl parent) { + private static ShapeImpl makeShapeWithPrimitiveExtensionArray(ShapeImpl parent, Transition transition) { assert parent.getLayout().hasPrimitiveExtensionArray(); assert !parent.hasPrimitiveArray(); BaseAllocator allocator = parent.allocator().addLocation(parent.getLayout().getPrimitiveArrayLocation()); - ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, parent.propertyMap, allocator, parent.id); + ShapeImpl newShape = parent.createShape(parent.layout, parent.sharedData, parent, parent.objectType, parent.propertyMap, transition, allocator, parent.id); assert newShape.hasPrimitiveArray(); assert newShape.depth == allocator.depth; return newShape; @@ -415,17 +425,15 @@ private ShapeImpl addPrimitiveExtensionArray() { assert layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray(); - Transition key = new Transition.ReservePrimitiveArrayTransition(); - ShapeImpl cachedShape = this.getTransitionMapForRead().get(key); + Transition transition = new ReservePrimitiveArrayTransition(); + ShapeImpl cachedShape = queryTransition(transition); if (cachedShape != null) { - shapeCacheHitCount.inc(); - return (ShapeImpl) layout.getStrategy().returnCached(cachedShape); + return cachedShape; } - shapeCacheMissCount.inc(); ShapeImpl oldShape = (ShapeImpl) layout.getStrategy().ensureSpace(this, layout.getPrimitiveArrayLocation()); - ShapeImpl newShape = makeShapeWithPrimitiveExtensionArray(oldShape); - oldShape.addTransition(key, newShape); + ShapeImpl newShape = makeShapeWithPrimitiveExtensionArray(oldShape, transition); + oldShape.addDirectTransition(transition, newShape); return newShape; } @@ -455,8 +463,7 @@ @Override public final List getPropertyList(Pred filter) { LinkedList props = new LinkedList<>(); - next: for (ShapeImpl current = this; current != getRoot(); current = current.parent) { - Property currentProperty = current.getLastProperty(); + next: for (Property currentProperty : this.propertyMap.reverseOrderValues()) { if (!currentProperty.isHidden() && filter.test(currentProperty)) { if (currentProperty.getLocation() instanceof DeclaredLocation) { for (Iterator iter = props.iterator(); iter.hasNext();) { @@ -488,11 +495,11 @@ @Override public final List getPropertyListInternal(boolean ascending) { LinkedList props = new LinkedList<>(); - for (ShapeImpl current = this; current != getRoot(); current = current.parent) { + for (Property current : this.propertyMap.reverseOrderValues()) { if (ascending) { - props.addFirst(current.getLastProperty()); + props.addFirst(current); } else { - props.add(current.getLastProperty()); + props.add(current); } } return props; @@ -507,8 +514,7 @@ @Override public final List getKeyList(Pred filter) { LinkedList keys = new LinkedList<>(); - for (ShapeImpl current = this; current != getRoot(); current = current.parent) { - Property currentProperty = current.getLastProperty(); + for (Property currentProperty : this.propertyMap.reverseOrderValues()) { if (!currentProperty.isHidden() && filter.test(currentProperty) && !currentProperty.isShadow()) { keys.addFirst(currentProperty.getKey()); } @@ -526,12 +532,9 @@ return getKeyList(); } - public final void setTypeTransition(ShapeImpl successorShape, Property before, Property after) { - getTransitionMapForWrite().put(new Transition.TypeTransition(before, after), successorShape); - } - - private static Assumption createValidAssumption() { - return Truffle.getRuntime().createAssumption("valid shape"); + @Override + public final boolean isValid() { + return getValidAssumption().isValid(); } @Override @@ -539,27 +542,47 @@ return validAssumption; } + private static Assumption createValidAssumption() { + return Truffle.getRuntime().createAssumption("valid shape"); + } + + public final void invalidateValidAssumption() { + getValidAssumption().invalidate(); + } + @Override - public final boolean isValid() { - return getValidAssumption().isValid(); + public final boolean isLeaf() { + return leafAssumption == null || leafAssumption.isValid(); + } + + @Override + public final Assumption getLeafAssumption() { + if (leafAssumption == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + synchronized (getMutex()) { + if (leafAssumption == null) { + leafAssumption = isLeafHelper() ? createLeafAssumption() : NeverValidAssumption.INSTANCE; + } + } + } + return leafAssumption; + } + + private boolean isLeafHelper() { + return getTransitionMapForRead().isEmpty(); } private static Assumption createLeafAssumption() { return Truffle.getRuntime().createAssumption("leaf shape"); } - @Override - public final Assumption getLeafAssumption() { - return leafAssumption; - } - - @Override - public final boolean isLeaf() { - return getLeafAssumption().isValid(); - } - private void invalidateLeafAssumption() { - getLeafAssumption().invalidate(); + Assumption assumption = leafAssumption; + if (assumption != null) { + assumption.invalidate(); + } else { + leafAssumption = NeverValidAssumption.INSTANCE; + } } @Override @@ -611,24 +634,24 @@ @TruffleBoundary @Override public final ShapeImpl removeProperty(Property prop) { - RemoveTransition transition = new RemoveTransition(prop); - ShapeImpl cachedShape = getTransitionMapForRead().get(transition); + RemovePropertyTransition transition = new RemovePropertyTransition(prop); + ShapeImpl cachedShape = queryTransition(transition); if (cachedShape != null) { - return (ShapeImpl) layout.getStrategy().returnCached(cachedShape); + return cachedShape; } ShapeImpl shape = getShapeFromProperty(prop); if (shape != null) { - List properties = new ArrayList<>(); + List transitionList = new ArrayList<>(); ShapeImpl current = this; while (current != shape) { - properties.add(current.getLastProperty()); + transitionList.add(current.getTransitionFromParent()); current = current.parent; } ShapeImpl newShape = shape.parent; - for (ListIterator iterator = properties.listIterator(properties.size()); iterator.hasPrevious();) { - Property previous = iterator.previous(); - newShape = newShape.append(previous); + for (ListIterator iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) { + Transition previous = iterator.previous(); + newShape = newShape.applyTransition(previous, true); } getTransitionMapForWrite().put(transition, newShape); @@ -644,6 +667,18 @@ return addProperty(oldProperty.relocate(allocator().moveLocation(oldProperty.getLocation()))); } + public final ShapeImpl applyTransition(Transition transition, boolean append) { + if (transition instanceof AddPropertyTransition) { + return append ? append(((AddPropertyTransition) transition).getProperty()) : addProperty(((AddPropertyTransition) transition).getProperty()); + } else if (transition instanceof ObjectTypeTransition) { + return changeType(((ObjectTypeTransition) transition).getObjectType()); + } else if (transition instanceof ReservePrimitiveArrayTransition) { + return reservePrimitiveExtensionArray(); + } else { + throw new UnsupportedOperationException(); + } + } + @Override public final BaseAllocator allocator() { return layout.getStrategy().createAllocator(this); @@ -653,27 +688,34 @@ * Duplicate shape exchanging existing property with new property. */ @Override - public final ShapeImpl replaceProperty(Property oldProperty, Property newProp) { + public final ShapeImpl replaceProperty(Property oldProperty, Property newProperty) { + Transition replacePropertyTransition = new Transition.ReplacePropertyTransition(oldProperty, newProperty); + ShapeImpl cachedShape = queryTransition(replacePropertyTransition); + if (cachedShape != null) { + return cachedShape; + } + ShapeImpl top = this; - List propertyList = new ArrayList<>(); + List transitionList = new ArrayList<>(); boolean found = false; while (top != getRoot() && !found) { - Property prop = top.getLastProperty(); - propertyList.add(prop); - if (prop.getKey().equals(newProp.getKey())) { + Transition transition = top.getTransitionFromParent(); + transitionList.add(transition); + if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) { found = true; } top = top.parent; } ShapeImpl newShape = top; - for (ListIterator iterator = propertyList.listIterator(propertyList.size()); iterator.hasPrevious();) { - Property prop = iterator.previous(); - if (prop.getKey().equals(newProp.getKey())) { - newShape = newShape.addProperty(newProp); + for (ListIterator iterator = transitionList.listIterator(transitionList.size()); iterator.hasPrevious();) { + Transition transition = iterator.previous(); + if (transition instanceof AddPropertyTransition && ((AddPropertyTransition) transition).getProperty().getKey().equals(newProperty.getKey())) { + newShape = newShape.addProperty(newProperty); } else { - newShape = newShape.addProperty(prop); + newShape = newShape.applyTransition(transition, false); } } + addIndirectTransition(replacePropertyTransition, newShape); return newShape; } @@ -725,9 +767,6 @@ return newShape; } - /** - * NB: this is not an accurate property count. - */ @Override public final int getPropertyCount() { return propertyCount; @@ -809,19 +848,19 @@ @Override @TruffleBoundary public final ShapeImpl changeType(ObjectType newOps) { - OperationsTransition transition = new OperationsTransition(newOps); - ShapeImpl cachedShape = getTransitionMapForRead().get(transition); + ObjectTypeTransition transition = new ObjectTypeTransition(newOps); + ShapeImpl cachedShape = queryTransition(transition); if (cachedShape != null) { return cachedShape; - } else { - ShapeImpl newShape = createShape(layout, extraData, this, newOps, propertyMap, allocator(), id); - addTransition(transition, newShape); - return newShape; } + + ShapeImpl newShape = createShape(layout, sharedData, this, newOps, propertyMap, transition, allocator(), id); + addDirectTransition(transition, newShape); + return newShape; } @Override - public final Shape reservePrimitiveExtensionArray() { + public final ShapeImpl reservePrimitiveExtensionArray() { if (layout.hasPrimitiveExtensionArray() && !hasPrimitiveArray()) { return addPrimitiveExtensionArray(); } diff -r 02b5114b74c1 -r e22a21b27036 graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java --- a/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java Fri Dec 05 11:09:57 2014 +0100 +++ b/graal/com.oracle.truffle.object/src/com/oracle/truffle/object/Transition.java Sun Dec 07 20:43:33 2014 +0100 @@ -47,6 +47,8 @@ return true; } + public abstract boolean isDirect(); + public abstract static class PropertyTransition extends Transition { private final Property property; @@ -79,47 +81,62 @@ } } - public static final class AddTransition extends PropertyTransition { - public AddTransition(Property property) { + public static final class AddPropertyTransition extends PropertyTransition { + public AddPropertyTransition(Property property) { super(property); } + + @Override + public boolean isDirect() { + return true; + } } - public static final class RemoveTransition extends PropertyTransition { - public RemoveTransition(Property property) { + public static final class RemovePropertyTransition extends PropertyTransition { + public RemovePropertyTransition(Property property) { super(property); } + + @Override + public boolean isDirect() { + return false; + } } - public static final class OperationsTransition extends Transition { - private final ObjectType operations; + public static final class ObjectTypeTransition extends Transition { + private final ObjectType objectType; - public OperationsTransition(ObjectType operations) { - this.operations = operations; + public ObjectTypeTransition(ObjectType objectType) { + this.objectType = objectType; } - public ObjectType getOperations() { - return operations; + public ObjectType getObjectType() { + return objectType; } @Override public boolean equals(Object other) { - return super.equals(other) && Objects.equals(operations, ((OperationsTransition) other).operations); + return super.equals(other) && Objects.equals(objectType, ((ObjectTypeTransition) other).objectType); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + ((operations == null) ? 0 : operations.hashCode()); + result = prime * result + ((objectType == null) ? 0 : objectType.hashCode()); return result; } + + @Override + public boolean isDirect() { + return true; + } } - public static final class TypeTransition extends PropertyTransition { + public static final class ReplacePropertyTransition extends PropertyTransition { private final Property after; - public TypeTransition(Property before, Property after) { + public ReplacePropertyTransition(Property before, Property after) { super(before); this.after = after; } @@ -131,11 +148,21 @@ public Property getPropertyAfter() { return after; } + + @Override + public boolean isDirect() { + return false; + } } public static final class ReservePrimitiveArrayTransition extends Transition { public ReservePrimitiveArrayTransition() { } + + @Override + public boolean isDirect() { + return true; + } } public String getShortName() { diff -r 02b5114b74c1 -r e22a21b27036 make/Makefile --- a/make/Makefile Fri Dec 05 11:09:57 2014 +0100 +++ b/make/Makefile Sun Dec 07 20:43:33 2014 +0100 @@ -306,9 +306,20 @@ $(MAKE_ARGS) $(VM_TARGET) + +ifeq (, $(shell python2.7 --version 2>/dev/null && echo ok)) + ifeq (, $(shell python2.6 --version 2>/dev/null && echo ok)) + PYTHON=python + else + PYTHON=python2.6 + endif +else + PYTHON=python2.7 +endif + # Builds code that can be shared among different build flavors buildshared: - python2 -u $(GAMMADIR)/mxtool/mx.py build --no-native --export-dir $(SHARED_DIR) + $(PYTHON) -u $(GAMMADIR)/mxtool/mx.py build --no-native --export-dir $(SHARED_DIR) # Export file rule generic_export: $(EXPORT_LIST) diff -r 02b5114b74c1 -r e22a21b27036 mx/mx_graal.py --- a/mx/mx_graal.py Fri Dec 05 11:09:57 2014 +0100 +++ b/mx/mx_graal.py Sun Dec 07 20:43:33 2014 +0100 @@ -755,7 +755,7 @@ if not exists(opts2.export_dir): os.makedirs(opts2.export_dir) else: - assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir) + assert os.path.isdir(opts2.export_dir), '{0} is not a directory'.format(opts2.export_dir) defsPath = join(_graal_home, 'make', 'defs.make') with open(defsPath) as fp: @@ -1438,7 +1438,7 @@ with VM('server', 'product'): # hosted mode with Task('UnitTests:hosted-product', tasks): - unittest(['--enable-timing', '--verbose']) + unittest(['--enable-timing', '--verbose', '--fail-fast']) with VM('server', 'product'): # hosted mode with Task('UnitTests-BaselineCompiler:hosted-product', tasks): @@ -1835,7 +1835,7 @@ deps = d['deps'] makejmhdep(artifactId, groupId, deps) except ValueError as e: - mx.abort('Error parsing {}:\n{}'.format(f, e)) + mx.abort('Error parsing {0}:\n{1}'.format(f, e)) def buildjmh(args): """build the JMH benchmarks""" @@ -1916,7 +1916,7 @@ else: jmhArgs[n] = v except ValueError as e: - mx.abort('error parsing JSON input: {}\n{}'.format(j, e)) + mx.abort('error parsing JSON input: {0}\n{1}'.format(j, e)) jmhPath = _get_jmh_path() mx.log('Using benchmarks in ' + jmhPath) @@ -2271,13 +2271,14 @@ assert exists(findbugsJar) nonTestProjects = [p for p in mx.projects() if not p.name.endswith('.test') and not p.name.endswith('.jtt')] outputDirs = map(mx._cygpathU2W, [p.output_dir() for p in nonTestProjects]) + javaCompliance = max([p.javaCompliance for p in nonTestProjects]) findbugsResults = join(_graal_home, 'findbugs.results') cmd = ['-jar', mx._cygpathU2W(findbugsJar), '-textui', '-low', '-maxRank', '15'] if sys.stdout.isatty(): cmd.append('-progress') cmd = cmd + ['-auxclasspath', mx._separatedCygpathU2W(mx.classpath([d.name for d in _jdkDeployedDists] + [p.name for p in nonTestProjects])), '-output', mx._cygpathU2W(findbugsResults), '-exitcode'] + args + outputDirs - exitcode = mx.run_java(cmd, nonZeroIsFatal=False) + exitcode = mx.run_java(cmd, nonZeroIsFatal=False, javaConfig=mx.java(javaCompliance)) if exitcode != 0: with open(findbugsResults) as fp: mx.log(fp.read()) @@ -2309,7 +2310,7 @@ if not matcher.match(content): failures[f] = csConfig for n, v in failures.iteritems(): - mx.log('{}: header does not match RegexpHeader defined in {}'.format(n, v)) + mx.log('{0}: header does not match RegexpHeader defined in {1}'.format(n, v)) return len(failures) def mx_init(suite): diff -r 02b5114b74c1 -r e22a21b27036 mxtool/mx.py --- a/mxtool/mx.py Fri Dec 05 11:09:57 2014 +0100 +++ b/mxtool/mx.py Sun Dec 07 20:43:33 2014 +0100 @@ -109,7 +109,7 @@ try: excl = [dependency(d) for d in self.excludedDependencies] except SystemExit as e: - abort('invalid excluded dependency for {} distribution: {}'.format(self.name, e)) + abort('invalid excluded dependency for {0} distribution: {1}'.format(self.name, e)) return deps + [d for d in sorted_deps(self.deps, includeLibs=includeLibs) if d not in excl] def __str__(self): @@ -698,14 +698,14 @@ abspath = _make_absolute(path, self.suite.dir) if not optional and not exists(abspath): if not len(urls): - abort('Non-optional library {} must either exist at {} or specify one or more URLs from which it can be retrieved'.format(name, abspath)) + abort('Non-optional library {0} must either exist at {1} or specify one or more URLs from which it can be retrieved'.format(name, abspath)) def _checkSha1PropertyCondition(propName, cond, inputPath): if not cond: absInputPath = _make_absolute(inputPath, self.suite.dir) if exists(absInputPath): - abort('Missing "{}" property for library {}. Add the following line to projects file:\nlibrary@{}@{}={}'.format(propName, name, name, propName, sha1OfFile(absInputPath))) - abort('Missing "{}" property for library {}'.format(propName, name)) + abort('Missing "{0}" property for library {1}. Add the following line to projects file:\nlibrary@{2}@{3}={4}'.format(propName, name, name, propName, sha1OfFile(absInputPath))) + abort('Missing "{0}" property for library {1}'.format(propName, name)) _checkSha1PropertyCondition('sha1', sha1, path) _checkSha1PropertyCondition('sourceSha1', not sourcePath or sourceSha1, sourcePath) @@ -880,7 +880,7 @@ if not existing: suite[s] = additional else: - conflicting = additional.keys() & existing.keys() + conflicting = frozenset(additional.keys()) & frozenset(existing.keys()) if conflicting: abort(modulePath + ' redefines: ' + ', '.join(conflicting)) existing.update(additional) @@ -1181,12 +1181,12 @@ finally: d.optional = True if not path: - logv('[omitting optional library {} as {} does not exist]'.format(d, d.path)) + logv('[omitting optional library {0} as {1} does not exist]'.format(d, d.path)) del _libs[d.name] self.libs.remove(d) elif d.isProject(): if java(d.javaCompliance) is None: - logv('[omitting project {} as Java compliance {} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance)) + logv('[omitting project {0} as Java compliance {1} cannot be satisfied by configured JDKs]'.format(d, d.javaCompliance)) del _projects[d.name] self.projects.remove(d) else: @@ -1195,19 +1195,19 @@ if jreLib: if not jreLib.is_present_in_jdk(java(d.javaCompliance)): if jreLib.optional: - logv('[omitting project {} as dependency {} is missing]'.format(d, name)) + logv('[omitting project {0} as dependency {1} is missing]'.format(d, name)) del _projects[d.name] self.projects.remove(d) else: - abort('JRE library {} required by {} not found'.format(jreLib, d)) + abort('JRE library {0} required by {1} not found'.format(jreLib, d)) elif not dependency(name, fatalIfMissing=False): - logv('[omitting project {} as dependency {} is missing]'.format(d, name)) + logv('[omitting project {0} as dependency {1} is missing]'.format(d, name)) del _projects[d.name] self.projects.remove(d) for dist in _dists.itervalues(): for name in list(dist.deps): if not dependency(name, fatalIfMissing=False): - logv('[omitting {} from distribution {}]'.format(name, dist)) + logv('[omitting {0} from distribution {1}]'.format(name, dist)) dist.deps.remove(name) if hasattr(self, 'mx_post_parse_cmd_line'): @@ -1673,6 +1673,9 @@ opts = self.parse_args() + global _opts + _opts = opts + # Give the timeout options a default value to avoid the need for hasattr() tests opts.__dict__.setdefault('timeout', 0) opts.__dict__.setdefault('ptimeout', 0) @@ -2209,7 +2212,7 @@ the object's value is printed and the exit status is one. """ - if _opts.killwithsigquit: + if _opts and _opts.killwithsigquit: _send_sigquit() def is_alive(p): @@ -2227,7 +2230,7 @@ _kill_process_group(p.pid, signal.SIGKILL) except BaseException as e: if is_alive(p): - log('error while killing subprocess {} "{}": {}'.format(p.pid, ' '.join(args), e)) + log('error while killing subprocess {0} "{1}": {2}'.format(p.pid, ' '.join(args), e)) if _opts and _opts.verbose: import traceback @@ -2304,7 +2307,7 @@ return self.proj.name def logCompilation(self, compiler): - log('Compiling Java sources for {} with {}... [{}]'.format(self.proj.name, compiler, self.reason)) + log('Compiling Java sources for {0} with {1}... [{2}]'.format(self.proj.name, compiler, self.reason)) def execute(self): argfileName = join(self.proj.dir, 'javafilelist.txt') @@ -2688,8 +2691,8 @@ failed += joinTasks(active) if len(failed): for t in failed: - log('Compiling {} failed'.format(t.proj.name)) - abort('{} Java compilation tasks failed'.format(len(failed))) + log('Compiling {0} failed'.format(t.proj.name)) + abort('{0} Java compilation tasks failed'.format(len(failed))) if args.java: for dist in sorted_dists(): @@ -3039,7 +3042,7 @@ candidates.difference_update(c.all_deps([], False, False)) candidates = [d.name for d in candidates] - abort('{} does not use any packages defined in these projects: {}\nComputed project dependencies: {}'.format( + abort('{0} does not use any packages defined in these projects: {1}\nComputed project dependencies: {2}'.format( p, ', '.join(ignoredDeps), ','.join(candidates))) excess = frozenset(p.deps) - set(p.canonical_deps()) @@ -3166,7 +3169,7 @@ if name == 'file': source[0] = attrs['name'] elif name == 'error': - errors.append('{}:{}: {}'.format(source[0], attrs['line'], attrs['message'])) + errors.append('{0}:{1}: {2}'.format(source[0], attrs['line'], attrs['message'])) xp = xml.parsers.expat.ParserCreate() xp.StartElementHandler = start_element @@ -4782,9 +4785,9 @@ if not 'version' in subprocess.check_output(['dot', '-V'], stderr=subprocess.STDOUT): dotErr = 'dot -V does not print a string containing "version"' except subprocess.CalledProcessError as e: - dotErr = 'error calling "dot -V": {}'.format(e) + dotErr = 'error calling "dot -V": {0}'.format(e) except OSError as e: - dotErr = 'error calling "dot -V": {}'.format(e) + dotErr = 'error calling "dot -V": {0}'.format(e) if dotErr != None: abort('cannot generate dependency graph: ' + dotErr) @@ -4824,7 +4827,7 @@ # Create HTML that embeds the svg file in an frame with open(html, 'w') as fp: - print >> fp, ''.format(args.dot_output_base) + print >> fp, ''.format(args.dot_output_base) if exists(args.base): shutil.rmtree(args.base) @@ -5177,9 +5180,9 @@ abort('no primary suite found') opts, commandAndArgs = _argParser._parse_cmd_line() - - global _opts, _java_homes - _opts = opts + assert _opts == opts + + global _java_homes defaultJdk = JavaConfig(opts.java_home, opts.java_dbg_port) _java_homes = [defaultJdk] if opts.extra_java_homes: diff -r 02b5114b74c1 -r e22a21b27036 src/cpu/x86/vm/nativeInst_x86.hpp --- a/src/cpu/x86/vm/nativeInst_x86.hpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/cpu/x86/vm/nativeInst_x86.hpp Sun Dec 07 20:43:33 2014 +0100 @@ -562,26 +562,24 @@ (ubyte_at(0) & 0xF0) == 0x70; /* short jump */ } inline bool NativeInstruction::is_safepoint_poll() { #ifdef AMD64 - if (Assembler::is_polling_page_far()) { - // two cases, depending on the choice of the base register in the address. - if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix && - ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl && - (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) || - ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && - (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) { - return true; - } else { - return false; - } - } else { - if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && - ubyte_at(1) == 0x05) { // 00 rax 101 - address fault = addr_at(6) + int_at(2); - return os::is_poll_address(fault); - } else { - return false; - } + // Try decoding a near safepoint first: + if (ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && + ubyte_at(1) == 0x05) { // 00 rax 101 + address fault = addr_at(6) + int_at(2); + NOT_GRAAL(assert(!Assembler::is_polling_page_far(), "unexpected poll encoding");) + return os::is_poll_address(fault); } + // Now try decoding a far safepoint: + // two cases, depending on the choice of the base register in the address. + if (((ubyte_at(0) & NativeTstRegMem::instruction_rex_prefix_mask) == NativeTstRegMem::instruction_rex_prefix && + ubyte_at(1) == NativeTstRegMem::instruction_code_memXregl && + (ubyte_at(2) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) || + ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl && + (ubyte_at(1) & NativeTstRegMem::modrm_mask) == NativeTstRegMem::modrm_reg) { + NOT_GRAAL(assert(Assembler::is_polling_page_far(), "unexpected poll encoding");) + return true; + } + return false; #else return ( ubyte_at(0) == NativeMovRegMem::instruction_code_mem2reg || ubyte_at(0) == NativeTstRegMem::instruction_code_memXregl ) && diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.cpp Sun Dec 07 20:43:33 2014 +0100 @@ -96,6 +96,10 @@ oop SystemDictionary::graal_loader() { return _graal_loader; } +void SystemDictionary::init_graal_loader(oop loader) { + assert(UseGraalClassLoader == (loader != NULL), "must be"); + _graal_loader = loader; +} #endif // lazily initialized klass variables @@ -1931,18 +1935,6 @@ } } -#ifdef GRAAL -void SystemDictionary::initialize_preloaded_graal_classes(TRAPS) { - assert(WK_KLASS(CompilerThread_klass) == NULL, "preloaded Graal classes should only be initialized once"); - if (UseGraalClassLoader) { - _graal_loader = GraalRuntime::compute_graal_class_loader(CHECK); - } - - WKID scan = FIRST_GRAAL_WKID; - initialize_wk_klasses_through(LAST_GRAAL_WKID, scan, CHECK); -} -#endif - // Tells if a given klass is a box (wrapper class, such as java.lang.Integer). // If so, returns the basic type it holds. If not, returns T_OBJECT. BasicType SystemDictionary::box_klass_type(Klass* k) { diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/classfile/systemDictionary.hpp Sun Dec 07 20:43:33 2014 +0100 @@ -185,8 +185,7 @@ \ /* Support for Graal */ \ do_klass(BitSet_klass, java_util_BitSet, Opt ) \ - /* Graal classes */ \ - GRAAL_ONLY(do_klass(CompilerThread_klass, com_oracle_graal_compiler_CompilerThread, Graal)) \ + /* Graal classes. These are loaded on-demand. */ \ GRAAL_ONLY(do_klass(Node_klass, com_oracle_graal_graph_Node, Graal)) \ GRAAL_ONLY(do_klass(NodeClass_klass, com_oracle_graal_graph_NodeClass, Graal)) \ GRAAL_ONLY(do_klass(HotSpotCompiledCode_klass, com_oracle_graal_hotspot_HotSpotCompiledCode, Graal)) \ @@ -262,7 +261,7 @@ WKID_LIMIT, #ifdef GRAAL - FIRST_GRAAL_WKID = WK_KLASS_ENUM_NAME(CompilerThread_klass), + FIRST_GRAAL_WKID = WK_KLASS_ENUM_NAME(Node_klass), LAST_GRAAL_WKID = WK_KLASS_ENUM_NAME(AbstractValue_klass), #endif @@ -538,6 +537,8 @@ // Returns the Graal loader. This will be NULL if !UseGraalClassLoader // in which case it's equivalent to the boot loader static oop graal_loader(); + // Sets the Graal loader. This is called at most once. + static void init_graal_loader(oop loader); #endif // Compute the default system loader @@ -705,10 +706,6 @@ public: static bool is_ext_class_loader(Handle class_loader); -#ifdef GRAAL - static void initialize_preloaded_graal_classes(TRAPS); -#endif - private: static Klass* find_shared_class(Symbol* class_name); diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Sun Dec 07 20:43:33 2014 +0100 @@ -291,7 +291,6 @@ \ /* Support for Graal */ \ template(java_util_BitSet, "java/util/BitSet") \ - GRAAL_ONLY(template(com_oracle_graal_compiler_CompilerThread, "com/oracle/graal/compiler/CompilerThread")) \ GRAAL_ONLY(template(com_oracle_graal_graph_Node, "com/oracle/graal/graph/Node")) \ GRAAL_ONLY(template(com_oracle_graal_graph_NodeClass, "com/oracle/graal/graph/NodeClass")) \ GRAAL_ONLY(template(com_oracle_graal_hotspot_HotSpotGraalRuntime, "com/oracle/graal/hotspot/HotSpotGraalRuntime")) \ diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/graal/graalCompiler.cpp --- a/src/share/vm/graal/graalCompiler.cpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/graal/graalCompiler.cpp Sun Dec 07 20:43:33 2014 +0100 @@ -115,6 +115,7 @@ return; } + GraalRuntime::ensure_graal_class_loader_is_initialized(); HandleMark hm; ResourceMark rm; JavaValue result(T_VOID); diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/graal/graalRuntime.cpp Sun Dec 07 20:43:33 2014 +0100 @@ -49,6 +49,8 @@ AMD64_ONLY(guarantee(heap_end < allocation_end, "heap end too close to end of address space (might lead to erroneous TLAB allocations)")); NOT_LP64(error("check TLAB allocation code for address space conflicts")); + ensure_graal_class_loader_is_initialized(); + JavaThread* THREAD = JavaThread::current(); { ThreadToNativeFromVM trans(THREAD); @@ -656,6 +658,13 @@ return value; JRT_END +// private static void Factory.init() +JVM_ENTRY(void, JVM_InitGraalClassLoader(JNIEnv *env, jclass c, jobject loader_handle)) + SystemDictionary::init_graal_loader(JNIHandles::resolve(loader_handle)); + SystemDictionary::WKID scan = SystemDictionary::FIRST_GRAAL_WKID; + SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_GRAAL_WKID, scan, CHECK); +JVM_END + // private static GraalRuntime Graal.initializeRuntime() JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c)) return GraalRuntime::get_HotSpotGraalRuntime_jobject(); @@ -670,6 +679,7 @@ // private static TruffleRuntime Truffle.createRuntime() JVM_ENTRY(jobject, JVM_CreateTruffleRuntime(JNIEnv *env, jclass c)) + GraalRuntime::ensure_graal_class_loader_is_initialized(); TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/truffle/hotspot/HotSpotTruffleRuntime", CHECK_NULL); KlassHandle klass = GraalRuntime::resolve_or_fail(name, CHECK_NULL); @@ -748,6 +758,48 @@ return result; JVM_END + +void GraalRuntime::ensure_graal_class_loader_is_initialized() { + // This initialization code is guarded by a static pointer to the Factory class. + // Once it is non-null, the Graal class loader and well known Graal classes are + // guaranteed to have been initialized. By going through the static + // initializer of Factory, we can rely on class initialization semantics to + // synchronize threads racing to do the initialization. + static Klass* _FactoryKlass = NULL; + if (_FactoryKlass == NULL) { + Thread* THREAD = Thread::current(); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/loader/Factory", CHECK_ABORT); + KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, THREAD); + if (HAS_PENDING_EXCEPTION) { + static volatile int seen_error = 0; + if (!seen_error && Atomic::cmpxchg(1, &seen_error, 0) == 0) { + // Only report the failure on the first thread that hits it + abort_on_pending_exception(PENDING_EXCEPTION, "Graal classes are not available"); + } else { + CLEAR_PENDING_EXCEPTION; + // Give first thread time to report the error. + os::sleep(THREAD, 100, false); + vm_abort(false); + } + } + + // We cannot use graalJavaAccess for this because we are currently in the + // process of initializing that mechanism. + TempNewSymbol field_name = SymbolTable::new_symbol("useGraalClassLoader", CHECK_ABORT); + fieldDescriptor field_desc; + if (klass->find_field(field_name, vmSymbols::bool_signature(), &field_desc) == NULL) { + ResourceMark rm; + fatal(err_msg("Invalid layout of %s at %s", field_name->as_C_string(), klass->external_name())); + } + + InstanceKlass* ik = InstanceKlass::cast(klass()); + address addr = ik->static_field_addr(field_desc.offset() - InstanceMirrorKlass::offset_of_static_fields()); + *((jboolean *) addr) = (jboolean) UseGraalClassLoader; + klass->initialize(CHECK_ABORT); + _FactoryKlass = klass(); + } +} + jint GraalRuntime::check_arguments(TRAPS) { KlassHandle nullHandle; parse_arguments(nullHandle, THREAD); @@ -800,6 +852,7 @@ } void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { + ensure_graal_class_loader_is_initialized(); char first = arg[0]; char* name; size_t name_len; @@ -1017,17 +1070,6 @@ thread); } -oop GraalRuntime::compute_graal_class_loader(TRAPS) { - assert(UseGraalClassLoader, "must be"); - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/loader/Factory", CHECK_NULL); - KlassHandle klass = SystemDictionary::resolve_or_fail(name, true, CHECK_NULL); - - TempNewSymbol getClassLoader = SymbolTable::new_symbol("newClassLoader", CHECK_NULL); - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, klass, getClassLoader, vmSymbols::void_classloader_signature(), CHECK_NULL); - return (oop) result.get_jobject(); -} - void GraalRuntime::abort_on_pending_exception(Handle exception, const char* message, bool dump_core) { Thread* THREAD = Thread::current(); CLEAR_PENDING_EXCEPTION; diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/graal/graalRuntime.hpp Sun Dec 07 20:43:33 2014 +0100 @@ -127,6 +127,11 @@ public: + /** + * Ensures that the Graal class loader is initialized and the well known Graal classes are loaded. + */ + static void ensure_graal_class_loader_is_initialized(); + static void initialize_natives(JNIEnv *env, jclass c2vmClass); static bool is_HotSpotGraalRuntime_initialized() { return _HotSpotGraalRuntime_initialized; } @@ -200,11 +205,6 @@ */ static Klass* load_required_class(Symbol* name); - /** - * Creates a separate class loader for classes in graal.jar and graal-truffle.jar. - */ - static oop compute_graal_class_loader(TRAPS); - static BufferBlob* initialize_buffer_blob(); /** diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/prims/nativeLookup.cpp Sun Dec 07 20:43:33 2014 +0100 @@ -127,6 +127,7 @@ void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); #ifdef GRAAL + void JNICALL JVM_InitGraalClassLoader(JNIEnv *env, jclass c, jobject loader); void JNICALL JVM_InitializeGraalNatives(JNIEnv *env, jclass compilerToVMClass); jobject JNICALL JVM_GetGraalRuntime(JNIEnv *env, jclass c); jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c); @@ -148,6 +149,7 @@ { CC"Java_sun_misc_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, #ifdef GRAAL + { CC"Java_com_oracle_graal_hotspot_loader_Factory_init", NULL, FN_PTR(JVM_InitGraalClassLoader) }, { CC"Java_com_oracle_graal_api_runtime_Graal_initializeRuntime", NULL, FN_PTR(JVM_GetGraalRuntime) }, { CC"Java_com_oracle_graal_api_runtime_Services_getServiceImpls", NULL, FN_PTR(JVM_GetGraalServiceImpls) }, { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, diff -r 02b5114b74c1 -r e22a21b27036 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Dec 05 11:09:57 2014 +0100 +++ b/src/share/vm/runtime/thread.cpp Sun Dec 07 20:43:33 2014 +0100 @@ -1433,7 +1433,7 @@ bool graal_counters_include(JavaThread* thread) { oop threadObj = thread->threadObj(); - return !GraalCountersExcludeCompiler || (!thread->is_Compiler_thread() && (threadObj == NULL || threadObj->klass() != SystemDictionary::CompilerThread_klass())); + return !GraalCountersExcludeCompiler || !thread->is_Compiler_thread(); } void JavaThread::collect_counters(typeArrayOop array) { @@ -3686,11 +3686,6 @@ // set_init_completed has just been called, causing exceptions not to be shortcut // anymore. We call vm_exit_during_initialization directly instead. SystemDictionary::compute_java_system_loader(THREAD); -#ifdef GRAAL - if (!HAS_PENDING_EXCEPTION) { - SystemDictionary::initialize_preloaded_graal_classes(THREAD); - } -#endif if (HAS_PENDING_EXCEPTION) { vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); }