test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestAssembler.java
changeset 47216 71c04702a3d5
parent 43478 72039e58b2a8
child 58851 f1e6442241ca
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 package jdk.vm.ci.code.test;
       
    25 
       
    26 import jdk.vm.ci.code.CallingConvention;
       
    27 import jdk.vm.ci.code.CodeCacheProvider;
       
    28 import jdk.vm.ci.code.DebugInfo;
       
    29 import jdk.vm.ci.code.Register;
       
    30 import jdk.vm.ci.code.StackSlot;
       
    31 import jdk.vm.ci.code.ValueKindFactory;
       
    32 import jdk.vm.ci.code.site.Call;
       
    33 import jdk.vm.ci.code.site.ConstantReference;
       
    34 import jdk.vm.ci.code.site.DataPatch;
       
    35 import jdk.vm.ci.code.site.DataSectionReference;
       
    36 import jdk.vm.ci.code.site.Infopoint;
       
    37 import jdk.vm.ci.code.site.InfopointReason;
       
    38 import jdk.vm.ci.code.site.Mark;
       
    39 import jdk.vm.ci.code.site.Reference;
       
    40 import jdk.vm.ci.code.site.Site;
       
    41 import jdk.vm.ci.hotspot.HotSpotCompiledCode;
       
    42 import jdk.vm.ci.hotspot.HotSpotCompiledCode.Comment;
       
    43 import jdk.vm.ci.hotspot.HotSpotCompiledNmethod;
       
    44 import jdk.vm.ci.hotspot.HotSpotConstant;
       
    45 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
       
    46 import jdk.vm.ci.meta.AllocatableValue;
       
    47 import jdk.vm.ci.meta.Assumptions.Assumption;
       
    48 import jdk.vm.ci.meta.InvokeTarget;
       
    49 import jdk.vm.ci.meta.JavaKind;
       
    50 import jdk.vm.ci.meta.PlatformKind;
       
    51 import jdk.vm.ci.meta.ResolvedJavaMethod;
       
    52 import jdk.vm.ci.meta.VMConstant;
       
    53 import jdk.vm.ci.meta.ValueKind;
       
    54 
       
    55 import java.nio.ByteBuffer;
       
    56 import java.nio.ByteOrder;
       
    57 import java.util.ArrayList;
       
    58 import java.util.Arrays;
       
    59 
       
    60 /**
       
    61  * Simple assembler used by the code installation tests.
       
    62  */
       
    63 public abstract class TestAssembler {
       
    64 
       
    65     /**
       
    66      * Emit the method prologue code (e.g. building the new stack frame).
       
    67      */
       
    68     public abstract void emitPrologue();
       
    69 
       
    70     /**
       
    71      * Emit the method epilogue code (e.g. the deopt handler).
       
    72      */
       
    73     public abstract void emitEpilogue();
       
    74 
       
    75     /**
       
    76      * Emit code to grow the stack frame.
       
    77      *
       
    78      * @param size the size in bytes that the stack should grow
       
    79      */
       
    80     public abstract void emitGrowStack(int size);
       
    81 
       
    82     /**
       
    83      * Get the register containing the first 32-bit integer argument.
       
    84      */
       
    85     public abstract Register emitIntArg0();
       
    86 
       
    87     /**
       
    88      * Get the register containing the second 32-bit integer argument.
       
    89      */
       
    90     public abstract Register emitIntArg1();
       
    91 
       
    92     /**
       
    93      * Emit code to add two 32-bit integer registers. May reuse one of the argument registers.
       
    94      */
       
    95     public abstract Register emitIntAdd(Register a, Register b);
       
    96 
       
    97     /**
       
    98      * Emit code to load a constant 32-bit integer to a register.
       
    99      */
       
   100     public abstract Register emitLoadInt(int value);
       
   101 
       
   102     /**
       
   103      * Emit code to load a constant 64-bit integer to a register.
       
   104      */
       
   105     public abstract Register emitLoadLong(long value);
       
   106 
       
   107     /**
       
   108      * Emit code to load a constant single-precision float to a register.
       
   109      */
       
   110     public abstract Register emitLoadFloat(float value);
       
   111 
       
   112     /**
       
   113      * Emit code to load a constant oop or metaspace pointer to a register. The pointer may be wide
       
   114      * or narrow, depending on {@link HotSpotConstant#isCompressed() c.isCompressed()}.
       
   115      */
       
   116     public abstract Register emitLoadPointer(HotSpotConstant c);
       
   117 
       
   118     /**
       
   119      * Emit code to load a wide pointer from the {@link HotSpotCompiledCode#dataSection} to a
       
   120      * register.
       
   121      */
       
   122     public abstract Register emitLoadPointer(DataSectionReference ref);
       
   123 
       
   124     /**
       
   125      * Emit code to load a narrow pointer from the {@link HotSpotCompiledCode#dataSection} to a
       
   126      * register.
       
   127      */
       
   128     public abstract Register emitLoadNarrowPointer(DataSectionReference ref);
       
   129 
       
   130     /**
       
   131      * Emit code to load a (wide) pointer from a memory location to a register.
       
   132      */
       
   133     public abstract Register emitLoadPointer(Register base, int offset);
       
   134 
       
   135     /**
       
   136      * Emit code to store a 32-bit integer from a register to a new stack slot.
       
   137      */
       
   138     public abstract StackSlot emitIntToStack(Register a);
       
   139 
       
   140     /**
       
   141      * Emit code to store a 64-bit integer from a register to a new stack slot.
       
   142      */
       
   143     public abstract StackSlot emitLongToStack(Register a);
       
   144 
       
   145     /**
       
   146      * Emit code to store a single-precision float from a register to a new stack slot.
       
   147      */
       
   148     public abstract StackSlot emitFloatToStack(Register a);
       
   149 
       
   150     /**
       
   151      * Emit code to store a double-precision float from a register to a new stack slot.
       
   152      */
       
   153     public abstract StackSlot emitDoubleToStack(Register a);
       
   154 
       
   155     /**
       
   156      * Emit code to store a wide pointer from a register to a new stack slot.
       
   157      */
       
   158     public abstract StackSlot emitPointerToStack(Register a);
       
   159 
       
   160     /**
       
   161      * Emit code to store a narrow pointer from a register to a new stack slot.
       
   162      */
       
   163     public abstract StackSlot emitNarrowPointerToStack(Register a);
       
   164 
       
   165     /**
       
   166      * Emit code to uncompress a narrow pointer. The input pointer is guaranteed to be non-null.
       
   167      */
       
   168     public abstract Register emitUncompressPointer(Register compressed, long base, int shift);
       
   169 
       
   170     /**
       
   171      * Emit code to return from a function, returning a 32-bit integer.
       
   172      */
       
   173     public abstract void emitIntRet(Register a);
       
   174 
       
   175     /**
       
   176      * Emit code to return from a function, returning a single precision float.
       
   177      */
       
   178     public abstract void emitFloatRet(Register a);
       
   179 
       
   180     /**
       
   181      * Emit code to return from a function, returning a wide oop pointer.
       
   182      */
       
   183     public abstract void emitPointerRet(Register a);
       
   184 
       
   185     /**
       
   186      * Emit code that traps, forcing a deoptimization.
       
   187      */
       
   188     public abstract void emitTrap(DebugInfo info);
       
   189 
       
   190     public final ValueKind<?> narrowOopKind;
       
   191 
       
   192     protected final Buffer code;
       
   193     protected final Buffer data;
       
   194     private final ArrayList<Site> sites;
       
   195     private final ArrayList<DataPatch> dataPatches;
       
   196 
       
   197     protected final CodeCacheProvider codeCache;
       
   198     protected final TestHotSpotVMConfig config;
       
   199 
       
   200     private final Register[] registers;
       
   201     private int nextRegister;
       
   202 
       
   203     protected int frameSize;
       
   204     private int stackAlignment;
       
   205     private int curStackSlot;
       
   206 
       
   207     private StackSlot deoptRescue;
       
   208 
       
   209     public ValueKindFactory<TestValueKind> valueKindFactory = new ValueKindFactory<TestAssembler.TestValueKind>() {
       
   210         public TestValueKind getValueKind(JavaKind javaKind) {
       
   211             return (TestValueKind) TestAssembler.this.getValueKind(javaKind);
       
   212         }
       
   213     };
       
   214 
       
   215     static class TestValueKind extends ValueKind<TestValueKind> {
       
   216 
       
   217         TestValueKind(PlatformKind kind) {
       
   218             super(kind);
       
   219         }
       
   220 
       
   221         @Override
       
   222         public TestValueKind changeType(PlatformKind kind) {
       
   223             return new TestValueKind(kind);
       
   224         }
       
   225     }
       
   226 
       
   227     protected TestAssembler(CodeCacheProvider codeCache, TestHotSpotVMConfig config, int initialFrameSize, int stackAlignment, PlatformKind narrowOopKind, Register... registers) {
       
   228         this.narrowOopKind = new TestValueKind(narrowOopKind);
       
   229 
       
   230         this.code = new Buffer();
       
   231         this.data = new Buffer();
       
   232         this.sites = new ArrayList<>();
       
   233         this.dataPatches = new ArrayList<>();
       
   234 
       
   235         this.codeCache = codeCache;
       
   236         this.config = config;
       
   237 
       
   238         this.registers = registers;
       
   239         this.nextRegister = 0;
       
   240 
       
   241         this.frameSize = initialFrameSize;
       
   242         this.stackAlignment = stackAlignment;
       
   243         this.curStackSlot = initialFrameSize;
       
   244     }
       
   245 
       
   246     public ValueKind<?> getValueKind(JavaKind kind) {
       
   247         return new TestValueKind(codeCache.getTarget().arch.getPlatformKind(kind));
       
   248     }
       
   249 
       
   250     protected Register newRegister() {
       
   251         return registers[nextRegister++];
       
   252     }
       
   253 
       
   254     protected StackSlot newStackSlot(PlatformKind kind) {
       
   255         growFrame(kind.getSizeInBytes());
       
   256         return StackSlot.get(new TestValueKind(kind), -curStackSlot, true);
       
   257     }
       
   258 
       
   259     public int getOffset(StackSlot slot) {
       
   260         return slot.getOffset(frameSize);
       
   261     }
       
   262 
       
   263     protected void growFrame(int sizeInBytes) {
       
   264         curStackSlot += sizeInBytes;
       
   265         if (curStackSlot > frameSize) {
       
   266             int newFrameSize = curStackSlot;
       
   267             if (newFrameSize % stackAlignment != 0) {
       
   268                 newFrameSize += stackAlignment - (newFrameSize % stackAlignment);
       
   269             }
       
   270             emitGrowStack(newFrameSize - frameSize);
       
   271             frameSize = newFrameSize;
       
   272         }
       
   273     }
       
   274 
       
   275     protected void setDeoptRescueSlot(StackSlot deoptRescue) {
       
   276         this.deoptRescue = deoptRescue;
       
   277     }
       
   278 
       
   279     protected void recordCall(InvokeTarget target, int size, boolean direct, DebugInfo debugInfo) {
       
   280         sites.add(new Call(target, code.position(), size, direct, debugInfo));
       
   281     }
       
   282 
       
   283     protected void recordMark(Object id) {
       
   284         sites.add(new Mark(code.position(), id));
       
   285     }
       
   286 
       
   287     protected void recordImplicitException(DebugInfo info) {
       
   288         sites.add(new Infopoint(code.position(), info, InfopointReason.IMPLICIT_EXCEPTION));
       
   289     }
       
   290 
       
   291     protected void recordDataPatchInCode(Reference ref) {
       
   292         sites.add(new DataPatch(code.position(), ref));
       
   293     }
       
   294 
       
   295     protected void recordDataPatchInData(Reference ref) {
       
   296         dataPatches.add(new DataPatch(data.position(), ref));
       
   297     }
       
   298 
       
   299     public DataSectionReference emitDataItem(HotSpotConstant c) {
       
   300         DataSectionReference ref = new DataSectionReference();
       
   301         ref.setOffset(data.position());
       
   302 
       
   303         recordDataPatchInData(new ConstantReference((VMConstant) c));
       
   304         if (c.isCompressed()) {
       
   305             data.emitInt(0xDEADDEAD);
       
   306         } else {
       
   307             data.emitLong(0xDEADDEADDEADDEADL);
       
   308         }
       
   309 
       
   310         return ref;
       
   311     }
       
   312 
       
   313     public HotSpotCompiledCode finish(HotSpotResolvedJavaMethod method) {
       
   314         int id = method.allocateCompileId(0);
       
   315         byte[] finishedCode = code.finish();
       
   316         Site[] finishedSites = sites.toArray(new Site[0]);
       
   317         byte[] finishedData = data.finish();
       
   318         DataPatch[] finishedDataPatches = dataPatches.toArray(new DataPatch[0]);
       
   319         return new HotSpotCompiledNmethod(method.getName(), finishedCode, finishedCode.length, finishedSites, new Assumption[0], new ResolvedJavaMethod[]{method}, new Comment[0], finishedData, 16,
       
   320                         finishedDataPatches, false, frameSize, deoptRescue, method, 0, id, 0L, false);
       
   321     }
       
   322 
       
   323     protected static class Buffer {
       
   324 
       
   325         private ByteBuffer data = ByteBuffer.allocate(32).order(ByteOrder.nativeOrder());
       
   326 
       
   327         private void ensureSize(int length) {
       
   328             if (length >= data.limit()) {
       
   329                 byte[] newBuf = Arrays.copyOf(data.array(), length * 4);
       
   330                 ByteBuffer newData = ByteBuffer.wrap(newBuf);
       
   331                 newData.order(data.order());
       
   332                 newData.position(data.position());
       
   333                 data = newData;
       
   334             }
       
   335         }
       
   336 
       
   337         public int position() {
       
   338             return data.position();
       
   339         }
       
   340 
       
   341         public void emitByte(int b) {
       
   342             ensureSize(data.position() + 1);
       
   343             data.put((byte) (b & 0xFF));
       
   344         }
       
   345 
       
   346         public void emitShort(int b) {
       
   347             ensureSize(data.position() + 2);
       
   348             data.putShort((short) b);
       
   349         }
       
   350 
       
   351         public void emitInt(int b) {
       
   352             ensureSize(data.position() + 4);
       
   353             data.putInt(b);
       
   354         }
       
   355 
       
   356         public void emitLong(long b) {
       
   357             ensureSize(data.position() + 8);
       
   358             data.putLong(b);
       
   359         }
       
   360 
       
   361         public void emitFloat(float f) {
       
   362             ensureSize(data.position() + 4);
       
   363             data.putFloat(f);
       
   364         }
       
   365 
       
   366         public void emitDouble(double f) {
       
   367             ensureSize(data.position() + 8);
       
   368             data.putDouble(f);
       
   369         }
       
   370 
       
   371         public void align(int alignment) {
       
   372             int pos = data.position();
       
   373             int misaligned = pos % alignment;
       
   374             if (misaligned != 0) {
       
   375                 pos += alignment - misaligned;
       
   376                 data.position(pos);
       
   377             }
       
   378         }
       
   379 
       
   380         private byte[] finish() {
       
   381             return Arrays.copyOf(data.array(), data.position());
       
   382         }
       
   383     }
       
   384 
       
   385     /**
       
   386      * Loads a primitive into the Allocatable <code>av</code>. Implementors may only implement
       
   387      * primitive types.
       
   388      */
       
   389     public abstract void emitLoad(AllocatableValue av, Object prim);
       
   390 
       
   391     /**
       
   392      * Emit a call to a fixed address <code>addr</code>
       
   393      */
       
   394     public abstract void emitCall(long addr);
       
   395 
       
   396     /**
       
   397      * Emit code which is necessary to call a method with {@link CallingConvention} <code>cc</code>
       
   398      * and arguments <coe>prim</code>.
       
   399      */
       
   400     public abstract void emitCallPrologue(CallingConvention cc, Object... prim);
       
   401 
       
   402     /**
       
   403      * Emit code which is necessary after calling a method with CallingConvention <code>cc</code>.
       
   404      */
       
   405     public abstract void emitCallEpilogue(CallingConvention cc);
       
   406 
       
   407 }