# HG changeset patch # User Roland Schatz # Date 1437049068 -7200 # Node ID 8c2f3922bb9eca43c28db950df01b25def9142e2 # Parent 179db500f6e537471ca9b408220e04b3713b4e3b Make LocationMarker extensible. diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Thu Jul 16 07:47:07 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,451 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.lir.alloc.lsra; - -import static jdk.internal.jvmci.code.ValueUtil.*; - -import java.util.*; -import java.util.function.*; - -import jdk.internal.jvmci.code.*; -import jdk.internal.jvmci.debug.*; -import jdk.internal.jvmci.meta.*; - -import com.oracle.graal.compiler.common.alloc.*; -import com.oracle.graal.compiler.common.cfg.*; -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.lir.gen.*; -import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; -import com.oracle.graal.lir.phases.*; - -/** - * Mark all live references for a frame state. The frame state use this information to build the OOP - * maps. - */ -public final class LocationMarker extends AllocationPhase { - - @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, - RegisterAllocationConfig registerAllocationConfig) { - new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); - } - - /** - * Ensures that an element is only in the worklist once. - * - * @param - */ - static class UniqueWorkList> extends ArrayDeque { - private static final long serialVersionUID = 8009554570990975712L; - BitSet valid; - - public UniqueWorkList(int size) { - this.valid = new BitSet(size); - } - - @Override - public T poll() { - T result = super.poll(); - if (result != null) { - valid.set(result.getId(), false); - } - return result; - } - - @Override - public boolean add(T pred) { - if (!valid.get(pred.getId())) { - valid.set(pred.getId(), true); - return super.add(pred); - } - return false; - } - - @Override - public boolean addAll(Collection collection) { - boolean changed = false; - for (T element : collection) { - if (!valid.get(element.getId())) { - valid.set(element.getId(), true); - super.add(element); - changed = true; - } - } - return changed; - } - } - - private static final class ValueSet { - private Value[] values; - - ValueSet() { - values = Value.NO_VALUES; - } - - ValueSet(ValueSet other) { - int limit = other.values.length; - while (limit > 0) { - if (other.values[limit - 1] == null) { - limit--; - continue; - } - break; - } - values = new Value[limit]; - System.arraycopy(other.values, 0, values, 0, values.length); - } - - void put(int index, Value value) { - if (value != null && value.getLIRKind().isValue()) { - return; - } - if (values.length <= index) { - if (value == null) { - return; - } - Value[] newValues = new Value[index + 1]; - System.arraycopy(values, 0, newValues, 0, values.length); - values = newValues; - values[index] = value; - } else { - values[index] = value; - } - } - - public void putAll(ValueSet stack) { - Value[] otherValues = stack.values; - int limit = otherValues.length; - if (limit > values.length) { - while (limit > 0) { - if (otherValues[limit - 1] == null) { - limit--; - continue; - } - break; - } - if (limit > values.length) { - Value[] newValues = new Value[limit]; - System.arraycopy(values, 0, newValues, 0, values.length); - values = newValues; - } - } - for (int i = 0; i < limit; i++) { - Value value = otherValues[i]; - if (value != null) { - values[i] = value; - } - } - } - - @Override - public boolean equals(Object other) { - if (other instanceof ValueSet) { - ValueSet that = (ValueSet) other; - int limit = Math.min(values.length, that.values.length); - for (int i = 0; i < limit; i++) { - if (!Objects.equals(values[i], that.values[i])) { - return false; - } - } - for (int i = limit; i < values.length; i++) { - if (values[i] != null) { - return false; - } - } - for (int i = limit; i < that.values.length; i++) { - if (that.values[i] != null) { - return false; - } - } - return true; - } - return false; - } - - public void addLiveValues(ReferenceMap refMap) { - for (Value v : values) { - if (v != null) { - refMap.addLiveValue(v); - } - } - } - - @Override - public int hashCode() { - throw new UnsupportedOperationException(); - } - } - - private static final class Marker> { - - private final class LiveValueSet implements Consumer> { - - public void accept(AbstractBlockBase succ) { - putAll(liveInMap.get(succ)); - } - - private final ValueSet registers; - private final ValueSet stack; - private Set extraStack; - - public LiveValueSet() { - registers = new ValueSet(); - stack = new ValueSet(); - } - - public LiveValueSet(LiveValueSet s) { - registers = new ValueSet(s.registers); - stack = new ValueSet(s.stack); - if (s.extraStack != null) { - extraStack = new HashSet<>(s.extraStack); - } - } - - public void put(Value v) { - if (isRegister(v)) { - int index = asRegister(v).getReferenceMapIndex(); - registers.put(index, v); - } else if (isStackSlot(v)) { - int index = frameMap.offsetForStackSlot(asStackSlot(v)); - assert index >= 0; - if (index % 4 == 0) { - stack.put(index / 4, v); - } else { - if (extraStack == null) { - extraStack = new HashSet<>(); - } - extraStack.add(v); - } - } - } - - public void putAll(LiveValueSet v) { - registers.putAll(v.registers); - stack.putAll(v.stack); - if (v.extraStack != null) { - if (extraStack == null) { - extraStack = new HashSet<>(); - } - extraStack.addAll(v.extraStack); - } - } - - public void remove(Value v) { - if (isRegister(v)) { - int index = asRegister(v).getReferenceMapIndex(); - registers.put(index, null); - } else if (isStackSlot(v)) { - int index = frameMap.offsetForStackSlot(asStackSlot(v)); - assert index >= 0; - if (index % 4 == 0) { - stack.put(index / 4, null); - } else if (extraStack != null) { - extraStack.remove(v); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public boolean equals(Object obj) { - if (obj instanceof Marker.LiveValueSet) { - LiveValueSet other = (LiveValueSet) obj; - return registers.equals(other.registers) && stack.equals(other.stack) && Objects.equals(extraStack, other.extraStack); - } else { - return false; - } - } - - @Override - public int hashCode() { - throw new UnsupportedOperationException(); - } - - public void addLiveValues(ReferenceMap refMap) { - registers.addLiveValues(refMap); - stack.addLiveValues(refMap); - if (extraStack != null) { - for (Value v : extraStack) { - refMap.addLiveValue(v); - } - } - } - } - - private final LIR lir; - private final FrameMap frameMap; - private final RegisterAttributes[] registerAttributes; - private final BlockMap liveInMap; - private final BlockMap liveOutMap; - - private Marker(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()); - } - - @SuppressWarnings("unchecked") - void build() { - UniqueWorkList worklist = new UniqueWorkList<>(lir.getControlFlowGraph().getBlocks().size()); - for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) { - worklist.add((T) lir.getControlFlowGraph().getBlocks().get(i)); - } - for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { - liveInMap.put(block, new LiveValueSet()); - } - while (!worklist.isEmpty()) { - AbstractBlockBase block = worklist.poll(); - processBlock(block, worklist); - } - } - - /** - * Merge outSet with in-set of successors. - */ - private boolean updateOutBlock(AbstractBlockBase block) { - LiveValueSet union = new LiveValueSet(); - block.getSuccessors().forEach(union); - LiveValueSet outSet = liveOutMap.get(block); - // check if changed - if (outSet == null || !union.equals(outSet)) { - liveOutMap.put(block, union); - return true; - } - return false; - } - - private void processBlock(AbstractBlockBase block, UniqueWorkList worklist) { - if (updateOutBlock(block)) { - try (Indent indent = Debug.logAndIndent("handle block %s", block)) { - currentSet = new LiveValueSet(liveOutMap.get(block)); - List instructions = lir.getLIRforBlock(block); - for (int i = instructions.size() - 1; i >= 0; i--) { - LIRInstruction inst = instructions.get(i); - processInstructionBottomUp(inst); - } - liveInMap.put(block, currentSet); - currentSet = null; - 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 LiveValueSet 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(defConsumer); - op.visitEachOutput(defConsumer); - if (op.destroysCallerSavedRegisters()) { - for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { - defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); - } - } - - // gen - values that are considered alive for this state - op.visitEachAlive(useConsumer); - op.visitEachState(useConsumer); - // mark locations - op.forEachState(stateConsumer); - // gen - op.visitEachInput(useConsumer); - } - } - - InstructionStateProcedure stateConsumer = new InstructionStateProcedure() { - public void doState(LIRInstruction inst, LIRFrameState info) { - markLocation(inst, info, currentSet); - } - }; - - ValueConsumer useConsumer = new ValueConsumer() { - public void visitValue(Value operand, OperandMode mode, EnumSet flags) { - if (shouldProcessValue(operand)) { - // no need to insert values and derived reference - if (Debug.isLogEnabled()) { - Debug.log("set operand: %s", operand); - } - currentSet.put(operand); - } - } - }; - - ValueConsumer defConsumer = new ValueConsumer() { - public void visitValue(Value operand, OperandMode mode, EnumSet flags) { - if (shouldProcessValue(operand)) { - if (Debug.isLogEnabled()) { - Debug.log("clear operand: %s", operand); - } - currentSet.remove(operand); - } else { - assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s", - operand, mode); - } - } - }; - - protected boolean shouldProcessValue(Value operand) { - return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal; - } - - /** - * This method does the actual marking. - */ - private void markLocation(LIRInstruction op, LIRFrameState info, LiveValueSet values) { - if (!info.hasDebugInfo()) { - info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved()); - } - - ReferenceMap refMap = info.debugInfo().getReferenceMap(); - refMap.reset(); - frameMap.addLiveValues(refMap); - values.addLiveValues(refMap); - refMap.finish(); - } - - /** - * 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 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LiveValueSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LiveValueSet.java Thu Jul 16 14:17:48 2015 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.dfa; + +import jdk.internal.jvmci.meta.*; + +abstract class LiveValueSet> { + + public abstract void put(Value v); + + public abstract void remove(Value v); + + public abstract void putAll(S s); + + public abstract S copy(); +} diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarker.java Thu Jul 16 14:17:48 2015 +0200 @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.dfa; + +import static jdk.internal.jvmci.code.ValueUtil.*; + +import java.util.*; + +import jdk.internal.jvmci.code.*; +import jdk.internal.jvmci.debug.*; +import jdk.internal.jvmci.meta.*; + +import com.oracle.graal.compiler.common.cfg.*; +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.*; + +public abstract class LocationMarker, S extends LiveValueSet> { + + private final LIR lir; + private final BlockMap liveInMap; + private final BlockMap liveOutMap; + + protected final FrameMap frameMap; + + protected LocationMarker(LIR lir, FrameMap frameMap) { + this.lir = lir; + this.frameMap = frameMap; + liveInMap = new BlockMap<>(lir.getControlFlowGraph()); + liveOutMap = new BlockMap<>(lir.getControlFlowGraph()); + } + + protected abstract S newLiveValueSet(); + + protected abstract boolean shouldProcessValue(Value operand); + + protected abstract void processState(LIRInstruction op, LIRFrameState info, S values); + + @SuppressWarnings("unchecked") + void build() { + UniqueWorkList worklist = new UniqueWorkList<>(lir.getControlFlowGraph().getBlocks().size()); + for (int i = lir.getControlFlowGraph().getBlocks().size() - 1; i >= 0; i--) { + worklist.add((T) lir.getControlFlowGraph().getBlocks().get(i)); + } + for (AbstractBlockBase block : lir.getControlFlowGraph().getBlocks()) { + liveInMap.put(block, newLiveValueSet()); + } + while (!worklist.isEmpty()) { + AbstractBlockBase block = worklist.poll(); + processBlock(block, worklist); + } + } + + /** + * Merge outSet with in-set of successors. + */ + private boolean updateOutBlock(AbstractBlockBase block) { + S union = newLiveValueSet(); + for (T succ : block.getSuccessors()) { + union.putAll(liveInMap.get(succ)); + } + S outSet = liveOutMap.get(block); + // check if changed + if (outSet == null || !union.equals(outSet)) { + liveOutMap.put(block, union); + return true; + } + return false; + } + + private void processBlock(AbstractBlockBase block, UniqueWorkList worklist) { + if (updateOutBlock(block)) { + try (Indent indent = Debug.logAndIndent("handle block %s", block)) { + currentSet = liveOutMap.get(block).copy(); + List instructions = lir.getLIRforBlock(block); + for (int i = instructions.size() - 1; i >= 0; i--) { + LIRInstruction inst = instructions.get(i); + processInstructionBottomUp(inst); + } + liveInMap.put(block, currentSet); + currentSet = null; + 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 S 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(defConsumer); + op.visitEachOutput(defConsumer); + if (op.destroysCallerSavedRegisters()) { + for (Register reg : frameMap.getRegisterConfig().getCallerSaveRegisters()) { + defConsumer.visitValue(reg.asValue(REFERENCE_KIND), OperandMode.TEMP, REGISTER_FLAG_SET); + } + } + + // gen - values that are considered alive for this state + op.visitEachAlive(useConsumer); + op.visitEachState(useConsumer); + // mark locations + op.forEachState(stateConsumer); + // gen + op.visitEachInput(useConsumer); + } + } + + InstructionStateProcedure stateConsumer = new InstructionStateProcedure() { + public void doState(LIRInstruction inst, LIRFrameState info) { + processState(inst, info, currentSet); + } + }; + + ValueConsumer useConsumer = new ValueConsumer() { + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { + if (shouldProcessValue(operand)) { + // no need to insert values and derived reference + if (Debug.isLogEnabled()) { + Debug.log("set operand: %s", operand); + } + currentSet.put(operand); + } + } + }; + + ValueConsumer defConsumer = new ValueConsumer() { + public void visitValue(Value operand, OperandMode mode, EnumSet flags) { + if (shouldProcessValue(operand)) { + if (Debug.isLogEnabled()) { + Debug.log("clear operand: %s", operand); + } + currentSet.remove(operand); + } else { + assert isIllegal(operand) || operand.getPlatformKind() != Kind.Illegal || mode == OperandMode.TEMP : String.format("Illegal PlatformKind is only allowed for TEMP mode: %s, %s", + operand, mode); + } + } + }; +} diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarkerPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/LocationMarkerPhase.java Thu Jul 16 14:17:48 2015 +0200 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.dfa; + +import static jdk.internal.jvmci.code.ValueUtil.*; + +import java.util.*; + +import jdk.internal.jvmci.code.*; +import jdk.internal.jvmci.meta.*; + +import com.oracle.graal.compiler.common.alloc.*; +import com.oracle.graal.compiler.common.cfg.*; +import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; +import com.oracle.graal.lir.phases.*; + +/** + * Mark all live references for a frame state. The frame state use this information to build the OOP + * maps. + */ +public final class LocationMarkerPhase extends AllocationPhase { + + @Override + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { + new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); + } + + private static final class Marker> extends LocationMarker.RegStackValueSet> { + + private final class RegStackValueSet extends LiveValueSet.RegStackValueSet> { + + private final ValueSet registers; + private final ValueSet stack; + private Set extraStack; + + public RegStackValueSet() { + registers = new ValueSet(); + stack = new ValueSet(); + } + + private RegStackValueSet(RegStackValueSet s) { + registers = new ValueSet(s.registers); + stack = new ValueSet(s.stack); + if (s.extraStack != null) { + extraStack = new HashSet<>(s.extraStack); + } + } + + @Override + public Marker.RegStackValueSet copy() { + return new RegStackValueSet(this); + } + + @Override + public void put(Value v) { + if (isRegister(v)) { + int index = asRegister(v).getReferenceMapIndex(); + registers.put(index, v); + } else if (isStackSlot(v)) { + int index = frameMap.offsetForStackSlot(asStackSlot(v)); + assert index >= 0; + if (index % 4 == 0) { + stack.put(index / 4, v); + } else { + if (extraStack == null) { + extraStack = new HashSet<>(); + } + extraStack.add(v); + } + } + } + + @Override + public void putAll(RegStackValueSet v) { + registers.putAll(v.registers); + stack.putAll(v.stack); + if (v.extraStack != null) { + if (extraStack == null) { + extraStack = new HashSet<>(); + } + extraStack.addAll(v.extraStack); + } + } + + @Override + public void remove(Value v) { + if (isRegister(v)) { + int index = asRegister(v).getReferenceMapIndex(); + registers.put(index, null); + } else if (isStackSlot(v)) { + int index = frameMap.offsetForStackSlot(asStackSlot(v)); + assert index >= 0; + if (index % 4 == 0) { + stack.put(index / 4, null); + } else if (extraStack != null) { + extraStack.remove(v); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public boolean equals(Object obj) { + if (obj instanceof Marker.RegStackValueSet) { + RegStackValueSet other = (RegStackValueSet) obj; + return registers.equals(other.registers) && stack.equals(other.stack) && Objects.equals(extraStack, other.extraStack); + } else { + return false; + } + } + + @Override + public int hashCode() { + throw new UnsupportedOperationException(); + } + + public void addLiveValues(ReferenceMap refMap) { + registers.addLiveValues(refMap); + stack.addLiveValues(refMap); + if (extraStack != null) { + for (Value v : extraStack) { + refMap.addLiveValue(v); + } + } + } + } + + private final RegisterAttributes[] registerAttributes; + + private Marker(LIR lir, FrameMap frameMap) { + super(lir, frameMap); + this.registerAttributes = frameMap.getRegisterConfig().getAttributesMap(); + } + + @Override + protected Marker.RegStackValueSet newLiveValueSet() { + return new RegStackValueSet(); + } + + @Override + protected boolean shouldProcessValue(Value operand) { + return (isRegister(operand) && attributes(asRegister(operand)).isAllocatable() || isStackSlot(operand)) && operand.getPlatformKind() != Kind.Illegal; + } + + /** + * This method does the actual marking. + */ + @Override + protected void processState(LIRInstruction op, LIRFrameState info, RegStackValueSet values) { + if (!info.hasDebugInfo()) { + info.initDebugInfo(frameMap, !op.destroysCallerSavedRegisters() || !frameMap.getRegisterConfig().areAllAllocatableRegistersCallerSaved()); + } + + ReferenceMap refMap = info.debugInfo().getReferenceMap(); + refMap.reset(); + frameMap.addLiveValues(refMap); + values.addLiveValues(refMap); + refMap.finish(); + } + + /** + * Gets an object describing the attributes of a given register according to this register + * configuration. + */ + private RegisterAttributes attributes(Register reg) { + return registerAttributes[reg.number]; + } + + } +} diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/UniqueWorkList.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/UniqueWorkList.java Thu Jul 16 14:17:48 2015 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.dfa; + +import java.util.*; + +import com.oracle.graal.compiler.common.cfg.*; + +/** + * Ensures that an element is only in the worklist once. + * + * @param + */ +class UniqueWorkList> extends ArrayDeque { + private static final long serialVersionUID = 8009554570990975712L; + BitSet valid; + + public UniqueWorkList(int size) { + this.valid = new BitSet(size); + } + + @Override + public T poll() { + T result = super.poll(); + if (result != null) { + valid.set(result.getId(), false); + } + return result; + } + + @Override + public boolean add(T pred) { + if (!valid.get(pred.getId())) { + valid.set(pred.getId(), true); + return super.add(pred); + } + return false; + } + + @Override + public boolean addAll(Collection collection) { + boolean changed = false; + for (T element : collection) { + if (!valid.get(element.getId())) { + valid.set(element.getId(), true); + super.add(element); + changed = true; + } + } + return changed; + } +} diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/ValueSet.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/dfa/ValueSet.java Thu Jul 16 14:17:48 2015 +0200 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.dfa; + +import java.util.*; + +import jdk.internal.jvmci.code.*; +import jdk.internal.jvmci.meta.*; + +final class ValueSet { + private Value[] values; + + ValueSet() { + values = Value.NO_VALUES; + } + + ValueSet(ValueSet other) { + int limit = other.values.length; + while (limit > 0) { + if (other.values[limit - 1] == null) { + limit--; + continue; + } + break; + } + values = new Value[limit]; + System.arraycopy(other.values, 0, values, 0, values.length); + } + + void put(int index, Value value) { + if (value != null && value.getLIRKind().isValue()) { + return; + } + if (values.length <= index) { + if (value == null) { + return; + } + Value[] newValues = new Value[index + 1]; + System.arraycopy(values, 0, newValues, 0, values.length); + values = newValues; + values[index] = value; + } else { + values[index] = value; + } + } + + public void putAll(ValueSet stack) { + Value[] otherValues = stack.values; + int limit = otherValues.length; + if (limit > values.length) { + while (limit > 0) { + if (otherValues[limit - 1] == null) { + limit--; + continue; + } + break; + } + if (limit > values.length) { + Value[] newValues = new Value[limit]; + System.arraycopy(values, 0, newValues, 0, values.length); + values = newValues; + } + } + for (int i = 0; i < limit; i++) { + Value value = otherValues[i]; + if (value != null) { + values[i] = value; + } + } + } + + @Override + public boolean equals(Object other) { + if (other instanceof ValueSet) { + ValueSet that = (ValueSet) other; + int limit = Math.min(values.length, that.values.length); + for (int i = 0; i < limit; i++) { + if (!Objects.equals(values[i], that.values[i])) { + return false; + } + } + for (int i = limit; i < values.length; i++) { + if (values[i] != null) { + return false; + } + } + for (int i = limit; i < that.values.length; i++) { + if (that.values[i] != null) { + return false; + } + } + return true; + } + return false; + } + + public void addLiveValues(ReferenceMap refMap) { + for (Value v : values) { + if (v != null) { + refMap.addLiveValue(v); + } + } + } + + @Override + public int hashCode() { + throw new UnsupportedOperationException(); + } +} diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java Thu Jul 16 07:47:07 2015 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationStage.java Thu Jul 16 14:17:48 2015 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.lir.phases; import com.oracle.graal.lir.alloc.lsra.*; +import com.oracle.graal.lir.dfa.*; import com.oracle.graal.lir.phases.AllocationPhase.AllocationContext; import com.oracle.graal.lir.stackslotalloc.*; @@ -37,6 +38,6 @@ appendPhase(new SimpleStackSlotAllocator()); } // currently we mark locations only if we do register allocation - appendPhase(new LocationMarker()); + appendPhase(new LocationMarkerPhase()); } } diff -r 179db500f6e5 -r 8c2f3922bb9e graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/EconomyAllocationStage.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/EconomyAllocationStage.java Thu Jul 16 07:47:07 2015 -0700 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/EconomyAllocationStage.java Thu Jul 16 14:17:48 2015 +0200 @@ -23,6 +23,7 @@ package com.oracle.graal.lir.phases; import com.oracle.graal.lir.alloc.lsra.*; +import com.oracle.graal.lir.dfa.*; import com.oracle.graal.lir.phases.AllocationPhase.AllocationContext; import com.oracle.graal.lir.stackslotalloc.*; @@ -34,6 +35,6 @@ appendPhase(new SimpleStackSlotAllocator()); // currently we mark locations only if we do register allocation - appendPhase(new LocationMarker()); + appendPhase(new LocationMarkerPhase()); } }