Mercurial > hg > truffle
changeset 18443:1c92d437179b
FrameMapBuilder: move into package.
line wrap: on
line diff
--- a/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.baseline/src/com/oracle/graal/baseline/BaselineBytecodeParser.java Mon Nov 17 16:41:44 2014 +0100 @@ -43,6 +43,7 @@ import com.oracle.graal.java.BciBlockMapping.LocalLiveness; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.BlockEndOp; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.phases.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Mon Nov 17 16:41:44 2014 +0100 @@ -44,6 +44,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; import com.oracle.graal.lir.constopt.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.cfg.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/alloc/LinearScan.java Mon Nov 17 16:41:44 2014 +0100 @@ -42,11 +42,11 @@ import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; import com.oracle.graal.lir.*; -import com.oracle.graal.lir.FrameMapBuilder.FrameMappable; -import com.oracle.graal.lir.FrameMapBuilder.FrameMappingTool; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.framemap.*; +import com.oracle.graal.lir.framemap.FrameMapBuilder.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.options.*;
--- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Mon Nov 17 16:41:44 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Mon Nov 17 16:41:44 2014 +0100 @@ -46,6 +46,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*;
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; /** * Emits code that enters a stack frame which is tailored to call the C++ method
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveCurrentStackFrameOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; /** * Pops the current frame off the stack including the return address and restores the return
--- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.amd64.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; /** * Emits code that leaves a stack frame which is tailored to call the C++ method
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackend.java Mon Nov 17 16:41:44 2014 +0100 @@ -65,6 +65,7 @@ import com.oracle.graal.java.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp;
--- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotLIRGenerationResult.java Mon Nov 17 16:41:44 2014 +0100 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.hsail.HSAILControlFlow.DeoptimizingOp;
--- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Mon Nov 17 16:41:44 2014 +0100 @@ -48,6 +48,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.ptx.PTXControlFlow.PTXPredicatedLIRInstruction; import com.oracle.graal.lir.ptx.*;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Mon Nov 17 16:41:44 2014 +0100 @@ -51,6 +51,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.lir.sparc.*; import com.oracle.graal.nodes.*;
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotLIRGenerationResult.java Mon Nov 17 16:41:44 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.hotspot.stubs.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.lir.gen.*; public class SPARCHotSpotLIRGenerationResult extends LIRGenerationResultBase {
--- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotRegisterConfig.java Mon Nov 17 16:41:44 2014 +0100 @@ -33,7 +33,7 @@ import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.hotspot.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.sparc.*; public class SPARCHotSpotRegisterConfig implements RegisterConfig {
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotBackend.java Mon Nov 17 16:41:44 2014 +0100 @@ -40,6 +40,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.LabelOp; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.nodes.*; import com.oracle.graal.phases.tiers.*; import com.oracle.graal.word.*;
--- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotLockStack.java Mon Nov 17 16:41:44 2014 +0100 @@ -26,7 +26,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; /** * Manages allocation and re-use of lock slots in a scoped manner. The slots are used in HotSpot's
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMap.java Mon Nov 17 16:41:44 2014 +0100 @@ -27,7 +27,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; /** * AMD64 specific frame map. @@ -36,7 +36,7 @@ * * <pre> * Base Contents - * + * * : : ----- * caller | incoming overflow argument n | ^ * frame : ... : | positive
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMapBuilder.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64FrameMapBuilder.java Mon Nov 17 16:41:44 2014 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.lir.amd64; import com.oracle.graal.api.code.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; public class AMD64FrameMapBuilder extends DelayedFrameMapBuilder {
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64SaveRegistersOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; /** * Saves registers to stack slots.
--- a/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ZapRegistersOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; /** * Writes well known garbage values to registers.
--- a/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILFrameMap.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.hsail/src/com/oracle/graal/lir/hsail/HSAILFrameMap.java Mon Nov 17 16:41:44 2014 +0100 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; /** * HSAIL specific frame map.
--- a/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXFrameMap.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.ptx/src/com/oracle/graal/lir/ptx/PTXFrameMap.java Mon Nov 17 16:41:44 2014 +0100 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; /** * PTX specific frame map.
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCFrameMap.java Mon Nov 17 16:41:44 2014 +0100 @@ -25,7 +25,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.sparc.*; /**
--- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCSaveRegistersOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.lir.*; import com.oracle.graal.lir.StandardOp.SaveRegistersOp; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.sparc.*; /**
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/DelayedFrameMapBuilder.java Mon Nov 17 16:14:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,188 +0,0 @@ -/* - * 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.lir; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.asm.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.lir.gen.*; - -/** - * A FrameMapBuilder that records allocation. - */ -public class DelayedFrameMapBuilder implements FrameMapBuilder { - - @FunctionalInterface - public interface FrameMapFactory { - FrameMap newFrameMap(RegisterConfig registerConfig); - } - - private final RegisterConfig registerConfig; - private final CodeCacheProvider codeCache; - protected final FrameMap frameMap; - private final List<TrackedVirtualStackSlot> stackSlots; - private final List<CallingConvention> calls; - - public DelayedFrameMapBuilder(FrameMapFactory factory, CodeCacheProvider codeCache, RegisterConfig registerConfig) { - this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig; - this.codeCache = codeCache; - this.frameMap = factory.newFrameMap(registerConfig); - this.stackSlots = new ArrayList<>(); - this.calls = new ArrayList<>(); - this.mappables = new ArrayList<>(); - } - - private final List<FrameMappable> mappables; - - public VirtualStackSlot allocateSpillSlot(LIRKind kind) { - SimpleVirtualStackSlot slot = new SimpleVirtualStackSlot(kind); - stackSlots.add(slot); - return slot; - } - - public abstract class TrackedVirtualStackSlot extends VirtualStackSlot { - /** - * - */ - private static final long serialVersionUID = 408446797222290182L; - - public TrackedVirtualStackSlot(LIRKind lirKind) { - super(lirKind); - } - - public abstract StackSlot transform(); - } - - private class SimpleVirtualStackSlot extends TrackedVirtualStackSlot { - - private static final long serialVersionUID = 7654295701165421750L; - - public SimpleVirtualStackSlot(LIRKind lirKind) { - super(lirKind); - } - - @Override - public StackSlot transform() { - int size = frameMap.spillSlotSize(getLIRKind()); - frameMap.spillSize = NumUtil.roundUp(frameMap.spillSize + size, size); - return frameMap.allocateNewSpillSlot(getLIRKind(), 0); - } - - } - - private class VirtualStackSlotRange extends TrackedVirtualStackSlot { - - private static final long serialVersionUID = 5152592950118317121L; - private final BitSet objects; - private final int slots; - - public VirtualStackSlotRange(int slots, BitSet objects) { - super(LIRKind.reference(Kind.Object)); - this.slots = slots; - this.objects = (BitSet) objects.clone(); - } - - @Override - public StackSlot transform() { - frameMap.spillSize += (slots * frameMap.getTarget().wordSize); - - if (!objects.isEmpty()) { - assert objects.length() <= slots; - StackSlot result = null; - for (int slotIndex = 0; slotIndex < slots; slotIndex++) { - StackSlot objectSlot = null; - if (objects.get(slotIndex)) { - objectSlot = frameMap.allocateNewSpillSlot(LIRKind.reference(Kind.Object), slotIndex * frameMap.getTarget().wordSize); - frameMap.addObjectStackSlot(objectSlot); - } - if (slotIndex == 0) { - if (objectSlot != null) { - result = objectSlot; - } else { - result = frameMap.allocateNewSpillSlot(LIRKind.value(frameMap.getTarget().wordKind), 0); - } - } - } - assert result != null; - return result; - - } else { - return frameMap.allocateNewSpillSlot(LIRKind.value(frameMap.getTarget().wordKind), 0); - } - } - - } - - public VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) { - if (slots == 0) { - return null; - } - if (outObjectStackSlots != null) { - throw GraalInternalError.unimplemented(); - } - VirtualStackSlotRange slot = new VirtualStackSlotRange(slots, objects); - stackSlots.add(slot); - return slot; - } - - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - - public CodeCacheProvider getCodeCache() { - return codeCache; - } - - public void callsMethod(CallingConvention cc) { - calls.add(cc); - } - - public FrameMap buildFrameMap(LIRGenerationResult res) { - HashMap<VirtualStackSlot, StackSlot> mapping = new HashMap<>(); - // fill - mapStackSlots(mapping); - for (CallingConvention cc : calls) { - frameMap.callsMethod(cc); - } - // rewrite - mappables.forEach(m -> m.map(mapping::get)); - - frameMap.finish(); - return frameMap; - } - - protected void mapStackSlots(HashMap<VirtualStackSlot, StackSlot> mapping) { - for (TrackedVirtualStackSlot virtualSlot : stackSlots) { - StackSlot slot = virtualSlot.transform(); - mapping.put(virtualSlot, slot); - } - } - - public void requireMapping(FrameMappable mappable) { - this.mappables.add(mappable); - } - -}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMap.java Mon Nov 17 16:14:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2009, 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.lir; - -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.asm.*; - -/** - * This class is used to build the stack frame layout for a compiled method. A {@link StackSlot} is - * used to index slots of the frame relative to the stack pointer. The frame size is only fixed - * after register allocation when all spill slots have been allocated. Both the outgoing argument - * area and the spill are can grow until then. Therefore, outgoing arguments are indexed from the - * stack pointer, while spill slots are indexed from the beginning of the frame (and the total frame - * size has to be added to get the actual offset from the stack pointer). - */ -public abstract class FrameMap { - - private final TargetDescription target; - private final RegisterConfig registerConfig; - - /** - * The final frame size, not including the size of the - * {@link Architecture#getReturnAddressSize() return address slot}. The value is only set after - * register allocation is complete, i.e., after all spill slots have been allocated. - */ - private int frameSize; - - /** - * Initial size of the area occupied by spill slots and other stack-allocated memory blocks. - */ - protected int initialSpillSize; - - /** - * Size of the area occupied by spill slots and other stack-allocated memory blocks. - */ - protected int spillSize; - - /** - * Size of the area occupied by outgoing overflow arguments. This value is adjusted as calling - * conventions for outgoing calls are retrieved. On some platforms, there is a minimum outgoing - * size even if no overflow arguments are on the stack. - */ - protected int outgoingSize; - - /** - * Determines if this frame has values on the stack for outgoing calls. - */ - private boolean hasOutgoingStackArguments; - - /** - * The list of stack slots allocated in this frame that are present in every reference map. - */ - private final List<StackSlot> objectStackSlots; - - /** - * Records whether an offset to an incoming stack argument was ever returned by - * {@link #offsetForStackSlot(StackSlot)}. - */ - private boolean accessesCallerFrame; - - /** - * Creates a new frame map for the specified method. The given registerConfig is optional, in - * case null is passed the default RegisterConfig from the CodeCacheProvider will be used. - */ - public FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig) { - this.target = codeCache.getTarget(); - this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig; - this.frameSize = -1; - this.outgoingSize = codeCache.getMinimumOutgoingSize(); - this.objectStackSlots = new ArrayList<>(); - } - - public RegisterConfig getRegisterConfig() { - return registerConfig; - } - - public TargetDescription getTarget() { - return target; - } - - protected int returnAddressSize() { - return getTarget().arch.getReturnAddressSize(); - } - - protected int calleeSaveAreaSize() { - CalleeSaveLayout csl = getRegisterConfig().getCalleeSaveLayout(); - return csl != null ? csl.size : 0; - } - - /** - * Determines if an offset to an incoming stack argument was ever returned by - * {@link #offsetForStackSlot(StackSlot)}. - */ - public boolean accessesCallerFrame() { - return accessesCallerFrame; - } - - /** - * Gets the frame size of the compiled frame, not including the size of the - * {@link Architecture#getReturnAddressSize() return address slot}. - * - * @return The size of the frame (in bytes). - */ - public int frameSize() { - assert frameSize != -1 : "frame size not computed yet"; - return frameSize; - } - - public int outgoingSize() { - return outgoingSize; - } - - /** - * Determines if any space is used in the frame apart from the - * {@link Architecture#getReturnAddressSize() return address slot}. - */ - public boolean frameNeedsAllocating() { - int unalignedFrameSize = spillSize - returnAddressSize(); - return hasOutgoingStackArguments || unalignedFrameSize != 0; - } - - /** - * Gets the total frame size of the compiled frame, including the size of the - * {@link Architecture#getReturnAddressSize() return address slot}. - * - * @return The total size of the frame (in bytes). - */ - public abstract int totalFrameSize(); - - /** - * Gets the current size of this frame. This is the size that would be returned by - * {@link #frameSize()} if {@link #finish()} were called now. - */ - public abstract int currentFrameSize(); - - /** - * Aligns the given frame size to the stack alignment size and return the aligned size. - * - * @param size the initial frame size to be aligned - * @return the aligned frame size - */ - protected abstract int alignFrameSize(int size); - - /** - * Computes the final size of this frame. After this method has been called, methods that change - * the frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can - * be requested. - */ - public void finish() { - frameSize = currentFrameSize(); - if (frameSize > getRegisterConfig().getMaximumFrameSize()) { - throw new BailoutException("Frame size (%d) exceeded maximum allowed frame size (%d).", frameSize, getRegisterConfig().getMaximumFrameSize()); - } - } - - /** - * Computes the offset of a stack slot relative to the frame register. - * - * @param slot a stack slot - * @return the offset of the stack slot - */ - public int offsetForStackSlot(StackSlot slot) { - // @formatter:off - assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) || - (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) || - (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0) : - String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize); - // @formatter:on - if (slot.isInCallerFrame()) { - accessesCallerFrame = true; - } - return slot.getOffset(totalFrameSize()); - } - - /** - * Gets the offset from the stack pointer to the stack area where callee-saved registers are - * stored. - * - * @return The offset to the callee save area (in bytes). - */ - public abstract int offsetToCalleeSaveArea(); - - /** - * Informs the frame map that the compiled code calls a particular method, which may need stack - * space for outgoing arguments. - * - * @param cc The calling convention for the called method. - */ - public void callsMethod(CallingConvention cc) { - reserveOutgoing(cc.getStackSize()); - } - - /** - * Reserves space for stack-based outgoing arguments. - * - * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments. - */ - public void reserveOutgoing(int argsSize) { - assert frameSize == -1 : "frame size must not yet be fixed"; - outgoingSize = Math.max(outgoingSize, argsSize); - hasOutgoingStackArguments = hasOutgoingStackArguments || argsSize > 0; - } - - /** - * Reserves a new spill slot in the frame of the method being compiled. The returned slot is - * aligned on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte - * boundary. - * - * @param kind The kind of the spill slot to be reserved. - * @param additionalOffset - * @return A spill slot denoting the reserved memory area. - */ - protected abstract StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset); - - /** - * Returns the spill slot size for the given {@link LIRKind}. The default value is the size in - * bytes for the target architecture. - * - * @param kind the {@link LIRKind} to be stored in the spill slot. - * @return the size in bytes - */ - public int spillSlotSize(LIRKind kind) { - return getTarget().getSizeInBytes(kind.getPlatformKind()); - } - - /** - * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned - * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary, unless - * overridden by a subclass. - * - * @param kind The kind of the spill slot to be reserved. - * @return A spill slot denoting the reserved memory area. - */ - protected StackSlot allocateSpillSlot(LIRKind kind) { - assert frameSize == -1 : "frame size must not yet be fixed"; - int size = spillSlotSize(kind); - spillSize = NumUtil.roundUp(spillSize + size, size); - return allocateNewSpillSlot(kind, 0); - } - - /** - * Reserves a number of contiguous slots in the frame of the method being compiled. If the - * requested number of slots is 0, this method returns {@code null}. - * - * @param slots the number of slots to reserve - * @param objects specifies the indexes of the object pointer slots. The caller is responsible - * for guaranteeing that each such object pointer slot is initialized before any - * instruction that uses a reference map. Without this guarantee, the garbage - * collector could see garbage object values. - * @return the first reserved stack slot (i.e., at the lowest address) - */ - protected StackSlot allocateStackSlots(int slots, BitSet objects) { - assert frameSize == -1 : "frame size must not yet be fixed"; - if (slots == 0) { - return null; - } - spillSize += (slots * getTarget().wordSize); - - if (!objects.isEmpty()) { - assert objects.length() <= slots; - StackSlot result = null; - for (int slotIndex = 0; slotIndex < slots; slotIndex++) { - StackSlot objectSlot = null; - if (objects.get(slotIndex)) { - objectSlot = allocateNewSpillSlot(LIRKind.reference(Kind.Object), slotIndex * getTarget().wordSize); - addObjectStackSlot(objectSlot); - } - if (slotIndex == 0) { - if (objectSlot != null) { - result = objectSlot; - } else { - result = allocateNewSpillSlot(LIRKind.value(getTarget().wordKind), 0); - } - } - } - assert result != null; - return result; - - } else { - return allocateNewSpillSlot(LIRKind.value(getTarget().wordKind), 0); - } - } - - protected void addObjectStackSlot(StackSlot objectSlot) { - objectStackSlots.add(objectSlot); - } - - public ReferenceMap initReferenceMap(boolean hasRegisters) { - ReferenceMap refMap = getTarget().createReferenceMap(hasRegisters, frameSize() / getTarget().wordSize); - for (StackSlot slot : objectStackSlots) { - setReference(slot, refMap); - } - return refMap; - } - - /** - * Marks the specified location as a reference in the reference map of the debug information. - * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a - * {@link JavaConstant} is automatically tracked. - * - * @param location The location to be added to the reference map. - * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}. - */ - public void setReference(Value location, ReferenceMap refMap) { - LIRKind kind = location.getLIRKind(); - if (isRegister(location)) { - refMap.setRegister(asRegister(location).getReferenceMapIndex(), kind); - } else if (isStackSlot(location)) { - int offset = offsetForStackSlot(asStackSlot(location)); - refMap.setStackSlot(offset, kind); - } else { - assert isConstant(location); - } - } -}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/FrameMapBuilder.java Mon Nov 17 16:14:47 2014 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +0,0 @@ -/* - * 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.lir; - -import java.util.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.lir.gen.*; - -/** - * A {@link FrameMapBuilder} is used to collect all information necessary to - * {@linkplain #buildFrameMap create} a {@link FrameMap}. - */ -public interface FrameMapBuilder { - - /** - * A tool to get the real stack slot from a virtual stack slot. - */ - @FunctionalInterface - interface FrameMappingTool { - StackSlot getStackSlot(VirtualStackSlot slot); - } - - /** - * This interface should be implemented by all classes that store virtual stack slots to convert - * them into real stack slots when {@link FrameMapBuilder#buildFrameMap} is called. - */ - interface FrameMappable { - void map(FrameMappingTool tool); - } - - /** - * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned - * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary, unless - * overridden by a subclass. - * - * @param kind The kind of the spill slot to be reserved. - * @return A spill slot denoting the reserved memory area. - */ - VirtualStackSlot allocateSpillSlot(LIRKind kind); - - /** - * Reserves a number of contiguous slots in the frame of the method being compiled. If the - * requested number of slots is 0, this method returns {@code null}. - * - * @param slots the number of slots to reserve - * @param objects specifies the indexes of the object pointer slots. The caller is responsible - * for guaranteeing that each such object pointer slot is initialized before any - * instruction that uses a reference map. Without this guarantee, the garbage - * collector could see garbage object values. - * @param outObjectStackSlots if non-null, the object pointer slots allocated are added to this - * list - * @return the first reserved stack slot (i.e., at the lowest address) - */ - VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots); - - RegisterConfig getRegisterConfig(); - - CodeCacheProvider getCodeCache(); - - /** - * Informs the frame map that the compiled code calls a particular method, which may need stack - * space for outgoing arguments. - * - * @param cc The calling convention for the called method. - */ - void callsMethod(CallingConvention cc); - - /** - * Registers a FrameMappable class so that virtual stack slots can be changed to real stack - * slots. - */ - void requireMapping(FrameMappable mappable); - - /** - * Creates a {@linkplain FrameMap} based on the information collected by this - * {@linkplain FrameMapBuilder}. - */ - FrameMap buildFrameMap(LIRGenerationResult result); -}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIR.java Mon Nov 17 16:41:44 2014 +0100 @@ -31,10 +31,9 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.lir.FrameMapBuilder.FrameMappable; -import com.oracle.graal.lir.FrameMapBuilder.FrameMappingTool; import com.oracle.graal.lir.StandardOp.BlockEndOp; import com.oracle.graal.lir.StandardOp.LabelOp; +import com.oracle.graal.lir.framemap.FrameMapBuilder.*; /** * This class implements the overall container for the LIR graph and directs its construction,
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRFrameState.java Mon Nov 17 16:41:44 2014 +0100 @@ -30,6 +30,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.framemap.*; /** * This class represents garbage collection and deoptimization information attached to a LIR
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/LIRVerifier.java Mon Nov 17 16:41:44 2014 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.debug.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; +import com.oracle.graal.lir.framemap.*; public final class LIRVerifier {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/RedundantMoveElimination.java Mon Nov 17 16:41:44 2014 +0100 @@ -33,6 +33,7 @@ import com.oracle.graal.lir.LIRInstruction.OperandFlag; import com.oracle.graal.lir.LIRInstruction.OperandMode; import com.oracle.graal.lir.StandardOp.MoveOp; +import com.oracle.graal.lir.framemap.*; /** * Removes move instructions, where the destination value is already in place.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/StandardOp.java Mon Nov 17 16:41:44 2014 +0100 @@ -32,6 +32,7 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; /** * A collection of machine-independent LIR operations, as well as interfaces to be implemented for
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilder.java Mon Nov 17 16:41:44 2014 +0100 @@ -37,6 +37,7 @@ import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; /** * Fills in a {@link CompilationResult} as its code is being assembled.
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilderFactory.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/asm/CompilationResultBuilderFactory.java Mon Nov 17 16:41:44 2014 +0100 @@ -24,7 +24,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.asm.*; -import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; /** * Factory class for creating {@link CompilationResultBuilder}s.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/DelayedFrameMapBuilder.java Mon Nov 17 16:41:44 2014 +0100 @@ -0,0 +1,188 @@ +/* + * 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.lir.framemap; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.asm.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.lir.gen.*; + +/** + * A FrameMapBuilder that records allocation. + */ +public class DelayedFrameMapBuilder implements FrameMapBuilder { + + @FunctionalInterface + public interface FrameMapFactory { + FrameMap newFrameMap(RegisterConfig registerConfig); + } + + private final RegisterConfig registerConfig; + private final CodeCacheProvider codeCache; + protected final FrameMap frameMap; + private final List<TrackedVirtualStackSlot> stackSlots; + private final List<CallingConvention> calls; + + public DelayedFrameMapBuilder(FrameMapFactory factory, CodeCacheProvider codeCache, RegisterConfig registerConfig) { + this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig; + this.codeCache = codeCache; + this.frameMap = factory.newFrameMap(registerConfig); + this.stackSlots = new ArrayList<>(); + this.calls = new ArrayList<>(); + this.mappables = new ArrayList<>(); + } + + private final List<FrameMappable> mappables; + + public VirtualStackSlot allocateSpillSlot(LIRKind kind) { + SimpleVirtualStackSlot slot = new SimpleVirtualStackSlot(kind); + stackSlots.add(slot); + return slot; + } + + public abstract class TrackedVirtualStackSlot extends VirtualStackSlot { + /** + * + */ + private static final long serialVersionUID = 408446797222290182L; + + public TrackedVirtualStackSlot(LIRKind lirKind) { + super(lirKind); + } + + public abstract StackSlot transform(); + } + + private class SimpleVirtualStackSlot extends TrackedVirtualStackSlot { + + private static final long serialVersionUID = 7654295701165421750L; + + public SimpleVirtualStackSlot(LIRKind lirKind) { + super(lirKind); + } + + @Override + public StackSlot transform() { + int size = frameMap.spillSlotSize(getLIRKind()); + frameMap.spillSize = NumUtil.roundUp(frameMap.spillSize + size, size); + return frameMap.allocateNewSpillSlot(getLIRKind(), 0); + } + + } + + private class VirtualStackSlotRange extends TrackedVirtualStackSlot { + + private static final long serialVersionUID = 5152592950118317121L; + private final BitSet objects; + private final int slots; + + public VirtualStackSlotRange(int slots, BitSet objects) { + super(LIRKind.reference(Kind.Object)); + this.slots = slots; + this.objects = (BitSet) objects.clone(); + } + + @Override + public StackSlot transform() { + frameMap.spillSize += (slots * frameMap.getTarget().wordSize); + + if (!objects.isEmpty()) { + assert objects.length() <= slots; + StackSlot result = null; + for (int slotIndex = 0; slotIndex < slots; slotIndex++) { + StackSlot objectSlot = null; + if (objects.get(slotIndex)) { + objectSlot = frameMap.allocateNewSpillSlot(LIRKind.reference(Kind.Object), slotIndex * frameMap.getTarget().wordSize); + frameMap.addObjectStackSlot(objectSlot); + } + if (slotIndex == 0) { + if (objectSlot != null) { + result = objectSlot; + } else { + result = frameMap.allocateNewSpillSlot(LIRKind.value(frameMap.getTarget().wordKind), 0); + } + } + } + assert result != null; + return result; + + } else { + return frameMap.allocateNewSpillSlot(LIRKind.value(frameMap.getTarget().wordKind), 0); + } + } + + } + + public VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots) { + if (slots == 0) { + return null; + } + if (outObjectStackSlots != null) { + throw GraalInternalError.unimplemented(); + } + VirtualStackSlotRange slot = new VirtualStackSlotRange(slots, objects); + stackSlots.add(slot); + return slot; + } + + public RegisterConfig getRegisterConfig() { + return registerConfig; + } + + public CodeCacheProvider getCodeCache() { + return codeCache; + } + + public void callsMethod(CallingConvention cc) { + calls.add(cc); + } + + public FrameMap buildFrameMap(LIRGenerationResult res) { + HashMap<VirtualStackSlot, StackSlot> mapping = new HashMap<>(); + // fill + mapStackSlots(mapping); + for (CallingConvention cc : calls) { + frameMap.callsMethod(cc); + } + // rewrite + mappables.forEach(m -> m.map(mapping::get)); + + frameMap.finish(); + return frameMap; + } + + protected void mapStackSlots(HashMap<VirtualStackSlot, StackSlot> mapping) { + for (TrackedVirtualStackSlot virtualSlot : stackSlots) { + StackSlot slot = virtualSlot.transform(); + mapping.put(virtualSlot, slot); + } + } + + public void requireMapping(FrameMappable mappable) { + this.mappables.add(mappable); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMap.java Mon Nov 17 16:41:44 2014 +0100 @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2009, 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.lir.framemap; + +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.asm.*; + +/** + * This class is used to build the stack frame layout for a compiled method. A {@link StackSlot} is + * used to index slots of the frame relative to the stack pointer. The frame size is only fixed + * after register allocation when all spill slots have been allocated. Both the outgoing argument + * area and the spill are can grow until then. Therefore, outgoing arguments are indexed from the + * stack pointer, while spill slots are indexed from the beginning of the frame (and the total frame + * size has to be added to get the actual offset from the stack pointer). + */ +public abstract class FrameMap { + + private final TargetDescription target; + private final RegisterConfig registerConfig; + + /** + * The final frame size, not including the size of the + * {@link Architecture#getReturnAddressSize() return address slot}. The value is only set after + * register allocation is complete, i.e., after all spill slots have been allocated. + */ + private int frameSize; + + /** + * Initial size of the area occupied by spill slots and other stack-allocated memory blocks. + */ + protected int initialSpillSize; + + /** + * Size of the area occupied by spill slots and other stack-allocated memory blocks. + */ + protected int spillSize; + + /** + * Size of the area occupied by outgoing overflow arguments. This value is adjusted as calling + * conventions for outgoing calls are retrieved. On some platforms, there is a minimum outgoing + * size even if no overflow arguments are on the stack. + */ + protected int outgoingSize; + + /** + * Determines if this frame has values on the stack for outgoing calls. + */ + private boolean hasOutgoingStackArguments; + + /** + * The list of stack slots allocated in this frame that are present in every reference map. + */ + private final List<StackSlot> objectStackSlots; + + /** + * Records whether an offset to an incoming stack argument was ever returned by + * {@link #offsetForStackSlot(StackSlot)}. + */ + private boolean accessesCallerFrame; + + /** + * Creates a new frame map for the specified method. The given registerConfig is optional, in + * case null is passed the default RegisterConfig from the CodeCacheProvider will be used. + */ + public FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig) { + this.target = codeCache.getTarget(); + this.registerConfig = registerConfig == null ? codeCache.getRegisterConfig() : registerConfig; + this.frameSize = -1; + this.outgoingSize = codeCache.getMinimumOutgoingSize(); + this.objectStackSlots = new ArrayList<>(); + } + + public RegisterConfig getRegisterConfig() { + return registerConfig; + } + + public TargetDescription getTarget() { + return target; + } + + protected int returnAddressSize() { + return getTarget().arch.getReturnAddressSize(); + } + + protected int calleeSaveAreaSize() { + CalleeSaveLayout csl = getRegisterConfig().getCalleeSaveLayout(); + return csl != null ? csl.size : 0; + } + + /** + * Determines if an offset to an incoming stack argument was ever returned by + * {@link #offsetForStackSlot(StackSlot)}. + */ + public boolean accessesCallerFrame() { + return accessesCallerFrame; + } + + /** + * Gets the frame size of the compiled frame, not including the size of the + * {@link Architecture#getReturnAddressSize() return address slot}. + * + * @return The size of the frame (in bytes). + */ + public int frameSize() { + assert frameSize != -1 : "frame size not computed yet"; + return frameSize; + } + + public int outgoingSize() { + return outgoingSize; + } + + /** + * Determines if any space is used in the frame apart from the + * {@link Architecture#getReturnAddressSize() return address slot}. + */ + public boolean frameNeedsAllocating() { + int unalignedFrameSize = spillSize - returnAddressSize(); + return hasOutgoingStackArguments || unalignedFrameSize != 0; + } + + /** + * Gets the total frame size of the compiled frame, including the size of the + * {@link Architecture#getReturnAddressSize() return address slot}. + * + * @return The total size of the frame (in bytes). + */ + public abstract int totalFrameSize(); + + /** + * Gets the current size of this frame. This is the size that would be returned by + * {@link #frameSize()} if {@link #finish()} were called now. + */ + public abstract int currentFrameSize(); + + /** + * Aligns the given frame size to the stack alignment size and return the aligned size. + * + * @param size the initial frame size to be aligned + * @return the aligned frame size + */ + protected abstract int alignFrameSize(int size); + + /** + * Computes the final size of this frame. After this method has been called, methods that change + * the frame size cannot be called anymore, e.g., no more spill slots or outgoing arguments can + * be requested. + */ + public void finish() { + frameSize = currentFrameSize(); + if (frameSize > getRegisterConfig().getMaximumFrameSize()) { + throw new BailoutException("Frame size (%d) exceeded maximum allowed frame size (%d).", frameSize, getRegisterConfig().getMaximumFrameSize()); + } + } + + /** + * Computes the offset of a stack slot relative to the frame register. + * + * @param slot a stack slot + * @return the offset of the stack slot + */ + public int offsetForStackSlot(StackSlot slot) { + // @formatter:off + assert (!slot.getRawAddFrameSize() && slot.getRawOffset() < outgoingSize) || + (slot.getRawAddFrameSize() && slot.getRawOffset() < 0 && -slot.getRawOffset() <= spillSize) || + (slot.getRawAddFrameSize() && slot.getRawOffset() >= 0) : + String.format("RawAddFrameSize: %b RawOffset: 0x%x spillSize: 0x%x outgoingSize: 0x%x", slot.getRawAddFrameSize(), slot.getRawOffset(), spillSize, outgoingSize); + // @formatter:on + if (slot.isInCallerFrame()) { + accessesCallerFrame = true; + } + return slot.getOffset(totalFrameSize()); + } + + /** + * Gets the offset from the stack pointer to the stack area where callee-saved registers are + * stored. + * + * @return The offset to the callee save area (in bytes). + */ + public abstract int offsetToCalleeSaveArea(); + + /** + * Informs the frame map that the compiled code calls a particular method, which may need stack + * space for outgoing arguments. + * + * @param cc The calling convention for the called method. + */ + public void callsMethod(CallingConvention cc) { + reserveOutgoing(cc.getStackSize()); + } + + /** + * Reserves space for stack-based outgoing arguments. + * + * @param argsSize The amount of space (in bytes) to reserve for stack-based outgoing arguments. + */ + public void reserveOutgoing(int argsSize) { + assert frameSize == -1 : "frame size must not yet be fixed"; + outgoingSize = Math.max(outgoingSize, argsSize); + hasOutgoingStackArguments = hasOutgoingStackArguments || argsSize > 0; + } + + /** + * Reserves a new spill slot in the frame of the method being compiled. The returned slot is + * aligned on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte + * boundary. + * + * @param kind The kind of the spill slot to be reserved. + * @param additionalOffset + * @return A spill slot denoting the reserved memory area. + */ + protected abstract StackSlot allocateNewSpillSlot(LIRKind kind, int additionalOffset); + + /** + * Returns the spill slot size for the given {@link LIRKind}. The default value is the size in + * bytes for the target architecture. + * + * @param kind the {@link LIRKind} to be stored in the spill slot. + * @return the size in bytes + */ + public int spillSlotSize(LIRKind kind) { + return getTarget().getSizeInBytes(kind.getPlatformKind()); + } + + /** + * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned + * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary, unless + * overridden by a subclass. + * + * @param kind The kind of the spill slot to be reserved. + * @return A spill slot denoting the reserved memory area. + */ + protected StackSlot allocateSpillSlot(LIRKind kind) { + assert frameSize == -1 : "frame size must not yet be fixed"; + int size = spillSlotSize(kind); + spillSize = NumUtil.roundUp(spillSize + size, size); + return allocateNewSpillSlot(kind, 0); + } + + /** + * Reserves a number of contiguous slots in the frame of the method being compiled. If the + * requested number of slots is 0, this method returns {@code null}. + * + * @param slots the number of slots to reserve + * @param objects specifies the indexes of the object pointer slots. The caller is responsible + * for guaranteeing that each such object pointer slot is initialized before any + * instruction that uses a reference map. Without this guarantee, the garbage + * collector could see garbage object values. + * @return the first reserved stack slot (i.e., at the lowest address) + */ + protected StackSlot allocateStackSlots(int slots, BitSet objects) { + assert frameSize == -1 : "frame size must not yet be fixed"; + if (slots == 0) { + return null; + } + spillSize += (slots * getTarget().wordSize); + + if (!objects.isEmpty()) { + assert objects.length() <= slots; + StackSlot result = null; + for (int slotIndex = 0; slotIndex < slots; slotIndex++) { + StackSlot objectSlot = null; + if (objects.get(slotIndex)) { + objectSlot = allocateNewSpillSlot(LIRKind.reference(Kind.Object), slotIndex * getTarget().wordSize); + addObjectStackSlot(objectSlot); + } + if (slotIndex == 0) { + if (objectSlot != null) { + result = objectSlot; + } else { + result = allocateNewSpillSlot(LIRKind.value(getTarget().wordKind), 0); + } + } + } + assert result != null; + return result; + + } else { + return allocateNewSpillSlot(LIRKind.value(getTarget().wordKind), 0); + } + } + + protected void addObjectStackSlot(StackSlot objectSlot) { + objectStackSlots.add(objectSlot); + } + + public ReferenceMap initReferenceMap(boolean hasRegisters) { + ReferenceMap refMap = getTarget().createReferenceMap(hasRegisters, frameSize() / getTarget().wordSize); + for (StackSlot slot : objectStackSlots) { + setReference(slot, refMap); + } + return refMap; + } + + /** + * Marks the specified location as a reference in the reference map of the debug information. + * The tracked location can be a {@link RegisterValue} or a {@link StackSlot}. Note that a + * {@link JavaConstant} is automatically tracked. + * + * @param location The location to be added to the reference map. + * @param refMap A reference map, as created by {@link #initReferenceMap(boolean)}. + */ + public void setReference(Value location, ReferenceMap refMap) { + LIRKind kind = location.getLIRKind(); + if (isRegister(location)) { + refMap.setRegister(asRegister(location).getReferenceMapIndex(), kind); + } else if (isStackSlot(location)) { + int offset = offsetForStackSlot(asStackSlot(location)); + refMap.setStackSlot(offset, kind); + } else { + assert isConstant(location); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/framemap/FrameMapBuilder.java Mon Nov 17 16:41:44 2014 +0100 @@ -0,0 +1,101 @@ +/* + * 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.lir.framemap; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.lir.gen.*; + +/** + * A {@link FrameMapBuilder} is used to collect all information necessary to + * {@linkplain #buildFrameMap create} a {@link FrameMap}. + */ +public interface FrameMapBuilder { + + /** + * A tool to get the real stack slot from a virtual stack slot. + */ + @FunctionalInterface + interface FrameMappingTool { + StackSlot getStackSlot(VirtualStackSlot slot); + } + + /** + * This interface should be implemented by all classes that store virtual stack slots to convert + * them into real stack slots when {@link FrameMapBuilder#buildFrameMap} is called. + */ + interface FrameMappable { + void map(FrameMappingTool tool); + } + + /** + * Reserves a spill slot in the frame of the method being compiled. The returned slot is aligned + * on its natural alignment, i.e., an 8-byte spill slot is aligned at an 8-byte boundary, unless + * overridden by a subclass. + * + * @param kind The kind of the spill slot to be reserved. + * @return A spill slot denoting the reserved memory area. + */ + VirtualStackSlot allocateSpillSlot(LIRKind kind); + + /** + * Reserves a number of contiguous slots in the frame of the method being compiled. If the + * requested number of slots is 0, this method returns {@code null}. + * + * @param slots the number of slots to reserve + * @param objects specifies the indexes of the object pointer slots. The caller is responsible + * for guaranteeing that each such object pointer slot is initialized before any + * instruction that uses a reference map. Without this guarantee, the garbage + * collector could see garbage object values. + * @param outObjectStackSlots if non-null, the object pointer slots allocated are added to this + * list + * @return the first reserved stack slot (i.e., at the lowest address) + */ + VirtualStackSlot allocateStackSlots(int slots, BitSet objects, List<VirtualStackSlot> outObjectStackSlots); + + RegisterConfig getRegisterConfig(); + + CodeCacheProvider getCodeCache(); + + /** + * Informs the frame map that the compiled code calls a particular method, which may need stack + * space for outgoing arguments. + * + * @param cc The calling convention for the called method. + */ + void callsMethod(CallingConvention cc); + + /** + * Registers a FrameMappable class so that virtual stack slots can be changed to real stack + * slots. + */ + void requireMapping(FrameMappable mappable); + + /** + * Creates a {@linkplain FrameMap} based on the information collected by this + * {@linkplain FrameMapBuilder}. + */ + FrameMap buildFrameMap(LIRGenerationResult result); +}
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResult.java Mon Nov 17 16:41:44 2014 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.lir.gen; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; public interface LIRGenerationResult {
--- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/LIRGenerationResultBase.java Mon Nov 17 16:41:44 2014 +0100 @@ -23,6 +23,7 @@ package com.oracle.graal.lir.gen; import com.oracle.graal.lir.*; +import com.oracle.graal.lir.framemap.*; public class LIRGenerationResultBase implements LIRGenerationResult { private final LIR lir;
--- a/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot.amd64/src/com/oracle/graal/truffle/hotspot/amd64/AMD64OptimizedCallTargetInstrumentationFactory.java Mon Nov 17 16:41:44 2014 +0100 @@ -32,8 +32,8 @@ import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.truffle.*; import com.oracle.graal.truffle.hotspot.*;
--- a/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Mon Nov 17 16:14:47 2014 +0100 +++ b/graal/com.oracle.graal.truffle.hotspot/src/com/oracle/graal/truffle/hotspot/OptimizedCallTargetInstrumentation.java Mon Nov 17 16:41:44 2014 +0100 @@ -31,8 +31,8 @@ import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.HotSpotCodeCacheProvider.MarkId; import com.oracle.graal.hotspot.meta.*; -import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; +import com.oracle.graal.lir.framemap.*; import com.oracle.graal.truffle.*; /**