# HG changeset patch # User Thomas Wuerthinger # Date 1325707151 -3600 # Node ID 5c80ccb800364b40c8f61284c5111a7628c6db0d # Parent 35b05867c94a83394eb01f25469489d0db5ae64c Renaming of VMExits and VMEntries part 1. diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java Wed Jan 04 10:49:09 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/Compiler.java Wed Jan 04 20:59:11 2012 +0100 @@ -26,12 +26,13 @@ import com.oracle.max.cri.ri.*; import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.hotspot.bridge.*; import com.oracle.max.graal.hotspot.ri.*; public interface Compiler { - VMEntries getVMEntries(); - VMExits getVMExits(); + CompilerToVM getVMEntries(); + VMToCompiler getVMExits(); GraalCompiler getCompiler(); RiType lookupType(String returnType, HotSpotTypeResolved accessingClass); HotSpotVMConfig getConfig(); diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java Wed Jan 04 10:49:09 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/CompilerImpl.java Wed Jan 04 20:59:11 2012 +0100 @@ -32,6 +32,7 @@ import com.oracle.max.graal.compiler.*; import com.oracle.max.graal.compiler.observer.*; import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.hotspot.bridge.*; import com.oracle.max.graal.hotspot.logging.*; import com.oracle.max.graal.hotspot.ri.*; import com.oracle.max.graal.hotspot.server.*; @@ -63,7 +64,7 @@ System.out.println("Graal compiler started in client/server mode, server: " + remote); Socket socket = new Socket(remote, 1199); ReplacingStreams streams = new ReplacingStreams(socket.getOutputStream(), socket.getInputStream()); - streams.getInvocation().sendResult(new VMEntriesNative()); + streams.getInvocation().sendResult(new CompilerToVMImpl()); theInstance = (Compiler) streams.getInvocation().waitForResult(false); } catch (IOException e1) { @@ -79,14 +80,14 @@ } } - public static Compiler initializeServer(VMEntries entries) { + public static Compiler initializeServer(CompilerToVM entries) { assert theInstance == null; theInstance = new CompilerImpl(entries); return theInstance; } - private final VMEntries vmEntries; - private final VMExits vmExits; + private final CompilerToVM vmEntries; + private final VMToCompiler vmExits; private GraalContext context; private HotSpotRuntime runtime; @@ -99,25 +100,25 @@ return config; } - private CompilerImpl(VMEntries initialEntries) { + private CompilerImpl(CompilerToVM initialEntries) { - VMEntries entries = initialEntries; + CompilerToVM entries = initialEntries; // initialize VMEntries if (entries == null) { - entries = new VMEntriesNative(); + entries = new CompilerToVMImpl(); } // initialize VMExits - VMExits exits = new VMExitsNative(this); + VMToCompiler exits = new VMToCompilerImpl(this); // logging, etc. if (CountingProxy.ENABLED) { - exits = CountingProxy.getProxy(VMExits.class, exits); - entries = CountingProxy.getProxy(VMEntries.class, entries); + exits = CountingProxy.getProxy(VMToCompiler.class, exits); + entries = CountingProxy.getProxy(CompilerToVM.class, entries); } if (Logger.ENABLED) { - exits = LoggingProxy.getProxy(VMExits.class, exits); - entries = LoggingProxy.getProxy(VMEntries.class, entries); + exits = LoggingProxy.getProxy(VMToCompiler.class, exits); + entries = LoggingProxy.getProxy(CompilerToVM.class, entries); } // set the final fields @@ -166,19 +167,19 @@ } @Override - public VMEntries getVMEntries() { + public CompilerToVM getVMEntries() { return vmEntries; } @Override - public VMExits getVMExits() { + public VMToCompiler getVMExits() { return vmExits; } @Override public RiType lookupType(String returnType, HotSpotTypeResolved accessingClass) { - if (returnType.length() == 1 && vmExits instanceof VMExitsNative) { - VMExitsNative exitsNative = (VMExitsNative) vmExits; + if (returnType.length() == 1 && vmExits instanceof VMToCompilerImpl) { + VMToCompilerImpl exitsNative = (VMToCompilerImpl) vmExits; CiKind kind = CiKind.fromPrimitiveOrVoidTypeChar(returnType.charAt(0)); switch(kind) { case Boolean: diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotCompiledMethod.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotCompiledMethod.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import com.oracle.max.cri.ri.*; - -/** - * Implementation of RiCompiledMethod for HotSpot. Stores a reference to the nmethod which contains the compiled code. - */ -public class HotSpotCompiledMethod implements RiCompiledMethod { - - private final RiResolvedMethod method; - private long nmethod; - - public HotSpotCompiledMethod(RiResolvedMethod method) { - this.method = method; - } - - @Override - public RiResolvedMethod method() { - return method; - } - - @Override - public boolean isValid() { - return nmethod != 0; - } - - @Override - public String toString() { - return "compiled method " + method + " @" + nmethod; - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotConstantPool.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotConstantPool.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.ri.*; - -/** - * Implementation of RiConstantPool for HotSpot. - */ -public class HotSpotConstantPool extends CompilerObject implements RiConstantPool { - /** - * - */ - private static final long serialVersionUID = -5443206401485234850L; - private final HotSpotTypeResolvedImpl type; - - public HotSpotConstantPool(Compiler compiler, HotSpotTypeResolvedImpl type) { - super(compiler); - this.type = type; - } - - @Override - public Object lookupConstant(int cpi) { - Object constant = compiler.getVMEntries().RiConstantPool_lookupConstant(type, cpi); - return constant; - } - - @Override - public RiSignature lookupSignature(int cpi) { - throw new UnsupportedOperationException(); - } - - @Override - public RiMethod lookupMethod(int cpi, int byteCode) { - return compiler.getVMEntries().RiConstantPool_lookupMethod(type, cpi, (byte) byteCode); - } - - @Override - public RiType lookupType(int cpi, int opcode) { - return compiler.getVMEntries().RiConstantPool_lookupType(type, cpi); - } - - @Override - public RiField lookupField(int cpi, int opcode) { - return compiler.getVMEntries().RiConstantPool_lookupField(type, cpi, (byte) opcode); - } - - @Override - public void loadReferencedType(int cpi, int bytecode) { - compiler.getVMEntries().RiConstantPool_loadReferencedType(type, cpi, (byte) bytecode); - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotExceptionHandler.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotExceptionHandler.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import com.oracle.max.cri.ri.*; - - -public class HotSpotExceptionHandler extends CompilerObject implements RiExceptionHandler { - /** - * - */ - private static final long serialVersionUID = 7110038548061733686L; - private int startBci; - private int endBci; - private int handlerBci; - private int catchClassIndex; - private RiType catchClass; - - public HotSpotExceptionHandler() { - super(null); - } - - @Override - public int startBCI() { - return startBci; - } - - @Override - public int endBCI() { - return endBci; - } - - @Override - public int handlerBCI() { - return handlerBci; - } - - @Override - public int catchTypeCPI() { - return catchClassIndex; - } - - @Override - public boolean isCatchAll() { - return catchClassIndex == 0; - } - - @Override - public RiType catchType() { - return catchClass; - } - - @Override - public String toString() { - return String.format("HotSpotExceptionHandler[startBci=%d, endBci=%d, handlerBci=%d, catchClassIndex=%d, catchClass=%s", startBci, endBci, handlerBci, catchClassIndex, catchClass); - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotField.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotField.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import java.lang.annotation.*; -import java.lang.reflect.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiType.*; -import com.oracle.max.graal.compiler.*; - -/** - * Represents a field in a HotSpot type. - */ -public class HotSpotField extends CompilerObject implements RiResolvedField { - - /** - * - */ - private static final long serialVersionUID = 7692985878836955683L; - private final RiResolvedType holder; - private final String name; - private final RiType type; - private final int offset; - private final int accessFlags; - private CiConstant constant; // Constant part only valid for static fields. - - public HotSpotField(Compiler compiler, RiResolvedType holder, String name, RiType type, int offset, int accessFlags) { - super(compiler); - this.holder = holder; - this.name = name; - this.type = type; - assert offset != -1; - this.offset = offset; - this.accessFlags = accessFlags; - } - - @Override - public int accessFlags() { - return accessFlags; - } - - @Override - public CiConstant constantValue(CiConstant receiver) { - if (receiver == null) { - assert Modifier.isStatic(accessFlags); - if (constant == null) { - if (holder.isInitialized() && holder.toJava() != System.class) { - if (Modifier.isFinal(accessFlags()) || assumeStaticFieldsFinal(holder.toJava())) { - CiConstant encoding = holder.getEncoding(Representation.StaticFields); - constant = this.kind(false).readUnsafeConstant(encoding.asObject(), offset); - } - } - } - return constant; - } else { - assert !Modifier.isStatic(accessFlags); - if (Modifier.isFinal(accessFlags())) { - return this.kind(false).readUnsafeConstant(receiver.asObject(), offset); - } - } - return null; - } - - private static boolean assumeStaticFieldsFinal(Class< ? > clazz) { - return clazz == GraalOptions.class; - } - - @Override - public RiResolvedType holder() { - return holder; - } - - @Override - public CiKind kind(boolean architecture) { - return type().kind(architecture); - } - - @Override - public String name() { - return name; - } - - @Override - public RiType type() { - return type; - } - - public int offset() { - return offset; - } - - @Override - public String toString() { - return "HotSpotField<" + CiUtil.format("%h.%n", this) + ":" + offset + ">"; - } - - @Override - public T getAnnotation(Class annotationClass) { - Field javaField = toJava(); - if (javaField != null) { - return javaField.getAnnotation(annotationClass); - } - return null; - } - - private Field toJava() { - try { - return holder.toJava().getDeclaredField(name); - } catch (NoSuchFieldException e) { - return null; - } - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRegisterConfig.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRegisterConfig.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.hotspot; - -import static com.oracle.max.asm.target.amd64.AMD64.*; - -import java.util.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiCallingConvention.*; -import com.oracle.max.cri.ci.CiRegister.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.compiler.util.*; - -public class HotSpotRegisterConfig implements RiRegisterConfig { - - // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp - private final CiRegister[] allocatable = { - rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/ - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - private final EnumMap categorized = CiRegister.categorize(allocatable); - - private final RiRegisterAttributes[] attributesMap; - - @Override - public CiRegister[] getAllocatableRegisters() { - return allocatable; - } - - @Override - public EnumMap getCategorizedAllocatableRegisters() { - return categorized; - } - - @Override - public RiRegisterAttributes[] getAttributesMap() { - return attributesMap; - } - - private final CiRegister[] generalParameterRegisters; - private final CiRegister[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}; - private final CiRegister[] allParameterRegisters; - - private final CiRegister[] rsaRegs = { - rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, - r8, r9, r10, r11, r12, r13, r14, r15, - xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, - xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 - }; - - private final CiCalleeSaveLayout registerSaveArea; - - public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { - if (config.windowsOs) { - generalParameterRegisters = new CiRegister[] {rdx, r8, r9, rdi, rsi, rcx}; - } else { - generalParameterRegisters = new CiRegister[] {rsi, rdx, rcx, r8, r9, rdi}; - } - - if (globalStubConfig) { - registerSaveArea = new CiCalleeSaveLayout(0, -1, 8, rsaRegs); - } else { - registerSaveArea = new CiCalleeSaveLayout(0, 8, 8, new CiRegister[0]); - } - - attributesMap = RiRegisterAttributes.createMap(this, AMD64.allRegisters); - allParameterRegisters = Arrays.copyOf(generalParameterRegisters, generalParameterRegisters.length + xmmParameterRegisters.length); - System.arraycopy(xmmParameterRegisters, 0, allParameterRegisters, generalParameterRegisters.length, xmmParameterRegisters.length); - } - - @Override - public CiRegister[] getCallerSaveRegisters() { - return getAllocatableRegisters(); - } - - @Override - public CiRegister getRegisterForRole(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public CiCallingConvention getCallingConvention(Type type, CiKind[] parameters, CiTarget target, boolean stackOnly) { - if (type == Type.NativeCall) { - throw new UnsupportedOperationException(); - } - return callingConvention(parameters, type, target, stackOnly); - } - - public CiRegister[] getCallingConventionRegisters(Type type, RegisterFlag flag) { - return allParameterRegisters; - } - - private CiCallingConvention callingConvention(CiKind[] types, Type type, CiTarget target, boolean stackOnly) { - CiValue[] locations = new CiValue[types.length]; - - int currentGeneral = 0; - int currentXMM = 0; - int currentStackOffset = 0; - - for (int i = 0; i < types.length; i++) { - final CiKind kind = types[i]; - - switch (kind) { - case Byte: - case Boolean: - case Short: - case Char: - case Int: - case Long: - case Object: - if (!stackOnly && currentGeneral < generalParameterRegisters.length) { - CiRegister register = generalParameterRegisters[currentGeneral++]; - locations[i] = register.asValue(kind); - } - break; - case Float: - case Double: - if (!stackOnly && currentXMM < xmmParameterRegisters.length) { - CiRegister register = xmmParameterRegisters[currentXMM++]; - locations[i] = register.asValue(kind); - } - break; - default: - throw Util.shouldNotReachHere(); - } - - if (locations[i] == null) { - locations[i] = CiStackSlot.get(kind.stackKind(), currentStackOffset, !type.out); - currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize); - } - } - - return new CiCallingConvention(locations, currentStackOffset); - } - - @Override - public CiRegister getReturnRegister(CiKind kind) { - switch (kind) { - case Boolean: - case Byte: - case Char: - case Short: - case Int: - case Long: - case Object: - return rax; - case Float: - case Double: - return xmm0; - case Void: - case Illegal: - return null; - default: - throw new UnsupportedOperationException("no return register for type " + kind); - } - } - - @Override - public CiRegister getScratchRegister() { - return r10; - } - - @Override - public CiRegister getFrameRegister() { - return rsp; - } - - public CiCalleeSaveLayout getCalleeSaveLayout() { - return registerSaveArea; - } - - @Override - public String toString() { - String res = String.format( - "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + - "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n" + - "CalleeSave: " + getCalleeSaveLayout() + "%n" + - "Scratch: " + getScratchRegister() + "%n"); - return res; - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRuntime.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotRuntime.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,432 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.hotspot; - -import java.io.*; -import java.lang.reflect.*; -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiTargetMethod.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiType.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.cri.*; -import com.oracle.max.graal.graph.*; -import com.oracle.max.graal.hotspot.nodes.*; -import com.oracle.max.graal.hotspot.ri.*; -import com.oracle.max.graal.nodes.*; -import com.oracle.max.graal.nodes.calc.*; -import com.oracle.max.graal.nodes.extended.*; -import com.oracle.max.graal.nodes.java.*; -import com.oracle.max.graal.snippets.nodes.*; -import com.sun.max.asm.dis.*; -import com.sun.max.lang.*; - -/** - * CRI runtime implementation for the HotSpot VM. - */ -public class HotSpotRuntime implements GraalRuntime { - final GraalContext context; - final HotSpotVMConfig config; - final HotSpotRegisterConfig regConfig; - final HotSpotRegisterConfig globalStubRegConfig; - private final Compiler compiler; - - public HotSpotRuntime(GraalContext context, HotSpotVMConfig config, Compiler compiler) { - this.context = context; - this.config = config; - this.compiler = compiler; - regConfig = new HotSpotRegisterConfig(config, false); - globalStubRegConfig = new HotSpotRegisterConfig(config, true); - } - - @Override - public int codeOffset() { - return 0; - } - - - public Compiler getCompiler() { - return compiler; - } - - @Override - public String disassemble(byte[] code, long address) { - return disassemble(code, new DisassemblyPrinter(false), address); - } - - private static String disassemble(byte[] code, DisassemblyPrinter disassemblyPrinter, long address) { - final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - final ISA instructionSet = ISA.AMD64; - Disassembler.disassemble(byteArrayOutputStream, code, instructionSet, WordWidth.BITS_64, address, null, disassemblyPrinter); - return byteArrayOutputStream.toString(); - } - - @Override - public String disassemble(final CiTargetMethod targetMethod) { - - final DisassemblyPrinter disassemblyPrinter = new DisassemblyPrinter(false) { - - private String siteInfo(int pcOffset) { - for (Safepoint site : targetMethod.safepoints) { - if (site.pcOffset == pcOffset) { - return "{safepoint}"; - } - } - for (DataPatch site : targetMethod.dataReferences) { - if (site.pcOffset == pcOffset) { - return "{" + site.constant + "}"; - } - } - return null; - } - - @Override - protected String disassembledObjectString(Disassembler disassembler, DisassembledObject disassembledObject) { - final String string = super.disassembledObjectString(disassembler, disassembledObject); - - String site = siteInfo(disassembledObject.startPosition()); - if (site != null) { - return string + " " + site; - } - return string; - } - }; - final byte[] code = Arrays.copyOf(targetMethod.targetCode(), targetMethod.targetCodeSize()); - return disassemble(code, disassemblyPrinter, 0L); - } - - @Override - public String disassemble(RiResolvedMethod method) { - return "No disassembler available"; - } - - @Override - public RiResolvedType asRiType(CiKind kind) { - return (RiResolvedType) compiler.getVMEntries().getType(kind.toJavaClass()); - } - - @Override - public RiResolvedType getTypeOf(CiConstant constant) { - return (RiResolvedType) compiler.getVMEntries().getRiType(constant); - } - - @Override - public boolean isExceptionType(RiResolvedType type) { - return type.isSubtypeOf((RiResolvedType) compiler.getVMEntries().getType(Throwable.class)); - } - - @Override - public Object registerCompilerStub(CiTargetMethod targetMethod, String name) { - return HotSpotTargetMethod.installStub(compiler, targetMethod, name); - } - - @Override - public int sizeOfLockData() { - // TODO shouldn't be hard coded - return 8; - } - - @Override - public int sizeOfBasicObjectLock() { - // TODO shouldn't be hard coded - return 2 * 8; - } - - @Override - public int basicObjectLockOffsetInBytes() { - return 8; - } - - @Override - public boolean areConstantObjectsEqual(CiConstant x, CiConstant y) { - return compiler.getVMEntries().compareConstantObjects(x, y); - } - - @Override - public RiRegisterConfig getRegisterConfig(RiMethod method) { - return regConfig; - } - - /** - * HotSpots needs an area suitable for storing a program counter for temporary use during the deoptimization process. - */ - @Override - public int getCustomStackAreaSize() { - // TODO shouldn't be hard coded - return 8; - } - - @Override - public int getMinimumOutgoingSize() { - return config.runtimeCallStackSize; - } - - @Override - public int getArrayLength(CiConstant array) { - return compiler.getVMEntries().getArrayLength(array); - } - - @Override - public Class asJavaClass(CiConstant c) { - return (Class) c.asObject(); - } - - @Override - public Object asJavaObject(CiConstant c) { - return c.asObject(); - } - - @Override - public void lower(Node n, CiLoweringTool tool) { - if (!GraalOptions.Lower) { - return; - } - - if (n instanceof ArrayLengthNode) { - ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; - SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array()); - FixedNode nextNode = arrayLengthNode.next(); - arrayLengthNode.clearSuccessors(); - safeReadArrayLength.setNext(nextNode); - arrayLengthNode.replaceAndDelete(safeReadArrayLength); - safeReadArrayLength.lower(tool); - } else if (n instanceof LoadFieldNode) { - LoadFieldNode field = (LoadFieldNode) n; - if (field.isVolatile()) { - return; - } - Graph graph = field.graph(); - int displacement = ((HotSpotField) field.field()).offset(); - assert field.kind() != CiKind.Illegal; - ReadNode memoryRead = graph.unique(new ReadNode(field.field().kind(true).stackKind(), field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph))); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)))); - FixedNode next = field.next(); - field.setNext(null); - memoryRead.setNext(next); - field.replaceAndDelete(memoryRead); - } else if (n instanceof StoreFieldNode) { - StoreFieldNode field = (StoreFieldNode) n; - if (field.isVolatile()) { - return; - } - Graph graph = field.graph(); - int displacement = ((HotSpotField) field.field()).offset(); - WriteNode memoryWrite = graph.add(new WriteNode(field.object(), field.value(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph))); - memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)))); - memoryWrite.setStateAfter(field.stateAfter()); - FixedNode next = field.next(); - field.setNext(null); - if (field.field().kind(true) == CiKind.Object && !field.value().isNullConstant()) { - FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(field.object())); - memoryWrite.setNext(writeBarrier); - writeBarrier.setNext(next); - } else { - memoryWrite.setNext(next); - } - field.replaceAndDelete(memoryWrite); - } else if (n instanceof LoadIndexedNode) { - LoadIndexedNode loadIndexed = (LoadIndexedNode) n; - Graph graph = loadIndexed.graph(); - GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool); - - CiKind elementKind = loadIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); - ReadNode memoryRead = graph.unique(new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation)); - memoryRead.setGuard(boundsCheck); - FixedNode next = loadIndexed.next(); - loadIndexed.setNext(null); - memoryRead.setNext(next); - loadIndexed.replaceAndDelete(memoryRead); - } else if (n instanceof StoreIndexedNode) { - StoreIndexedNode storeIndexed = (StoreIndexedNode) n; - Graph graph = storeIndexed.graph(); - AnchorNode anchor = graph.add(new AnchorNode()); - GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool); - - FixedWithNextNode append = anchor; - - CiKind elementKind = storeIndexed.elementKind(); - LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); - ValueNode value = storeIndexed.value(); - ValueNode array = storeIndexed.array(); - if (elementKind == CiKind.Object && !value.isNullConstant()) { - // Store check! - if (array.exactType() != null) { - RiResolvedType elementType = array.exactType().componentType(); - if (elementType.superType() != null) { - ConstantNode type = graph.unique(ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph)); - value = graph.unique(new CheckCastNode(anchor, type, elementType, value)); - } else { - assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); - } - } else { - GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false))); - ReadNode arrayClass = graph.unique(new ReadNode(CiKind.Object, array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph))); - arrayClass.setGuard(guard); - append.setNext(arrayClass); - append = arrayClass; - ReadNode arrayElementKlass = graph.unique(new ReadNode(CiKind.Object, arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph))); - value = graph.unique(new CheckCastNode(anchor, arrayElementKlass, null, value)); - } - } - WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation)); - memoryWrite.setGuard(boundsCheck); - memoryWrite.setStateAfter(storeIndexed.stateAfter()); - FixedNode next = storeIndexed.next(); - storeIndexed.setNext(null); - append.setNext(memoryWrite); - if (elementKind == CiKind.Object && !value.isNullConstant()) { - ArrayWriteBarrier writeBarrier = graph.add(new ArrayWriteBarrier(array, arrayLocation)); - memoryWrite.setNext(writeBarrier); - writeBarrier.setNext(next); - } else { - memoryWrite.setNext(next); - } - storeIndexed.replaceAtPredecessors(anchor); - storeIndexed.safeDelete(); - } else if (n instanceof UnsafeLoadNode) { - UnsafeLoadNode load = (UnsafeLoadNode) n; - Graph graph = load.graph(); - assert load.kind() != CiKind.Illegal; - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph); - location.setIndexScalingEnabled(false); - ReadNode memoryRead = graph.unique(new ReadNode(load.kind(), load.object(), location)); - memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)))); - FixedNode next = load.next(); - load.setNext(null); - memoryRead.setNext(next); - load.replaceAndDelete(memoryRead); - } else if (n instanceof UnsafeStoreNode) { - UnsafeStoreNode store = (UnsafeStoreNode) n; - Graph graph = store.graph(); - IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph); - location.setIndexScalingEnabled(false); - WriteNode write = graph.add(new WriteNode(store.object(), store.value(), location)); - FieldWriteBarrier barrier = graph.add(new FieldWriteBarrier(store.object())); - FixedNode next = store.next(); - store.setNext(null); - barrier.setNext(next); - write.setNext(barrier); - write.setStateAfter(store.stateAfter()); - store.replaceAtPredecessors(write); - store.safeDelete(); - } else if (n instanceof ArrayHeaderSizeNode) { - n.replaceAndDelete(ConstantNode.forLong(config.getArrayOffset(((ArrayHeaderSizeNode) n).elementKind()), n.graph())); - } - } - - private IndexedLocationNode createArrayLocation(Graph graph, CiKind elementKind, ValueNode index) { - return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph); - } - - private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { - return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length()))); - } - - @Override - public StructuredGraph intrinsicGraph(RiResolvedMethod caller, int bci, RiResolvedMethod method, List parameters) { - RiType holder = method.holder(); - String fullName = method.name() + method.signature().asString(); - String holderName = holder.name(); - if (holderName.equals("Ljava/lang/Object;")) { - if (fullName.equals("getClass()Ljava/lang/Class;")) { - ValueNode obj = (ValueNode) parameters.get(0); - if (obj.stamp().nonNull() && obj.stamp().exactType() != null) { - StructuredGraph graph = new StructuredGraph(); - ValueNode result = ConstantNode.forObject(obj.stamp().exactType().toJava(), this, graph); - ReturnNode ret = graph.add(new ReturnNode(result)); - graph.start().setNext(ret); - return graph; - } - StructuredGraph graph = new StructuredGraph(); - LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); - SafeReadNode klassOop = safeReadHub(graph, receiver); - ReadNode result = graph.add(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph))); - ReturnNode ret = graph.add(new ReturnNode(result)); - graph.start().setNext(klassOop); - klassOop.setNext(ret); - return graph; - } - } else if (holderName.equals("Ljava/lang/Class;")) { - if (fullName.equals("getModifiers()I")) { - StructuredGraph graph = new StructuredGraph(); - LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); - SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset); - graph.start().setNext(klassOop); - // TODO(tw): Care about primitive classes! - ReadNode result = graph.unique(new ReadNode(CiKind.Int, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph))); - ReturnNode ret = graph.add(new ReturnNode(result)); - klassOop.setNext(ret); - return graph; - } - } else if (holderName.equals("Ljava/lang/Thread;")) { - if (fullName.equals("currentThread()Ljava/lang/Thread;")) { - StructuredGraph graph = new StructuredGraph(); - ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset)))); - graph.start().setNext(ret); - return graph; - } - } - return null; - } - - private SafeReadNode safeReadHub(Graph graph, ValueNode value) { - return safeRead(graph, CiKind.Object, value, config.hubOffset); - } - - private SafeReadNode safeReadArrayLength(Graph graph, ValueNode value) { - return safeRead(graph, CiKind.Int, value, config.arrayLengthOffset); - } - - private static SafeReadNode safeRead(Graph graph, CiKind kind, ValueNode value, int offset) { - return graph.add(new SafeReadNode(kind, value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph))); - } - - public RiResolvedType getType(Class clazz) { - return (RiResolvedType) compiler.getVMEntries().getType(clazz); - } - - public Object asCallTarget(Object target) { - return target; - } - - public long getMaxCallTargetOffset(CiRuntimeCall rtcall) { - return compiler.getVMEntries().getMaxCallTargetOffset(rtcall); - } - - public RiResolvedMethod getRiMethod(Method reflectionMethod) { - return (RiResolvedMethod) compiler.getVMEntries().getRiMethod(reflectionMethod); - } - - public void installMethod(RiMethod method, CiTargetMethod code) { - HotSpotTargetMethod.installMethod(CompilerImpl.getInstance(), (HotSpotMethodResolved) method, code, true); - } - - @Override - public RiCompiledMethod addMethod(RiResolvedMethod method, CiTargetMethod code) { - Compiler compilerInstance = CompilerImpl.getInstance(); - return HotSpotTargetMethod.installMethod(compilerInstance, (HotSpotMethodResolved) method, code, false); - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotSignature.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotSignature.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import java.util.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.ri.*; -import com.oracle.max.graal.java.*; - -/** - * Represents a method signature. - */ -public class HotSpotSignature extends CompilerObject implements RiSignature { - - /** - * - */ - private static final long serialVersionUID = -2890917956072366116L; - private final List arguments = new ArrayList<>(); - private final String returnType; - private final String originalString; - private RiType[] argumentTypes; - private RiType returnTypeCache; - - public HotSpotSignature(Compiler compiler, String signature) { - super(compiler); - assert signature.length() > 0; - this.originalString = signature; - - if (signature.charAt(0) == '(') { - int cur = 1; - while (cur < signature.length() && signature.charAt(cur) != ')') { - int nextCur = parseSignature(signature, cur); - arguments.add(signature.substring(cur, nextCur)); - cur = nextCur; - } - - cur++; - int nextCur = parseSignature(signature, cur); - returnType = signature.substring(cur, nextCur); - assert nextCur == signature.length(); - } else { - returnType = null; - } - } - - private static int parseSignature(String signature, int start) { - int cur = start; - char first; - do { - first = signature.charAt(cur++); - } while (first == '['); - - switch (first) { - case 'L': - while (signature.charAt(cur) != ';') { - cur++; - } - cur++; - break; - case 'V': - case 'I': - case 'B': - case 'C': - case 'D': - case 'F': - case 'J': - case 'S': - case 'Z': - break; - default: - assert false; - } - return cur; - } - - @Override - public int argumentCount(boolean withReceiver) { - return arguments.size() + (withReceiver ? 1 : 0); - } - - @Override - public CiKind argumentKindAt(int index, boolean architecture) { - return CiKind.fromTypeString(arguments.get(index)); - } - - @Override - public int argumentSlots(boolean withReceiver) { - int argSlots = 0; - for (int i = 0; i < argumentCount(false); i++) { - argSlots += FrameStateBuilder.stackSlots(argumentKindAt(i, false)); - } - return argSlots + (withReceiver ? 1 : 0); - } - - @Override - public RiType argumentTypeAt(int index, RiType accessingClass) { - if (argumentTypes == null) { - argumentTypes = new RiType[arguments.size()]; - } - RiType type = argumentTypes[index]; - if (type == null) { - type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass); - argumentTypes[index] = type; - } - return type; - } - - @Override - public String asString() { - return originalString; - } - - @Override - public CiKind returnKind(boolean architecture) { - return CiKind.fromTypeString(returnType); - } - - @Override - public RiType returnType(RiType accessingClass) { - if (returnTypeCache == null) { - returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass); - } - return returnTypeCache; - } - - @Override - public String toString() { - return "HotSpotSignature<" + originalString + ">"; - } - -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotXirGenerator.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/HotSpotXirGenerator.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1442 +0,0 @@ -/* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.max.graal.hotspot; - -import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; -import static com.oracle.max.cri.ci.CiValueUtil.*; -import static com.oracle.max.graal.hotspot.TemplateFlag.*; - -import java.lang.reflect.*; -import java.util.*; -import java.util.concurrent.*; - -import com.oracle.max.asm.target.amd64.*; -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiAddress.*; -import com.oracle.max.cri.ci.CiRegister.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.cri.ri.RiType.*; -import com.oracle.max.cri.xir.*; -import com.oracle.max.cri.xir.CiXirAssembler.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.hotspot.ri.*; - -public class HotSpotXirGenerator implements RiXirGenerator { - - // this needs to correspond to graal_CodeInstaller.hpp - // @formatter:off - private static final Integer MARK_VERIFIED_ENTRY = 0x0001; - private static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; - private static final Integer MARK_OSR_ENTRY = 0x0003; - private static final Integer MARK_UNWIND_ENTRY = 0x0004; - private static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; - private static final Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; - - private static final Integer MARK_STATIC_CALL_STUB = 0x1000; - - private static final Integer MARK_INVOKEINTERFACE = 0x2001; - private static final Integer MARK_INVOKESTATIC = 0x2002; - private static final Integer MARK_INVOKESPECIAL = 0x2003; - private static final Integer MARK_INVOKEVIRTUAL = 0x2004; - - private static final Integer MARK_IMPLICIT_NULL = 0x3000; - private static final Integer MARK_POLL_NEAR = 0x3001; - private static final Integer MARK_POLL_RETURN_NEAR = 0x3002; - private static final Integer MARK_POLL_FAR = 0x3003; - private static final Integer MARK_POLL_RETURN_FAR = 0x3004; - - // @formatter:on - - private final HotSpotVMConfig config; - private final CiTarget target; - private final RiRegisterConfig registerConfig; - private final Compiler compiler; - - private CiXirAssembler globalAsm; - - public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig, Compiler compiler) { - this.config = config; - this.target = target; - this.registerConfig = registerConfig; - this.compiler = compiler; - } - - private XirConstant wordConst(CiXirAssembler asm, long value) { - if (target.wordKind == CiKind.Long) { - return asm.createConstant(CiConstant.forLong(value)); - } else { - assert target.wordKind == CiKind.Int; - return asm.createConstant(CiConstant.forInt((int) value)); - } - } - - private XirArgument wordArg(long value) { - if (target.wordKind == CiKind.Long) { - return XirArgument.forLong(value); - } else { - assert target.wordKind == CiKind.Int; - return XirArgument.forInt((int) value); - } - } - - private SimpleTemplates prologueTemplates = new SimpleTemplates(STATIC_METHOD) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirOperand framePointer = asm.createRegisterTemp("frame pointer", target.wordKind, AMD64.rbp); - XirOperand stackPointer = asm.createRegisterTemp("stack pointer", target.wordKind, AMD64.rsp); - XirLabel unverifiedStub = null; - - asm.mark(MARK_OSR_ENTRY); - asm.mark(MARK_UNVERIFIED_ENTRY); - if (!is(STATIC_METHOD, flags)) { - unverifiedStub = asm.createOutOfLineLabel("unverified"); - - XirOperand temp = asm.createRegisterTemp("temp (r10)", target.wordKind, AMD64.r10); - XirOperand cache = asm.createRegisterTemp("cache (rax)", target.wordKind, AMD64.rax); - - CiCallingConvention conventions = registerConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false); - XirOperand receiver = asm.createRegister("receiver", target.wordKind, asRegister(conventions.locations[0])); - - asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), false); - asm.jneq(unverifiedStub, cache, temp); - } - asm.align(config.codeEntryAlignment); - asm.mark(MARK_VERIFIED_ENTRY); - asm.stackOverflowCheck(); - asm.push(framePointer); - asm.mov(framePointer, stackPointer); - // Compensate for the push of framePointer (the XIR instruction pushFrame is not flexible enough to reduce the frame size, wait until XIR goes away to fix this). - asm.add(stackPointer, stackPointer, asm.i(8)); - asm.pushFrame(); - - // -- out of line ------------------------------------------------------- - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object); - XirLabel unwind = asm.createOutOfLineLabel("unwind"); - asm.bindOutOfLine(unwind); - - asm.mark(MARK_UNWIND_ENTRY); - - asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false); - asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false); - asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); - - asm.callRuntime(config.unwindExceptionStub, null, exceptionOop); - asm.shouldNotReachHere(); - - asm.mark(MARK_EXCEPTION_HANDLER_ENTRY); - asm.callRuntime(config.handleExceptionStub, null); - asm.shouldNotReachHere(); - - asm.mark(MARK_DEOPT_HANDLER_ENTRY); - asm.callRuntime(config.handleDeoptStub, null); - asm.shouldNotReachHere(); - - if (!is(STATIC_METHOD, flags)) { - asm.bindOutOfLine(unverifiedStub); - asm.jmpRuntime(config.inlineCacheMissStub); - } - - return asm.finishTemplate(is(STATIC_METHOD, flags) ? "static prologue" : "prologue"); - } - }; - - private SimpleTemplates epilogueTemplates = new SimpleTemplates(STATIC_METHOD, SYNCHRONIZED) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirOperand framePointer = asm.createRegisterTemp("frame pointer", target.wordKind, AMD64.rbp); - XirOperand stackPointer = asm.createRegisterTemp("stack pointer", target.wordKind, AMD64.rsp); - - asm.popFrame(); - asm.pload(CiKind.Long, framePointer, stackPointer, asm.i(-8), false); - - if (GraalOptions.GenSafepoints) { - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); - if (config.isPollingPageFar) { - asm.mov(temp, wordConst(asm, config.safepointPollingAddress)); - asm.mark(MARK_POLL_RETURN_FAR); - asm.pload(target.wordKind, temp, temp, true); - } else { - XirOperand rip = asm.createRegister("rip", target.wordKind, AMD64.rip); - asm.mark(MARK_POLL_RETURN_NEAR); - asm.pload(target.wordKind, temp, rip, asm.i(0xEFBEADDE), true); - } - } - - return asm.finishTemplate("epilogue"); - } - }; - - private SimpleTemplates safepointTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); - if (config.isPollingPageFar) { - asm.mov(temp, wordConst(asm, config.safepointPollingAddress)); - asm.mark(MARK_POLL_FAR); - asm.pload(target.wordKind, temp, temp, true); - } else { - XirOperand rip = asm.createRegister("rip", target.wordKind, AMD64.rip); - asm.mark(MARK_POLL_NEAR); - asm.pload(target.wordKind, temp, rip, asm.i(0xEFBEADDE), true); - } - - return asm.finishTemplate("safepoint"); - } - }; - - private SimpleTemplates exceptionObjectTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - XirOperand result = asm.restart(CiKind.Object); - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - - asm.pload(CiKind.Object, result, thread, asm.i(config.threadExceptionOopOffset), false); - asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.o(null), false); - asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); - - return asm.finishTemplate("exception object"); - } - }; - - private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirOperand tempO = asm.createRegisterTemp("tempO", CiKind.Object, AMD64.rax); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, receiver, true); - } - asm.mark(MARK_INVOKEINTERFACE); - asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); - - return asm.finishTemplate(addr, "invokeinterface"); - } - }; - - private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirOperand tempO = asm.createRegisterTemp("tempO", CiKind.Object, AMD64.rax); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, receiver, true); - } - asm.mark(MARK_INVOKEVIRTUAL); - asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); - - return asm.finishTemplate(addr, "invokevirtual"); - } - }; - - private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); - XirLabel stub = asm.createOutOfLineLabel("call stub"); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, temp, receiver, true); - } - asm.mark(MARK_INVOKESPECIAL); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(stub); - XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); - asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); - asm.mov(method, wordConst(asm, 0)); - XirLabel dummy = asm.createOutOfLineLabel("dummy"); - asm.jmp(dummy); - asm.bindOutOfLine(dummy); - - return asm.finishTemplate(addr, "invokespecial"); - } - }; - - private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); - - XirLabel stub = asm.createOutOfLineLabel("call stub"); - asm.mark(MARK_INVOKESTATIC); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(stub); - XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); - asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); - asm.mov(method, wordConst(asm, 0)); - XirLabel dummy = asm.createOutOfLineLabel("dummy"); - asm.jmp(dummy); - asm.bindOutOfLine(dummy); - - return asm.finishTemplate(addr, "invokestatic"); - } - }; - - private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - XirParameter lock = asm.createInputParameter("lock", target.wordKind); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - asm.pload(target.wordKind, asm.createTemp("temp", target.wordKind), object, true); - } - - - // (tw) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object - // is not correctly garbage collected. - final boolean useInfoAfter = true; - - if (config.useFastLocking) { - useRegisters(asm, AMD64.rax, AMD64.rbx); - useRegisters(asm, getGeneralParameterRegister(0)); - useRegisters(asm, getGeneralParameterRegister(1)); - asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock); - } else { - asm.reserveOutgoingStack(target.wordSize * 2); - XirOperand rsp = asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)); - asm.pstore(CiKind.Object, rsp, asm.i(target.wordSize), object, false); - asm.pstore(target.wordKind, rsp, asm.i(0), lock, false); - asm.callRuntime(config.monitorEnterStub, null, useInfoAfter); - } - - return asm.finishTemplate("monitorEnter"); - } - }; - - private CiRegister getGeneralParameterRegister(int index) { - return registerConfig.getCallingConventionRegisters(CiCallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index]; - } - - private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - XirParameter lock = asm.createInputParameter("lock", target.wordKind); - - if (config.useFastLocking) { - useRegisters(asm, AMD64.rax, AMD64.rbx); - useRegisters(asm, getGeneralParameterRegister(0)); - useRegisters(asm, getGeneralParameterRegister(1)); - asm.callRuntime(config.fastMonitorExitStub, null, object, lock); - } else { - asm.reserveOutgoingStack(target.wordSize); - asm.pstore(target.wordKind, asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)), asm.i(0), lock, false); - asm.callRuntime(config.monitorExitStub, null); - } - - return asm.finishTemplate("monitorExit"); - } - }; - - private KindTemplates getFieldTemplates = new KindTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - XirOperand result = asm.restart(kind); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - - XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pload(kind, result, object, fieldOffset, is(NULL_CHECK, flags)); - return asm.finishTemplate("getfield<" + kind + ">"); - } - }; - - private KindTemplates writeBarrierTemplate = new KindTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - asm.restart(CiKind.Void); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - - // Need temp operand, because the write barrier destroys the object pointer. - XirOperand temp = asm.createTemp("temp", target.wordKind); - asm.mov(temp, object); - - writeBarrier(asm, temp); - return asm.finishTemplate("writeBarrier"); - } - }; - - private KindTemplates putFieldTemplates = new KindTemplates(WRITE_BARRIER, NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - asm.restart(CiKind.Void); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - XirParameter value = asm.createInputParameter("value", kind); - XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); - if (kind == CiKind.Object) { - verifyPointer(asm, value); - } - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pstore(kind, object, fieldOffset, value, is(NULL_CHECK, flags)); - if (is(WRITE_BARRIER, flags) && kind == CiKind.Object) { - XirOperand temp = asm.createTemp("temp", target.wordKind); - asm.mov(temp, object); - writeBarrier(asm, temp); - } - return asm.finishTemplate("putfield<" + kind + ">"); - } - }; - - private final IndexTemplates newInstanceTemplates = new IndexTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int size) { - XirOperand result = asm.restart(target.wordKind); - XirOperand type = asm.createInputParameter("type", CiKind.Object); - - XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); - XirOperand temp1o = asm.createRegisterTemp("temp1o", CiKind.Object, AMD64.rcx); - XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rbx); - XirOperand temp2i = asm.createRegisterTemp("temp2i", CiKind.Int, AMD64.rbx); - useRegisters(asm, AMD64.rsi); - XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); - XirLabel resume = asm.createInlineLabel("resume"); - - // check if the class is already initialized - asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false); - asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); - - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); - asm.add(temp1, result, wordConst(asm, size)); - asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); - - asm.jgt(tlabFull, temp1, temp2); - asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); - - asm.bindInline(resume); - - asm.pload(target.wordKind, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); - asm.mov(temp1o, type); // need a temporary register since Intel cannot store 64-bit constants to memory - asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), temp1o, false); - - if (size > 2 * target.wordSize) { - asm.mov(temp1, wordConst(asm, 0)); - for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { - asm.pstore(target.wordKind, result, asm.i(offset), temp1, false); - } - } - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(tlabFull); - XirOperand arg = asm.createRegisterTemp("runtime call argument", CiKind.Object, AMD64.rdx); - asm.mov(arg, type); - useRegisters(asm, AMD64.rax); - asm.callRuntime(config.newInstanceStub, result); - asm.jmp(resume); - - return asm.finishTemplate("new instance"); - } - }; - - private SimpleTemplates newObjectArrayCloneTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - XirOperand result = asm.restart(CiKind.Object); - XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true); - XirParameter src = asm.createInputParameter("src", CiKind.Object); - - // Set up length and hub. - XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx); - XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx); - asm.pload(CiKind.Object, hub, src, asm.i(config.hubOffset), false); - asm.mov(length, lengthParam); - - useRegisters(asm, AMD64.rsi, AMD64.rcx, AMD64.rdi, AMD64.rax); - asm.callRuntime(config.newObjectArrayStub, result); - return asm.finishTemplate("objectArrayClone"); - } - }; - - private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - emitNewTypeArray(asm, CiKind.Object, config.useFastNewObjectArray, config.newObjectArrayStub); - return asm.finishTemplate("newObjectArray"); - } - }; - - private void emitNewTypeArray(CiXirAssembler asm, CiKind kind, boolean useFast, long slowPathStub) { - XirOperand result = asm.restart(target.wordKind); - - XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true); - - XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx); - XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx); - - // Registers rsi, rcx, rdi, and rax are needed by the runtime call. - // Hub needs to be on rdx, length on rbx. - XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); - XirOperand temp1o = asm.createRegisterTemp("temp1o", CiKind.Object, AMD64.rcx); - XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rax); - XirOperand temp3 = asm.createRegisterTemp("temp3", target.wordKind, AMD64.rdi); - XirOperand size = asm.createRegisterTemp("size", CiKind.Int, AMD64.rsi); - - asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); - asm.mov(length, lengthParam); - - if (useFast) { - - XirLabel slowPath = asm.createOutOfLineLabel("slowPath"); - - XirLabel done = asm.createInlineLabel("done"); - - // Check for negative array size. - // TODO: Also check for upper bound - asm.jlt(slowPath, length, asm.i(0)); - - final int aligning = target.wordSize; - final int arrayLengthOffset = target.wordSize * 2; - final int arrayElementOffset = config.getArrayOffset(kind); - - // Calculate aligned size - asm.mov(size, length); - int scale = CiUtil.log2(target.sizeInBytes(kind)); - if (scale != 0) { - asm.shl(size, size, asm.i(scale)); - } - asm.add(size, size, asm.i(arrayElementOffset + aligning - 1)); - long mask = 0xFFFFFFFFL; - mask <<= CiUtil.log2(aligning); - asm.and(size, size, asm.i((int) mask)); - - // Try tlab allocation - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); - asm.add(temp1, result, size); - asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); - asm.jgt(slowPath, temp1, temp2); - asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); - - // Now the new object is in result, store mark word and klass - asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); - asm.pstore(target.wordKind, result, temp1, false); - asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory - asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), temp1o, false); - - // Store array length - asm.pstore(CiKind.Int, result, asm.i(arrayLengthOffset), length, false); - - // Initialize with 0 - XirLabel top = asm.createInlineLabel("top"); - asm.sub(size, size, asm.i(arrayElementOffset)); - asm.shr(size, size, asm.i(Scale.Times8.log2)); - asm.jeq(done, size, asm.i(0)); - asm.xor(temp3, temp3, temp3); - asm.bindInline(top); - asm.pstore(target.wordKind, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false); - asm.decAndJumpNotZero(top, size); - - asm.bindInline(done); - - // Slow path - asm.bindOutOfLine(slowPath); - asm.callRuntime(slowPathStub, result); - asm.jmp(done); - } else { - asm.callRuntime(slowPathStub, result); - } - } - - private KindTemplates newTypeArrayTemplates = new KindTemplates() { - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub); - return asm.finishTemplate("newTypeArray<" + kind.toString() + ">"); - } - }; - - private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) { - XirOperand result = asm.restart(CiKind.Object); - - XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rax); - XirOperand rank = asm.createRegisterTemp("rank", CiKind.Int, AMD64.rbx); - XirOperand sizes = asm.createRegisterTemp("sizes", CiKind.Long, AMD64.rcx); - XirOperand thread = asm.createRegisterTemp("thread", CiKind.Long, AMD64.r15); - asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); - for (int i = 0; i < dimensions; i++) { - XirParameter length = asm.createInputParameter("length" + i, CiKind.Int, true); - asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false); - } - - asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); - - asm.mov(rank, asm.i(dimensions)); - useRegisters(asm, AMD64.rax); - asm.callRuntime(config.newMultiArrayStub, result); - return asm.finishTemplate("multiNewArray" + dimensions); - } - }; - - private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub; - hub = asm.createConstantInputParameter("hub", CiKind.Object); - - XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - - XirLabel end = asm.createInlineLabel("end"); - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - - if (is(NULL_CHECK, flags)) { - // null can be cast to anything - asm.jeq(end, object, asm.o(null)); - } - - asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jneq(slowPath, objHub, hub); - asm.bindInline(end); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jneq(end, objHub, asm.o(null)); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 2)); - - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.shouldNotReachHere(); - - return asm.finishTemplate("checkcast"); - } - }; - - private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(CiKind.Void); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub; - hub = asm.createConstantInputParameter("hub", CiKind.Object); - - XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); - XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); - - if (is(NULL_CHECK, flags)) { - // null isn't "instanceof" anything - asm.jeq(falseSucc, object, asm.o(null)); - } - - asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jeq(trueSucc, objHub, hub); - asm.jmp(slowPath); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); - - return asm.finishTemplate("instanceof"); - } - }; - - private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - XirOperand result = asm.restart(CiKind.Int); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - final XirOperand hub; - hub = asm.createConstantInputParameter("hub", CiKind.Object); - XirOperand trueValue = asm.createConstantInputParameter("trueValue", CiKind.Int); - XirOperand falseValue = asm.createConstantInputParameter("falseValue", CiKind.Int); - - XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - - XirLabel slowPath = asm.createOutOfLineLabel("slow path"); - XirLabel trueSucc = asm.createInlineLabel("ok"); - XirLabel falseSucc = asm.createInlineLabel("ko"); - XirLabel end = asm.createInlineLabel("end"); - - if (is(NULL_CHECK, flags)) { - // null isn't "instanceof" anything - asm.jeq(falseSucc, object, asm.o(null)); - } - - asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - // if we get an exact match: succeed immediately - asm.jeq(trueSucc, objHub, hub); - asm.jmp(slowPath); - - asm.bindInline(trueSucc); - asm.mov(result, trueValue); - asm.jmp(end); - asm.bindInline(falseSucc); - asm.mov(result, falseValue); - asm.bindInline(end); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - checkSubtype(asm, objHub, objHub, hub); - asm.jeq(falseSucc, objHub, asm.o(null)); - asm.jmp(trueSucc); - - return asm.finishTemplate("instanceof"); - } - }; - - private XirOperand genArrayLength(CiXirAssembler asm, XirOperand array, boolean implicitNullException) { - XirOperand length = asm.createTemp("length", CiKind.Int); - genArrayLength(asm, length, array, implicitNullException); - return length; - } - - private void genArrayLength(CiXirAssembler asm, XirOperand length, XirOperand array, boolean implicitNullException) { - if (implicitNullException) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException); - } - - private KindTemplates arrayLoadTemplates = new KindTemplates(NULL_CHECK, READ_BARRIER, BOUNDS_CHECK, GIVEN_LENGTH) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - XirOperand result = asm.restart(kind); - XirParameter array = asm.createInputParameter("array", CiKind.Object); - XirParameter index = asm.createInputParameter("index", CiKind.Int, true); - XirLabel failBoundsCheck = null; - // if the length is known the array cannot be null - boolean implicitNullException = is(NULL_CHECK, flags); - - if (is(BOUNDS_CHECK, flags)) { - // load the array length and check the index - failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); - XirOperand length; - if (is(GIVEN_LENGTH, flags)) { - length = asm.createInputParameter("length", CiKind.Int, true); - } else { - length = genArrayLength(asm, array, implicitNullException); - } - asm.jugteq(failBoundsCheck, index, length); - implicitNullException = false; - } - int elemSize = target.sizeInBytes(kind); - if (implicitNullException) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); - if (is(BOUNDS_CHECK, flags)) { - asm.bindOutOfLine(failBoundsCheck); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 0)); - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.shouldNotReachHere(); - } - return asm.finishTemplate("arrayload<" + kind + ">"); - } - }; - - private SimpleTemplates getClassTemplates = new SimpleTemplates() { - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - XirOperand result = asm.restart(CiKind.Object); - XirOperand object = asm.createInputParameter("object", CiKind.Object); - asm.pload(CiKind.Object, result, object, asm.i(config.hubOffset), is(NULL_CHECK, flags)); - asm.pload(CiKind.Object, result, result, asm.i(config.classMirrorOffset), false); - return asm.finishTemplate("getClass"); - } - }; - - private SimpleTemplates currentThreadTemplates = new SimpleTemplates() { - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - XirOperand result = asm.restart(CiKind.Object); - XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); - asm.pload(CiKind.Object, result, thread, asm.i(config.threadObjectOffset), false); - return asm.finishTemplate("currentThread"); - } - }; - - @Override - public XirSnippet genCurrentThread(XirSite site) { - return new XirSnippet(currentThreadTemplates.get(site)); - } - - @Override - public XirSnippet genGetClass(XirSite site, XirArgument object) { - return new XirSnippet(getClassTemplates.get(site), object); - } - - private KindTemplates arrayCopyTemplates = new KindTemplates() { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - asm.restart(CiKind.Void); - XirParameter src = asm.createInputParameter("src", CiKind.Object); - XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int, true); - XirParameter dest = asm.createInputParameter("dest", CiKind.Object); - XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int, true); - XirParameter length = asm.createInputParameter("length", CiKind.Int, true); - - XirOperand tempSrc = asm.createTemp("tempSrc", target.wordKind); - XirOperand tempDest = asm.createTemp("tempDest", target.wordKind); - XirOperand lengthOperand = asm.createRegisterTemp("lengthOperand", CiKind.Int, AMD64.rax); - - XirOperand compHub = null; - XirOperand valueHub = null; - XirOperand temp = null; - XirLabel store = null; - XirLabel slowStoreCheck = null; - - if (is(STORE_CHECK, flags) && kind == CiKind.Object) { - valueHub = asm.createRegisterTemp("valueHub", target.wordKind, AMD64.rdi); - compHub = asm.createRegisterTemp("compHub", target.wordKind, AMD64.rsi); - temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); - } - - // Calculate the factor for the repeat move instruction. - int elementSize = target.sizeInBytes(kind); - int factor; - boolean wordSize; - if (elementSize >= target.wordSize) { - assert elementSize % target.wordSize == 0; - wordSize = true; - factor = elementSize / target.wordSize; - } else { - factor = elementSize; - wordSize = false; - } - - // Adjust the length if the factor is not 1. - if (factor != 1) { - asm.shl(lengthOperand, length, asm.i(CiUtil.log2(factor))); - } else { - asm.mov(lengthOperand, length); - } - - // Set the start and the end pointer. - asm.lea(tempSrc, src, srcPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - - XirLabel reverse = null; - XirLabel normal = null; - - if (is(STORE_CHECK, flags)) { - reverse = asm.createInlineLabel("reverse"); - asm.jneq(reverse, src, dest); - } - - if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { - normal = asm.createInlineLabel("normal"); - asm.jneq(normal, src, dest); - } - - if (!is(INPUTS_DIFFERENT, flags)) { - if (reverse == null) { - reverse = asm.createInlineLabel("reverse"); - } - asm.jlt(reverse, srcPos, destPos); - } - - if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { - asm.bindInline(normal); - } - - // Everything set up => repeat mov. - if (wordSize) { - asm.repmov(tempSrc, tempDest, lengthOperand); - } else { - asm.repmovb(tempSrc, tempDest, lengthOperand); - } - - if (!is(INPUTS_DIFFERENT, flags) || is(STORE_CHECK, flags)) { - - XirLabel end = asm.createInlineLabel("end"); - asm.jmp(end); - - // Implement reverse copy, because srcPos < destPos and src == dest. - asm.bindInline(reverse); - - if (is(STORE_CHECK, flags)) { - asm.pload(CiKind.Object, compHub, dest, asm.i(config.hubOffset), false); - asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); - } - - CiKind copyKind = wordSize ? CiKind.Object : CiKind.Byte; - XirOperand tempValue = asm.createTemp("tempValue", copyKind); - XirLabel start = asm.createInlineLabel("start"); - asm.bindInline(start); - asm.sub(lengthOperand, lengthOperand, asm.i(1)); - asm.jlt(end, lengthOperand, asm.i(0)); - - Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1; - asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false); - - if (is(STORE_CHECK, flags)) { - slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); - store = asm.createInlineLabel("store"); - asm.jeq(store, tempValue, asm.o(null)); // first check if value is null - asm.pload(CiKind.Object, valueHub, tempValue, asm.i(config.hubOffset), false); - asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub - asm.bindInline(store); - } - - asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false); - - asm.jmp(start); - asm.bindInline(end); - } - - if (kind == CiKind.Object) { - // Do write barriers - asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - asm.shr(tempDest, tempDest, asm.i(config.cardtableShift)); - asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDest, asm.b(false), false); - - XirOperand tempDestEnd = tempSrc; // Reuse src temp - asm.lea(tempDestEnd, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); - asm.add(tempDestEnd, tempDestEnd, length); - asm.shr(tempDestEnd, tempDestEnd, asm.i(config.cardtableShift)); - - // Jump to out-of-line write barrier loop if the array is big. - XirLabel writeBarrierLoop = asm.createOutOfLineLabel("writeBarrierLoop"); - asm.jneq(writeBarrierLoop, tempDest, tempSrc); - XirLabel back = asm.createInlineLabel("back"); - asm.bindInline(back); - - asm.bindOutOfLine(writeBarrierLoop); - asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDestEnd, asm.b(false), false); - asm.sub(tempDestEnd, tempDestEnd, asm.i(1)); - asm.jneq(writeBarrierLoop, tempDestEnd, tempDest); - asm.jmp(back); - } - - if (is(STORE_CHECK, flags)) { - assert kind == CiKind.Object; - useRegisters(asm, AMD64.rax); - asm.bindOutOfLine(slowStoreCheck); - checkSubtype(asm, temp, valueHub, compHub); - asm.jneq(store, temp, wordConst(asm, 0)); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 0)); - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.jmp(store); - } - - return asm.finishTemplate("arraycopy<" + kind + ">"); - } - }; - - private KindTemplates arrayStoreTemplates = new KindTemplates(NULL_CHECK, WRITE_BARRIER, BOUNDS_CHECK, STORE_CHECK, GIVEN_LENGTH) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { - asm.restart(CiKind.Void); - XirParameter array = asm.createInputParameter("array", CiKind.Object); - XirParameter index = asm.createInputParameter("index", CiKind.Int, true); - XirParameter value = asm.createInputParameter("value", kind, kind != CiKind.Object); - XirOperand temp = asm.createTemp("temp", target.wordKind); - XirOperand valueHub = null; - XirOperand compHub = null; - XirLabel store = asm.createInlineLabel("store"); - XirLabel failBoundsCheck = null; - XirLabel slowStoreCheck = null; - // if the length is known the array cannot be null - boolean implicitNullException = is(NULL_CHECK, flags); - - if (is(BOUNDS_CHECK, flags)) { - // load the array length and check the index - failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); - XirOperand length; - if (is(GIVEN_LENGTH, flags)) { - length = asm.createInputParameter("length", CiKind.Int); - } else { - length = asm.createTemp("length", CiKind.Int); - if (implicitNullException) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException); - implicitNullException = false; - } - asm.jugteq(failBoundsCheck, index, length); - - } - if (is(STORE_CHECK, flags) && kind == CiKind.Object) { - slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); - asm.jeq(store, value, asm.o(null)); // first check if value is null - valueHub = asm.createTemp("valueHub", CiKind.Object); - compHub = asm.createTemp("compHub", CiKind.Object); - if (implicitNullException) { - asm.mark(MARK_IMPLICIT_NULL); - } - asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), implicitNullException); - asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); - asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false); - asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub - - implicitNullException = false; - } - asm.bindInline(store); - int elemSize = target.sizeInBytes(kind); - - if (implicitNullException) { - asm.mark(MARK_IMPLICIT_NULL); - } - int disp = config.getArrayOffset(kind); - Scale scale = Scale.fromInt(elemSize); - if (kind == CiKind.Object) { - verifyPointer(asm, value); - } - if (is(WRITE_BARRIER, flags) && kind == CiKind.Object) { - asm.lea(temp, array, index, disp, scale); - asm.pstore(kind, temp, value, implicitNullException); - writeBarrier(asm, temp); - } else { - asm.pstore(kind, array, index, value, disp, scale, implicitNullException); - } - - // -- out of line ------------------------------------------------------- - if (is(BOUNDS_CHECK, flags)) { - asm.bindOutOfLine(failBoundsCheck); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 0)); - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.shouldNotReachHere(); - } - if (is(STORE_CHECK, flags) && kind == CiKind.Object) { - useRegisters(asm, AMD64.rax); - asm.bindOutOfLine(slowStoreCheck); - checkSubtype(asm, temp, valueHub, compHub); - asm.jneq(store, temp, wordConst(asm, 0)); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 0)); - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.shouldNotReachHere(); - } - return asm.finishTemplate("arraystore<" + kind + ">"); - } - }; - - private SimpleTemplates arrayLengthTemplates = new SimpleTemplates(NULL_CHECK) { - - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - XirOperand result = asm.restart(CiKind.Int); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - } - verifyPointer(asm, object); - asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true); - return asm.finishTemplate("arrayLength"); - } - }; - - private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { - @Override - protected XirTemplate create(CiXirAssembler asm, long flags) { - asm.restart(); - XirParameter object = asm.createInputParameter("object", CiKind.Object); - XirOperand hub = asm.createConstantInputParameter("hub", CiKind.Object); - - XirOperand objHub = asm.createTemp("objHub", CiKind.Object); - XirOperand checkHub = asm.createTemp("checkHub", CiKind.Object); - - XirLabel slowPath = asm.createOutOfLineLabel("deopt"); - - if (is(NULL_CHECK, flags)) { - asm.mark(MARK_IMPLICIT_NULL); - } - - asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); - asm.mov(checkHub, hub); - // if we get an exact match: continue - asm.jneq(slowPath, objHub, checkHub); - - // -- out of line ------------------------------------------------------- - asm.bindOutOfLine(slowPath); - XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); - asm.mov(scratch, wordConst(asm, 2)); - - asm.callRuntime(CiRuntimeCall.Deoptimize, null); - asm.shouldNotReachHere(); - - return asm.finishTemplate(object, "typeCheck"); - } - }; - - @Override - public XirSnippet genPrologue(XirSite site, RiResolvedMethod method) { - boolean staticMethod = Modifier.isStatic(method.accessFlags()); - return new XirSnippet(staticMethod ? prologueTemplates.get(site, STATIC_METHOD) : prologueTemplates.get(site)); - } - - @Override - public XirSnippet genEpilogue(XirSite site, RiResolvedMethod method) { - return new XirSnippet(epilogueTemplates.get(site)); - } - - @Override - public XirSnippet genSafepointPoll(XirSite site) { - return new XirSnippet(safepointTemplates.get(site)); - } - - @Override - public XirSnippet genExceptionObject(XirSite site) { - return new XirSnippet(exceptionObjectTemplates.get(site)); - } - - @Override - public XirSnippet genResolveClass(XirSite site, RiType type, Representation rep) { - throw new CiBailout("Xir ResolveClass not available"); - } - - @Override - public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) { - return null; - } - - @Override - public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) { - return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, wordArg(0)); - } - - @Override - public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { - return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0)); - } - - @Override - public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) { - return new XirSnippet(invokeSpecialTemplates.get(site), receiver, wordArg(0)); - } - - @Override - public XirSnippet genInvokeStatic(XirSite site, RiMethod method) { - return new XirSnippet(invokeStaticTemplates.get(site), wordArg(0)); - } - - @Override - public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) { - return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress); - } - - @Override - public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) { - return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress); - } - - @Override - public XirSnippet genGetField(XirSite site, XirArgument object, RiField field) { - return new XirSnippet(getFieldTemplates.get(site, field.kind(false)), object, XirArgument.forInt(((HotSpotField) field).offset())); - } - - @Override - public XirSnippet genWriteBarrier(XirArgument object) { - return new XirSnippet(writeBarrierTemplate.get(null, CiKind.Void), object); - } - - @Override - public XirSnippet genPutField(XirSite site, XirArgument object, RiField field, XirArgument value) { - return new XirSnippet(putFieldTemplates.get(site, field.kind(false)), object, value, XirArgument.forInt(((HotSpotField) field).offset())); - } - - @Override - public XirSnippet genGetStatic(XirSite site, XirArgument object, RiField field) { - return new XirSnippet(getFieldTemplates.get(site, field.kind(false)), object, XirArgument.forInt(((HotSpotField) field).offset())); - } - - @Override - public XirSnippet genPutStatic(XirSite site, XirArgument object, RiField field, XirArgument value) { - return new XirSnippet(putFieldTemplates.get(site, field.kind(false)), object, value, XirArgument.forInt(((HotSpotField) field).offset())); - } - - @Override - public XirSnippet genNewInstance(XirSite site, RiType type) { - int instanceSize = ((HotSpotTypeResolved) type).instanceSize(); - return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(type)); - } - - @Override - public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { - if (elementKind == CiKind.Object) { - assert arrayType instanceof RiResolvedType; - return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(arrayType)); - } else { - assert arrayType == null; - RiType primitiveArrayType = compiler.getVMEntries().getPrimitiveArrayType(elementKind); - return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(primitiveArrayType)); - } - } - - @Override - public XirSnippet genNewObjectArrayClone(XirSite site, XirArgument newLength, XirArgument referenceArray) { - return new XirSnippet(newObjectArrayCloneTemplates.get(site), newLength, referenceArray); - } - - @Override - public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { - XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); - params[lengths.length] = XirArgument.forObject(type); - return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); - } - - @Override - public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { - return new XirSnippet(checkCastTemplates.get(site), receiver, hub); - } - - @Override - public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) { - return new XirSnippet(instanceOfTemplates.get(site), object, hub); - } - - @Override - public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type) { - return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub, trueValue, falseValue); - } - - @Override - public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType) { - return new XirSnippet(arrayLoadTemplates.get(site, elementKind), array, index); - } - - @Override - public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument value, CiKind elementKind, RiType elementType) { - return new XirSnippet(arrayStoreTemplates.get(site, elementKind), array, index, value); - } - - @Override - public XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent) { - if (elementType == null) { - return null; - } - assert !inputsDifferent || !inputsSame; - XirTemplate template = null; - if (inputsDifferent) { - template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_DIFFERENT); - } else if (inputsSame) { - template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_SAME); - } else { - template = arrayCopyTemplates.get(site, elementType.kind(true)); - } - return new XirSnippet(template, src, srcPos, dest, destPos, length); - } - - @Override - public XirSnippet genArrayLength(XirSite site, XirArgument array) { - return new XirSnippet(arrayLengthTemplates.get(site), array); - } - - @Override - public XirSnippet genTypeCheck(XirSite site, XirArgument object, XirArgument hub, RiType type) { - assert type instanceof RiResolvedType; - return new XirSnippet(typeCheckTemplates.get(site), object, hub); - } - - @Override - public List makeTemplates(CiXirAssembler asm) { - this.globalAsm = asm; - List templates = new ArrayList<>(); - return templates; - } - - private void verifyPointer(CiXirAssembler asm, XirOperand pointer) { - if (config.verifyPointers) { - // The verify pointer stub wants the argument in a fixed register. - XirOperand fixed = asm.createRegisterTemp("fixed", CiKind.Object, AMD64.r13); - asm.push(fixed); - asm.mov(fixed, pointer); - asm.callRuntime(config.verifyPointerStub, null); - asm.pop(fixed); - } - } - - private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { - asm.push(objHub); - asm.push(hub); - asm.callRuntime(config.instanceofStub, null); - asm.pop(result); - asm.pop(result); - } - - private static void useRegisters(CiXirAssembler asm, CiRegister... registers) { - if (registers != null) { - for (CiRegister register : registers) { - asm.createRegisterTemp("reg", CiKind.Illegal, register); - } - } - } - - private void writeBarrier(CiXirAssembler asm, XirOperand base) { - asm.shr(base, base, asm.i(config.cardtableShift)); - asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), base, asm.b(false), false); - } - - public boolean is(TemplateFlag check, long flags) { - return (flags & check.bits()) == check.bits(); - } - - /** - * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of - * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates). - */ - private abstract class Templates { - - private ConcurrentHashMap templates = new ConcurrentHashMap<>(); - private final long mask; - - /** - * Each flag passed to this method will cause templates with and without it to be generated. - */ - public Templates(TemplateFlag... flags) { - this.mask = getBits((int) INDEX_MASK, null, flags); - } - - protected abstract XirTemplate create(CiXirAssembler asm, long flags); - - protected long getBits(int index, XirSite site, TemplateFlag... flags) { - long bits = index; - if (site != null) { - bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0; - bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0; - bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0; - bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0; - bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0; - } - if (flags != null) { - for (TemplateFlag flag : flags) { - bits |= flag.bits(); - } - } - return bits; - } - - protected XirTemplate getInternal(long flags) { - long maskedFlags = flags & mask; - XirTemplate template = templates.get(maskedFlags); - if (template == null) { - template = create(HotSpotXirGenerator.this.globalAsm.copy(), maskedFlags); - templates.put(maskedFlags, template); - } - return template; - } - } - - private abstract class SimpleTemplates extends Templates { - - public SimpleTemplates(TemplateFlag... flags) { - super(flags); - } - - public XirTemplate get(XirSite site, TemplateFlag... flags) { - return getInternal(getBits(0, site, flags)); - } - } - - private abstract class IndexTemplates extends Templates { - - public IndexTemplates(TemplateFlag... flags) { - super(flags); - } - - @Override - protected final XirTemplate create(CiXirAssembler asm, long flags) { - return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK)); - } - - protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index); - - public XirTemplate get(XirSite site, int size, TemplateFlag... flags) { - return getInternal(getBits(size, site, flags)); - } - } - - private abstract class KindTemplates extends Templates { - - public KindTemplates(TemplateFlag... flags) { - super(flags); - } - - @Override - protected final XirTemplate create(CiXirAssembler asm, long flags) { - return create(asm, flags & FLAGS_MASK, CiKind.VALUES[(int) (flags & INDEX_MASK)]); - } - - protected abstract XirTemplate create(CiXirAssembler asm, long flags, CiKind kind); - - public XirTemplate get(XirSite site, CiKind kind, TemplateFlag... flags) { - return getInternal(getBits(kind.ordinal(), site, flags)); - } - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/TemplateFlag.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/TemplateFlag.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -enum TemplateFlag { - NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED; - - private static final long FIRST_FLAG = 0x0000000100000000L; - public static final long FLAGS_MASK = 0x0000FFFF00000000L; - public static final long INDEX_MASK = 0x00000000FFFFFFFFL; - - public long bits() { - assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0; - return FIRST_FLAG << ordinal(); - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMEntries.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMEntries.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import java.lang.reflect.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.ri.*; - -/** - * Entries into the HotSpot VM from Java code. - */ -public interface VMEntries { - - // Checkstyle: stop - - byte[] RiMethod_code(HotSpotMethodResolved method); - - String RiMethod_signature(HotSpotMethodResolved method); - - RiExceptionHandler[] RiMethod_exceptionHandlers(HotSpotMethodResolved method); - - boolean RiMethod_hasBalancedMonitors(HotSpotMethodResolved method); - - RiMethod RiMethod_uniqueConcreteMethod(HotSpotMethodResolved method); - - int RiMethod_invocationCount(HotSpotMethodResolved method); - - int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci); - - RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci); - - double RiMethod_branchProbability(HotSpotMethodResolved method, int bci); - - double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci); - - RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); - - Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi); - - RiMethod RiConstantPool_lookupMethod(HotSpotTypeResolved pool, int cpi, byte byteCode); - - RiType RiConstantPool_lookupType(HotSpotTypeResolved pool, int cpi); - - RiField RiConstantPool_lookupField(HotSpotTypeResolved pool, int cpi, byte byteCode); - - void RiConstantPool_loadReferencedType(HotSpotTypeResolved pool, int cpi, byte byteCode); - - HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); - - long installStub(HotSpotTargetMethod targetMethod); - - HotSpotVMConfig getConfiguration(); - - RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); - - boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); - - RiType getPrimitiveArrayType(CiKind kind); - - RiType RiType_arrayOf(HotSpotTypeResolved klass); - - RiType RiType_componentType(HotSpotTypeResolved klass); - - boolean RiType_isInitialized(HotSpotTypeResolved klass); - - RiType getType(Class javaClass); - - RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass); - - RiType RiType_superType(HotSpotTypeResolved klass); - - int getArrayLength(CiConstant array); - - boolean compareConstantObjects(CiConstant x, CiConstant y); - - RiType getRiType(CiConstant constant); - - RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); - - boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); - - RiMethod getRiMethod(Method reflectionMethod); - - long getMaxCallTargetOffset(CiRuntimeCall rtcall); - - // Checkstyle: resume -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMEntriesNative.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMEntriesNative.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import java.lang.reflect.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.ri.*; -import com.oracle.max.graal.hotspot.server.*; - -/** - * Entries into the HotSpot VM from Java code. - */ -public class VMEntriesNative implements VMEntries, Remote { - - // Checkstyle: stop - - @Override - public native RiMethod getRiMethod(Method reflectionMethod); - - @Override - public native byte[] RiMethod_code(HotSpotMethodResolved method); - - @Override - public native String RiMethod_signature(HotSpotMethodResolved method); - - @Override - public native RiExceptionHandler[] RiMethod_exceptionHandlers(HotSpotMethodResolved method); - - @Override - public native boolean RiMethod_hasBalancedMonitors(HotSpotMethodResolved method); - - @Override - public native RiMethod RiMethod_uniqueConcreteMethod(HotSpotMethodResolved method); - - @Override - public native int RiMethod_invocationCount(HotSpotMethodResolved method); - - @Override - public native int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci); - - @Override - public native RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci); - - @Override - public native double RiMethod_branchProbability(HotSpotMethodResolved method, int bci); - - @Override - public native double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci); - - @Override - public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); - - @Override - public native Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi); - - @Override - public native RiMethod RiConstantPool_lookupMethod(HotSpotTypeResolved pool, int cpi, byte byteCode); - - @Override - public native RiType RiConstantPool_lookupType(HotSpotTypeResolved pool, int cpi); - - @Override - public native void RiConstantPool_loadReferencedType(HotSpotTypeResolved pool, int cpi, byte byteCode); - - @Override - public native RiField RiConstantPool_lookupField(HotSpotTypeResolved pool, int cpi, byte byteCode); - - @Override - public native HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); - - @Override - public native long installStub(HotSpotTargetMethod targetMethod); - - @Override - public native HotSpotVMConfig getConfiguration(); - - @Override - public native RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); - - @Override - public native boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); - - @Override - public native RiType getPrimitiveArrayType(CiKind kind); - - @Override - public native RiType RiType_arrayOf(HotSpotTypeResolved klass); - - @Override - public native RiType RiType_componentType(HotSpotTypeResolved klass); - - @Override - public native RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass); - - @Override - public native RiType RiType_superType(HotSpotTypeResolved klass); - - @Override - public native boolean RiType_isInitialized(HotSpotTypeResolved klass); - - @Override - public native RiType getType(Class javaClass); - - @Override - public int getArrayLength(CiConstant array) { - return Array.getLength(array.asObject()); - } - - @Override - public boolean compareConstantObjects(CiConstant x, CiConstant y) { - return x.asObject() == y.asObject(); - } - - @Override - public RiType getRiType(CiConstant constant) { - Object o = constant.asObject(); - if (o == null) { - return null; - } - return getType(o.getClass()); - } - - @Override - public native RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); - - @Override - public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); - - @Override - public native long getMaxCallTargetOffset(CiRuntimeCall rtcall); - - // Checkstyle: resume -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMExits.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMExits.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.ri.*; - -/** - * Exits from the HotSpot VM into Java code. - */ -public interface VMExits { - - void compileMethod(HotSpotMethodResolved method, int entryBCI, boolean blocking) throws Throwable; - - void shutdownCompiler() throws Throwable; - - void startCompiler() throws Throwable; - - void bootstrap() throws Throwable; - - RiMethod createRiMethodUnresolved(String name, String signature, RiType holder); - - RiSignature createRiSignature(String signature); - - RiField createRiField(RiType holder, String name, RiType type, int offset, int flags); - - RiType createRiType(HotSpotConstantPool pool, String name); - - RiType createRiTypePrimitive(int basicType); - - RiType createRiTypeUnresolved(String name); - - CiConstant createCiConstant(CiKind kind, long value); - - CiConstant createCiConstantFloat(float value); - - CiConstant createCiConstantDouble(double value); - - CiConstant createCiConstantObject(Object object); -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMExitsNative.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/VMExitsNative.java Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,286 +0,0 @@ -/* - * Copyright (c) 2011, 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.max.graal.hotspot; - -import java.lang.reflect.*; -import java.util.concurrent.*; - -import com.oracle.max.cri.ci.*; -import com.oracle.max.cri.ci.CiCompiler.*; -import com.oracle.max.cri.ri.*; -import com.oracle.max.criutils.*; -import com.oracle.max.graal.compiler.*; -import com.oracle.max.graal.compiler.phases.*; -import com.oracle.max.graal.compiler.phases.PhasePlan.*; -import com.oracle.max.graal.hotspot.ri.*; -import com.oracle.max.graal.hotspot.server.*; -import com.oracle.max.graal.java.*; -import com.oracle.max.graal.snippets.*; - -/** - * Exits from the HotSpot VM into Java code. - */ -public class VMExitsNative implements VMExits, Remote { - - private final Compiler compiler; - - public final HotSpotTypePrimitive typeBoolean; - public final HotSpotTypePrimitive typeChar; - public final HotSpotTypePrimitive typeFloat; - public final HotSpotTypePrimitive typeDouble; - public final HotSpotTypePrimitive typeByte; - public final HotSpotTypePrimitive typeShort; - public final HotSpotTypePrimitive typeInt; - public final HotSpotTypePrimitive typeLong; - public final HotSpotTypePrimitive typeVoid; - - ThreadFactory daemonThreadFactory = new ThreadFactory() { - @Override - public Thread newThread(Runnable r) { - Thread t = new CompilerThread(r); - t.setDaemon(true); - return t; - } - }; - private static final class CompilerThread extends Thread { - public CompilerThread(Runnable r) { - super(r); - this.setName("CompilerThread-" + this.getId()); - } - } - private ThreadPoolExecutor compileQueue; - - public VMExitsNative(Compiler compiler) { - this.compiler = compiler; - - typeBoolean = new HotSpotTypePrimitive(compiler, CiKind.Boolean); - typeChar = new HotSpotTypePrimitive(compiler, CiKind.Char); - typeFloat = new HotSpotTypePrimitive(compiler, CiKind.Float); - typeDouble = new HotSpotTypePrimitive(compiler, CiKind.Double); - typeByte = new HotSpotTypePrimitive(compiler, CiKind.Byte); - typeShort = new HotSpotTypePrimitive(compiler, CiKind.Short); - typeInt = new HotSpotTypePrimitive(compiler, CiKind.Int); - typeLong = new HotSpotTypePrimitive(compiler, CiKind.Long); - typeVoid = new HotSpotTypePrimitive(compiler, CiKind.Void); - } - - public void startCompiler() throws Throwable { - // Make sure TTY is initialized here such that the correct System.out is used for TTY. - TTY.initialize(); - - // Install intrinsics. - HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime; - if (GraalOptions.Intrinsify) { - GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), GraalOptions.PlotSnippets, PhasePlan.DEFAULT); - Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), GraalOptions.PlotSnippets, PhasePlan.DEFAULT); - } - - // Create compilation queue. - compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), daemonThreadFactory); - - // Create queue status printing thread. - if (GraalOptions.PrintQueue) { - Thread t = new Thread() { - @Override - public void run() { - while (true) { - TTY.println(compileQueue.toString()); - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - } - } - } - }; - t.setDaemon(true); - t.start(); - } - } - - public void bootstrap() throws Throwable { - TTY.print("Bootstrapping Graal"); - TTY.flush(); - long startTime = System.currentTimeMillis(); - - // Initialize compile queue with a selected set of methods. - Class objectKlass = Object.class; - enqueue(objectKlass.getDeclaredMethod("equals", Object.class)); - enqueue(objectKlass.getDeclaredMethod("toString")); - - // Compile until the queue is empty. - int z = 0; - while (compileQueue.getCompletedTaskCount() < Math.max(2, compileQueue.getTaskCount())) { - Thread.sleep(100); - while (z < compileQueue.getCompletedTaskCount() / 100) { - ++z; - TTY.print("."); - TTY.flush(); - } - } - - TTY.println(" in %d ms", System.currentTimeMillis() - startTime); - System.gc(); - } - - private void enqueue(Method m) throws Throwable { - RiMethod riMethod = compiler.getRuntime().getRiMethod(m); - assert !Modifier.isAbstract(((HotSpotMethodResolved) riMethod).accessFlags()) && !Modifier.isNative(((HotSpotMethodResolved) riMethod).accessFlags()) : riMethod; - compileMethod((HotSpotMethodResolved) riMethod, 0, false); - } - - public void shutdownCompiler() throws Throwable { - compiler.getCompiler().context.print(); - compileQueue.shutdown(); - } - - @Override - public void compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking) throws Throwable { - try { - if (Thread.currentThread() instanceof CompilerThread && method.holder().name().contains("java/util/concurrent")) { - return; - } - - Runnable runnable = new Runnable() { - public void run() { - try { - PhasePlan plan = new PhasePlan(); - GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), null); - plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); - CiTargetMethod result = compiler.getCompiler().compileMethod(method, -1, null, DebugInfoLevel.FULL, plan); - HotSpotTargetMethod.installMethod(compiler, method, result, true); - } catch (CiBailout bailout) { - if (GraalOptions.ExitVMOnBailout) { - bailout.printStackTrace(TTY.cachedOut); - System.exit(-1); - } - } catch (Throwable t) { - if (GraalOptions.ExitVMOnException) { - t.printStackTrace(TTY.cachedOut); - System.exit(-1); - } - } - } - }; - - if (blocking) { - runnable.run(); - } else { - compileQueue.execute(runnable); - } - } catch (RejectedExecutionException e) { - // The compile queue was already shut down. - return; - } - } - - @Override - public RiMethod createRiMethodUnresolved(String name, String signature, RiType holder) { - return new HotSpotMethodUnresolved(compiler, name, signature, holder); - } - - @Override - public RiSignature createRiSignature(String signature) { - return new HotSpotSignature(compiler, signature); - } - - @Override - public RiField createRiField(RiType holder, String name, RiType type, int offset, int flags) { - if (offset != -1) { - HotSpotTypeResolved resolved = (HotSpotTypeResolved) holder; - return resolved.createRiField(name, type, offset, flags); - } - return new BaseUnresolvedField(holder, name, type); - } - - @Override - public RiType createRiType(HotSpotConstantPool pool, String name) { - throw new RuntimeException("not implemented"); - } - - @Override - public RiType createRiTypePrimitive(int basicType) { - switch (basicType) { - case 4: - return typeBoolean; - case 5: - return typeChar; - case 6: - return typeFloat; - case 7: - return typeDouble; - case 8: - return typeByte; - case 9: - return typeShort; - case 10: - return typeInt; - case 11: - return typeLong; - case 14: - return typeVoid; - default: - throw new IllegalArgumentException("Unknown basic type: " + basicType); - } - } - - @Override - public RiType createRiTypeUnresolved(String name) { - return new HotSpotTypeUnresolved(compiler, name); - } - - @Override - public CiConstant createCiConstant(CiKind kind, long value) { - if (kind == CiKind.Long) { - return CiConstant.forLong(value); - } else if (kind == CiKind.Int) { - return CiConstant.forInt((int) value); - } else if (kind == CiKind.Short) { - return CiConstant.forShort((short) value); - } else if (kind == CiKind.Char) { - return CiConstant.forChar((char) value); - } else if (kind == CiKind.Byte) { - return CiConstant.forByte((byte) value); - } else if (kind == CiKind.Boolean) { - return (value == 0) ? CiConstant.FALSE : CiConstant.TRUE; - } else { - throw new IllegalArgumentException(); - } - } - - @Override - public CiConstant createCiConstantFloat(float value) { - return CiConstant.forFloat(value); - } - - @Override - public CiConstant createCiConstantDouble(double value) { - return CiConstant.forDouble(value); - } - - @Override - public CiConstant createCiConstantObject(Object object) { - return CiConstant.forObject(object); - } -} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVM.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.bridge; + +import java.lang.reflect.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.ri.*; + +/** + * Entries into the HotSpot VM from Java code. + */ +public interface CompilerToVM { + + // Checkstyle: stop + + byte[] RiMethod_code(HotSpotMethodResolved method); + + String RiMethod_signature(HotSpotMethodResolved method); + + RiExceptionHandler[] RiMethod_exceptionHandlers(HotSpotMethodResolved method); + + boolean RiMethod_hasBalancedMonitors(HotSpotMethodResolved method); + + RiMethod RiMethod_uniqueConcreteMethod(HotSpotMethodResolved method); + + int RiMethod_invocationCount(HotSpotMethodResolved method); + + int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci); + + RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci); + + double RiMethod_branchProbability(HotSpotMethodResolved method, int bci); + + double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci); + + RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); + + Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi); + + RiMethod RiConstantPool_lookupMethod(HotSpotTypeResolved pool, int cpi, byte byteCode); + + RiType RiConstantPool_lookupType(HotSpotTypeResolved pool, int cpi); + + RiField RiConstantPool_lookupField(HotSpotTypeResolved pool, int cpi, byte byteCode); + + void RiConstantPool_loadReferencedType(HotSpotTypeResolved pool, int cpi, byte byteCode); + + HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); + + long installStub(HotSpotTargetMethod targetMethod); + + HotSpotVMConfig getConfiguration(); + + RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); + + boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); + + RiType getPrimitiveArrayType(CiKind kind); + + RiType RiType_arrayOf(HotSpotTypeResolved klass); + + RiType RiType_componentType(HotSpotTypeResolved klass); + + boolean RiType_isInitialized(HotSpotTypeResolved klass); + + RiType getType(Class javaClass); + + RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass); + + RiType RiType_superType(HotSpotTypeResolved klass); + + int getArrayLength(CiConstant array); + + boolean compareConstantObjects(CiConstant x, CiConstant y); + + RiType getRiType(CiConstant constant); + + RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); + + boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); + + RiMethod getRiMethod(Method reflectionMethod); + + long getMaxCallTargetOffset(CiRuntimeCall rtcall); + + // Checkstyle: resume +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/CompilerToVMImpl.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.bridge; + +import java.lang.reflect.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.ri.*; +import com.oracle.max.graal.hotspot.server.*; + +/** + * Entries into the HotSpot VM from Java code. + */ +public class CompilerToVMImpl implements CompilerToVM, Remote { + + // Checkstyle: stop + + @Override + public native RiMethod getRiMethod(Method reflectionMethod); + + @Override + public native byte[] RiMethod_code(HotSpotMethodResolved method); + + @Override + public native String RiMethod_signature(HotSpotMethodResolved method); + + @Override + public native RiExceptionHandler[] RiMethod_exceptionHandlers(HotSpotMethodResolved method); + + @Override + public native boolean RiMethod_hasBalancedMonitors(HotSpotMethodResolved method); + + @Override + public native RiMethod RiMethod_uniqueConcreteMethod(HotSpotMethodResolved method); + + @Override + public native int RiMethod_invocationCount(HotSpotMethodResolved method); + + @Override + public native int RiMethod_exceptionProbability(HotSpotMethodResolved method, int bci); + + @Override + public native RiTypeProfile RiMethod_typeProfile(HotSpotMethodResolved method, int bci); + + @Override + public native double RiMethod_branchProbability(HotSpotMethodResolved method, int bci); + + @Override + public native double[] RiMethod_switchProbability(HotSpotMethodResolved method, int bci); + + @Override + public native RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); + + @Override + public native Object RiConstantPool_lookupConstant(HotSpotTypeResolved pool, int cpi); + + @Override + public native RiMethod RiConstantPool_lookupMethod(HotSpotTypeResolved pool, int cpi, byte byteCode); + + @Override + public native RiType RiConstantPool_lookupType(HotSpotTypeResolved pool, int cpi); + + @Override + public native void RiConstantPool_loadReferencedType(HotSpotTypeResolved pool, int cpi, byte byteCode); + + @Override + public native RiField RiConstantPool_lookupField(HotSpotTypeResolved pool, int cpi, byte byteCode); + + @Override + public native HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); + + @Override + public native long installStub(HotSpotTargetMethod targetMethod); + + @Override + public native HotSpotVMConfig getConfiguration(); + + @Override + public native RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); + + @Override + public native boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); + + @Override + public native RiType getPrimitiveArrayType(CiKind kind); + + @Override + public native RiType RiType_arrayOf(HotSpotTypeResolved klass); + + @Override + public native RiType RiType_componentType(HotSpotTypeResolved klass); + + @Override + public native RiType RiType_uniqueConcreteSubtype(HotSpotTypeResolved klass); + + @Override + public native RiType RiType_superType(HotSpotTypeResolved klass); + + @Override + public native boolean RiType_isInitialized(HotSpotTypeResolved klass); + + @Override + public native RiType getType(Class javaClass); + + @Override + public int getArrayLength(CiConstant array) { + return Array.getLength(array.asObject()); + } + + @Override + public boolean compareConstantObjects(CiConstant x, CiConstant y) { + return x.asObject() == y.asObject(); + } + + @Override + public RiType getRiType(CiConstant constant) { + Object o = constant.asObject(); + if (o == null) { + return null; + } + return getType(o.getClass()); + } + + @Override + public native RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); + + @Override + public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); + + @Override + public native long getMaxCallTargetOffset(CiRuntimeCall rtcall); + + // Checkstyle: resume +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompiler.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.bridge; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.hotspot.ri.*; + +/** + * Exits from the HotSpot VM into Java code. + */ +public interface VMToCompiler { + + void compileMethod(HotSpotMethodResolved method, int entryBCI, boolean blocking) throws Throwable; + + void shutdownCompiler() throws Throwable; + + void startCompiler() throws Throwable; + + void bootstrap() throws Throwable; + + RiMethod createRiMethodUnresolved(String name, String signature, RiType holder); + + RiSignature createRiSignature(String signature); + + RiField createRiField(RiType holder, String name, RiType type, int offset, int flags); + + RiType createRiType(HotSpotConstantPool pool, String name); + + RiType createRiTypePrimitive(int basicType); + + RiType createRiTypeUnresolved(String name); + + CiConstant createCiConstant(CiKind kind, long value); + + CiConstant createCiConstantFloat(float value); + + CiConstant createCiConstantDouble(double value); + + CiConstant createCiConstantObject(Object object); +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/bridge/VMToCompilerImpl.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.bridge; + +import java.lang.reflect.*; +import java.util.concurrent.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiCompiler.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.criutils.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.phases.*; +import com.oracle.max.graal.compiler.phases.PhasePlan.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.Compiler; +import com.oracle.max.graal.hotspot.ri.*; +import com.oracle.max.graal.hotspot.server.*; +import com.oracle.max.graal.java.*; +import com.oracle.max.graal.snippets.*; + +/** + * Exits from the HotSpot VM into Java code. + */ +public class VMToCompilerImpl implements VMToCompiler, Remote { + + private final Compiler compiler; + + public final HotSpotTypePrimitive typeBoolean; + public final HotSpotTypePrimitive typeChar; + public final HotSpotTypePrimitive typeFloat; + public final HotSpotTypePrimitive typeDouble; + public final HotSpotTypePrimitive typeByte; + public final HotSpotTypePrimitive typeShort; + public final HotSpotTypePrimitive typeInt; + public final HotSpotTypePrimitive typeLong; + public final HotSpotTypePrimitive typeVoid; + + ThreadFactory daemonThreadFactory = new ThreadFactory() { + @Override + public Thread newThread(Runnable r) { + Thread t = new CompilerThread(r); + t.setDaemon(true); + return t; + } + }; + private static final class CompilerThread extends Thread { + public CompilerThread(Runnable r) { + super(r); + this.setName("CompilerThread-" + this.getId()); + } + } + private ThreadPoolExecutor compileQueue; + + public VMToCompilerImpl(Compiler compiler) { + this.compiler = compiler; + + typeBoolean = new HotSpotTypePrimitive(compiler, CiKind.Boolean); + typeChar = new HotSpotTypePrimitive(compiler, CiKind.Char); + typeFloat = new HotSpotTypePrimitive(compiler, CiKind.Float); + typeDouble = new HotSpotTypePrimitive(compiler, CiKind.Double); + typeByte = new HotSpotTypePrimitive(compiler, CiKind.Byte); + typeShort = new HotSpotTypePrimitive(compiler, CiKind.Short); + typeInt = new HotSpotTypePrimitive(compiler, CiKind.Int); + typeLong = new HotSpotTypePrimitive(compiler, CiKind.Long); + typeVoid = new HotSpotTypePrimitive(compiler, CiKind.Void); + } + + public void startCompiler() throws Throwable { + // Make sure TTY is initialized here such that the correct System.out is used for TTY. + TTY.initialize(); + + // Install intrinsics. + HotSpotRuntime runtime = (HotSpotRuntime) compiler.getCompiler().runtime; + if (GraalOptions.Intrinsify) { + GraalIntrinsics.installIntrinsics(runtime, runtime.getCompiler().getTarget(), PhasePlan.DEFAULT); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new SystemSnippets(), GraalOptions.PlotSnippets, PhasePlan.DEFAULT); + Snippets.install(runtime, runtime.getCompiler().getTarget(), new UnsafeSnippets(), GraalOptions.PlotSnippets, PhasePlan.DEFAULT); + } + + // Create compilation queue. + compileQueue = new ThreadPoolExecutor(GraalOptions.Threads, GraalOptions.Threads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), daemonThreadFactory); + + // Create queue status printing thread. + if (GraalOptions.PrintQueue) { + Thread t = new Thread() { + @Override + public void run() { + while (true) { + TTY.println(compileQueue.toString()); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + } + }; + t.setDaemon(true); + t.start(); + } + } + + public void bootstrap() throws Throwable { + TTY.print("Bootstrapping Graal"); + TTY.flush(); + long startTime = System.currentTimeMillis(); + + // Initialize compile queue with a selected set of methods. + Class objectKlass = Object.class; + enqueue(objectKlass.getDeclaredMethod("equals", Object.class)); + enqueue(objectKlass.getDeclaredMethod("toString")); + + // Compile until the queue is empty. + int z = 0; + while (compileQueue.getCompletedTaskCount() < Math.max(2, compileQueue.getTaskCount())) { + Thread.sleep(100); + while (z < compileQueue.getCompletedTaskCount() / 100) { + ++z; + TTY.print("."); + TTY.flush(); + } + } + + TTY.println(" in %d ms", System.currentTimeMillis() - startTime); + System.gc(); + } + + private void enqueue(Method m) throws Throwable { + RiMethod riMethod = compiler.getRuntime().getRiMethod(m); + assert !Modifier.isAbstract(((HotSpotMethodResolved) riMethod).accessFlags()) && !Modifier.isNative(((HotSpotMethodResolved) riMethod).accessFlags()) : riMethod; + compileMethod((HotSpotMethodResolved) riMethod, 0, false); + } + + public void shutdownCompiler() throws Throwable { + compiler.getCompiler().context.print(); + compileQueue.shutdown(); + } + + @Override + public void compileMethod(final HotSpotMethodResolved method, final int entryBCI, boolean blocking) throws Throwable { + try { + if (Thread.currentThread() instanceof CompilerThread && method.holder().name().contains("java/util/concurrent")) { + return; + } + + Runnable runnable = new Runnable() { + public void run() { + try { + PhasePlan plan = new PhasePlan(); + GraphBuilderPhase graphBuilderPhase = new GraphBuilderPhase(compiler.getRuntime(), null); + plan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase); + CiTargetMethod result = compiler.getCompiler().compileMethod(method, -1, null, DebugInfoLevel.FULL, plan); + HotSpotTargetMethod.installMethod(compiler, method, result, true); + } catch (CiBailout bailout) { + if (GraalOptions.ExitVMOnBailout) { + bailout.printStackTrace(TTY.cachedOut); + System.exit(-1); + } + } catch (Throwable t) { + if (GraalOptions.ExitVMOnException) { + t.printStackTrace(TTY.cachedOut); + System.exit(-1); + } + } + } + }; + + if (blocking) { + runnable.run(); + } else { + compileQueue.execute(runnable); + } + } catch (RejectedExecutionException e) { + // The compile queue was already shut down. + return; + } + } + + @Override + public RiMethod createRiMethodUnresolved(String name, String signature, RiType holder) { + return new HotSpotMethodUnresolved(compiler, name, signature, holder); + } + + @Override + public RiSignature createRiSignature(String signature) { + return new HotSpotSignature(compiler, signature); + } + + @Override + public RiField createRiField(RiType holder, String name, RiType type, int offset, int flags) { + if (offset != -1) { + HotSpotTypeResolved resolved = (HotSpotTypeResolved) holder; + return resolved.createRiField(name, type, offset, flags); + } + return new BaseUnresolvedField(holder, name, type); + } + + @Override + public RiType createRiType(HotSpotConstantPool pool, String name) { + throw new RuntimeException("not implemented"); + } + + @Override + public RiType createRiTypePrimitive(int basicType) { + switch (basicType) { + case 4: + return typeBoolean; + case 5: + return typeChar; + case 6: + return typeFloat; + case 7: + return typeDouble; + case 8: + return typeByte; + case 9: + return typeShort; + case 10: + return typeInt; + case 11: + return typeLong; + case 14: + return typeVoid; + default: + throw new IllegalArgumentException("Unknown basic type: " + basicType); + } + } + + @Override + public RiType createRiTypeUnresolved(String name) { + return new HotSpotTypeUnresolved(compiler, name); + } + + @Override + public CiConstant createCiConstant(CiKind kind, long value) { + if (kind == CiKind.Long) { + return CiConstant.forLong(value); + } else if (kind == CiKind.Int) { + return CiConstant.forInt((int) value); + } else if (kind == CiKind.Short) { + return CiConstant.forShort((short) value); + } else if (kind == CiKind.Char) { + return CiConstant.forChar((char) value); + } else if (kind == CiKind.Byte) { + return CiConstant.forByte((byte) value); + } else if (kind == CiKind.Boolean) { + return (value == 0) ? CiConstant.FALSE : CiConstant.TRUE; + } else { + throw new IllegalArgumentException(); + } + } + + @Override + public CiConstant createCiConstantFloat(float value) { + return CiConstant.forFloat(value); + } + + @Override + public CiConstant createCiConstantDouble(double value) { + return CiConstant.forDouble(value); + } + + @Override + public CiConstant createCiConstantObject(Object object) { + return CiConstant.forObject(object); + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.ri; + +import com.oracle.max.cri.ri.*; + +/** + * Implementation of RiCompiledMethod for HotSpot. Stores a reference to the nmethod which contains the compiled code. + */ +public class HotSpotCompiledMethod implements RiCompiledMethod { + + private final RiResolvedMethod method; + private long nmethod; + + public HotSpotCompiledMethod(RiResolvedMethod method) { + this.method = method; + } + + @Override + public RiResolvedMethod method() { + return method; + } + + @Override + public boolean isValid() { + return nmethod != 0; + } + + @Override + public String toString() { + return "compiled method " + method + " @" + nmethod; + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotConstantPool.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotConstantPool.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.ri; + +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.Compiler; + +/** + * Implementation of RiConstantPool for HotSpot. + */ +public class HotSpotConstantPool extends CompilerObject implements RiConstantPool { + /** + * + */ + private static final long serialVersionUID = -5443206401485234850L; + private final HotSpotTypeResolvedImpl type; + + public HotSpotConstantPool(Compiler compiler, HotSpotTypeResolvedImpl type) { + super(compiler); + this.type = type; + } + + @Override + public Object lookupConstant(int cpi) { + Object constant = compiler.getVMEntries().RiConstantPool_lookupConstant(type, cpi); + return constant; + } + + @Override + public RiSignature lookupSignature(int cpi) { + throw new UnsupportedOperationException(); + } + + @Override + public RiMethod lookupMethod(int cpi, int byteCode) { + return compiler.getVMEntries().RiConstantPool_lookupMethod(type, cpi, (byte) byteCode); + } + + @Override + public RiType lookupType(int cpi, int opcode) { + return compiler.getVMEntries().RiConstantPool_lookupType(type, cpi); + } + + @Override + public RiField lookupField(int cpi, int opcode) { + return compiler.getVMEntries().RiConstantPool_lookupField(type, cpi, (byte) opcode); + } + + @Override + public void loadReferencedType(int cpi, int bytecode) { + compiler.getVMEntries().RiConstantPool_loadReferencedType(type, cpi, (byte) bytecode); + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotExceptionHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotExceptionHandler.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.ri; + +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.hotspot.*; + + +public class HotSpotExceptionHandler extends CompilerObject implements RiExceptionHandler { + /** + * + */ + private static final long serialVersionUID = 7110038548061733686L; + private int startBci; + private int endBci; + private int handlerBci; + private int catchClassIndex; + private RiType catchClass; + + public HotSpotExceptionHandler() { + super(null); + } + + @Override + public int startBCI() { + return startBci; + } + + @Override + public int endBCI() { + return endBci; + } + + @Override + public int handlerBCI() { + return handlerBci; + } + + @Override + public int catchTypeCPI() { + return catchClassIndex; + } + + @Override + public boolean isCatchAll() { + return catchClassIndex == 0; + } + + @Override + public RiType catchType() { + return catchClass; + } + + @Override + public String toString() { + return String.format("HotSpotExceptionHandler[startBci=%d, endBci=%d, handlerBci=%d, catchClassIndex=%d, catchClass=%s", startBci, endBci, handlerBci, catchClassIndex, catchClass); + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotField.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotField.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.ri; + +import java.lang.annotation.*; +import java.lang.reflect.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.Compiler; + +/** + * Represents a field in a HotSpot type. + */ +public class HotSpotField extends CompilerObject implements RiResolvedField { + + /** + * + */ + private static final long serialVersionUID = 7692985878836955683L; + private final RiResolvedType holder; + private final String name; + private final RiType type; + private final int offset; + private final int accessFlags; + private CiConstant constant; // Constant part only valid for static fields. + + public HotSpotField(Compiler compiler, RiResolvedType holder, String name, RiType type, int offset, int accessFlags) { + super(compiler); + this.holder = holder; + this.name = name; + this.type = type; + assert offset != -1; + this.offset = offset; + this.accessFlags = accessFlags; + } + + @Override + public int accessFlags() { + return accessFlags; + } + + @Override + public CiConstant constantValue(CiConstant receiver) { + if (receiver == null) { + assert Modifier.isStatic(accessFlags); + if (constant == null) { + if (holder.isInitialized() && holder.toJava() != System.class) { + if (Modifier.isFinal(accessFlags()) || assumeStaticFieldsFinal(holder.toJava())) { + CiConstant encoding = holder.getEncoding(Representation.StaticFields); + constant = this.kind(false).readUnsafeConstant(encoding.asObject(), offset); + } + } + } + return constant; + } else { + assert !Modifier.isStatic(accessFlags); + if (Modifier.isFinal(accessFlags())) { + return this.kind(false).readUnsafeConstant(receiver.asObject(), offset); + } + } + return null; + } + + private static boolean assumeStaticFieldsFinal(Class< ? > clazz) { + return clazz == GraalOptions.class; + } + + @Override + public RiResolvedType holder() { + return holder; + } + + @Override + public CiKind kind(boolean architecture) { + return type().kind(architecture); + } + + @Override + public String name() { + return name; + } + + @Override + public RiType type() { + return type; + } + + public int offset() { + return offset; + } + + @Override + public String toString() { + return "HotSpotField<" + CiUtil.format("%h.%n", this) + ":" + offset + ">"; + } + + @Override + public T getAnnotation(Class annotationClass) { + Field javaField = toJava(); + if (javaField != null) { + return javaField.getAnnotation(annotationClass); + } + return null; + } + + private Field toJava() { + try { + return holder.toJava().getDeclaredField(name); + } catch (NoSuchFieldException e) { + return null; + } + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Wed Jan 04 10:49:09 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl.java Wed Jan 04 20:59:11 2012 +0100 @@ -30,7 +30,6 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; import com.oracle.max.criutils.*; -import com.oracle.max.graal.hotspot.*; /** * Implementation of RiMethod for resolved HotSpot methods. diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodUnresolved.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodUnresolved.java Wed Jan 04 10:49:09 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotMethodUnresolved.java Wed Jan 04 20:59:11 2012 +0100 @@ -23,7 +23,6 @@ package com.oracle.max.graal.hotspot.ri; import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.*; import com.oracle.max.graal.hotspot.Compiler; /** diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRegisterConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRegisterConfig.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.hotspot.ri; + +import static com.oracle.max.asm.target.amd64.AMD64.*; + +import java.util.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiCallingConvention.*; +import com.oracle.max.cri.ci.CiRegister.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.compiler.util.*; +import com.oracle.max.graal.hotspot.*; + +public class HotSpotRegisterConfig implements RiRegisterConfig { + + // be careful - the contents of this array are duplicated in graal_CodeInstaller.cpp + private final CiRegister[] allocatable = { + rax, rbx, rcx, rdx, rsi, rdi, r8, r9, /* r10, */r11, r12, r13, r14, /*r15*/ + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + + private final EnumMap categorized = CiRegister.categorize(allocatable); + + private final RiRegisterAttributes[] attributesMap; + + @Override + public CiRegister[] getAllocatableRegisters() { + return allocatable; + } + + @Override + public EnumMap getCategorizedAllocatableRegisters() { + return categorized; + } + + @Override + public RiRegisterAttributes[] getAttributesMap() { + return attributesMap; + } + + private final CiRegister[] generalParameterRegisters; + private final CiRegister[] xmmParameterRegisters = {xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7}; + private final CiRegister[] allParameterRegisters; + + private final CiRegister[] rsaRegs = { + rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, + r8, r9, r10, r11, r12, r13, r14, r15, + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + + private final CiCalleeSaveLayout registerSaveArea; + + public HotSpotRegisterConfig(HotSpotVMConfig config, boolean globalStubConfig) { + if (config.windowsOs) { + generalParameterRegisters = new CiRegister[] {rdx, r8, r9, rdi, rsi, rcx}; + } else { + generalParameterRegisters = new CiRegister[] {rsi, rdx, rcx, r8, r9, rdi}; + } + + if (globalStubConfig) { + registerSaveArea = new CiCalleeSaveLayout(0, -1, 8, rsaRegs); + } else { + registerSaveArea = new CiCalleeSaveLayout(0, 8, 8, new CiRegister[0]); + } + + attributesMap = RiRegisterAttributes.createMap(this, AMD64.allRegisters); + allParameterRegisters = Arrays.copyOf(generalParameterRegisters, generalParameterRegisters.length + xmmParameterRegisters.length); + System.arraycopy(xmmParameterRegisters, 0, allParameterRegisters, generalParameterRegisters.length, xmmParameterRegisters.length); + } + + @Override + public CiRegister[] getCallerSaveRegisters() { + return getAllocatableRegisters(); + } + + @Override + public CiRegister getRegisterForRole(int index) { + throw new UnsupportedOperationException(); + } + + @Override + public CiCallingConvention getCallingConvention(Type type, CiKind[] parameters, CiTarget target, boolean stackOnly) { + if (type == Type.NativeCall) { + throw new UnsupportedOperationException(); + } + return callingConvention(parameters, type, target, stackOnly); + } + + public CiRegister[] getCallingConventionRegisters(Type type, RegisterFlag flag) { + return allParameterRegisters; + } + + private CiCallingConvention callingConvention(CiKind[] types, Type type, CiTarget target, boolean stackOnly) { + CiValue[] locations = new CiValue[types.length]; + + int currentGeneral = 0; + int currentXMM = 0; + int currentStackOffset = 0; + + for (int i = 0; i < types.length; i++) { + final CiKind kind = types[i]; + + switch (kind) { + case Byte: + case Boolean: + case Short: + case Char: + case Int: + case Long: + case Object: + if (!stackOnly && currentGeneral < generalParameterRegisters.length) { + CiRegister register = generalParameterRegisters[currentGeneral++]; + locations[i] = register.asValue(kind); + } + break; + case Float: + case Double: + if (!stackOnly && currentXMM < xmmParameterRegisters.length) { + CiRegister register = xmmParameterRegisters[currentXMM++]; + locations[i] = register.asValue(kind); + } + break; + default: + throw Util.shouldNotReachHere(); + } + + if (locations[i] == null) { + locations[i] = CiStackSlot.get(kind.stackKind(), currentStackOffset, !type.out); + currentStackOffset += Math.max(target.sizeInBytes(kind), target.wordSize); + } + } + + return new CiCallingConvention(locations, currentStackOffset); + } + + @Override + public CiRegister getReturnRegister(CiKind kind) { + switch (kind) { + case Boolean: + case Byte: + case Char: + case Short: + case Int: + case Long: + case Object: + return rax; + case Float: + case Double: + return xmm0; + case Void: + case Illegal: + return null; + default: + throw new UnsupportedOperationException("no return register for type " + kind); + } + } + + @Override + public CiRegister getScratchRegister() { + return r10; + } + + @Override + public CiRegister getFrameRegister() { + return rsp; + } + + public CiCalleeSaveLayout getCalleeSaveLayout() { + return registerSaveArea; + } + + @Override + public String toString() { + String res = String.format( + "Allocatable: " + Arrays.toString(getAllocatableRegisters()) + "%n" + + "CallerSave: " + Arrays.toString(getCallerSaveRegisters()) + "%n" + + "CalleeSave: " + getCalleeSaveLayout() + "%n" + + "Scratch: " + getScratchRegister() + "%n"); + return res; + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotRuntime.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,433 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.hotspot.ri; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiTargetMethod.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.cri.*; +import com.oracle.max.graal.graph.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.Compiler; +import com.oracle.max.graal.hotspot.nodes.*; +import com.oracle.max.graal.nodes.*; +import com.oracle.max.graal.nodes.calc.*; +import com.oracle.max.graal.nodes.extended.*; +import com.oracle.max.graal.nodes.java.*; +import com.oracle.max.graal.snippets.nodes.*; +import com.sun.max.asm.dis.*; +import com.sun.max.lang.*; + +/** + * CRI runtime implementation for the HotSpot VM. + */ +public class HotSpotRuntime implements GraalRuntime { + final GraalContext context; + final HotSpotVMConfig config; + final HotSpotRegisterConfig regConfig; + public final HotSpotRegisterConfig globalStubRegConfig; + private final Compiler compiler; + + public HotSpotRuntime(GraalContext context, HotSpotVMConfig config, Compiler compiler) { + this.context = context; + this.config = config; + this.compiler = compiler; + regConfig = new HotSpotRegisterConfig(config, false); + globalStubRegConfig = new HotSpotRegisterConfig(config, true); + } + + @Override + public int codeOffset() { + return 0; + } + + + public Compiler getCompiler() { + return compiler; + } + + @Override + public String disassemble(byte[] code, long address) { + return disassemble(code, new DisassemblyPrinter(false), address); + } + + private static String disassemble(byte[] code, DisassemblyPrinter disassemblyPrinter, long address) { + final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + final ISA instructionSet = ISA.AMD64; + Disassembler.disassemble(byteArrayOutputStream, code, instructionSet, WordWidth.BITS_64, address, null, disassemblyPrinter); + return byteArrayOutputStream.toString(); + } + + @Override + public String disassemble(final CiTargetMethod targetMethod) { + + final DisassemblyPrinter disassemblyPrinter = new DisassemblyPrinter(false) { + + private String siteInfo(int pcOffset) { + for (Safepoint site : targetMethod.safepoints) { + if (site.pcOffset == pcOffset) { + return "{safepoint}"; + } + } + for (DataPatch site : targetMethod.dataReferences) { + if (site.pcOffset == pcOffset) { + return "{" + site.constant + "}"; + } + } + return null; + } + + @Override + protected String disassembledObjectString(Disassembler disassembler, DisassembledObject disassembledObject) { + final String string = super.disassembledObjectString(disassembler, disassembledObject); + + String site = siteInfo(disassembledObject.startPosition()); + if (site != null) { + return string + " " + site; + } + return string; + } + }; + final byte[] code = Arrays.copyOf(targetMethod.targetCode(), targetMethod.targetCodeSize()); + return disassemble(code, disassemblyPrinter, 0L); + } + + @Override + public String disassemble(RiResolvedMethod method) { + return "No disassembler available"; + } + + @Override + public RiResolvedType asRiType(CiKind kind) { + return (RiResolvedType) compiler.getVMEntries().getType(kind.toJavaClass()); + } + + @Override + public RiResolvedType getTypeOf(CiConstant constant) { + return (RiResolvedType) compiler.getVMEntries().getRiType(constant); + } + + @Override + public boolean isExceptionType(RiResolvedType type) { + return type.isSubtypeOf((RiResolvedType) compiler.getVMEntries().getType(Throwable.class)); + } + + @Override + public Object registerCompilerStub(CiTargetMethod targetMethod, String name) { + return HotSpotTargetMethod.installStub(compiler, targetMethod, name); + } + + @Override + public int sizeOfLockData() { + // TODO shouldn't be hard coded + return 8; + } + + @Override + public int sizeOfBasicObjectLock() { + // TODO shouldn't be hard coded + return 2 * 8; + } + + @Override + public int basicObjectLockOffsetInBytes() { + return 8; + } + + @Override + public boolean areConstantObjectsEqual(CiConstant x, CiConstant y) { + return compiler.getVMEntries().compareConstantObjects(x, y); + } + + @Override + public RiRegisterConfig getRegisterConfig(RiMethod method) { + return regConfig; + } + + /** + * HotSpots needs an area suitable for storing a program counter for temporary use during the deoptimization process. + */ + @Override + public int getCustomStackAreaSize() { + // TODO shouldn't be hard coded + return 8; + } + + @Override + public int getMinimumOutgoingSize() { + return config.runtimeCallStackSize; + } + + @Override + public int getArrayLength(CiConstant array) { + return compiler.getVMEntries().getArrayLength(array); + } + + @Override + public Class asJavaClass(CiConstant c) { + return (Class) c.asObject(); + } + + @Override + public Object asJavaObject(CiConstant c) { + return c.asObject(); + } + + @Override + public void lower(Node n, CiLoweringTool tool) { + if (!GraalOptions.Lower) { + return; + } + + if (n instanceof ArrayLengthNode) { + ArrayLengthNode arrayLengthNode = (ArrayLengthNode) n; + SafeReadNode safeReadArrayLength = safeReadArrayLength(arrayLengthNode.graph(), arrayLengthNode.array()); + FixedNode nextNode = arrayLengthNode.next(); + arrayLengthNode.clearSuccessors(); + safeReadArrayLength.setNext(nextNode); + arrayLengthNode.replaceAndDelete(safeReadArrayLength); + safeReadArrayLength.lower(tool); + } else if (n instanceof LoadFieldNode) { + LoadFieldNode field = (LoadFieldNode) n; + if (field.isVolatile()) { + return; + } + Graph graph = field.graph(); + int displacement = ((HotSpotField) field.field()).offset(); + assert field.kind() != CiKind.Illegal; + ReadNode memoryRead = graph.unique(new ReadNode(field.field().kind(true).stackKind(), field.object(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph))); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)))); + FixedNode next = field.next(); + field.setNext(null); + memoryRead.setNext(next); + field.replaceAndDelete(memoryRead); + } else if (n instanceof StoreFieldNode) { + StoreFieldNode field = (StoreFieldNode) n; + if (field.isVolatile()) { + return; + } + Graph graph = field.graph(); + int displacement = ((HotSpotField) field.field()).offset(); + WriteNode memoryWrite = graph.add(new WriteNode(field.object(), field.value(), LocationNode.create(field.field(), field.field().kind(true), displacement, graph))); + memoryWrite.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(field.object(), false)))); + memoryWrite.setStateAfter(field.stateAfter()); + FixedNode next = field.next(); + field.setNext(null); + if (field.field().kind(true) == CiKind.Object && !field.value().isNullConstant()) { + FieldWriteBarrier writeBarrier = graph.add(new FieldWriteBarrier(field.object())); + memoryWrite.setNext(writeBarrier); + writeBarrier.setNext(next); + } else { + memoryWrite.setNext(next); + } + field.replaceAndDelete(memoryWrite); + } else if (n instanceof LoadIndexedNode) { + LoadIndexedNode loadIndexed = (LoadIndexedNode) n; + Graph graph = loadIndexed.graph(); + GuardNode boundsCheck = createBoundsCheck(loadIndexed, tool); + + CiKind elementKind = loadIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, loadIndexed.index()); + ReadNode memoryRead = graph.unique(new ReadNode(elementKind.stackKind(), loadIndexed.array(), arrayLocation)); + memoryRead.setGuard(boundsCheck); + FixedNode next = loadIndexed.next(); + loadIndexed.setNext(null); + memoryRead.setNext(next); + loadIndexed.replaceAndDelete(memoryRead); + } else if (n instanceof StoreIndexedNode) { + StoreIndexedNode storeIndexed = (StoreIndexedNode) n; + Graph graph = storeIndexed.graph(); + AnchorNode anchor = graph.add(new AnchorNode()); + GuardNode boundsCheck = createBoundsCheck(storeIndexed, tool); + + FixedWithNextNode append = anchor; + + CiKind elementKind = storeIndexed.elementKind(); + LocationNode arrayLocation = createArrayLocation(graph, elementKind, storeIndexed.index()); + ValueNode value = storeIndexed.value(); + ValueNode array = storeIndexed.array(); + if (elementKind == CiKind.Object && !value.isNullConstant()) { + // Store check! + if (array.exactType() != null) { + RiResolvedType elementType = array.exactType().componentType(); + if (elementType.superType() != null) { + ConstantNode type = graph.unique(ConstantNode.forCiConstant(elementType.getEncoding(Representation.ObjectHub), this, graph)); + value = graph.unique(new CheckCastNode(anchor, type, elementType, value)); + } else { + assert elementType.name().equals("Ljava/lang/Object;") : elementType.name(); + } + } else { + GuardNode guard = (GuardNode) tool.createGuard(graph.unique(new NullCheckNode(array, false))); + ReadNode arrayClass = graph.unique(new ReadNode(CiKind.Object, array, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.hubOffset, graph))); + arrayClass.setGuard(guard); + append.setNext(arrayClass); + append = arrayClass; + ReadNode arrayElementKlass = graph.unique(new ReadNode(CiKind.Object, arrayClass, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.arrayClassElementOffset, graph))); + value = graph.unique(new CheckCastNode(anchor, arrayElementKlass, null, value)); + } + } + WriteNode memoryWrite = graph.add(new WriteNode(array, value, arrayLocation)); + memoryWrite.setGuard(boundsCheck); + memoryWrite.setStateAfter(storeIndexed.stateAfter()); + FixedNode next = storeIndexed.next(); + storeIndexed.setNext(null); + append.setNext(memoryWrite); + if (elementKind == CiKind.Object && !value.isNullConstant()) { + ArrayWriteBarrier writeBarrier = graph.add(new ArrayWriteBarrier(array, arrayLocation)); + memoryWrite.setNext(writeBarrier); + writeBarrier.setNext(next); + } else { + memoryWrite.setNext(next); + } + storeIndexed.replaceAtPredecessors(anchor); + storeIndexed.safeDelete(); + } else if (n instanceof UnsafeLoadNode) { + UnsafeLoadNode load = (UnsafeLoadNode) n; + Graph graph = load.graph(); + assert load.kind() != CiKind.Illegal; + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, load.loadKind(), load.displacement(), load.offset(), graph); + location.setIndexScalingEnabled(false); + ReadNode memoryRead = graph.unique(new ReadNode(load.kind(), load.object(), location)); + memoryRead.setGuard((GuardNode) tool.createGuard(graph.unique(new NullCheckNode(load.object(), false)))); + FixedNode next = load.next(); + load.setNext(null); + memoryRead.setNext(next); + load.replaceAndDelete(memoryRead); + } else if (n instanceof UnsafeStoreNode) { + UnsafeStoreNode store = (UnsafeStoreNode) n; + Graph graph = store.graph(); + IndexedLocationNode location = IndexedLocationNode.create(LocationNode.ANY_LOCATION, store.storeKind(), store.displacement(), store.offset(), graph); + location.setIndexScalingEnabled(false); + WriteNode write = graph.add(new WriteNode(store.object(), store.value(), location)); + FieldWriteBarrier barrier = graph.add(new FieldWriteBarrier(store.object())); + FixedNode next = store.next(); + store.setNext(null); + barrier.setNext(next); + write.setNext(barrier); + write.setStateAfter(store.stateAfter()); + store.replaceAtPredecessors(write); + store.safeDelete(); + } else if (n instanceof ArrayHeaderSizeNode) { + n.replaceAndDelete(ConstantNode.forLong(config.getArrayOffset(((ArrayHeaderSizeNode) n).elementKind()), n.graph())); + } + } + + private IndexedLocationNode createArrayLocation(Graph graph, CiKind elementKind, ValueNode index) { + return IndexedLocationNode.create(LocationNode.getArrayLocation(elementKind), elementKind, config.getArrayOffset(elementKind), index, graph); + } + + private static GuardNode createBoundsCheck(AccessIndexedNode n, CiLoweringTool tool) { + return (GuardNode) tool.createGuard(n.graph().unique(new CompareNode(n.index(), Condition.BT, n.length()))); + } + + @Override + public StructuredGraph intrinsicGraph(RiResolvedMethod caller, int bci, RiResolvedMethod method, List parameters) { + RiType holder = method.holder(); + String fullName = method.name() + method.signature().asString(); + String holderName = holder.name(); + if (holderName.equals("Ljava/lang/Object;")) { + if (fullName.equals("getClass()Ljava/lang/Class;")) { + ValueNode obj = (ValueNode) parameters.get(0); + if (obj.stamp().nonNull() && obj.stamp().exactType() != null) { + StructuredGraph graph = new StructuredGraph(); + ValueNode result = ConstantNode.forObject(obj.stamp().exactType().toJava(), this, graph); + ReturnNode ret = graph.add(new ReturnNode(result)); + graph.start().setNext(ret); + return graph; + } + StructuredGraph graph = new StructuredGraph(); + LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); + SafeReadNode klassOop = safeReadHub(graph, receiver); + ReadNode result = graph.add(new ReadNode(CiKind.Object, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Object, config.classMirrorOffset, graph))); + ReturnNode ret = graph.add(new ReturnNode(result)); + graph.start().setNext(klassOop); + klassOop.setNext(ret); + return graph; + } + } else if (holderName.equals("Ljava/lang/Class;")) { + if (fullName.equals("getModifiers()I")) { + StructuredGraph graph = new StructuredGraph(); + LocalNode receiver = graph.unique(new LocalNode(CiKind.Object, 0)); + SafeReadNode klassOop = safeRead(graph, CiKind.Object, receiver, config.klassOopOffset); + graph.start().setNext(klassOop); + // TODO(tw): Care about primitive classes! + ReadNode result = graph.unique(new ReadNode(CiKind.Int, klassOop, LocationNode.create(LocationNode.FINAL_LOCATION, CiKind.Int, config.klassModifierFlagsOffset, graph))); + ReturnNode ret = graph.add(new ReturnNode(result)); + klassOop.setNext(ret); + return graph; + } + } else if (holderName.equals("Ljava/lang/Thread;")) { + if (fullName.equals("currentThread()Ljava/lang/Thread;")) { + StructuredGraph graph = new StructuredGraph(); + ReturnNode ret = graph.add(new ReturnNode(graph.unique(new CurrentThread(config.threadObjectOffset)))); + graph.start().setNext(ret); + return graph; + } + } + return null; + } + + private SafeReadNode safeReadHub(Graph graph, ValueNode value) { + return safeRead(graph, CiKind.Object, value, config.hubOffset); + } + + private SafeReadNode safeReadArrayLength(Graph graph, ValueNode value) { + return safeRead(graph, CiKind.Int, value, config.arrayLengthOffset); + } + + private static SafeReadNode safeRead(Graph graph, CiKind kind, ValueNode value, int offset) { + return graph.add(new SafeReadNode(kind, value, LocationNode.create(LocationNode.FINAL_LOCATION, kind, offset, graph))); + } + + public RiResolvedType getType(Class clazz) { + return (RiResolvedType) compiler.getVMEntries().getType(clazz); + } + + public Object asCallTarget(Object target) { + return target; + } + + public long getMaxCallTargetOffset(CiRuntimeCall rtcall) { + return compiler.getVMEntries().getMaxCallTargetOffset(rtcall); + } + + public RiResolvedMethod getRiMethod(Method reflectionMethod) { + return (RiResolvedMethod) compiler.getVMEntries().getRiMethod(reflectionMethod); + } + + public void installMethod(RiMethod method, CiTargetMethod code) { + HotSpotTargetMethod.installMethod(CompilerImpl.getInstance(), (HotSpotMethodResolved) method, code, true); + } + + @Override + public RiCompiledMethod addMethod(RiResolvedMethod method, CiTargetMethod code) { + Compiler compilerInstance = CompilerImpl.getInstance(); + return HotSpotTargetMethod.installMethod(compilerInstance, (HotSpotMethodResolved) method, code, false); + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotSignature.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotSignature.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.ri; + +import java.util.*; + +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.Compiler; +import com.oracle.max.graal.java.*; + +/** + * Represents a method signature. + */ +public class HotSpotSignature extends CompilerObject implements RiSignature { + + /** + * + */ + private static final long serialVersionUID = -2890917956072366116L; + private final List arguments = new ArrayList<>(); + private final String returnType; + private final String originalString; + private RiType[] argumentTypes; + private RiType returnTypeCache; + + public HotSpotSignature(Compiler compiler, String signature) { + super(compiler); + assert signature.length() > 0; + this.originalString = signature; + + if (signature.charAt(0) == '(') { + int cur = 1; + while (cur < signature.length() && signature.charAt(cur) != ')') { + int nextCur = parseSignature(signature, cur); + arguments.add(signature.substring(cur, nextCur)); + cur = nextCur; + } + + cur++; + int nextCur = parseSignature(signature, cur); + returnType = signature.substring(cur, nextCur); + assert nextCur == signature.length(); + } else { + returnType = null; + } + } + + private static int parseSignature(String signature, int start) { + int cur = start; + char first; + do { + first = signature.charAt(cur++); + } while (first == '['); + + switch (first) { + case 'L': + while (signature.charAt(cur) != ';') { + cur++; + } + cur++; + break; + case 'V': + case 'I': + case 'B': + case 'C': + case 'D': + case 'F': + case 'J': + case 'S': + case 'Z': + break; + default: + assert false; + } + return cur; + } + + @Override + public int argumentCount(boolean withReceiver) { + return arguments.size() + (withReceiver ? 1 : 0); + } + + @Override + public CiKind argumentKindAt(int index, boolean architecture) { + return CiKind.fromTypeString(arguments.get(index)); + } + + @Override + public int argumentSlots(boolean withReceiver) { + int argSlots = 0; + for (int i = 0; i < argumentCount(false); i++) { + argSlots += FrameStateBuilder.stackSlots(argumentKindAt(i, false)); + } + return argSlots + (withReceiver ? 1 : 0); + } + + @Override + public RiType argumentTypeAt(int index, RiType accessingClass) { + if (argumentTypes == null) { + argumentTypes = new RiType[arguments.size()]; + } + RiType type = argumentTypes[index]; + if (type == null) { + type = compiler.lookupType(arguments.get(index), (HotSpotTypeResolved) accessingClass); + argumentTypes[index] = type; + } + return type; + } + + @Override + public String asString() { + return originalString; + } + + @Override + public CiKind returnKind(boolean architecture) { + return CiKind.fromTypeString(returnType); + } + + @Override + public RiType returnType(RiType accessingClass) { + if (returnTypeCache == null) { + returnTypeCache = compiler.lookupType(returnType, (HotSpotTypeResolved) accessingClass); + } + return returnTypeCache; + } + + @Override + public String toString() { + return "HotSpotSignature<" + originalString + ">"; + } + +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Wed Jan 04 10:49:09 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl.java Wed Jan 04 20:59:11 2012 +0100 @@ -28,7 +28,6 @@ import com.oracle.max.cri.ci.*; import com.oracle.max.cri.ri.*; -import com.oracle.max.graal.hotspot.*; /** * Implementation of RiType for resolved non-primitive HotSpot classes. diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/HotSpotXirGenerator.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,1443 @@ +/* + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.max.graal.hotspot.ri; + +import static com.oracle.max.cri.ci.CiCallingConvention.Type.*; +import static com.oracle.max.cri.ci.CiValueUtil.*; +import static com.oracle.max.graal.hotspot.ri.TemplateFlag.*; + +import java.lang.reflect.*; +import java.util.*; +import java.util.concurrent.*; + +import com.oracle.max.asm.target.amd64.*; +import com.oracle.max.cri.ci.*; +import com.oracle.max.cri.ci.CiAddress.*; +import com.oracle.max.cri.ci.CiRegister.*; +import com.oracle.max.cri.ri.*; +import com.oracle.max.cri.ri.RiType.*; +import com.oracle.max.cri.xir.*; +import com.oracle.max.cri.xir.CiXirAssembler.*; +import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.hotspot.*; +import com.oracle.max.graal.hotspot.Compiler; + +public class HotSpotXirGenerator implements RiXirGenerator { + + // this needs to correspond to graal_CodeInstaller.hpp + // @formatter:off + private static final Integer MARK_VERIFIED_ENTRY = 0x0001; + private static final Integer MARK_UNVERIFIED_ENTRY = 0x0002; + private static final Integer MARK_OSR_ENTRY = 0x0003; + private static final Integer MARK_UNWIND_ENTRY = 0x0004; + private static final Integer MARK_EXCEPTION_HANDLER_ENTRY = 0x0005; + private static final Integer MARK_DEOPT_HANDLER_ENTRY = 0x0006; + + private static final Integer MARK_STATIC_CALL_STUB = 0x1000; + + private static final Integer MARK_INVOKEINTERFACE = 0x2001; + private static final Integer MARK_INVOKESTATIC = 0x2002; + private static final Integer MARK_INVOKESPECIAL = 0x2003; + private static final Integer MARK_INVOKEVIRTUAL = 0x2004; + + private static final Integer MARK_IMPLICIT_NULL = 0x3000; + private static final Integer MARK_POLL_NEAR = 0x3001; + private static final Integer MARK_POLL_RETURN_NEAR = 0x3002; + private static final Integer MARK_POLL_FAR = 0x3003; + private static final Integer MARK_POLL_RETURN_FAR = 0x3004; + + // @formatter:on + + private final HotSpotVMConfig config; + private final CiTarget target; + private final RiRegisterConfig registerConfig; + private final Compiler compiler; + + private CiXirAssembler globalAsm; + + public HotSpotXirGenerator(HotSpotVMConfig config, CiTarget target, RiRegisterConfig registerConfig, Compiler compiler) { + this.config = config; + this.target = target; + this.registerConfig = registerConfig; + this.compiler = compiler; + } + + private XirConstant wordConst(CiXirAssembler asm, long value) { + if (target.wordKind == CiKind.Long) { + return asm.createConstant(CiConstant.forLong(value)); + } else { + assert target.wordKind == CiKind.Int; + return asm.createConstant(CiConstant.forInt((int) value)); + } + } + + private XirArgument wordArg(long value) { + if (target.wordKind == CiKind.Long) { + return XirArgument.forLong(value); + } else { + assert target.wordKind == CiKind.Int; + return XirArgument.forInt((int) value); + } + } + + private SimpleTemplates prologueTemplates = new SimpleTemplates(STATIC_METHOD) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + XirOperand framePointer = asm.createRegisterTemp("frame pointer", target.wordKind, AMD64.rbp); + XirOperand stackPointer = asm.createRegisterTemp("stack pointer", target.wordKind, AMD64.rsp); + XirLabel unverifiedStub = null; + + asm.mark(MARK_OSR_ENTRY); + asm.mark(MARK_UNVERIFIED_ENTRY); + if (!is(STATIC_METHOD, flags)) { + unverifiedStub = asm.createOutOfLineLabel("unverified"); + + XirOperand temp = asm.createRegisterTemp("temp (r10)", target.wordKind, AMD64.r10); + XirOperand cache = asm.createRegisterTemp("cache (rax)", target.wordKind, AMD64.rax); + + CiCallingConvention conventions = registerConfig.getCallingConvention(JavaCallee, new CiKind[] {CiKind.Object}, target, false); + XirOperand receiver = asm.createRegister("receiver", target.wordKind, asRegister(conventions.locations[0])); + + asm.pload(target.wordKind, temp, receiver, asm.i(config.hubOffset), false); + asm.jneq(unverifiedStub, cache, temp); + } + asm.align(config.codeEntryAlignment); + asm.mark(MARK_VERIFIED_ENTRY); + asm.stackOverflowCheck(); + asm.push(framePointer); + asm.mov(framePointer, stackPointer); + // Compensate for the push of framePointer (the XIR instruction pushFrame is not flexible enough to reduce the frame size, wait until XIR goes away to fix this). + asm.add(stackPointer, stackPointer, asm.i(8)); + asm.pushFrame(); + + // -- out of line ------------------------------------------------------- + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + XirOperand exceptionOop = asm.createTemp("exception oop", CiKind.Object); + XirLabel unwind = asm.createOutOfLineLabel("unwind"); + asm.bindOutOfLine(unwind); + + asm.mark(MARK_UNWIND_ENTRY); + + asm.pload(CiKind.Object, exceptionOop, thread, asm.i(config.threadExceptionOopOffset), false); + asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.createConstant(CiConstant.NULL_OBJECT), false); + asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); + + asm.callRuntime(config.unwindExceptionStub, null, exceptionOop); + asm.shouldNotReachHere(); + + asm.mark(MARK_EXCEPTION_HANDLER_ENTRY); + asm.callRuntime(config.handleExceptionStub, null); + asm.shouldNotReachHere(); + + asm.mark(MARK_DEOPT_HANDLER_ENTRY); + asm.callRuntime(config.handleDeoptStub, null); + asm.shouldNotReachHere(); + + if (!is(STATIC_METHOD, flags)) { + asm.bindOutOfLine(unverifiedStub); + asm.jmpRuntime(config.inlineCacheMissStub); + } + + return asm.finishTemplate(is(STATIC_METHOD, flags) ? "static prologue" : "prologue"); + } + }; + + private SimpleTemplates epilogueTemplates = new SimpleTemplates(STATIC_METHOD, SYNCHRONIZED) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + XirOperand framePointer = asm.createRegisterTemp("frame pointer", target.wordKind, AMD64.rbp); + XirOperand stackPointer = asm.createRegisterTemp("stack pointer", target.wordKind, AMD64.rsp); + + asm.popFrame(); + asm.pload(CiKind.Long, framePointer, stackPointer, asm.i(-8), false); + + if (GraalOptions.GenSafepoints) { + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); + if (config.isPollingPageFar) { + asm.mov(temp, wordConst(asm, config.safepointPollingAddress)); + asm.mark(MARK_POLL_RETURN_FAR); + asm.pload(target.wordKind, temp, temp, true); + } else { + XirOperand rip = asm.createRegister("rip", target.wordKind, AMD64.rip); + asm.mark(MARK_POLL_RETURN_NEAR); + asm.pload(target.wordKind, temp, rip, asm.i(0xEFBEADDE), true); + } + } + + return asm.finishTemplate("epilogue"); + } + }; + + private SimpleTemplates safepointTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); + if (config.isPollingPageFar) { + asm.mov(temp, wordConst(asm, config.safepointPollingAddress)); + asm.mark(MARK_POLL_FAR); + asm.pload(target.wordKind, temp, temp, true); + } else { + XirOperand rip = asm.createRegister("rip", target.wordKind, AMD64.rip); + asm.mark(MARK_POLL_NEAR); + asm.pload(target.wordKind, temp, rip, asm.i(0xEFBEADDE), true); + } + + return asm.finishTemplate("safepoint"); + } + }; + + private SimpleTemplates exceptionObjectTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + XirOperand result = asm.restart(CiKind.Object); + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + + asm.pload(CiKind.Object, result, thread, asm.i(config.threadExceptionOopOffset), false); + asm.pstore(CiKind.Object, thread, asm.i(config.threadExceptionOopOffset), asm.o(null), false); + asm.pstore(CiKind.Long, thread, asm.i(config.threadExceptionPcOffset), asm.l(0), false); + + return asm.finishTemplate("exception object"); + } + }; + + private SimpleTemplates invokeInterfaceTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirOperand tempO = asm.createRegisterTemp("tempO", CiKind.Object, AMD64.rax); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, receiver, true); + } + asm.mark(MARK_INVOKEINTERFACE); + asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); + + return asm.finishTemplate(addr, "invokeinterface"); + } + }; + + private SimpleTemplates invokeVirtualTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirOperand tempO = asm.createRegisterTemp("tempO", CiKind.Object, AMD64.rax); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, receiver, true); + } + asm.mark(MARK_INVOKEVIRTUAL); + asm.mov(tempO, asm.createConstant(CiConstant.forObject(HotSpotProxy.DUMMY_CONSTANT_OBJ))); + + return asm.finishTemplate(addr, "invokevirtual"); + } + }; + + private SimpleTemplates invokeSpecialTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter receiver = asm.createInputParameter("receiver", CiKind.Object); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + XirOperand temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.rax); + XirLabel stub = asm.createOutOfLineLabel("call stub"); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, temp, receiver, true); + } + asm.mark(MARK_INVOKESPECIAL); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(stub); + XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); + asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); + asm.mov(method, wordConst(asm, 0)); + XirLabel dummy = asm.createOutOfLineLabel("dummy"); + asm.jmp(dummy); + asm.bindOutOfLine(dummy); + + return asm.finishTemplate(addr, "invokespecial"); + } + }; + + private SimpleTemplates invokeStaticTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter addr = asm.createConstantInputParameter("addr", target.wordKind); + + XirLabel stub = asm.createOutOfLineLabel("call stub"); + asm.mark(MARK_INVOKESTATIC); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(stub); + XirOperand method = asm.createRegisterTemp("method", target.wordKind, AMD64.rbx); + asm.mark(MARK_STATIC_CALL_STUB, XirMark.CALLSITE); + asm.mov(method, wordConst(asm, 0)); + XirLabel dummy = asm.createOutOfLineLabel("dummy"); + asm.jmp(dummy); + asm.bindOutOfLine(dummy); + + return asm.finishTemplate(addr, "invokestatic"); + } + }; + + private SimpleTemplates monitorEnterTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + XirParameter lock = asm.createInputParameter("lock", target.wordKind); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + asm.pload(target.wordKind, asm.createTemp("temp", target.wordKind), object, true); + } + + + // (tw) It is important to use for this runtime call the debug info AFTER the monitor enter. Otherwise the monitor object + // is not correctly garbage collected. + final boolean useInfoAfter = true; + + if (config.useFastLocking) { + useRegisters(asm, AMD64.rax, AMD64.rbx); + useRegisters(asm, getGeneralParameterRegister(0)); + useRegisters(asm, getGeneralParameterRegister(1)); + asm.callRuntime(config.fastMonitorEnterStub, null, useInfoAfter, object, lock); + } else { + asm.reserveOutgoingStack(target.wordSize * 2); + XirOperand rsp = asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)); + asm.pstore(CiKind.Object, rsp, asm.i(target.wordSize), object, false); + asm.pstore(target.wordKind, rsp, asm.i(0), lock, false); + asm.callRuntime(config.monitorEnterStub, null, useInfoAfter); + } + + return asm.finishTemplate("monitorEnter"); + } + }; + + private CiRegister getGeneralParameterRegister(int index) { + return registerConfig.getCallingConventionRegisters(CiCallingConvention.Type.RuntimeCall, RegisterFlag.CPU)[index]; + } + + private SimpleTemplates monitorExitTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + XirParameter lock = asm.createInputParameter("lock", target.wordKind); + + if (config.useFastLocking) { + useRegisters(asm, AMD64.rax, AMD64.rbx); + useRegisters(asm, getGeneralParameterRegister(0)); + useRegisters(asm, getGeneralParameterRegister(1)); + asm.callRuntime(config.fastMonitorExitStub, null, object, lock); + } else { + asm.reserveOutgoingStack(target.wordSize); + asm.pstore(target.wordKind, asm.createRegister("rsp", target.wordKind, asRegister(AMD64.RSP)), asm.i(0), lock, false); + asm.callRuntime(config.monitorExitStub, null); + } + + return asm.finishTemplate("monitorExit"); + } + }; + + private KindTemplates getFieldTemplates = new KindTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + XirOperand result = asm.restart(kind); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + + XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pload(kind, result, object, fieldOffset, is(NULL_CHECK, flags)); + return asm.finishTemplate("getfield<" + kind + ">"); + } + }; + + private KindTemplates writeBarrierTemplate = new KindTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + asm.restart(CiKind.Void); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + + // Need temp operand, because the write barrier destroys the object pointer. + XirOperand temp = asm.createTemp("temp", target.wordKind); + asm.mov(temp, object); + + writeBarrier(asm, temp); + return asm.finishTemplate("writeBarrier"); + } + }; + + private KindTemplates putFieldTemplates = new KindTemplates(WRITE_BARRIER, NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + asm.restart(CiKind.Void); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + XirParameter value = asm.createInputParameter("value", kind); + XirParameter fieldOffset = asm.createConstantInputParameter("fieldOffset", CiKind.Int); + if (kind == CiKind.Object) { + verifyPointer(asm, value); + } + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pstore(kind, object, fieldOffset, value, is(NULL_CHECK, flags)); + if (is(WRITE_BARRIER, flags) && kind == CiKind.Object) { + XirOperand temp = asm.createTemp("temp", target.wordKind); + asm.mov(temp, object); + writeBarrier(asm, temp); + } + return asm.finishTemplate("putfield<" + kind + ">"); + } + }; + + private final IndexTemplates newInstanceTemplates = new IndexTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int size) { + XirOperand result = asm.restart(target.wordKind); + XirOperand type = asm.createInputParameter("type", CiKind.Object); + + XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); + XirOperand temp1o = asm.createRegisterTemp("temp1o", CiKind.Object, AMD64.rcx); + XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rbx); + XirOperand temp2i = asm.createRegisterTemp("temp2i", CiKind.Int, AMD64.rbx); + useRegisters(asm, AMD64.rsi); + XirLabel tlabFull = asm.createOutOfLineLabel("tlab full"); + XirLabel resume = asm.createInlineLabel("resume"); + + // check if the class is already initialized + asm.pload(CiKind.Int, temp2i, type, asm.i(config.klassStateOffset), false); + asm.jneq(tlabFull, temp2i, asm.i(config.klassStateFullyInitialized)); + + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); + asm.add(temp1, result, wordConst(asm, size)); + asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); + + asm.jgt(tlabFull, temp1, temp2); + asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); + + asm.bindInline(resume); + + asm.pload(target.wordKind, temp1, type, asm.i(config.instanceHeaderPrototypeOffset), false); + asm.pstore(target.wordKind, result, temp1, false); + asm.mov(temp1o, type); // need a temporary register since Intel cannot store 64-bit constants to memory + asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), temp1o, false); + + if (size > 2 * target.wordSize) { + asm.mov(temp1, wordConst(asm, 0)); + for (int offset = 2 * target.wordSize; offset < size; offset += target.wordSize) { + asm.pstore(target.wordKind, result, asm.i(offset), temp1, false); + } + } + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(tlabFull); + XirOperand arg = asm.createRegisterTemp("runtime call argument", CiKind.Object, AMD64.rdx); + asm.mov(arg, type); + useRegisters(asm, AMD64.rax); + asm.callRuntime(config.newInstanceStub, result); + asm.jmp(resume); + + return asm.finishTemplate("new instance"); + } + }; + + private SimpleTemplates newObjectArrayCloneTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + XirOperand result = asm.restart(CiKind.Object); + XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true); + XirParameter src = asm.createInputParameter("src", CiKind.Object); + + // Set up length and hub. + XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx); + XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx); + asm.pload(CiKind.Object, hub, src, asm.i(config.hubOffset), false); + asm.mov(length, lengthParam); + + useRegisters(asm, AMD64.rsi, AMD64.rcx, AMD64.rdi, AMD64.rax); + asm.callRuntime(config.newObjectArrayStub, result); + return asm.finishTemplate("objectArrayClone"); + } + }; + + private SimpleTemplates newObjectArrayTemplates = new SimpleTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + emitNewTypeArray(asm, CiKind.Object, config.useFastNewObjectArray, config.newObjectArrayStub); + return asm.finishTemplate("newObjectArray"); + } + }; + + private void emitNewTypeArray(CiXirAssembler asm, CiKind kind, boolean useFast, long slowPathStub) { + XirOperand result = asm.restart(target.wordKind); + + XirParameter lengthParam = asm.createInputParameter("length", CiKind.Int, true); + + XirOperand length = asm.createRegisterTemp("length", CiKind.Int, AMD64.rbx); + XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rdx); + + // Registers rsi, rcx, rdi, and rax are needed by the runtime call. + // Hub needs to be on rdx, length on rbx. + XirOperand temp1 = asm.createRegisterTemp("temp1", target.wordKind, AMD64.rcx); + XirOperand temp1o = asm.createRegisterTemp("temp1o", CiKind.Object, AMD64.rcx); + XirOperand temp2 = asm.createRegisterTemp("temp2", target.wordKind, AMD64.rax); + XirOperand temp3 = asm.createRegisterTemp("temp3", target.wordKind, AMD64.rdi); + XirOperand size = asm.createRegisterTemp("size", CiKind.Int, AMD64.rsi); + + asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); + asm.mov(length, lengthParam); + + if (useFast) { + + XirLabel slowPath = asm.createOutOfLineLabel("slowPath"); + + XirLabel done = asm.createInlineLabel("done"); + + // Check for negative array size. + // TODO: Also check for upper bound + asm.jlt(slowPath, length, asm.i(0)); + + final int aligning = target.wordSize; + final int arrayLengthOffset = target.wordSize * 2; + final int arrayElementOffset = config.getArrayOffset(kind); + + // Calculate aligned size + asm.mov(size, length); + int scale = CiUtil.log2(target.sizeInBytes(kind)); + if (scale != 0) { + asm.shl(size, size, asm.i(scale)); + } + asm.add(size, size, asm.i(arrayElementOffset + aligning - 1)); + long mask = 0xFFFFFFFFL; + mask <<= CiUtil.log2(aligning); + asm.and(size, size, asm.i((int) mask)); + + // Try tlab allocation + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + asm.pload(target.wordKind, result, thread, asm.i(config.threadTlabTopOffset), false); + asm.add(temp1, result, size); + asm.pload(target.wordKind, temp2, thread, asm.i(config.threadTlabEndOffset), false); + asm.jgt(slowPath, temp1, temp2); + asm.pstore(target.wordKind, thread, asm.i(config.threadTlabTopOffset), temp1, false); + + // Now the new object is in result, store mark word and klass + asm.pload(target.wordKind, temp1, hub, asm.i(config.instanceHeaderPrototypeOffset), false); + asm.pstore(target.wordKind, result, temp1, false); + asm.mov(temp1o, hub); // need a temporary register since Intel cannot store 64-bit constants to memory + asm.pstore(CiKind.Object, result, asm.i(config.hubOffset), temp1o, false); + + // Store array length + asm.pstore(CiKind.Int, result, asm.i(arrayLengthOffset), length, false); + + // Initialize with 0 + XirLabel top = asm.createInlineLabel("top"); + asm.sub(size, size, asm.i(arrayElementOffset)); + asm.shr(size, size, asm.i(Scale.Times8.log2)); + asm.jeq(done, size, asm.i(0)); + asm.xor(temp3, temp3, temp3); + asm.bindInline(top); + asm.pstore(target.wordKind, result, size, temp3, arrayElementOffset - target.wordSize, Scale.Times8, false); + asm.decAndJumpNotZero(top, size); + + asm.bindInline(done); + + // Slow path + asm.bindOutOfLine(slowPath); + asm.callRuntime(slowPathStub, result); + asm.jmp(done); + } else { + asm.callRuntime(slowPathStub, result); + } + } + + private KindTemplates newTypeArrayTemplates = new KindTemplates() { + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + emitNewTypeArray(asm, kind, config.useFastNewTypeArray, config.newTypeArrayStub); + return asm.finishTemplate("newTypeArray<" + kind.toString() + ">"); + } + }; + + private final IndexTemplates multiNewArrayTemplate = new IndexTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, int dimensions) { + XirOperand result = asm.restart(CiKind.Object); + + XirOperand hub = asm.createRegisterTemp("hub", CiKind.Object, AMD64.rax); + XirOperand rank = asm.createRegisterTemp("rank", CiKind.Int, AMD64.rbx); + XirOperand sizes = asm.createRegisterTemp("sizes", CiKind.Long, AMD64.rcx); + XirOperand thread = asm.createRegisterTemp("thread", CiKind.Long, AMD64.r15); + asm.add(sizes, thread, asm.l(config.threadMultiNewArrayStorage)); + for (int i = 0; i < dimensions; i++) { + XirParameter length = asm.createInputParameter("length" + i, CiKind.Int, true); + asm.pstore(CiKind.Int, sizes, asm.i(i * target.sizeInBytes(CiKind.Int)), length, false); + } + + asm.mov(hub, asm.createConstantInputParameter("hub", CiKind.Object)); + + asm.mov(rank, asm.i(dimensions)); + useRegisters(asm, AMD64.rax); + asm.callRuntime(config.newMultiArrayStub, result); + return asm.finishTemplate("multiNewArray" + dimensions); + } + }; + + private SimpleTemplates checkCastTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + final XirOperand hub; + hub = asm.createConstantInputParameter("hub", CiKind.Object); + + XirOperand objHub = asm.createTemp("objHub", CiKind.Object); + + XirLabel end = asm.createInlineLabel("end"); + XirLabel slowPath = asm.createOutOfLineLabel("slow path"); + + if (is(NULL_CHECK, flags)) { + // null can be cast to anything + asm.jeq(end, object, asm.o(null)); + } + + asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); + // if we get an exact match: succeed immediately + asm.jneq(slowPath, objHub, hub); + asm.bindInline(end); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jneq(end, objHub, asm.o(null)); + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 2)); + + asm.callRuntime(CiRuntimeCall.Deoptimize, null); + asm.shouldNotReachHere(); + + return asm.finishTemplate("checkcast"); + } + }; + + private SimpleTemplates instanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(CiKind.Void); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + final XirOperand hub; + hub = asm.createConstantInputParameter("hub", CiKind.Object); + + XirOperand objHub = asm.createTemp("objHub", CiKind.Object); + + XirLabel slowPath = asm.createOutOfLineLabel("slow path"); + XirLabel trueSucc = asm.createInlineLabel(XirLabel.TrueSuccessor); + XirLabel falseSucc = asm.createInlineLabel(XirLabel.FalseSuccessor); + + if (is(NULL_CHECK, flags)) { + // null isn't "instanceof" anything + asm.jeq(falseSucc, object, asm.o(null)); + } + + asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); + // if we get an exact match: succeed immediately + asm.jeq(trueSucc, objHub, hub); + asm.jmp(slowPath); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + + return asm.finishTemplate("instanceof"); + } + }; + + private SimpleTemplates materializeInstanceOfTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + XirOperand result = asm.restart(CiKind.Int); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + final XirOperand hub; + hub = asm.createConstantInputParameter("hub", CiKind.Object); + XirOperand trueValue = asm.createConstantInputParameter("trueValue", CiKind.Int); + XirOperand falseValue = asm.createConstantInputParameter("falseValue", CiKind.Int); + + XirOperand objHub = asm.createTemp("objHub", CiKind.Object); + + XirLabel slowPath = asm.createOutOfLineLabel("slow path"); + XirLabel trueSucc = asm.createInlineLabel("ok"); + XirLabel falseSucc = asm.createInlineLabel("ko"); + XirLabel end = asm.createInlineLabel("end"); + + if (is(NULL_CHECK, flags)) { + // null isn't "instanceof" anything + asm.jeq(falseSucc, object, asm.o(null)); + } + + asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); + // if we get an exact match: succeed immediately + asm.jeq(trueSucc, objHub, hub); + asm.jmp(slowPath); + + asm.bindInline(trueSucc); + asm.mov(result, trueValue); + asm.jmp(end); + asm.bindInline(falseSucc); + asm.mov(result, falseValue); + asm.bindInline(end); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + checkSubtype(asm, objHub, objHub, hub); + asm.jeq(falseSucc, objHub, asm.o(null)); + asm.jmp(trueSucc); + + return asm.finishTemplate("instanceof"); + } + }; + + private XirOperand genArrayLength(CiXirAssembler asm, XirOperand array, boolean implicitNullException) { + XirOperand length = asm.createTemp("length", CiKind.Int); + genArrayLength(asm, length, array, implicitNullException); + return length; + } + + private void genArrayLength(CiXirAssembler asm, XirOperand length, XirOperand array, boolean implicitNullException) { + if (implicitNullException) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException); + } + + private KindTemplates arrayLoadTemplates = new KindTemplates(NULL_CHECK, READ_BARRIER, BOUNDS_CHECK, GIVEN_LENGTH) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + XirOperand result = asm.restart(kind); + XirParameter array = asm.createInputParameter("array", CiKind.Object); + XirParameter index = asm.createInputParameter("index", CiKind.Int, true); + XirLabel failBoundsCheck = null; + // if the length is known the array cannot be null + boolean implicitNullException = is(NULL_CHECK, flags); + + if (is(BOUNDS_CHECK, flags)) { + // load the array length and check the index + failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); + XirOperand length; + if (is(GIVEN_LENGTH, flags)) { + length = asm.createInputParameter("length", CiKind.Int, true); + } else { + length = genArrayLength(asm, array, implicitNullException); + } + asm.jugteq(failBoundsCheck, index, length); + implicitNullException = false; + } + int elemSize = target.sizeInBytes(kind); + if (implicitNullException) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pload(kind, result, array, index, config.getArrayOffset(kind), Scale.fromInt(elemSize), implicitNullException); + if (is(BOUNDS_CHECK, flags)) { + asm.bindOutOfLine(failBoundsCheck); + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 0)); + asm.callRuntime(CiRuntimeCall.Deoptimize, null); + asm.shouldNotReachHere(); + } + return asm.finishTemplate("arrayload<" + kind + ">"); + } + }; + + private SimpleTemplates getClassTemplates = new SimpleTemplates() { + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + XirOperand result = asm.restart(CiKind.Object); + XirOperand object = asm.createInputParameter("object", CiKind.Object); + asm.pload(CiKind.Object, result, object, asm.i(config.hubOffset), is(NULL_CHECK, flags)); + asm.pload(CiKind.Object, result, result, asm.i(config.classMirrorOffset), false); + return asm.finishTemplate("getClass"); + } + }; + + private SimpleTemplates currentThreadTemplates = new SimpleTemplates() { + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + XirOperand result = asm.restart(CiKind.Object); + XirOperand thread = asm.createRegisterTemp("thread", target.wordKind, AMD64.r15); + asm.pload(CiKind.Object, result, thread, asm.i(config.threadObjectOffset), false); + return asm.finishTemplate("currentThread"); + } + }; + + @Override + public XirSnippet genCurrentThread(XirSite site) { + return new XirSnippet(currentThreadTemplates.get(site)); + } + + @Override + public XirSnippet genGetClass(XirSite site, XirArgument object) { + return new XirSnippet(getClassTemplates.get(site), object); + } + + private KindTemplates arrayCopyTemplates = new KindTemplates() { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + asm.restart(CiKind.Void); + XirParameter src = asm.createInputParameter("src", CiKind.Object); + XirParameter srcPos = asm.createInputParameter("srcPos", CiKind.Int, true); + XirParameter dest = asm.createInputParameter("dest", CiKind.Object); + XirParameter destPos = asm.createInputParameter("destPos", CiKind.Int, true); + XirParameter length = asm.createInputParameter("length", CiKind.Int, true); + + XirOperand tempSrc = asm.createTemp("tempSrc", target.wordKind); + XirOperand tempDest = asm.createTemp("tempDest", target.wordKind); + XirOperand lengthOperand = asm.createRegisterTemp("lengthOperand", CiKind.Int, AMD64.rax); + + XirOperand compHub = null; + XirOperand valueHub = null; + XirOperand temp = null; + XirLabel store = null; + XirLabel slowStoreCheck = null; + + if (is(STORE_CHECK, flags) && kind == CiKind.Object) { + valueHub = asm.createRegisterTemp("valueHub", target.wordKind, AMD64.rdi); + compHub = asm.createRegisterTemp("compHub", target.wordKind, AMD64.rsi); + temp = asm.createRegisterTemp("temp", target.wordKind, AMD64.r10); + } + + // Calculate the factor for the repeat move instruction. + int elementSize = target.sizeInBytes(kind); + int factor; + boolean wordSize; + if (elementSize >= target.wordSize) { + assert elementSize % target.wordSize == 0; + wordSize = true; + factor = elementSize / target.wordSize; + } else { + factor = elementSize; + wordSize = false; + } + + // Adjust the length if the factor is not 1. + if (factor != 1) { + asm.shl(lengthOperand, length, asm.i(CiUtil.log2(factor))); + } else { + asm.mov(lengthOperand, length); + } + + // Set the start and the end pointer. + asm.lea(tempSrc, src, srcPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); + asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); + + XirLabel reverse = null; + XirLabel normal = null; + + if (is(STORE_CHECK, flags)) { + reverse = asm.createInlineLabel("reverse"); + asm.jneq(reverse, src, dest); + } + + if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { + normal = asm.createInlineLabel("normal"); + asm.jneq(normal, src, dest); + } + + if (!is(INPUTS_DIFFERENT, flags)) { + if (reverse == null) { + reverse = asm.createInlineLabel("reverse"); + } + asm.jlt(reverse, srcPos, destPos); + } + + if (!is(STORE_CHECK, flags) && !is(INPUTS_DIFFERENT, flags) && !is(INPUTS_SAME, flags)) { + asm.bindInline(normal); + } + + // Everything set up => repeat mov. + if (wordSize) { + asm.repmov(tempSrc, tempDest, lengthOperand); + } else { + asm.repmovb(tempSrc, tempDest, lengthOperand); + } + + if (!is(INPUTS_DIFFERENT, flags) || is(STORE_CHECK, flags)) { + + XirLabel end = asm.createInlineLabel("end"); + asm.jmp(end); + + // Implement reverse copy, because srcPos < destPos and src == dest. + asm.bindInline(reverse); + + if (is(STORE_CHECK, flags)) { + asm.pload(CiKind.Object, compHub, dest, asm.i(config.hubOffset), false); + asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); + } + + CiKind copyKind = wordSize ? CiKind.Object : CiKind.Byte; + XirOperand tempValue = asm.createTemp("tempValue", copyKind); + XirLabel start = asm.createInlineLabel("start"); + asm.bindInline(start); + asm.sub(lengthOperand, lengthOperand, asm.i(1)); + asm.jlt(end, lengthOperand, asm.i(0)); + + Scale scale = wordSize ? Scale.fromInt(target.wordSize) : Scale.Times1; + asm.pload(copyKind, tempValue, tempSrc, lengthOperand, 0, scale, false); + + if (is(STORE_CHECK, flags)) { + slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); + store = asm.createInlineLabel("store"); + asm.jeq(store, tempValue, asm.o(null)); // first check if value is null + asm.pload(CiKind.Object, valueHub, tempValue, asm.i(config.hubOffset), false); + asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub + asm.bindInline(store); + } + + asm.pstore(copyKind, tempDest, lengthOperand, tempValue, 0, scale, false); + + asm.jmp(start); + asm.bindInline(end); + } + + if (kind == CiKind.Object) { + // Do write barriers + asm.lea(tempDest, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); + asm.shr(tempDest, tempDest, asm.i(config.cardtableShift)); + asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDest, asm.b(false), false); + + XirOperand tempDestEnd = tempSrc; // Reuse src temp + asm.lea(tempDestEnd, dest, destPos, config.getArrayOffset(kind), Scale.fromInt(elementSize)); + asm.add(tempDestEnd, tempDestEnd, length); + asm.shr(tempDestEnd, tempDestEnd, asm.i(config.cardtableShift)); + + // Jump to out-of-line write barrier loop if the array is big. + XirLabel writeBarrierLoop = asm.createOutOfLineLabel("writeBarrierLoop"); + asm.jneq(writeBarrierLoop, tempDest, tempSrc); + XirLabel back = asm.createInlineLabel("back"); + asm.bindInline(back); + + asm.bindOutOfLine(writeBarrierLoop); + asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), tempDestEnd, asm.b(false), false); + asm.sub(tempDestEnd, tempDestEnd, asm.i(1)); + asm.jneq(writeBarrierLoop, tempDestEnd, tempDest); + asm.jmp(back); + } + + if (is(STORE_CHECK, flags)) { + assert kind == CiKind.Object; + useRegisters(asm, AMD64.rax); + asm.bindOutOfLine(slowStoreCheck); + checkSubtype(asm, temp, valueHub, compHub); + asm.jneq(store, temp, wordConst(asm, 0)); + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 0)); + asm.callRuntime(CiRuntimeCall.Deoptimize, null); + asm.jmp(store); + } + + return asm.finishTemplate("arraycopy<" + kind + ">"); + } + }; + + private KindTemplates arrayStoreTemplates = new KindTemplates(NULL_CHECK, WRITE_BARRIER, BOUNDS_CHECK, STORE_CHECK, GIVEN_LENGTH) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags, CiKind kind) { + asm.restart(CiKind.Void); + XirParameter array = asm.createInputParameter("array", CiKind.Object); + XirParameter index = asm.createInputParameter("index", CiKind.Int, true); + XirParameter value = asm.createInputParameter("value", kind, kind != CiKind.Object); + XirOperand temp = asm.createTemp("temp", target.wordKind); + XirOperand valueHub = null; + XirOperand compHub = null; + XirLabel store = asm.createInlineLabel("store"); + XirLabel failBoundsCheck = null; + XirLabel slowStoreCheck = null; + // if the length is known the array cannot be null + boolean implicitNullException = is(NULL_CHECK, flags); + + if (is(BOUNDS_CHECK, flags)) { + // load the array length and check the index + failBoundsCheck = asm.createOutOfLineLabel("failBoundsCheck"); + XirOperand length; + if (is(GIVEN_LENGTH, flags)) { + length = asm.createInputParameter("length", CiKind.Int); + } else { + length = asm.createTemp("length", CiKind.Int); + if (implicitNullException) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pload(CiKind.Int, length, array, asm.i(config.arrayLengthOffset), implicitNullException); + implicitNullException = false; + } + asm.jugteq(failBoundsCheck, index, length); + + } + if (is(STORE_CHECK, flags) && kind == CiKind.Object) { + slowStoreCheck = asm.createOutOfLineLabel("slowStoreCheck"); + asm.jeq(store, value, asm.o(null)); // first check if value is null + valueHub = asm.createTemp("valueHub", CiKind.Object); + compHub = asm.createTemp("compHub", CiKind.Object); + if (implicitNullException) { + asm.mark(MARK_IMPLICIT_NULL); + } + asm.pload(CiKind.Object, compHub, array, asm.i(config.hubOffset), implicitNullException); + asm.pload(CiKind.Object, compHub, compHub, asm.i(config.arrayClassElementOffset), false); + asm.pload(CiKind.Object, valueHub, value, asm.i(config.hubOffset), false); + asm.jneq(slowStoreCheck, compHub, valueHub); // then check component hub matches value hub + + implicitNullException = false; + } + asm.bindInline(store); + int elemSize = target.sizeInBytes(kind); + + if (implicitNullException) { + asm.mark(MARK_IMPLICIT_NULL); + } + int disp = config.getArrayOffset(kind); + Scale scale = Scale.fromInt(elemSize); + if (kind == CiKind.Object) { + verifyPointer(asm, value); + } + if (is(WRITE_BARRIER, flags) && kind == CiKind.Object) { + asm.lea(temp, array, index, disp, scale); + asm.pstore(kind, temp, value, implicitNullException); + writeBarrier(asm, temp); + } else { + asm.pstore(kind, array, index, value, disp, scale, implicitNullException); + } + + // -- out of line ------------------------------------------------------- + if (is(BOUNDS_CHECK, flags)) { + asm.bindOutOfLine(failBoundsCheck); + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 0)); + asm.callRuntime(CiRuntimeCall.Deoptimize, null); + asm.shouldNotReachHere(); + } + if (is(STORE_CHECK, flags) && kind == CiKind.Object) { + useRegisters(asm, AMD64.rax); + asm.bindOutOfLine(slowStoreCheck); + checkSubtype(asm, temp, valueHub, compHub); + asm.jneq(store, temp, wordConst(asm, 0)); + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 0)); + asm.callRuntime(CiRuntimeCall.Deoptimize, null); + asm.shouldNotReachHere(); + } + return asm.finishTemplate("arraystore<" + kind + ">"); + } + }; + + private SimpleTemplates arrayLengthTemplates = new SimpleTemplates(NULL_CHECK) { + + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + XirOperand result = asm.restart(CiKind.Int); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + } + verifyPointer(asm, object); + asm.pload(CiKind.Int, result, object, asm.i(config.arrayLengthOffset), true); + return asm.finishTemplate("arrayLength"); + } + }; + + private SimpleTemplates typeCheckTemplates = new SimpleTemplates(NULL_CHECK) { + @Override + protected XirTemplate create(CiXirAssembler asm, long flags) { + asm.restart(); + XirParameter object = asm.createInputParameter("object", CiKind.Object); + XirOperand hub = asm.createConstantInputParameter("hub", CiKind.Object); + + XirOperand objHub = asm.createTemp("objHub", CiKind.Object); + XirOperand checkHub = asm.createTemp("checkHub", CiKind.Object); + + XirLabel slowPath = asm.createOutOfLineLabel("deopt"); + + if (is(NULL_CHECK, flags)) { + asm.mark(MARK_IMPLICIT_NULL); + } + + asm.pload(CiKind.Object, objHub, object, asm.i(config.hubOffset), false); + asm.mov(checkHub, hub); + // if we get an exact match: continue + asm.jneq(slowPath, objHub, checkHub); + + // -- out of line ------------------------------------------------------- + asm.bindOutOfLine(slowPath); + XirOperand scratch = asm.createRegisterTemp("scratch", target.wordKind, AMD64.r10); + asm.mov(scratch, wordConst(asm, 2)); + + asm.callRuntime(CiRuntimeCall.Deoptimize, null); + asm.shouldNotReachHere(); + + return asm.finishTemplate(object, "typeCheck"); + } + }; + + @Override + public XirSnippet genPrologue(XirSite site, RiResolvedMethod method) { + boolean staticMethod = Modifier.isStatic(method.accessFlags()); + return new XirSnippet(staticMethod ? prologueTemplates.get(site, STATIC_METHOD) : prologueTemplates.get(site)); + } + + @Override + public XirSnippet genEpilogue(XirSite site, RiResolvedMethod method) { + return new XirSnippet(epilogueTemplates.get(site)); + } + + @Override + public XirSnippet genSafepointPoll(XirSite site) { + return new XirSnippet(safepointTemplates.get(site)); + } + + @Override + public XirSnippet genExceptionObject(XirSite site) { + return new XirSnippet(exceptionObjectTemplates.get(site)); + } + + @Override + public XirSnippet genResolveClass(XirSite site, RiType type, Representation rep) { + throw new CiBailout("Xir ResolveClass not available"); + } + + @Override + public XirSnippet genIntrinsic(XirSite site, XirArgument[] arguments, RiMethod method) { + return null; + } + + @Override + public XirSnippet genInvokeInterface(XirSite site, XirArgument receiver, RiMethod method) { + return new XirSnippet(invokeInterfaceTemplates.get(site), receiver, wordArg(0)); + } + + @Override + public XirSnippet genInvokeVirtual(XirSite site, XirArgument receiver, RiMethod method) { + return new XirSnippet(invokeVirtualTemplates.get(site), receiver, wordArg(0)); + } + + @Override + public XirSnippet genInvokeSpecial(XirSite site, XirArgument receiver, RiMethod method) { + return new XirSnippet(invokeSpecialTemplates.get(site), receiver, wordArg(0)); + } + + @Override + public XirSnippet genInvokeStatic(XirSite site, RiMethod method) { + return new XirSnippet(invokeStaticTemplates.get(site), wordArg(0)); + } + + @Override + public XirSnippet genMonitorEnter(XirSite site, XirArgument receiver, XirArgument lockAddress) { + return new XirSnippet(monitorEnterTemplates.get(site), receiver, lockAddress); + } + + @Override + public XirSnippet genMonitorExit(XirSite site, XirArgument receiver, XirArgument lockAddress) { + return new XirSnippet(monitorExitTemplates.get(site), receiver, lockAddress); + } + + @Override + public XirSnippet genGetField(XirSite site, XirArgument object, RiField field) { + return new XirSnippet(getFieldTemplates.get(site, field.kind(false)), object, XirArgument.forInt(((HotSpotField) field).offset())); + } + + @Override + public XirSnippet genWriteBarrier(XirArgument object) { + return new XirSnippet(writeBarrierTemplate.get(null, CiKind.Void), object); + } + + @Override + public XirSnippet genPutField(XirSite site, XirArgument object, RiField field, XirArgument value) { + return new XirSnippet(putFieldTemplates.get(site, field.kind(false)), object, value, XirArgument.forInt(((HotSpotField) field).offset())); + } + + @Override + public XirSnippet genGetStatic(XirSite site, XirArgument object, RiField field) { + return new XirSnippet(getFieldTemplates.get(site, field.kind(false)), object, XirArgument.forInt(((HotSpotField) field).offset())); + } + + @Override + public XirSnippet genPutStatic(XirSite site, XirArgument object, RiField field, XirArgument value) { + return new XirSnippet(putFieldTemplates.get(site, field.kind(false)), object, value, XirArgument.forInt(((HotSpotField) field).offset())); + } + + @Override + public XirSnippet genNewInstance(XirSite site, RiType type) { + int instanceSize = ((HotSpotTypeResolved) type).instanceSize(); + return new XirSnippet(newInstanceTemplates.get(site, instanceSize), XirArgument.forObject(type)); + } + + @Override + public XirSnippet genNewArray(XirSite site, XirArgument length, CiKind elementKind, RiType componentType, RiType arrayType) { + if (elementKind == CiKind.Object) { + assert arrayType instanceof RiResolvedType; + return new XirSnippet(newObjectArrayTemplates.get(site), length, XirArgument.forObject(arrayType)); + } else { + assert arrayType == null; + RiType primitiveArrayType = compiler.getVMEntries().getPrimitiveArrayType(elementKind); + return new XirSnippet(newTypeArrayTemplates.get(site, elementKind), length, XirArgument.forObject(primitiveArrayType)); + } + } + + @Override + public XirSnippet genNewObjectArrayClone(XirSite site, XirArgument newLength, XirArgument referenceArray) { + return new XirSnippet(newObjectArrayCloneTemplates.get(site), newLength, referenceArray); + } + + @Override + public XirSnippet genNewMultiArray(XirSite site, XirArgument[] lengths, RiType type) { + XirArgument[] params = Arrays.copyOf(lengths, lengths.length + 1); + params[lengths.length] = XirArgument.forObject(type); + return new XirSnippet(multiNewArrayTemplate.get(site, lengths.length), params); + } + + @Override + public XirSnippet genCheckCast(XirSite site, XirArgument receiver, XirArgument hub, RiType type) { + return new XirSnippet(checkCastTemplates.get(site), receiver, hub); + } + + @Override + public XirSnippet genInstanceOf(XirSite site, XirArgument object, XirArgument hub, RiType type) { + return new XirSnippet(instanceOfTemplates.get(site), object, hub); + } + + @Override + public XirSnippet genMaterializeInstanceOf(XirSite site, XirArgument object, XirArgument hub, XirArgument trueValue, XirArgument falseValue, RiType type) { + return new XirSnippet(materializeInstanceOfTemplates.get(site), object, hub, trueValue, falseValue); + } + + @Override + public XirSnippet genArrayLoad(XirSite site, XirArgument array, XirArgument index, CiKind elementKind, RiType elementType) { + return new XirSnippet(arrayLoadTemplates.get(site, elementKind), array, index); + } + + @Override + public XirSnippet genArrayStore(XirSite site, XirArgument array, XirArgument index, XirArgument value, CiKind elementKind, RiType elementType) { + return new XirSnippet(arrayStoreTemplates.get(site, elementKind), array, index, value); + } + + @Override + public XirSnippet genArrayCopy(XirSite site, XirArgument src, XirArgument srcPos, XirArgument dest, XirArgument destPos, XirArgument length, RiType elementType, boolean inputsSame, boolean inputsDifferent) { + if (elementType == null) { + return null; + } + assert !inputsDifferent || !inputsSame; + XirTemplate template = null; + if (inputsDifferent) { + template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_DIFFERENT); + } else if (inputsSame) { + template = arrayCopyTemplates.get(site, elementType.kind(true), INPUTS_SAME); + } else { + template = arrayCopyTemplates.get(site, elementType.kind(true)); + } + return new XirSnippet(template, src, srcPos, dest, destPos, length); + } + + @Override + public XirSnippet genArrayLength(XirSite site, XirArgument array) { + return new XirSnippet(arrayLengthTemplates.get(site), array); + } + + @Override + public XirSnippet genTypeCheck(XirSite site, XirArgument object, XirArgument hub, RiType type) { + assert type instanceof RiResolvedType; + return new XirSnippet(typeCheckTemplates.get(site), object, hub); + } + + @Override + public List makeTemplates(CiXirAssembler asm) { + this.globalAsm = asm; + List templates = new ArrayList<>(); + return templates; + } + + private void verifyPointer(CiXirAssembler asm, XirOperand pointer) { + if (config.verifyPointers) { + // The verify pointer stub wants the argument in a fixed register. + XirOperand fixed = asm.createRegisterTemp("fixed", CiKind.Object, AMD64.r13); + asm.push(fixed); + asm.mov(fixed, pointer); + asm.callRuntime(config.verifyPointerStub, null); + asm.pop(fixed); + } + } + + private void checkSubtype(CiXirAssembler asm, XirOperand result, XirOperand objHub, XirOperand hub) { + asm.push(objHub); + asm.push(hub); + asm.callRuntime(config.instanceofStub, null); + asm.pop(result); + asm.pop(result); + } + + private static void useRegisters(CiXirAssembler asm, CiRegister... registers) { + if (registers != null) { + for (CiRegister register : registers) { + asm.createRegisterTemp("reg", CiKind.Illegal, register); + } + } + } + + private void writeBarrier(CiXirAssembler asm, XirOperand base) { + asm.shr(base, base, asm.i(config.cardtableShift)); + asm.pstore(CiKind.Boolean, wordConst(asm, config.cardtableStartAddress), base, asm.b(false), false); + } + + public boolean is(TemplateFlag check, long flags) { + return (flags & check.bits()) == check.bits(); + } + + /** + * Base class for all the ondemand template generators. It is not normally subclassed directly, but through one of + * its subclasses (SimpleTemplates, KindTemplates, IndexTemplates). + */ + private abstract class Templates { + + private ConcurrentHashMap templates = new ConcurrentHashMap<>(); + private final long mask; + + /** + * Each flag passed to this method will cause templates with and without it to be generated. + */ + public Templates(TemplateFlag... flags) { + this.mask = getBits((int) INDEX_MASK, null, flags); + } + + protected abstract XirTemplate create(CiXirAssembler asm, long flags); + + protected long getBits(int index, XirSite site, TemplateFlag... flags) { + long bits = index; + if (site != null) { + bits |= site.requiresNullCheck() ? NULL_CHECK.bits() : 0; + bits |= site.requiresReadBarrier() ? READ_BARRIER.bits() : 0; + bits |= site.requiresWriteBarrier() ? WRITE_BARRIER.bits() : 0; + bits |= site.requiresArrayStoreCheck() ? STORE_CHECK.bits() : 0; + bits |= site.requiresBoundsCheck() ? BOUNDS_CHECK.bits() : 0; + } + if (flags != null) { + for (TemplateFlag flag : flags) { + bits |= flag.bits(); + } + } + return bits; + } + + protected XirTemplate getInternal(long flags) { + long maskedFlags = flags & mask; + XirTemplate template = templates.get(maskedFlags); + if (template == null) { + template = create(HotSpotXirGenerator.this.globalAsm.copy(), maskedFlags); + templates.put(maskedFlags, template); + } + return template; + } + } + + private abstract class SimpleTemplates extends Templates { + + public SimpleTemplates(TemplateFlag... flags) { + super(flags); + } + + public XirTemplate get(XirSite site, TemplateFlag... flags) { + return getInternal(getBits(0, site, flags)); + } + } + + private abstract class IndexTemplates extends Templates { + + public IndexTemplates(TemplateFlag... flags) { + super(flags); + } + + @Override + protected final XirTemplate create(CiXirAssembler asm, long flags) { + return create(asm, flags & FLAGS_MASK, (int) (flags & INDEX_MASK)); + } + + protected abstract XirTemplate create(CiXirAssembler asm, long flags, int index); + + public XirTemplate get(XirSite site, int size, TemplateFlag... flags) { + return getInternal(getBits(size, site, flags)); + } + } + + private abstract class KindTemplates extends Templates { + + public KindTemplates(TemplateFlag... flags) { + super(flags); + } + + @Override + protected final XirTemplate create(CiXirAssembler asm, long flags) { + return create(asm, flags & FLAGS_MASK, CiKind.VALUES[(int) (flags & INDEX_MASK)]); + } + + protected abstract XirTemplate create(CiXirAssembler asm, long flags, CiKind kind); + + public XirTemplate get(XirSite site, CiKind kind, TemplateFlag... flags) { + return getInternal(getBits(kind.ordinal(), site, flags)); + } + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/ri/TemplateFlag.java Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2011, 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.max.graal.hotspot.ri; + +enum TemplateFlag { + NULL_CHECK, READ_BARRIER, WRITE_BARRIER, STORE_CHECK, BOUNDS_CHECK, GIVEN_LENGTH, INPUTS_DIFFERENT, INPUTS_SAME, STATIC_METHOD, SYNCHRONIZED; + + private static final long FIRST_FLAG = 0x0000000100000000L; + public static final long FLAGS_MASK = 0x0000FFFF00000000L; + public static final long INDEX_MASK = 0x00000000FFFFFFFFL; + + public long bits() { + assert ((FIRST_FLAG << ordinal()) & FLAGS_MASK) != 0; + return FIRST_FLAG << ordinal(); + } +} diff -r 35b05867c94a -r 5c80ccb80036 graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/server/CompilationServer.java --- a/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/server/CompilationServer.java Wed Jan 04 10:49:09 2012 -0800 +++ b/graal/com.oracle.max.graal.hotspot/src/com/oracle/max/graal/hotspot/server/CompilationServer.java Wed Jan 04 20:59:11 2012 +0100 @@ -30,6 +30,7 @@ import com.oracle.max.graal.hotspot.*; import com.oracle.max.graal.hotspot.Compiler; +import com.oracle.max.graal.hotspot.bridge.*; import com.oracle.max.graal.hotspot.logging.*; /** @@ -88,7 +89,7 @@ ReplacingStreams streams = new ReplacingStreams(socket.getOutputStream(), socket.getInputStream()); // get the VMEntries proxy from the client - VMEntries entries = (VMEntries) streams.getInvocation().waitForResult(false); + CompilerToVM entries = (CompilerToVM) streams.getInvocation().waitForResult(false); // return the initialized compiler to the client Compiler compiler = CompilerImpl.initializeServer(entries); diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Wed Jan 04 10:49:09 2012 -0800 +++ b/src/share/vm/classfile/systemDictionary.hpp Wed Jan 04 20:59:11 2012 +0100 @@ -195,7 +195,6 @@ template(HotSpotMethodResolved_klass, com_sun_hotspot_graal_HotSpotMethodResolved, Opt) \ template(HotSpotTargetMethod_klass, com_sun_hotspot_graal_HotSpotTargetMethod, Opt) \ template(HotSpotExceptionHandler_klass,com_sun_hotspot_graal_HotSpotExceptionHandler, Opt) \ - template(HotSpotProxy_klass, com_sun_hotspot_graal_HotSpotProxy, Opt) \ template(CiAssumptions_klass, com_sun_cri_ci_CiAssumptions, Opt) \ template(CiAssumptions_ConcreteSubtype_klass, com_sun_cri_ci_CiAssumptions_ConcreteSubtype, Opt) \ template(CiAssumptions_ConcreteMethod_klass, com_sun_cri_ci_CiAssumptions_ConcreteMethod, Opt) \ diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Wed Jan 04 10:49:09 2012 -0800 +++ b/src/share/vm/classfile/vmSymbols.hpp Wed Jan 04 20:59:11 2012 +0100 @@ -272,14 +272,13 @@ template(com_sun_hotspot_graal_VMExits, "com/oracle/max/graal/hotspot/VMExits") \ template(com_sun_hotspot_graal_HotSpotMethodResolved, "com/oracle/max/graal/hotspot/ri/HotSpotMethodResolvedImpl") \ template(com_sun_hotspot_graal_HotSpotTargetMethod, "com/oracle/max/graal/hotspot/HotSpotTargetMethod") \ - template(com_sun_hotspot_graal_HotSpotField, "com/oracle/max/graal/hotspot/HotSpotField") \ - template(com_sun_hotspot_graal_HotSpotCompiledMethod, "com/oracle/max/graal/hotspot/HotSpotCompiledMethod") \ + template(com_sun_hotspot_graal_HotSpotField, "com/oracle/max/graal/hotspot/ri/HotSpotField") \ + template(com_sun_hotspot_graal_HotSpotCompiledMethod, "com/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod") \ template(com_sun_graal_graalOptions, "com/sun/graal/graalOptions") \ template(com_sun_hotspot_graal_HotSpotOptions, "com/oracle/max/graal/hotspot/HotSpotOptions") \ template(com_sun_hotspot_graal_HotSpotTypeResolved, "com/oracle/max/graal/hotspot/ri/HotSpotTypeResolvedImpl") \ template(com_sun_hotspot_graal_HotSpotType, "com/oracle/max/graal/hotspot/ri/HotSpotType") \ - template(com_sun_hotspot_graal_HotSpotExceptionHandler,"com/oracle/max/graal/hotspot/HotSpotExceptionHandler") \ - template(com_sun_hotspot_graal_HotSpotProxy, "com/oracle/max/graal/hotspot/HotSpotProxy") \ + template(com_sun_hotspot_graal_HotSpotExceptionHandler,"com/oracle/max/graal/hotspot/ri/HotSpotExceptionHandler") \ template(com_sun_hotspot_graal_Compiler, "com/oracle/max/graal/hotspot/Compiler") \ template(com_sun_hotspot_graal_CompilerImpl, "com/oracle/max/graal/hotspot/CompilerImpl") \ template(com_sun_cri_ri_RiMethod, "com/oracle/max/cri/ri/RiMethod") \ diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Wed Jan 04 10:49:09 2012 -0800 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Wed Jan 04 20:59:11 2012 +0100 @@ -792,12 +792,7 @@ _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); TRACE_graal_3("relocating (HotSpotType) at %016x/%016x", instruction, operand); } else { - jobject value; - if (obj() == HotSpotProxy::DUMMY_CONSTANT_OBJ()) { - value = (jobject) Universe::non_oop_word(); - } else { - value = JNIHandles::make_local(obj()); - } + jobject value = JNIHandles::make_local(obj()); *((jobject*) operand) = value; _instructions->relocate(instruction, oop_Relocation::spec_for_immediate(), Assembler::imm_operand); TRACE_graal_3("relocating (oop constant) at %016x/%016x", instruction, operand); diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalCompilerToVM.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,1043 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "runtime/fieldDescriptor.hpp" +#include "c1/c1_Runtime1.hpp" +#include "ci/ciMethodData.hpp" +#include "compiler/compileBroker.hpp" +#include "graal/graalVMEntries.hpp" +#include "graal/graalCompiler.hpp" +#include "graal/graalEnv.hpp" +#include "graal/graalJavaAccess.hpp" +#include "graal/graalCodeInstaller.hpp" +#include "graal/graalVMExits.hpp" +#include "graal/graalVmIds.hpp" +#include "memory/oopFactory.hpp" +#include "oops/generateOopMap.hpp" + +methodOop getMethodFromHotSpotMethod(jobject hotspot_method) { + return getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method)); +} + +methodOop getMethodFromHotSpotMethod(oop hotspot_method) { + return (methodOop)HotSpotMethodResolved::javaMirror(hotspot_method); +} + +// public byte[] RiMethod_code(HotSpotResolvedMethod method); +JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1code(JNIEnv *env, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_code"); + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + int code_size = method->code_size(); + jbyteArray result = env->NewByteArray(code_size); + env->SetByteArrayRegion(result, 0, code_size, (const jbyte *) method->code_base()); + return result; +} + +// public String RiMethod_signature(HotSpotResolvedMethod method); +JNIEXPORT jstring JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1signature(JNIEnv *env, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_signature"); + VM_ENTRY_MARK + methodOop method = getMethodFromHotSpotMethod(hotspot_method); + assert(method != NULL && method->signature() != NULL, "signature required"); + return VmIds::toString(method->signature(), THREAD); +} + +// public RiExceptionHandler[] RiMethod_exceptionHandlers(long vmId); +JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_exceptionHandlers"); + VM_ENTRY_MARK + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + typeArrayHandle handlers = method->exception_table(); + int handler_count = handlers.is_null() ? 0 : handlers->length() / 4; + + instanceKlass::cast(HotSpotExceptionHandler::klass())->initialize(CHECK_NULL); + objArrayHandle array = oopFactory::new_objArray(SystemDictionary::RiExceptionHandler_klass(), handler_count, CHECK_NULL); + + for (int i = 0; i < handler_count; i++) { + // exception handlers are stored as four integers: start bci, end bci, handler bci, catch class constant pool index + int base = i * 4; + Handle entry = instanceKlass::cast(HotSpotExceptionHandler::klass())->allocate_instance(CHECK_NULL); + HotSpotExceptionHandler::set_startBci(entry, handlers->int_at(base + 0)); + HotSpotExceptionHandler::set_endBci(entry, handlers->int_at(base + 1)); + HotSpotExceptionHandler::set_handlerBci(entry, handlers->int_at(base + 2)); + int catch_class_index = handlers->int_at(base + 3); + HotSpotExceptionHandler::set_catchClassIndex(entry, catch_class_index); + + if (catch_class_index == 0) { + HotSpotExceptionHandler::set_catchClass(entry, NULL); + } else { + constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants(); + KlassHandle loading_klass = method->method_holder(); + Handle catch_class = GraalCompiler::get_RiType(cp, catch_class_index, loading_klass, CHECK_NULL); + if (catch_class->klass() == HotSpotTypeResolved::klass() && java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(catch_class)) == SystemDictionary::Throwable_klass()) { + HotSpotExceptionHandler::set_catchClass(entry, NULL); + HotSpotExceptionHandler::set_catchClassIndex(entry, 0); + } else { + HotSpotExceptionHandler::set_catchClass(entry, catch_class()); + } + } + array->obj_at_put(i, entry()); + } + + return (jobjectArray) JNIHandles::make_local(array()); +} + +// public boolean RiMethod_hasBalancedMonitors(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1hasBalancedMonitors(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_hasBalancedMonitors"); + + VM_ENTRY_MARK; + + // Analyze the method to see if monitors are used properly. + methodHandle method(THREAD, getMethodFromHotSpotMethod(hotspot_method)); + assert(method->has_monitor_bytecodes(), "should have checked this"); + + // Check to see if a previous compilation computed the monitor-matching analysis. + if (method->guaranteed_monitor_matching()) { + return true; + } + + { + EXCEPTION_MARK; + ResourceMark rm(THREAD); + GeneratePairingInfo gpi(method); + gpi.compute_map(CATCH); + if (!gpi.monitor_safe()) { + return false; + } + method->set_guaranteed_monitor_matching(); + } + return true; +} + +// public RiMethod getRiMethod(java.lang.reflect.Method reflectionMethod); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getRiMethod(JNIEnv *, jobject, jobject reflection_method_handle) { + TRACE_graal_3("CompilerToVM::getRiMethod"); + VM_ENTRY_MARK; + oop reflection_method = JNIHandles::resolve(reflection_method_handle); + oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); + int slot = java_lang_reflect_Method::slot(reflection_method); + klassOop holder = java_lang_Class::as_klassOop(reflection_holder); + methodOop method = instanceKlass::cast(holder)->method_with_idnum(slot); + Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); +} + +// public boolean RiMethod_uniqueConcreteMethod(long vmId); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_uniqueConcreteMethod"); + + VM_ENTRY_MARK; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + KlassHandle holder = method->method_holder(); + if (holder->is_interface()) { + // Cannot trust interfaces. Because of: + // interface I { void foo(); } + // class A { public void foo() {} } + // class B extends A implements I { } + // class C extends B { public void foo() { } } + // class D extends B { } + // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). + return false; + } + methodHandle unique_concrete; + { + ResourceMark rm; + MutexLocker locker(Compile_lock); + unique_concrete = Dependencies::find_unique_concrete_method(holder(), method()); + } + if (unique_concrete.is_null()) { + return NULL; + } else { + Handle method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete, CHECK_NULL); + return JNIHandles::make_local(THREAD, method_resolved()); + } +} + +// public native int RiMethod_invocationCount(long vmId); +JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1invocationCount(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_invocationCount"); + return getMethodFromHotSpotMethod(hotspot_method)->invocation_count(); +} + +// public native int RiMethod_exceptionProbability(long vmId, int bci); +JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { + TRACE_graal_3("CompilerToVM::RiMethod_exceptionProbability"); + VM_ENTRY_MARK; + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); + if (method_data == NULL || !method_data->is_mature()) { + return -1; + } + ProfileData* data = method_data->bci_to_data(bci); + if (data == NULL) { + return 0; + } + uint trap = Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; + if (trap > 0) { + return 100; + } else { + return trap; + } +} + +// ------------------------------------------------------------------ +// Adjust a CounterData count to be commensurate with +// interpreter_invocation_count. If the MDO exists for +// only 25% of the time the method exists, then the +// counts in the MDO should be scaled by 4X, so that +// they can be usefully and stably compared against the +// invocation counts in methods. +int scale_count(methodDataOop method_data, int count) { + if (count > 0) { + int counter_life; + int method_life = method_data->method()->interpreter_invocation_count(); + int current_mileage = methodDataOopDesc::mileage_of(method_data->method()); + int creation_mileage = method_data->creation_mileage(); + counter_life = current_mileage - creation_mileage; + + // counter_life due to backedge_counter could be > method_life + if (counter_life > method_life) + counter_life = method_life; + if (0 < counter_life && counter_life <= method_life) { + count = (int)((double)count * method_life / counter_life + 0.5); + count = (count > 0) ? count : 1; + } + } + return count; +} + +// public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2typeProfile(JNIEnv *, jobject, jobject hotspot_method, jint bci) { + TRACE_graal_3("CompilerToVM::RiMethod_typeProfile"); + VM_ENTRY_MARK; + Handle obj; + + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); + if (method_data == NULL || !method_data->is_mature()) { + return NULL; + } + ResourceMark rm; + ProfileData* data = method_data->bci_to_data(bci); + if (data != NULL && data->is_ReceiverTypeData()) { + ReceiverTypeData* recv = data->as_ReceiverTypeData(); + GrowableArray receivers; + GrowableArray counts; + // determine morphism + uint total_count = 0; + for (uint i = 0; i < recv->row_limit(); i++) { + klassOop receiver = recv->receiver(i); + if (receiver == NULL) continue; + uint count = recv->receiver_count(i); + total_count += count; + receivers.append(receiver); + counts.append(count); + } + + instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL); + obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL); + assert(obj() != NULL, "must succeed in allocating instance"); + + int count = MAX2(total_count, recv->count()); + RiTypeProfile::set_count(obj, scale_count(method_data(), count)); + RiTypeProfile::set_morphism(obj, receivers.length()); + + if (receivers.length() > 0) { + typeArrayHandle probabilities = oopFactory::new_typeArray(T_FLOAT, receivers.length(), CHECK_NULL); + objArrayHandle types = oopFactory::new_objArray(SystemDictionary::RiType_klass(), receivers.length(), CHECK_NULL); + for (int i = 0; i < receivers.length(); i++) { + KlassHandle receiver = receivers.at(i); + + float prob = counts.at(i) / (float) total_count; + Handle type = GraalCompiler::get_RiType(receiver, CHECK_NULL); + + probabilities->float_at_put(i, prob); + types->obj_at_put(i, type()); + + } + + RiTypeProfile::set_probabilities(obj, probabilities()); + RiTypeProfile::set_types(obj, types()); + } else { + RiTypeProfile::set_probabilities(obj, NULL); + RiTypeProfile::set_types(obj, NULL); + } + } + return JNIHandles::make_local(obj()); +} + +JNIEXPORT jdouble JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2branchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { + TRACE_graal_3("CompilerToVM::RiMethod_typeProfile"); + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); + + if (method_data == NULL || !method_data->is_mature()) return -1; + method_data->bci_to_data(bci); + + ProfileData* data = method_data->bci_to_data(bci); + if (data == NULL || !data->is_JumpData()) return -1; + + // get taken and not taken values + int taken = data->as_JumpData()->taken(); + int not_taken = 0; + if (data->is_BranchData()) { + not_taken = data->as_BranchData()->not_taken(); + } + + // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. + // We also check that individual counters are positive first, otherwise the sum can become positive. + if (taken < 0 || not_taken < 0 || taken + not_taken < 40) return -1; + + // Pin probability to sane limits + if (taken == 0) + return 0; + else if (not_taken == 0) + return 1; + else { // Compute probability of true path + return (jdouble)(taken) / (taken + not_taken); + } +} + +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_2switchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { + TRACE_graal_3("CompilerToVM::RiMethod_typeProfile"); + VM_ENTRY_MARK; + ResourceMark rm; + methodHandle method = getMethodFromHotSpotMethod(hotspot_method); + methodDataHandle method_data = method->method_data(); + + if (method_data == NULL || !method_data->is_mature()) return NULL; + + ProfileData* data = method_data->bci_to_data(bci); + if (data == NULL || !data->is_MultiBranchData()) return NULL; + + MultiBranchData* branch_data = data->as_MultiBranchData(); + + long sum = 0; + int cases = branch_data->number_of_cases(); + GrowableArray* counts = new GrowableArray(cases + 1); + + for (int i = 0; i < cases; i++) { + uint value = branch_data->count_at(i); + sum += value; + counts->append(value); + } + uint value = branch_data->default_count(); + sum += value; + counts->append(value); + + // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. + // We also check that individual counters are positive first, otherwise the sum can become positive. + if (sum < 10 * (cases + 3)) return NULL; + + typeArrayOop probability = oopFactory::new_typeArray(T_DOUBLE, cases + 1, CHECK_NULL); + for (int i = 0; i < cases + 1; i++) { + probability->double_at_put(i, counts->at(i) / (double) sum); + } + return JNIHandles::make_local(probability); +} + +// public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); +JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiMethod_1hasCompiledCode(JNIEnv *, jobject, jobject hotspot_method) { + TRACE_graal_3("CompilerToVM::RiMethod_hasCompiledCode"); + return getMethodFromHotSpotMethod(hotspot_method)->has_compiled_code(); +} + +// public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { + TRACE_graal_3("CompilerToVM::RiSignature_lookupType"); + VM_ENTRY_MARK; + ResourceMark rm; + + Symbol* nameSymbol = VmIds::toSymbol(jname); + Handle name = JNIHandles::resolve(jname); + + oop result; + if (nameSymbol == vmSymbols::int_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_INT, THREAD); + } else if (nameSymbol == vmSymbols::long_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_LONG, THREAD); + } else if (nameSymbol == vmSymbols::bool_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_BOOLEAN, THREAD); + } else if (nameSymbol == vmSymbols::char_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_CHAR, THREAD); + } else if (nameSymbol == vmSymbols::short_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_SHORT, THREAD); + } else if (nameSymbol == vmSymbols::byte_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_BYTE, THREAD); + } else if (nameSymbol == vmSymbols::double_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_DOUBLE, THREAD); + } else if (nameSymbol == vmSymbols::float_signature()) { + result = VMToCompiler::createRiTypePrimitive((int) T_FLOAT, THREAD); + } else { + klassOop resolved_type = NULL; + // if the name isn't in the symbol table then the class isn't loaded anyway... + if (nameSymbol != NULL) { + Handle classloader; + Handle protectionDomain; + if (JNIHandles::resolve(accessingClass) != NULL) { + classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader(); + protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain(); + } + resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + resolved_type = NULL; + } + } + if (resolved_type != NULL) { + Handle type = GraalCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); + result = type(); + } else { + Handle type = VMToCompiler::createRiTypeUnresolved(name, THREAD); + result = type(); + } + } + + return JNIHandles::make_local(THREAD, result); +} + +// public Object RiConstantPool_lookupConstant(HotSpotTypeResolved type, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jobject type, jint index) { + TRACE_graal_3("CompilerToVM::RiConstantPool_lookupConstant"); + VM_ENTRY_MARK; + + constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); + + oop result = NULL; + constantTag tag = cp->tag_at(index); + if (tag.is_int()) { + result = VMToCompiler::createCiConstant(CiKind::Int(), cp->int_at(index), CHECK_0); + } else if (tag.is_long()) { + result = VMToCompiler::createCiConstant(CiKind::Long(), cp->long_at(index), CHECK_0); + } else if (tag.is_float()) { + result = VMToCompiler::createCiConstantFloat(cp->float_at(index), CHECK_0); + } else if (tag.is_double()) { + result = VMToCompiler::createCiConstantDouble(cp->double_at(index), CHECK_0); + } else if (tag.is_string() || tag.is_unresolved_string()) { + oop string = NULL; + if (cp->is_pseudo_string_at(index)) { + string = cp->pseudo_string_at(index); + } else { + string = cp->string_at(index, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + // TODO: Gracefully exit compilation. + fatal("out of memory during compilation!"); + return NULL; + } + } + result = VMToCompiler::createCiConstantObject(string, CHECK_0); + } else if (tag.is_klass() || tag.is_unresolved_klass()) { + Handle type = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); + result = type(); + } else if (tag.is_object()) { + oop obj = cp->object_at(index); + assert(obj->is_instance(), "must be an instance"); + result = VMToCompiler::createCiConstantObject(obj, CHECK_NULL); + } else { + ShouldNotReachHere(); + } + + return JNIHandles::make_local(THREAD, result); +} + +// public RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode) { + TRACE_graal_3("CompilerToVM::RiConstantPool_lookupMethod"); + VM_ENTRY_MARK; + index = GraalCompiler::to_cp_index_u2(index); + constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); + instanceKlassHandle pool_holder(cp->pool_holder()); + + Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF); + methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); + if (!method.is_null()) { + Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); + } else { + // Get the method's name and signature. + Handle name = VmIds::toString(cp->name_ref_at(index), CHECK_NULL); + Handle signature = VmIds::toString(cp->signature_ref_at(index), CHECK_NULL); + int holder_index = cp->klass_ref_index_at(index); + Handle type = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, VMToCompiler::createRiMethodUnresolved(name, signature, type, THREAD)); + } +} + +// public RiType RiConstantPool_lookupType(long vmId, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupType(JNIEnv *env, jobject, jobject type, jint index) { + TRACE_graal_3("CompilerToVM::RiConstantPool_lookupType"); + VM_ENTRY_MARK; + + constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); + Handle result = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); + return JNIHandles::make_local(THREAD, result()); +} + +// public void RiConstantPool_loadReferencedType(long vmId, int cpi); +JNIEXPORT void JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1loadReferencedType(JNIEnv *env, jobject, jobject type, jint index, jbyte op) { + TRACE_graal_3("CompilerToVM::RiConstantPool_loadReferencedType"); + VM_ENTRY_MARK; + + constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); + int byteCode = (op & 0xFF); + if (byteCode != Bytecodes::_checkcast && byteCode != Bytecodes::_instanceof && byteCode != Bytecodes::_new && byteCode != Bytecodes::_anewarray && byteCode != Bytecodes::_multianewarray) { + index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); + } + constantTag tag = cp->tag_at(index); + if (tag.is_field_or_method()) { + index = cp->uncached_klass_ref_index_at(index); + tag = cp->tag_at(index); + } + + if (tag.is_unresolved_klass() || tag.is_klass()) { + klassOop klass = cp->klass_at(index, CHECK); + if (klass->klass_part()->oop_is_instance()) { + instanceKlass::cast(klass)->initialize(CHECK); + } + } +} + +// public RiField RiConstantPool_lookupField(long vmId, int cpi); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode) { + TRACE_graal_3("CompilerToVM::RiConstantPool_lookupField"); + VM_ENTRY_MARK; + ResourceMark rm; + + index = GraalCompiler::to_cp_index_u2(index); + constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(constantPoolHolder)))->constants(); + + int nt_index = cp->name_and_type_ref_index_at(index); + int sig_index = cp->signature_ref_index_at(nt_index); + Symbol* signature = cp->symbol_at(sig_index); + int name_index = cp->name_ref_index_at(nt_index); + Symbol* name = cp->symbol_at(name_index); + int holder_index = cp->klass_ref_index_at(index); + Handle holder = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); + instanceKlassHandle holder_klass; + + Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF); + int offset = -1; + AccessFlags flags; + BasicType basic_type; + if (holder->klass() == SystemDictionary::HotSpotTypeResolved_klass()) { + FieldAccessInfo result; + LinkResolver::resolve_field(result, cp, index, + Bytecodes::java_code(code), + true, false, Thread::current()); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } else { + offset = result.field_offset(); + flags = result.access_flags(); + holder_klass = result.klass()->as_klassOop(); + basic_type = result.field_type(); + holder = GraalCompiler::get_RiType(holder_klass, CHECK_NULL); + } + } + + Handle type = GraalCompiler::get_RiTypeFromSignature(cp, sig_index, cp->pool_holder(), CHECK_NULL); + Handle field_handle = GraalCompiler::get_RiField(offset, flags.as_int(), name, holder, type, code, THREAD); + + oop constant_object = NULL; + // Check to see if the field is constant. + if (!holder_klass.is_null() && holder_klass->is_initialized() && flags.is_final() && flags.is_static()) { + // This field just may be constant. The only cases where it will + // not be constant are: + // + // 1. The field holds a non-perm-space oop. The field is, strictly + // speaking, constant but we cannot embed non-perm-space oops into + // generated code. For the time being we need to consider the + // field to be not constant. + // 2. The field is a *special* static&final field whose value + // may change. The three examples are java.lang.System.in, + // java.lang.System.out, and java.lang.System.err. + + bool ok = true; + assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); + if( holder_klass->as_klassOop() == SystemDictionary::System_klass() ) { + // Check offsets for case 2: System.in, System.out, or System.err + if( offset == java_lang_System::in_offset_in_bytes() || + offset == java_lang_System::out_offset_in_bytes() || + offset == java_lang_System::err_offset_in_bytes() ) { + ok = false; + } + } + + if (ok) { + Handle mirror = holder_klass->java_mirror(); + switch(basic_type) { + case T_OBJECT: + case T_ARRAY: + constant_object = VMToCompiler::createCiConstantObject(mirror->obj_field(offset), CHECK_0); + break; + case T_DOUBLE: + constant_object = VMToCompiler::createCiConstantDouble(mirror->double_field(offset), CHECK_0); + break; + case T_FLOAT: + constant_object = VMToCompiler::createCiConstantFloat(mirror->float_field(offset), CHECK_0); + break; + case T_LONG: + constant_object = VMToCompiler::createCiConstant(CiKind::Long(), mirror->long_field(offset), CHECK_0); + break; + case T_INT: + constant_object = VMToCompiler::createCiConstant(CiKind::Int(), mirror->int_field(offset), CHECK_0); + break; + case T_SHORT: + constant_object = VMToCompiler::createCiConstant(CiKind::Short(), mirror->short_field(offset), CHECK_0); + break; + case T_CHAR: + constant_object = VMToCompiler::createCiConstant(CiKind::Char(), mirror->char_field(offset), CHECK_0); + break; + case T_BYTE: + constant_object = VMToCompiler::createCiConstant(CiKind::Byte(), mirror->byte_field(offset), CHECK_0); + break; + case T_BOOLEAN: + constant_object = VMToCompiler::createCiConstant(CiKind::Boolean(), mirror->bool_field(offset), CHECK_0); + break; + default: + fatal("Unhandled constant"); + break; + } + } + } + if (constant_object != NULL) { + HotSpotField::set_constant(field_handle, constant_object); + } + return JNIHandles::make_local(THREAD, field_handle()); +} + +// public RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) { + TRACE_graal_3("CompilerToVM::RiType_resolveMethodImpl"); + VM_ENTRY_MARK; + + assert(JNIHandles::resolve(resolved_type) != NULL, ""); + klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type)); + Symbol* name_symbol = VmIds::toSymbol(name); + Symbol* signature_symbol = VmIds::toSymbol(signature); + methodHandle method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); + if (method == NULL) { + if (TraceGraal >= 3) { + ResourceMark rm; + tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->klass_part()->name()->as_C_string()); + } + return NULL; + } + Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); + return JNIHandles::make_local(THREAD, ret()); +} + +// public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); +JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) { + TRACE_graal_3("CompilerToVM::RiType_isSubtypeOf"); + oop other = JNIHandles::resolve(jother); + assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected"); + assert(JNIHandles::resolve(klass) != NULL, ""); + klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); + klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other)); + if (thisKlass->klass_part()->oop_is_instance_slow()) { + return instanceKlass::cast(thisKlass)->is_subtype_of(otherKlass); + } else if (thisKlass->klass_part()->oop_is_array()) { + return arrayKlass::cast(thisKlass)->is_subtype_of(otherKlass); + } else { + fatal("unexpected class type"); + return false; + } +} + +// public RiType RiType_componentType(HotSpotResolvedType klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1componentType(JNIEnv *, jobject, jobject klass) { + TRACE_graal_3("CompilerToVM::RiType_componentType"); + VM_ENTRY_MARK; + KlassHandle array_klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); + if(array_klass->oop_is_typeArray()) { + BasicType t = typeArrayKlass::cast(array_klass())->element_type(); + oop primitive_type = VMToCompiler::createRiTypePrimitive((int) t, CHECK_NULL); + return JNIHandles::make_local(primitive_type); + } + assert(array_klass->oop_is_objArray(), "just checking"); + klassOop element_type = objArrayKlass::cast(array_klass())->element_klass(); + assert(JNIHandles::resolve(klass) != NULL, ""); + return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, THREAD)()); +} + +// public RiType RiType_superType(HotSpotResolvedType klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1superType(JNIEnv *, jobject, jobject klass) { + TRACE_graal_3("CompilerToVM::RiType_superType"); + VM_ENTRY_MARK; + KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + klassOop k; + + if (klass_handle->oop_is_array()) { + k = SystemDictionary::Object_klass(); + } else { + guarantee(klass_handle->oop_is_instance(), "must be instance klass"); + k = klass_handle->super(); + } + + if (k != NULL) { + return JNIHandles::make_local(GraalCompiler::get_RiType(k, THREAD)()); + } else { + return NULL; + } +} + +// public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) { + TRACE_graal_3("CompilerToVM::RiType_uniqueConcreteSubtype"); + VM_ENTRY_MARK; + KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + Klass *up_cast = klass_handle->up_cast_abstract(); + if (up_cast->is_leaf_class()) { + return JNIHandles::make_local(GraalCompiler::get_RiType(up_cast, THREAD)()); + } + return NULL; +} + +// public bool RiType_isInitialized(HotSpotResolvedType klass); +JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1isInitialized(JNIEnv *, jobject, jobject hotspot_klass) { + TRACE_graal_3("CompilerToVM::RiType_isInitialized"); + klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(hotspot_klass)); + assert(klass != NULL, "method must not be called for primitive types"); + return instanceKlass::cast(klass)->is_initialized(); +} + +// public RiType RiType_arrayOf(HotSpotTypeResolved klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1arrayOf(JNIEnv *, jobject, jobject klass) { + TRACE_graal_3("CompilerToVM::RiType_arrayOf"); + VM_ENTRY_MARK; + + KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); + KlassHandle arr = klass_handle->array_klass(THREAD); + Handle name = VmIds::toString(arr->name(), CHECK_NULL); + assert(arr->oop_is_array(), ""); + return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(arr, name, THREAD)()); +} + +// public RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_RiType_1fields(JNIEnv *, jobject, jobject klass) { + TRACE_graal_3("CompilerToVM::RiType_fields"); + VM_ENTRY_MARK; + ResourceMark rm; + + instanceKlassHandle k = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); + class MyFieldClosure : public FieldClosure { + public: + instanceKlassHandle _holder; + Handle _resolved_type_holder; + GrowableArray _field_array; + + MyFieldClosure(instanceKlassHandle& holder, Handle resolved_type_holder) : _holder(holder), _resolved_type_holder(resolved_type_holder) { } + + virtual void do_field(fieldDescriptor* fd) { + if (!Thread::current()->has_pending_exception()) { + if (fd->field_holder() == _holder()) { + Handle type = GraalCompiler::get_RiTypeFromSignature(fd->constants(), fd->signature_index(), fd->field_holder(), Thread::current()); + Handle field = VMToCompiler::createRiField(_resolved_type_holder, VmIds::toString(fd->name(), Thread::current()), type, fd->offset(), fd->access_flags().as_int(), Thread::current()); + _field_array.append(field()); + } + } + } + }; + MyFieldClosure closure(k, JNIHandles::resolve(klass)); + k->do_nonstatic_fields(&closure); + objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::RiResolvedField_klass(), closure._field_array.length(), CHECK_NULL); + for (int i=0; iobj_at_put(i, closure._field_array.at(i)()); + } + return JNIHandles::make_local(field_array()); +} + +// public RiType getPrimitiveArrayType(CiKind kind); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) { + TRACE_graal_3("CompilerToVM::getPrimitiveArrayType"); + VM_ENTRY_MARK; + BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(kind)); + assert(type != T_OBJECT, "primitive type expecteds"); + Handle result = GraalCompiler::get_RiType(Universe::typeArrayKlassObj(type), CHECK_NULL); + return JNIHandles::make_local(THREAD, result()); +} + +// public long getMaxCallTargetOffset(CiRuntimeCall rtcall); +JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getMaxCallTargetOffset(JNIEnv *env, jobject, jobject rtcall) { + TRACE_graal_3("CompilerToVM::getMaxCallTargetOffset"); + VM_ENTRY_MARK; + oop call = JNIHandles::resolve(rtcall); + address target_addr = CodeInstaller::runtime_call_target_address(call); + if (target_addr != 0x0) { + int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); + int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); + return MAX2(ABS(off_low), ABS(off_high)); + } + return -1; +} + +// public RiType getType(Class javaClass); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getType(JNIEnv *env, jobject, jobject javaClass) { + TRACE_graal_3("CompilerToVM::getType"); + VM_ENTRY_MARK; + oop javaClassOop = JNIHandles::resolve(javaClass); + if (javaClassOop == NULL) { + fatal("argument to CompilerToVM.getType must not be NULL"); + return NULL; + } else if (java_lang_Class::is_primitive(javaClassOop)) { + BasicType basicType = java_lang_Class::primitive_type(javaClassOop); + return JNIHandles::make_local(THREAD, VMToCompiler::createRiTypePrimitive((int) basicType, THREAD)); + } else { + KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop); + Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL); + + Handle type = GraalCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); + return JNIHandles::make_local(THREAD, type()); + } +} + + +// helpers used to set fields in the HotSpotVMConfig object +jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { + jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); + if (id == NULL) { + fatal(err_msg("field not found: %s (%s)", name, sig)); + } + return id; +} + +void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } +void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } +void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } +void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } +void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } + +jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } +jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } +jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } +jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } +jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } + + +BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; +int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); + +// public HotSpotVMConfig getConfiguration(); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_getConfiguration(JNIEnv *env, jobject) { + jclass klass = env->FindClass("com/oracle/max/graal/hotspot/HotSpotVMConfig"); + assert(klass != NULL, "HotSpot vm config class not found"); + jobject config = env->AllocObject(klass); +#ifdef _WIN64 + set_boolean(env, config, "windowsOs", true); +#else + set_boolean(env, config, "windowsOs", false); +#endif + set_boolean(env, config, "verifyPointers", VerifyOops); + set_boolean(env, config, "useFastLocking", UseFastLocking); + set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); + set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); + set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); + set_int(env, config, "vmPageSize", os::vm_page_size()); + set_int(env, config, "stackShadowPages", StackShadowPages); + set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); + set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); + set_int(env, config, "klassStateOffset", instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)); + set_int(env, config, "klassStateFullyInitialized", (int)instanceKlass::fully_initialized); + set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); + set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); + set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); + set_int(env, config, "instanceHeaderPrototypeOffset", Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); + set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); + set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); + set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset())); + set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes()); + + set_long(env, config, "debugStub", VmIds::addStub((address)warning)); + set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); + set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id))); + set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::fast_new_instance_init_check_id))); + set_long(env, config, "unresolvedNewInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id))); + set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); + set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id))); + set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id))); + set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id))); + set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id))); + set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub())); + set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); + set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id))); + set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); + set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); + set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id))); + set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id))); + set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorenter_id))); + set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id))); + set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); + set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); + set_int(env, config, "klassModifierFlagsOffset", Klass::modifier_flags_offset_in_bytes() + sizeof(oopDesc)); + set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes()); + set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); + + set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset()); + + BarrierSet* bs = Universe::heap()->barrier_set(); + switch (bs->kind()) { + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: { + jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; + assert(base != 0, "unexpected byte_map_base"); + set_long(env, config, "cardtableStartAddress", base); + set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift); + break; + } + case BarrierSet::ModRef: + case BarrierSet::Other: + set_long(env, config, "cardtableStartAddress", 0); + set_int(env, config, "cardtableShift", 0); + // No post barriers + break; +#ifndef SERIALGC + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: +#endif // SERIALGC + default: + ShouldNotReachHere(); + break; + } + + jintArray arrayOffsets = env->NewIntArray(basicTypeCount); + for (int i=0; iSetIntArrayRegion(arrayOffsets, i, 1, &offset); + } + set_int_array(env, config, "arrayOffsets", arrayOffsets); + set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)); + return config; +} + +// public HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); +JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod, jboolean install_code) { + VM_ENTRY_MARK; + ResourceMark rm; + HandleMark hm; + Handle targetMethodHandle = JNIHandles::resolve(targetMethod); + nmethod* nm = NULL; + Arena arena; + ciEnv env(&arena); + CodeInstaller installer(targetMethodHandle, nm, install_code != 0); + + // if install_code is true then we installed the code into the given method, no need to return an RiCompiledMethod + if (!install_code && nm != NULL) { + instanceKlass::cast(HotSpotCompiledMethod::klass())->initialize(CHECK_NULL); + Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL); + assert(obj() != NULL, "must succeed in allocating instance"); + HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm); + HotSpotCompiledMethod::set_method(obj, HotSpotTargetMethod::method(targetMethod)); + nm->set_graal_compiled_method(obj()); + return JNIHandles::make_local(obj()); + } else { + return NULL; + } +} + +// public long installStub(HotSpotTargetMethod targetMethod, String name); +JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { + VM_ENTRY_MARK; + ResourceMark rm; + HandleMark hm; + Handle targetMethodHandle = JNIHandles::resolve(targetMethod); + jlong id; + Arena arena; + ciEnv env(&arena); + CodeInstaller installer(targetMethodHandle, id); + return id; +} + + + +#define CC (char*) /*cast a literal from (const char*)*/ +#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &(Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_##f)) + +#define PROXY "J" +#define TYPE "Lcom/oracle/max/cri/ri/RiType;" +#define RESOLVED_TYPE "Lcom/oracle/max/graal/hotspot/ri/HotSpotTypeResolved;" +#define METHOD "Lcom/oracle/max/cri/ri/RiMethod;" +#define RESOLVED_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethodResolved;" +#define REFLECT_METHOD "Ljava/lang/reflect/Method;" +#define TYPE_PROFILE "Lcom/oracle/max/cri/ri/RiTypeProfile;" +#define SIGNATURE "Lcom/oracle/max/cri/ri/RiSignature;" +#define FIELD "Lcom/oracle/max/cri/ri/RiField;" +#define RESOLVED_FIELD "Lcom/oracle/max/cri/ri/RiResolvedField;" +#define CONSTANT_POOL "Lcom/oracle/max/cri/ri/RiConstantPool;" +#define EXCEPTION_HANDLERS "[Lcom/oracle/max/cri/ri/RiExceptionHandler;" +#define TARGET_METHOD "Lcom/oracle/max/graal/hotspot/HotSpotTargetMethod;" +#define CONFIG "Lcom/oracle/max/graal/hotspot/HotSpotVMConfig;" +#define HS_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethod;" +#define HS_COMP_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotCompiledMethod;" +#define CI_CONSTANT "Lcom/oracle/max/cri/ci/CiConstant;" +#define CI_KIND "Lcom/oracle/max/cri/ci/CiKind;" +#define CI_RUNTIME_CALL "Lcom/oracle/max/cri/ci/CiRuntimeCall;" +#define STRING "Ljava/lang/String;" +#define OBJECT "Ljava/lang/Object;" +#define CLASS "Ljava/lang/Class;" + +JNINativeMethod CompilerToVM_methods[] = { + {CC"RiMethod_code", CC"("RESOLVED_METHOD")[B", FN_PTR(RiMethod_1code)}, + {CC"RiMethod_signature", CC"("RESOLVED_METHOD")"STRING, FN_PTR(RiMethod_1signature)}, + {CC"RiMethod_exceptionHandlers", CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS, FN_PTR(RiMethod_1exceptionHandlers)}, + {CC"RiMethod_hasBalancedMonitors", CC"("RESOLVED_METHOD")Z", FN_PTR(RiMethod_1hasBalancedMonitors)}, + {CC"RiMethod_uniqueConcreteMethod", CC"("RESOLVED_METHOD")"METHOD, FN_PTR(RiMethod_1uniqueConcreteMethod)}, + {CC"getRiMethod", CC"("REFLECT_METHOD")"METHOD, FN_PTR(getRiMethod)}, + {CC"RiMethod_typeProfile", CC"("RESOLVED_METHOD"I)"TYPE_PROFILE, FN_PTR(RiMethod_2typeProfile)}, + {CC"RiMethod_branchProbability", CC"("RESOLVED_METHOD"I)D", FN_PTR(RiMethod_2branchProbability)}, + {CC"RiMethod_switchProbability", CC"("RESOLVED_METHOD"I)[D", FN_PTR(RiMethod_2switchProbability)}, + {CC"RiMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(RiMethod_1invocationCount)}, + {CC"RiMethod_exceptionProbability", CC"("RESOLVED_METHOD"I)I", FN_PTR(RiMethod_2exceptionProbability)}, + {CC"RiMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(RiMethod_1hasCompiledCode)}, + {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(RiSignature_1lookupType)}, + {CC"RiConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(RiConstantPool_1lookupConstant)}, + {CC"RiConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(RiConstantPool_1lookupMethod)}, + {CC"RiConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(RiConstantPool_1lookupType)}, + {CC"RiConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V", FN_PTR(RiConstantPool_1loadReferencedType)}, + {CC"RiConstantPool_lookupField", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(RiConstantPool_1lookupField)}, + {CC"RiType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(RiType_3resolveMethodImpl)}, + {CC"RiType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(RiType_2isSubtypeOf)}, + {CC"RiType_componentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1componentType)}, + {CC"RiType_uniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1uniqueConcreteSubtype)}, + {CC"RiType_superType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1superType)}, + {CC"RiType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(RiType_1arrayOf)}, + {CC"RiType_fields", CC"("RESOLVED_TYPE")["RESOLVED_FIELD, FN_PTR(RiType_1fields)}, + {CC"RiType_isInitialized", CC"("RESOLVED_TYPE")Z", FN_PTR(RiType_1isInitialized)}, + {CC"getPrimitiveArrayType", CC"("CI_KIND")"TYPE, FN_PTR(getPrimitiveArrayType)}, + {CC"getMaxCallTargetOffset", CC"("CI_RUNTIME_CALL")J", FN_PTR(getMaxCallTargetOffset)}, + {CC"getType", CC"("CLASS")"TYPE, FN_PTR(getType)}, + {CC"getConfiguration", CC"()"CONFIG, FN_PTR(getConfiguration)}, + {CC"installMethod", CC"("TARGET_METHOD"Z)"HS_COMP_METHOD, FN_PTR(installMethod)}, + {CC"installStub", CC"("TARGET_METHOD")"PROXY, FN_PTR(installStub)} +}; + +int CompilerToVM_methods_count() { + return sizeof(CompilerToVM_methods) / sizeof(JNINativeMethod); +} + diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Wed Jan 04 10:49:09 2012 -0800 +++ b/src/share/vm/graal/graalJavaAccess.hpp Wed Jan 04 20:59:11 2012 +0100 @@ -80,9 +80,6 @@ long_field(HotSpotCompiledMethod, nmethod) \ oop_field(HotSpotCompiledMethod, method, "Lcom/oracle/max/cri/ri/RiResolvedMethod;") \ end_class \ - start_class(HotSpotProxy) \ - static_oop_field(HotSpotProxy, DUMMY_CONSTANT_OBJ, "Ljava/lang/Long;") \ - end_class \ start_class(HotSpotTargetMethod) \ oop_field(HotSpotTargetMethod, targetMethod, "Lcom/oracle/max/cri/ci/CiTargetMethod;") \ oop_field(HotSpotTargetMethod, method, "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethodResolved;") \ diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalVMEntries.cpp --- a/src/share/vm/graal/graalVMEntries.cpp Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1043 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "runtime/fieldDescriptor.hpp" -#include "c1/c1_Runtime1.hpp" -#include "ci/ciMethodData.hpp" -#include "compiler/compileBroker.hpp" -#include "graal/graalVMEntries.hpp" -#include "graal/graalCompiler.hpp" -#include "graal/graalEnv.hpp" -#include "graal/graalJavaAccess.hpp" -#include "graal/graalCodeInstaller.hpp" -#include "graal/graalVMExits.hpp" -#include "graal/graalVmIds.hpp" -#include "memory/oopFactory.hpp" -#include "oops/generateOopMap.hpp" - -methodOop getMethodFromHotSpotMethod(jobject hotspot_method) { - return getMethodFromHotSpotMethod(JNIHandles::resolve(hotspot_method)); -} - -methodOop getMethodFromHotSpotMethod(oop hotspot_method) { - return (methodOop)HotSpotMethodResolved::javaMirror(hotspot_method); -} - -// public byte[] RiMethod_code(HotSpotResolvedMethod method); -JNIEXPORT jbyteArray JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1code(JNIEnv *env, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_code"); - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - int code_size = method->code_size(); - jbyteArray result = env->NewByteArray(code_size); - env->SetByteArrayRegion(result, 0, code_size, (const jbyte *) method->code_base()); - return result; -} - -// public String RiMethod_signature(HotSpotResolvedMethod method); -JNIEXPORT jstring JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1signature(JNIEnv *env, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_signature"); - VM_ENTRY_MARK - methodOop method = getMethodFromHotSpotMethod(hotspot_method); - assert(method != NULL && method->signature() != NULL, "signature required"); - return VmIds::toString(method->signature(), THREAD); -} - -// public RiExceptionHandler[] RiMethod_exceptionHandlers(long vmId); -JNIEXPORT jobjectArray JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1exceptionHandlers(JNIEnv *, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_exceptionHandlers"); - VM_ENTRY_MARK - ResourceMark rm; - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - typeArrayHandle handlers = method->exception_table(); - int handler_count = handlers.is_null() ? 0 : handlers->length() / 4; - - instanceKlass::cast(HotSpotExceptionHandler::klass())->initialize(CHECK_NULL); - objArrayHandle array = oopFactory::new_objArray(SystemDictionary::RiExceptionHandler_klass(), handler_count, CHECK_NULL); - - for (int i = 0; i < handler_count; i++) { - // exception handlers are stored as four integers: start bci, end bci, handler bci, catch class constant pool index - int base = i * 4; - Handle entry = instanceKlass::cast(HotSpotExceptionHandler::klass())->allocate_instance(CHECK_NULL); - HotSpotExceptionHandler::set_startBci(entry, handlers->int_at(base + 0)); - HotSpotExceptionHandler::set_endBci(entry, handlers->int_at(base + 1)); - HotSpotExceptionHandler::set_handlerBci(entry, handlers->int_at(base + 2)); - int catch_class_index = handlers->int_at(base + 3); - HotSpotExceptionHandler::set_catchClassIndex(entry, catch_class_index); - - if (catch_class_index == 0) { - HotSpotExceptionHandler::set_catchClass(entry, NULL); - } else { - constantPoolOop cp = instanceKlass::cast(method->method_holder())->constants(); - KlassHandle loading_klass = method->method_holder(); - Handle catch_class = GraalCompiler::get_RiType(cp, catch_class_index, loading_klass, CHECK_NULL); - if (catch_class->klass() == HotSpotTypeResolved::klass() && java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(catch_class)) == SystemDictionary::Throwable_klass()) { - HotSpotExceptionHandler::set_catchClass(entry, NULL); - HotSpotExceptionHandler::set_catchClassIndex(entry, 0); - } else { - HotSpotExceptionHandler::set_catchClass(entry, catch_class()); - } - } - array->obj_at_put(i, entry()); - } - - return (jobjectArray) JNIHandles::make_local(array()); -} - -// public boolean RiMethod_hasBalancedMonitors(long vmId); -JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1hasBalancedMonitors(JNIEnv *, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_hasBalancedMonitors"); - - VM_ENTRY_MARK; - - // Analyze the method to see if monitors are used properly. - methodHandle method(THREAD, getMethodFromHotSpotMethod(hotspot_method)); - assert(method->has_monitor_bytecodes(), "should have checked this"); - - // Check to see if a previous compilation computed the monitor-matching analysis. - if (method->guaranteed_monitor_matching()) { - return true; - } - - { - EXCEPTION_MARK; - ResourceMark rm(THREAD); - GeneratePairingInfo gpi(method); - gpi.compute_map(CATCH); - if (!gpi.monitor_safe()) { - return false; - } - method->set_guaranteed_monitor_matching(); - } - return true; -} - -// public RiMethod getRiMethod(java.lang.reflect.Method reflectionMethod); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_getRiMethod(JNIEnv *, jobject, jobject reflection_method_handle) { - TRACE_graal_3("VMEntries::getRiMethod"); - VM_ENTRY_MARK; - oop reflection_method = JNIHandles::resolve(reflection_method_handle); - oop reflection_holder = java_lang_reflect_Method::clazz(reflection_method); - int slot = java_lang_reflect_Method::slot(reflection_method); - klassOop holder = java_lang_Class::as_klassOop(reflection_holder); - methodOop method = instanceKlass::cast(holder)->method_with_idnum(slot); - Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret()); -} - -// public boolean RiMethod_uniqueConcreteMethod(long vmId); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1uniqueConcreteMethod(JNIEnv *, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_uniqueConcreteMethod"); - - VM_ENTRY_MARK; - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - KlassHandle holder = method->method_holder(); - if (holder->is_interface()) { - // Cannot trust interfaces. Because of: - // interface I { void foo(); } - // class A { public void foo() {} } - // class B extends A implements I { } - // class C extends B { public void foo() { } } - // class D extends B { } - // Would lead to identify C.foo() as the unique concrete method for I.foo() without seeing A.foo(). - return false; - } - methodHandle unique_concrete; - { - ResourceMark rm; - MutexLocker locker(Compile_lock); - unique_concrete = Dependencies::find_unique_concrete_method(holder(), method()); - } - if (unique_concrete.is_null()) { - return NULL; - } else { - Handle method_resolved = GraalCompiler::createHotSpotMethodResolved(unique_concrete, CHECK_NULL); - return JNIHandles::make_local(THREAD, method_resolved()); - } -} - -// public native int RiMethod_invocationCount(long vmId); -JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1invocationCount(JNIEnv *, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_invocationCount"); - return getMethodFromHotSpotMethod(hotspot_method)->invocation_count(); -} - -// public native int RiMethod_exceptionProbability(long vmId, int bci); -JNIEXPORT jint JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2exceptionProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { - TRACE_graal_3("VMEntries::RiMethod_exceptionProbability"); - VM_ENTRY_MARK; - ResourceMark rm; - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - methodDataHandle method_data = method->method_data(); - if (method_data == NULL || !method_data->is_mature()) { - return -1; - } - ProfileData* data = method_data->bci_to_data(bci); - if (data == NULL) { - return 0; - } - uint trap = Deoptimization::trap_state_is_recompiled(data->trap_state())? 1: 0; - if (trap > 0) { - return 100; - } else { - return trap; - } -} - -// ------------------------------------------------------------------ -// Adjust a CounterData count to be commensurate with -// interpreter_invocation_count. If the MDO exists for -// only 25% of the time the method exists, then the -// counts in the MDO should be scaled by 4X, so that -// they can be usefully and stably compared against the -// invocation counts in methods. -int scale_count(methodDataOop method_data, int count) { - if (count > 0) { - int counter_life; - int method_life = method_data->method()->interpreter_invocation_count(); - int current_mileage = methodDataOopDesc::mileage_of(method_data->method()); - int creation_mileage = method_data->creation_mileage(); - counter_life = current_mileage - creation_mileage; - - // counter_life due to backedge_counter could be > method_life - if (counter_life > method_life) - counter_life = method_life; - if (0 < counter_life && counter_life <= method_life) { - count = (int)((double)count * method_life / counter_life + 0.5); - count = (count > 0) ? count : 1; - } - } - return count; -} - -// public native RiTypeProfile RiMethod_typeProfile(long vmId, int bci); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2typeProfile(JNIEnv *, jobject, jobject hotspot_method, jint bci) { - TRACE_graal_3("VMEntries::RiMethod_typeProfile"); - VM_ENTRY_MARK; - Handle obj; - - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - methodDataHandle method_data = method->method_data(); - if (method_data == NULL || !method_data->is_mature()) { - return NULL; - } - ResourceMark rm; - ProfileData* data = method_data->bci_to_data(bci); - if (data != NULL && data->is_ReceiverTypeData()) { - ReceiverTypeData* recv = data->as_ReceiverTypeData(); - GrowableArray receivers; - GrowableArray counts; - // determine morphism - uint total_count = 0; - for (uint i = 0; i < recv->row_limit(); i++) { - klassOop receiver = recv->receiver(i); - if (receiver == NULL) continue; - uint count = recv->receiver_count(i); - total_count += count; - receivers.append(receiver); - counts.append(count); - } - - instanceKlass::cast(RiTypeProfile::klass())->initialize(CHECK_NULL); - obj = instanceKlass::cast(RiTypeProfile::klass())->allocate_instance(CHECK_NULL); - assert(obj() != NULL, "must succeed in allocating instance"); - - int count = MAX2(total_count, recv->count()); - RiTypeProfile::set_count(obj, scale_count(method_data(), count)); - RiTypeProfile::set_morphism(obj, receivers.length()); - - if (receivers.length() > 0) { - typeArrayHandle probabilities = oopFactory::new_typeArray(T_FLOAT, receivers.length(), CHECK_NULL); - objArrayHandle types = oopFactory::new_objArray(SystemDictionary::RiType_klass(), receivers.length(), CHECK_NULL); - for (int i = 0; i < receivers.length(); i++) { - KlassHandle receiver = receivers.at(i); - - float prob = counts.at(i) / (float) total_count; - Handle type = GraalCompiler::get_RiType(receiver, CHECK_NULL); - - probabilities->float_at_put(i, prob); - types->obj_at_put(i, type()); - - } - - RiTypeProfile::set_probabilities(obj, probabilities()); - RiTypeProfile::set_types(obj, types()); - } else { - RiTypeProfile::set_probabilities(obj, NULL); - RiTypeProfile::set_types(obj, NULL); - } - } - return JNIHandles::make_local(obj()); -} - -JNIEXPORT jdouble JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2branchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { - TRACE_graal_3("VMEntries::RiMethod_typeProfile"); - ResourceMark rm; - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - methodDataHandle method_data = method->method_data(); - - if (method_data == NULL || !method_data->is_mature()) return -1; - method_data->bci_to_data(bci); - - ProfileData* data = method_data->bci_to_data(bci); - if (data == NULL || !data->is_JumpData()) return -1; - - // get taken and not taken values - int taken = data->as_JumpData()->taken(); - int not_taken = 0; - if (data->is_BranchData()) { - not_taken = data->as_BranchData()->not_taken(); - } - - // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. - // We also check that individual counters are positive first, otherwise the sum can become positive. - if (taken < 0 || not_taken < 0 || taken + not_taken < 40) return -1; - - // Pin probability to sane limits - if (taken == 0) - return 0; - else if (not_taken == 0) - return 1; - else { // Compute probability of true path - return (jdouble)(taken) / (taken + not_taken); - } -} - -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2switchProbability(JNIEnv *, jobject, jobject hotspot_method, jint bci) { - TRACE_graal_3("VMEntries::RiMethod_typeProfile"); - VM_ENTRY_MARK; - ResourceMark rm; - methodHandle method = getMethodFromHotSpotMethod(hotspot_method); - methodDataHandle method_data = method->method_data(); - - if (method_data == NULL || !method_data->is_mature()) return NULL; - - ProfileData* data = method_data->bci_to_data(bci); - if (data == NULL || !data->is_MultiBranchData()) return NULL; - - MultiBranchData* branch_data = data->as_MultiBranchData(); - - long sum = 0; - int cases = branch_data->number_of_cases(); - GrowableArray* counts = new GrowableArray(cases + 1); - - for (int i = 0; i < cases; i++) { - uint value = branch_data->count_at(i); - sum += value; - counts->append(value); - } - uint value = branch_data->default_count(); - sum += value; - counts->append(value); - - // Give up if too few (or too many, in which case the sum will overflow) counts to be meaningful. - // We also check that individual counters are positive first, otherwise the sum can become positive. - if (sum < 10 * (cases + 3)) return NULL; - - typeArrayOop probability = oopFactory::new_typeArray(T_DOUBLE, cases + 1, CHECK_NULL); - for (int i = 0; i < cases + 1; i++) { - probability->double_at_put(i, counts->at(i) / (double) sum); - } - return JNIHandles::make_local(probability); -} - -// public native boolean RiMethod_hasCompiledCode(HotSpotMethodResolved method); -JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1hasCompiledCode(JNIEnv *, jobject, jobject hotspot_method) { - TRACE_graal_3("VMEntries::RiMethod_hasCompiledCode"); - return getMethodFromHotSpotMethod(hotspot_method)->has_compiled_code(); -} - -// public RiType RiSignature_lookupType(String returnType, HotSpotTypeResolved accessingClass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiSignature_1lookupType(JNIEnv *env, jobject, jstring jname, jobject accessingClass) { - TRACE_graal_3("VMEntries::RiSignature_lookupType"); - VM_ENTRY_MARK; - ResourceMark rm; - - Symbol* nameSymbol = VmIds::toSymbol(jname); - Handle name = JNIHandles::resolve(jname); - - oop result; - if (nameSymbol == vmSymbols::int_signature()) { - result = VMExits::createRiTypePrimitive((int) T_INT, THREAD); - } else if (nameSymbol == vmSymbols::long_signature()) { - result = VMExits::createRiTypePrimitive((int) T_LONG, THREAD); - } else if (nameSymbol == vmSymbols::bool_signature()) { - result = VMExits::createRiTypePrimitive((int) T_BOOLEAN, THREAD); - } else if (nameSymbol == vmSymbols::char_signature()) { - result = VMExits::createRiTypePrimitive((int) T_CHAR, THREAD); - } else if (nameSymbol == vmSymbols::short_signature()) { - result = VMExits::createRiTypePrimitive((int) T_SHORT, THREAD); - } else if (nameSymbol == vmSymbols::byte_signature()) { - result = VMExits::createRiTypePrimitive((int) T_BYTE, THREAD); - } else if (nameSymbol == vmSymbols::double_signature()) { - result = VMExits::createRiTypePrimitive((int) T_DOUBLE, THREAD); - } else if (nameSymbol == vmSymbols::float_signature()) { - result = VMExits::createRiTypePrimitive((int) T_FLOAT, THREAD); - } else { - klassOop resolved_type = NULL; - // if the name isn't in the symbol table then the class isn't loaded anyway... - if (nameSymbol != NULL) { - Handle classloader; - Handle protectionDomain; - if (JNIHandles::resolve(accessingClass) != NULL) { - classloader = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->class_loader(); - protectionDomain = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(accessingClass))->klass_part()->protection_domain(); - } - resolved_type = SystemDictionary::resolve_or_null(nameSymbol, classloader, protectionDomain, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - resolved_type = NULL; - } - } - if (resolved_type != NULL) { - Handle type = GraalCompiler::createHotSpotTypeResolved(resolved_type, name, CHECK_NULL); - result = type(); - } else { - Handle type = VMExits::createRiTypeUnresolved(name, THREAD); - result = type(); - } - } - - return JNIHandles::make_local(THREAD, result); -} - -// public Object RiConstantPool_lookupConstant(HotSpotTypeResolved type, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupConstant(JNIEnv *env, jobject, jobject type, jint index) { - TRACE_graal_3("VMEntries::RiConstantPool_lookupConstant"); - VM_ENTRY_MARK; - - constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); - - oop result = NULL; - constantTag tag = cp->tag_at(index); - if (tag.is_int()) { - result = VMExits::createCiConstant(CiKind::Int(), cp->int_at(index), CHECK_0); - } else if (tag.is_long()) { - result = VMExits::createCiConstant(CiKind::Long(), cp->long_at(index), CHECK_0); - } else if (tag.is_float()) { - result = VMExits::createCiConstantFloat(cp->float_at(index), CHECK_0); - } else if (tag.is_double()) { - result = VMExits::createCiConstantDouble(cp->double_at(index), CHECK_0); - } else if (tag.is_string() || tag.is_unresolved_string()) { - oop string = NULL; - if (cp->is_pseudo_string_at(index)) { - string = cp->pseudo_string_at(index); - } else { - string = cp->string_at(index, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - // TODO: Gracefully exit compilation. - fatal("out of memory during compilation!"); - return NULL; - } - } - result = VMExits::createCiConstantObject(string, CHECK_0); - } else if (tag.is_klass() || tag.is_unresolved_klass()) { - Handle type = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); - result = type(); - } else if (tag.is_object()) { - oop obj = cp->object_at(index); - assert(obj->is_instance(), "must be an instance"); - result = VMExits::createCiConstantObject(obj, CHECK_NULL); - } else { - ShouldNotReachHere(); - } - - return JNIHandles::make_local(THREAD, result); -} - -// public RiMethod RiConstantPool_lookupMethod(long vmId, int cpi, byte byteCode); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupMethod(JNIEnv *env, jobject, jobject type, jint index, jbyte byteCode) { - TRACE_graal_3("VMEntries::RiConstantPool_lookupMethod"); - VM_ENTRY_MARK; - index = GraalCompiler::to_cp_index_u2(index); - constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); - instanceKlassHandle pool_holder(cp->pool_holder()); - - Bytecodes::Code bc = (Bytecodes::Code) (((int) byteCode) & 0xFF); - methodHandle method = GraalEnv::get_method_by_index(cp, index, bc, pool_holder); - if (!method.is_null()) { - Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret()); - } else { - // Get the method's name and signature. - Handle name = VmIds::toString(cp->name_ref_at(index), CHECK_NULL); - Handle signature = VmIds::toString(cp->signature_ref_at(index), CHECK_NULL); - int holder_index = cp->klass_ref_index_at(index); - Handle type = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); - return JNIHandles::make_local(THREAD, VMExits::createRiMethodUnresolved(name, signature, type, THREAD)); - } -} - -// public RiType RiConstantPool_lookupType(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupType(JNIEnv *env, jobject, jobject type, jint index) { - TRACE_graal_3("VMEntries::RiConstantPool_lookupType"); - VM_ENTRY_MARK; - - constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); - Handle result = GraalCompiler::get_RiType(cp, index, cp->pool_holder(), CHECK_NULL); - return JNIHandles::make_local(THREAD, result()); -} - -// public void RiConstantPool_loadReferencedType(long vmId, int cpi); -JNIEXPORT void JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1loadReferencedType(JNIEnv *env, jobject, jobject type, jint index, jbyte op) { - TRACE_graal_3("VMEntries::RiConstantPool_loadReferencedType"); - VM_ENTRY_MARK; - - constantPoolOop cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(type)))->constants(); - int byteCode = (op & 0xFF); - if (byteCode != Bytecodes::_checkcast && byteCode != Bytecodes::_instanceof && byteCode != Bytecodes::_new && byteCode != Bytecodes::_anewarray && byteCode != Bytecodes::_multianewarray) { - index = cp->remap_instruction_operand_from_cache(GraalCompiler::to_cp_index_u2(index)); - } - constantTag tag = cp->tag_at(index); - if (tag.is_field_or_method()) { - index = cp->uncached_klass_ref_index_at(index); - tag = cp->tag_at(index); - } - - if (tag.is_unresolved_klass() || tag.is_klass()) { - klassOop klass = cp->klass_at(index, CHECK); - if (klass->klass_part()->oop_is_instance()) { - instanceKlass::cast(klass)->initialize(CHECK); - } - } -} - -// public RiField RiConstantPool_lookupField(long vmId, int cpi); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupField(JNIEnv *env, jobject, jobject constantPoolHolder, jint index, jbyte byteCode) { - TRACE_graal_3("VMEntries::RiConstantPool_lookupField"); - VM_ENTRY_MARK; - ResourceMark rm; - - index = GraalCompiler::to_cp_index_u2(index); - constantPoolHandle cp = instanceKlass::cast(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(constantPoolHolder)))->constants(); - - int nt_index = cp->name_and_type_ref_index_at(index); - int sig_index = cp->signature_ref_index_at(nt_index); - Symbol* signature = cp->symbol_at(sig_index); - int name_index = cp->name_ref_index_at(nt_index); - Symbol* name = cp->symbol_at(name_index); - int holder_index = cp->klass_ref_index_at(index); - Handle holder = GraalCompiler::get_RiType(cp, holder_index, cp->pool_holder(), CHECK_NULL); - instanceKlassHandle holder_klass; - - Bytecodes::Code code = (Bytecodes::Code)(((int) byteCode) & 0xFF); - int offset = -1; - AccessFlags flags; - BasicType basic_type; - if (holder->klass() == SystemDictionary::HotSpotTypeResolved_klass()) { - FieldAccessInfo result; - LinkResolver::resolve_field(result, cp, index, - Bytecodes::java_code(code), - true, false, Thread::current()); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } else { - offset = result.field_offset(); - flags = result.access_flags(); - holder_klass = result.klass()->as_klassOop(); - basic_type = result.field_type(); - holder = GraalCompiler::get_RiType(holder_klass, CHECK_NULL); - } - } - - Handle type = GraalCompiler::get_RiTypeFromSignature(cp, sig_index, cp->pool_holder(), CHECK_NULL); - Handle field_handle = GraalCompiler::get_RiField(offset, flags.as_int(), name, holder, type, code, THREAD); - - oop constant_object = NULL; - // Check to see if the field is constant. - if (!holder_klass.is_null() && holder_klass->is_initialized() && flags.is_final() && flags.is_static()) { - // This field just may be constant. The only cases where it will - // not be constant are: - // - // 1. The field holds a non-perm-space oop. The field is, strictly - // speaking, constant but we cannot embed non-perm-space oops into - // generated code. For the time being we need to consider the - // field to be not constant. - // 2. The field is a *special* static&final field whose value - // may change. The three examples are java.lang.System.in, - // java.lang.System.out, and java.lang.System.err. - - bool ok = true; - assert( SystemDictionary::System_klass() != NULL, "Check once per vm"); - if( holder_klass->as_klassOop() == SystemDictionary::System_klass() ) { - // Check offsets for case 2: System.in, System.out, or System.err - if( offset == java_lang_System::in_offset_in_bytes() || - offset == java_lang_System::out_offset_in_bytes() || - offset == java_lang_System::err_offset_in_bytes() ) { - ok = false; - } - } - - if (ok) { - Handle mirror = holder_klass->java_mirror(); - switch(basic_type) { - case T_OBJECT: - case T_ARRAY: - constant_object = VMExits::createCiConstantObject(mirror->obj_field(offset), CHECK_0); - break; - case T_DOUBLE: - constant_object = VMExits::createCiConstantDouble(mirror->double_field(offset), CHECK_0); - break; - case T_FLOAT: - constant_object = VMExits::createCiConstantFloat(mirror->float_field(offset), CHECK_0); - break; - case T_LONG: - constant_object = VMExits::createCiConstant(CiKind::Long(), mirror->long_field(offset), CHECK_0); - break; - case T_INT: - constant_object = VMExits::createCiConstant(CiKind::Int(), mirror->int_field(offset), CHECK_0); - break; - case T_SHORT: - constant_object = VMExits::createCiConstant(CiKind::Short(), mirror->short_field(offset), CHECK_0); - break; - case T_CHAR: - constant_object = VMExits::createCiConstant(CiKind::Char(), mirror->char_field(offset), CHECK_0); - break; - case T_BYTE: - constant_object = VMExits::createCiConstant(CiKind::Byte(), mirror->byte_field(offset), CHECK_0); - break; - case T_BOOLEAN: - constant_object = VMExits::createCiConstant(CiKind::Boolean(), mirror->bool_field(offset), CHECK_0); - break; - default: - fatal("Unhandled constant"); - break; - } - } - } - if (constant_object != NULL) { - HotSpotField::set_constant(field_handle, constant_object); - } - return JNIHandles::make_local(THREAD, field_handle()); -} - -// public RiMethod RiType_resolveMethodImpl(HotSpotTypeResolved klass, String name, String signature); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_3resolveMethodImpl(JNIEnv *, jobject, jobject resolved_type, jstring name, jstring signature) { - TRACE_graal_3("VMEntries::RiType_resolveMethodImpl"); - VM_ENTRY_MARK; - - assert(JNIHandles::resolve(resolved_type) != NULL, ""); - klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(resolved_type)); - Symbol* name_symbol = VmIds::toSymbol(name); - Symbol* signature_symbol = VmIds::toSymbol(signature); - methodHandle method = klass->klass_part()->lookup_method(name_symbol, signature_symbol); - if (method == NULL) { - if (TraceGraal >= 3) { - ResourceMark rm; - tty->print_cr("Could not resolve method %s %s on klass %s", name_symbol->as_C_string(), signature_symbol->as_C_string(), klass->klass_part()->name()->as_C_string()); - } - return NULL; - } - Handle ret = GraalCompiler::createHotSpotMethodResolved(method, CHECK_NULL); - return JNIHandles::make_local(THREAD, ret()); -} - -// public boolean RiType_isSubtypeOf(HotSpotTypeResolved klass, RiType other); -JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_2isSubtypeOf(JNIEnv *, jobject, jobject klass, jobject jother) { - TRACE_graal_3("VMEntries::RiType_isSubtypeOf"); - oop other = JNIHandles::resolve(jother); - assert(other->is_a(HotSpotTypeResolved::klass()), "resolved hotspot type expected"); - assert(JNIHandles::resolve(klass) != NULL, ""); - klassOop thisKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); - klassOop otherKlass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(other)); - if (thisKlass->klass_part()->oop_is_instance_slow()) { - return instanceKlass::cast(thisKlass)->is_subtype_of(otherKlass); - } else if (thisKlass->klass_part()->oop_is_array()) { - return arrayKlass::cast(thisKlass)->is_subtype_of(otherKlass); - } else { - fatal("unexpected class type"); - return false; - } -} - -// public RiType RiType_componentType(HotSpotResolvedType klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1componentType(JNIEnv *, jobject, jobject klass) { - TRACE_graal_3("VMEntries::RiType_componentType"); - VM_ENTRY_MARK; - KlassHandle array_klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); - if(array_klass->oop_is_typeArray()) { - BasicType t = typeArrayKlass::cast(array_klass())->element_type(); - oop primitive_type = VMExits::createRiTypePrimitive((int) t, CHECK_NULL); - return JNIHandles::make_local(primitive_type); - } - assert(array_klass->oop_is_objArray(), "just checking"); - klassOop element_type = objArrayKlass::cast(array_klass())->element_klass(); - assert(JNIHandles::resolve(klass) != NULL, ""); - return JNIHandles::make_local(GraalCompiler::get_RiType(element_type, THREAD)()); -} - -// public RiType RiType_superType(HotSpotResolvedType klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1superType(JNIEnv *, jobject, jobject klass) { - TRACE_graal_3("VMEntries::RiType_superType"); - VM_ENTRY_MARK; - KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - klassOop k; - - if (klass_handle->oop_is_array()) { - k = SystemDictionary::Object_klass(); - } else { - guarantee(klass_handle->oop_is_instance(), "must be instance klass"); - k = klass_handle->super(); - } - - if (k != NULL) { - return JNIHandles::make_local(GraalCompiler::get_RiType(k, THREAD)()); - } else { - return NULL; - } -} - -// public RiType RiType_uniqueConcreteSubtype(HotSpotResolvedType klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1uniqueConcreteSubtype(JNIEnv *, jobject, jobject klass) { - TRACE_graal_3("VMEntries::RiType_uniqueConcreteSubtype"); - VM_ENTRY_MARK; - KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - Klass *up_cast = klass_handle->up_cast_abstract(); - if (up_cast->is_leaf_class()) { - return JNIHandles::make_local(GraalCompiler::get_RiType(up_cast, THREAD)()); - } - return NULL; -} - -// public bool RiType_isInitialized(HotSpotResolvedType klass); -JNIEXPORT jboolean JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1isInitialized(JNIEnv *, jobject, jobject hotspot_klass) { - TRACE_graal_3("VMEntries::RiType_isInitialized"); - klassOop klass = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(hotspot_klass)); - assert(klass != NULL, "method must not be called for primitive types"); - return instanceKlass::cast(klass)->is_initialized(); -} - -// public RiType RiType_arrayOf(HotSpotTypeResolved klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1arrayOf(JNIEnv *, jobject, jobject klass) { - TRACE_graal_3("VMEntries::RiType_arrayOf"); - VM_ENTRY_MARK; - - KlassHandle klass_handle(java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass))); - KlassHandle arr = klass_handle->array_klass(THREAD); - Handle name = VmIds::toString(arr->name(), CHECK_NULL); - assert(arr->oop_is_array(), ""); - return JNIHandles::make_local(THREAD, GraalCompiler::createHotSpotTypeResolved(arr, name, THREAD)()); -} - -// public RiResolvedField[] RiType_fields(HotSpotTypeResolved klass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_RiType_1fields(JNIEnv *, jobject, jobject klass) { - TRACE_graal_3("VMEntries::RiType_fields"); - VM_ENTRY_MARK; - ResourceMark rm; - - instanceKlassHandle k = java_lang_Class::as_klassOop(HotSpotTypeResolved::javaMirror(klass)); - class MyFieldClosure : public FieldClosure { - public: - instanceKlassHandle _holder; - Handle _resolved_type_holder; - GrowableArray _field_array; - - MyFieldClosure(instanceKlassHandle& holder, Handle resolved_type_holder) : _holder(holder), _resolved_type_holder(resolved_type_holder) { } - - virtual void do_field(fieldDescriptor* fd) { - if (!Thread::current()->has_pending_exception()) { - if (fd->field_holder() == _holder()) { - Handle type = GraalCompiler::get_RiTypeFromSignature(fd->constants(), fd->signature_index(), fd->field_holder(), Thread::current()); - Handle field = VMExits::createRiField(_resolved_type_holder, VmIds::toString(fd->name(), Thread::current()), type, fd->offset(), fd->access_flags().as_int(), Thread::current()); - _field_array.append(field()); - } - } - } - }; - MyFieldClosure closure(k, JNIHandles::resolve(klass)); - k->do_nonstatic_fields(&closure); - objArrayHandle field_array = oopFactory::new_objArray(SystemDictionary::RiResolvedField_klass(), closure._field_array.length(), CHECK_NULL); - for (int i=0; iobj_at_put(i, closure._field_array.at(i)()); - } - return JNIHandles::make_local(field_array()); -} - -// public RiType getPrimitiveArrayType(CiKind kind); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_getPrimitiveArrayType(JNIEnv *env, jobject, jobject kind) { - TRACE_graal_3("VMEntries::VMEntries_getPrimitiveArrayType"); - VM_ENTRY_MARK; - BasicType type = GraalCompiler::kindToBasicType(CiKind::typeChar(kind)); - assert(type != T_OBJECT, "primitive type expecteds"); - Handle result = GraalCompiler::get_RiType(Universe::typeArrayKlassObj(type), CHECK_NULL); - return JNIHandles::make_local(THREAD, result()); -} - -// public long getMaxCallTargetOffset(CiRuntimeCall rtcall); -JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_VMEntries_getMaxCallTargetOffset(JNIEnv *env, jobject, jobject rtcall) { - TRACE_graal_3("VMEntries::VMEntries_getMaxCallTargetOffset"); - VM_ENTRY_MARK; - oop call = JNIHandles::resolve(rtcall); - address target_addr = CodeInstaller::runtime_call_target_address(call); - if (target_addr != 0x0) { - int64_t off_low = (int64_t)target_addr - ((int64_t)CodeCache::low_bound() + sizeof(int)); - int64_t off_high = (int64_t)target_addr - ((int64_t)CodeCache::high_bound() + sizeof(int)); - return MAX2(ABS(off_low), ABS(off_high)); - } - return -1; -} - -// public RiType getType(Class javaClass); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_getType(JNIEnv *env, jobject, jobject javaClass) { - TRACE_graal_3("VMEntries::VMEntries_getType"); - VM_ENTRY_MARK; - oop javaClassOop = JNIHandles::resolve(javaClass); - if (javaClassOop == NULL) { - fatal("argument to VMEntries.getType must not be NULL"); - return NULL; - } else if (java_lang_Class::is_primitive(javaClassOop)) { - BasicType basicType = java_lang_Class::primitive_type(javaClassOop); - return JNIHandles::make_local(THREAD, VMExits::createRiTypePrimitive((int) basicType, THREAD)); - } else { - KlassHandle klass = java_lang_Class::as_klassOop(javaClassOop); - Handle name = java_lang_String::create_from_symbol(klass->name(), CHECK_NULL); - - Handle type = GraalCompiler::createHotSpotTypeResolved(klass, name, CHECK_NULL); - return JNIHandles::make_local(THREAD, type()); - } -} - - -// helpers used to set fields in the HotSpotVMConfig object -jfieldID getFieldID(JNIEnv* env, jobject obj, const char* name, const char* sig) { - jfieldID id = env->GetFieldID(env->GetObjectClass(obj), name, sig); - if (id == NULL) { - fatal(err_msg("field not found: %s (%s)", name, sig)); - } - return id; -} - -void set_boolean(JNIEnv* env, jobject obj, const char* name, bool value) { env->SetBooleanField(obj, getFieldID(env, obj, name, "Z"), value); } -void set_int(JNIEnv* env, jobject obj, const char* name, int value) { env->SetIntField(obj, getFieldID(env, obj, name, "I"), value); } -void set_long(JNIEnv* env, jobject obj, const char* name, jlong value) { env->SetLongField(obj, getFieldID(env, obj, name, "J"), value); } -void set_object(JNIEnv* env, jobject obj, const char* name, jobject value) { env->SetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;"), value); } -void set_int_array(JNIEnv* env, jobject obj, const char* name, jarray value) { env->SetObjectField(obj, getFieldID(env, obj, name, "[I"), value); } - -jboolean get_boolean(JNIEnv* env, jobject obj, const char* name) { return env->GetBooleanField(obj, getFieldID(env, obj, name, "Z")); } -jint get_int(JNIEnv* env, jobject obj, const char* name) { return env->GetIntField(obj, getFieldID(env, obj, name, "I")); } -jlong get_long(JNIEnv* env, jobject obj, const char* name) { return env->GetLongField(obj, getFieldID(env, obj, name, "J")); } -jobject get_object(JNIEnv* env, jobject obj, const char* name) { return env->GetObjectField(obj, getFieldID(env, obj, name, "Ljava/lang/Object;")); } -jobject get_object(JNIEnv* env, jobject obj, const char* name, const char* sig) { return env->GetObjectField(obj, getFieldID(env, obj, name, sig)); } - - -BasicType basicTypes[] = { T_BOOLEAN, T_BYTE, T_SHORT, T_CHAR, T_INT, T_FLOAT, T_LONG, T_DOUBLE, T_OBJECT }; -int basicTypeCount = sizeof(basicTypes) / sizeof(BasicType); - -// public HotSpotVMConfig getConfiguration(); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_getConfiguration(JNIEnv *env, jobject) { - jclass klass = env->FindClass("com/oracle/max/graal/hotspot/HotSpotVMConfig"); - assert(klass != NULL, "HotSpot vm config class not found"); - jobject config = env->AllocObject(klass); -#ifdef _WIN64 - set_boolean(env, config, "windowsOs", true); -#else - set_boolean(env, config, "windowsOs", false); -#endif - set_boolean(env, config, "verifyPointers", VerifyOops); - set_boolean(env, config, "useFastLocking", UseFastLocking); - set_boolean(env, config, "useFastNewObjectArray", UseFastNewObjectArray); - set_boolean(env, config, "useFastNewTypeArray", UseFastNewTypeArray); - set_int(env, config, "codeEntryAlignment", CodeEntryAlignment); - set_int(env, config, "vmPageSize", os::vm_page_size()); - set_int(env, config, "stackShadowPages", StackShadowPages); - set_int(env, config, "hubOffset", oopDesc::klass_offset_in_bytes()); - set_int(env, config, "arrayLengthOffset", arrayOopDesc::length_offset_in_bytes()); - set_int(env, config, "klassStateOffset", instanceKlass::init_state_offset_in_bytes() + sizeof(oopDesc)); - set_int(env, config, "klassStateFullyInitialized", (int)instanceKlass::fully_initialized); - set_int(env, config, "threadTlabTopOffset", in_bytes(JavaThread::tlab_top_offset())); - set_int(env, config, "threadTlabEndOffset", in_bytes(JavaThread::tlab_end_offset())); - set_int(env, config, "threadObjectOffset", in_bytes(JavaThread::threadObj_offset())); - set_int(env, config, "instanceHeaderPrototypeOffset", Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()); - set_int(env, config, "threadExceptionOopOffset", in_bytes(JavaThread::exception_oop_offset())); - set_int(env, config, "threadExceptionPcOffset", in_bytes(JavaThread::exception_pc_offset())); - set_int(env, config, "threadMultiNewArrayStorage", in_bytes(JavaThread::graal_multinewarray_storage_offset())); - set_int(env, config, "classMirrorOffset", klassOopDesc::klass_part_offset_in_bytes() + Klass::java_mirror_offset_in_bytes()); - - set_long(env, config, "debugStub", VmIds::addStub((address)warning)); - set_long(env, config, "instanceofStub", VmIds::addStub(Runtime1::entry_for(Runtime1::slow_subtype_check_id))); - set_long(env, config, "verifyPointerStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_verify_pointer_id))); - set_long(env, config, "newInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::fast_new_instance_init_check_id))); - set_long(env, config, "unresolvedNewInstanceStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_instance_id))); - set_long(env, config, "newTypeArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_type_array_id))); - set_long(env, config, "newObjectArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_object_array_id))); - set_long(env, config, "newMultiArrayStub", VmIds::addStub(Runtime1::entry_for(Runtime1::new_multi_array_id))); - set_long(env, config, "loadKlassStub", VmIds::addStub(Runtime1::entry_for(Runtime1::load_klass_patching_id))); - set_long(env, config, "accessFieldStub", VmIds::addStub(Runtime1::entry_for(Runtime1::access_field_patching_id))); - set_long(env, config, "resolveStaticCallStub", VmIds::addStub(SharedRuntime::get_resolve_static_call_stub())); - set_long(env, config, "inlineCacheMissStub", VmIds::addStub(SharedRuntime::get_ic_miss_stub())); - set_long(env, config, "unwindExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_unwind_exception_call_id))); - set_long(env, config, "handleExceptionStub", VmIds::addStub(Runtime1::entry_for(Runtime1::handle_exception_nofpu_id))); - set_long(env, config, "handleDeoptStub", VmIds::addStub(SharedRuntime::deopt_blob()->unpack())); - set_long(env, config, "monitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorenter_id))); - set_long(env, config, "monitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::monitorexit_id))); - set_long(env, config, "fastMonitorEnterStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorenter_id))); - set_long(env, config, "fastMonitorExitStub", VmIds::addStub(Runtime1::entry_for(Runtime1::graal_monitorexit_id))); - set_long(env, config, "safepointPollingAddress", (jlong)(os::get_polling_page() + (SafepointPollOffset % os::vm_page_size()))); - set_int(env, config, "runtimeCallStackSize", (jint)frame::arg_reg_save_area_bytes); - set_int(env, config, "klassModifierFlagsOffset", Klass::modifier_flags_offset_in_bytes() + sizeof(oopDesc)); - set_int(env, config, "klassOopOffset", java_lang_Class::klass_offset_in_bytes()); - set_boolean(env, config, "isPollingPageFar", Assembler::is_polling_page_far()); - - set_int(env, config, "nmethodEntryOffset", nmethod::verified_entry_point_offset()); - - BarrierSet* bs = Universe::heap()->barrier_set(); - switch (bs->kind()) { - case BarrierSet::CardTableModRef: - case BarrierSet::CardTableExtension: { - jlong base = (jlong)((CardTableModRefBS*)bs)->byte_map_base; - assert(base != 0, "unexpected byte_map_base"); - set_long(env, config, "cardtableStartAddress", base); - set_int(env, config, "cardtableShift", CardTableModRefBS::card_shift); - break; - } - case BarrierSet::ModRef: - case BarrierSet::Other: - set_long(env, config, "cardtableStartAddress", 0); - set_int(env, config, "cardtableShift", 0); - // No post barriers - break; -#ifndef SERIALGC - case BarrierSet::G1SATBCT: - case BarrierSet::G1SATBCTLogging: -#endif // SERIALGC - default: - ShouldNotReachHere(); - break; - } - - jintArray arrayOffsets = env->NewIntArray(basicTypeCount); - for (int i=0; iSetIntArrayRegion(arrayOffsets, i, 1, &offset); - } - set_int_array(env, config, "arrayOffsets", arrayOffsets); - set_int(env, config, "arrayClassElementOffset", objArrayKlass::element_klass_offset_in_bytes() + sizeof(oopDesc)); - return config; -} - -// public HotSpotCompiledMethod installMethod(HotSpotTargetMethod targetMethod, boolean installCode); -JNIEXPORT jobject JNICALL Java_com_oracle_graal_hotspot_VMEntries_installMethod(JNIEnv *jniEnv, jobject, jobject targetMethod, jboolean install_code) { - VM_ENTRY_MARK; - ResourceMark rm; - HandleMark hm; - Handle targetMethodHandle = JNIHandles::resolve(targetMethod); - nmethod* nm = NULL; - Arena arena; - ciEnv env(&arena); - CodeInstaller installer(targetMethodHandle, nm, install_code != 0); - - // if install_code is true then we installed the code into the given method, no need to return an RiCompiledMethod - if (!install_code && nm != NULL) { - instanceKlass::cast(HotSpotCompiledMethod::klass())->initialize(CHECK_NULL); - Handle obj = instanceKlass::cast(HotSpotCompiledMethod::klass())->allocate_permanent_instance(CHECK_NULL); - assert(obj() != NULL, "must succeed in allocating instance"); - HotSpotCompiledMethod::set_nmethod(obj, (jlong) nm); - HotSpotCompiledMethod::set_method(obj, HotSpotTargetMethod::method(targetMethod)); - nm->set_graal_compiled_method(obj()); - return JNIHandles::make_local(obj()); - } else { - return NULL; - } -} - -// public HotSpotProxy installStub(HotSpotTargetMethod targetMethod, String name); -JNIEXPORT jlong JNICALL Java_com_oracle_graal_hotspot_VMEntries_installStub(JNIEnv *jniEnv, jobject, jobject targetMethod) { - VM_ENTRY_MARK; - ResourceMark rm; - HandleMark hm; - Handle targetMethodHandle = JNIHandles::resolve(targetMethod); - jlong id; - Arena arena; - ciEnv env(&arena); - CodeInstaller installer(targetMethodHandle, id); - return id; -} - - - -#define CC (char*) /*cast a literal from (const char*)*/ -#define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) - -#define PROXY "J" -#define TYPE "Lcom/oracle/max/cri/ri/RiType;" -#define RESOLVED_TYPE "Lcom/oracle/max/graal/hotspot/ri/HotSpotTypeResolved;" -#define METHOD "Lcom/oracle/max/cri/ri/RiMethod;" -#define RESOLVED_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethodResolved;" -#define REFLECT_METHOD "Ljava/lang/reflect/Method;" -#define TYPE_PROFILE "Lcom/oracle/max/cri/ri/RiTypeProfile;" -#define SIGNATURE "Lcom/oracle/max/cri/ri/RiSignature;" -#define FIELD "Lcom/oracle/max/cri/ri/RiField;" -#define RESOLVED_FIELD "Lcom/oracle/max/cri/ri/RiResolvedField;" -#define CONSTANT_POOL "Lcom/oracle/max/cri/ri/RiConstantPool;" -#define EXCEPTION_HANDLERS "[Lcom/oracle/max/cri/ri/RiExceptionHandler;" -#define TARGET_METHOD "Lcom/oracle/max/graal/hotspot/HotSpotTargetMethod;" -#define CONFIG "Lcom/oracle/max/graal/hotspot/HotSpotVMConfig;" -#define HS_METHOD "Lcom/oracle/max/graal/hotspot/ri/HotSpotMethod;" -#define HS_COMP_METHOD "Lcom/oracle/max/graal/hotspot/HotSpotCompiledMethod;" -#define CI_CONSTANT "Lcom/oracle/max/cri/ci/CiConstant;" -#define CI_KIND "Lcom/oracle/max/cri/ci/CiKind;" -#define CI_RUNTIME_CALL "Lcom/oracle/max/cri/ci/CiRuntimeCall;" -#define STRING "Ljava/lang/String;" -#define OBJECT "Ljava/lang/Object;" -#define CLASS "Ljava/lang/Class;" - -JNINativeMethod VMEntries_methods[] = { - {CC"RiMethod_code", CC"("RESOLVED_METHOD")[B", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1code)}, - {CC"RiMethod_signature", CC"("RESOLVED_METHOD")"STRING, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1signature)}, - {CC"RiMethod_exceptionHandlers", CC"("RESOLVED_METHOD")"EXCEPTION_HANDLERS, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1exceptionHandlers)}, - {CC"RiMethod_hasBalancedMonitors", CC"("RESOLVED_METHOD")Z", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1hasBalancedMonitors)}, - {CC"RiMethod_uniqueConcreteMethod", CC"("RESOLVED_METHOD")"METHOD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1uniqueConcreteMethod)}, - {CC"getRiMethod", CC"("REFLECT_METHOD")"METHOD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_getRiMethod)}, - {CC"RiMethod_typeProfile", CC"("RESOLVED_METHOD"I)"TYPE_PROFILE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2typeProfile)}, - {CC"RiMethod_branchProbability", CC"("RESOLVED_METHOD"I)D", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2branchProbability)}, - {CC"RiMethod_switchProbability", CC"("RESOLVED_METHOD"I)[D", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2switchProbability)}, - {CC"RiMethod_invocationCount", CC"("RESOLVED_METHOD")I", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1invocationCount)}, - {CC"RiMethod_exceptionProbability", CC"("RESOLVED_METHOD"I)I", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_2exceptionProbability)}, - {CC"RiMethod_hasCompiledCode", CC"("RESOLVED_METHOD")Z", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiMethod_1hasCompiledCode)}, - {CC"RiSignature_lookupType", CC"("STRING RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiSignature_1lookupType)}, - {CC"RiConstantPool_lookupConstant", CC"("RESOLVED_TYPE"I)"OBJECT, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupConstant)}, - {CC"RiConstantPool_lookupMethod", CC"("RESOLVED_TYPE"IB)"METHOD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupMethod)}, - {CC"RiConstantPool_lookupType", CC"("RESOLVED_TYPE"I)"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupType)}, - {CC"RiConstantPool_loadReferencedType", CC"("RESOLVED_TYPE"IB)V", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1loadReferencedType)}, - {CC"RiConstantPool_lookupField", CC"("RESOLVED_TYPE"IB)"FIELD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiConstantPool_1lookupField)}, - {CC"RiType_resolveMethodImpl", CC"("RESOLVED_TYPE STRING STRING")"METHOD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_3resolveMethodImpl)}, - {CC"RiType_isSubtypeOf", CC"("RESOLVED_TYPE TYPE")Z", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_2isSubtypeOf)}, - {CC"RiType_componentType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_1componentType)}, - {CC"RiType_uniqueConcreteSubtype", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_1uniqueConcreteSubtype)}, - {CC"RiType_superType", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_1superType)}, - {CC"RiType_arrayOf", CC"("RESOLVED_TYPE")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_1arrayOf)}, - {CC"RiType_fields", CC"("RESOLVED_TYPE")["RESOLVED_FIELD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_1fields)}, - {CC"RiType_isInitialized", CC"("RESOLVED_TYPE")Z", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_RiType_1isInitialized)}, - {CC"getPrimitiveArrayType", CC"("CI_KIND")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_getPrimitiveArrayType)}, - {CC"getMaxCallTargetOffset", CC"("CI_RUNTIME_CALL")J", FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_getMaxCallTargetOffset)}, - {CC"getType", CC"("CLASS")"TYPE, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_getType)}, - {CC"getConfiguration", CC"()"CONFIG, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_getConfiguration)}, - {CC"installMethod", CC"("TARGET_METHOD"Z)"HS_COMP_METHOD, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_installMethod)}, - {CC"installStub", CC"("TARGET_METHOD")"PROXY, FN_PTR(Java_com_oracle_graal_hotspot_VMEntries_installStub)} -}; - -int VMEntries_methods_count() { - return sizeof(VMEntries_methods) / sizeof(JNINativeMethod); -} - diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalVMEntries.hpp --- a/src/share/vm/graal/graalVMEntries.hpp Wed Jan 04 10:49:09 2012 -0800 +++ b/src/share/vm/graal/graalVMEntries.hpp Wed Jan 04 20:59:11 2012 +0100 @@ -23,8 +23,8 @@ #include "prims/jni.h" -extern JNINativeMethod VMEntries_methods[]; -int VMEntries_methods_count(); +extern JNINativeMethod CompilerToVM_methods[]; +int CompilerToVM_methods_count(); methodOop getMethodFromHotSpotMethod(oop hotspotMethod); diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalVMExits.cpp --- a/src/share/vm/graal/graalVMExits.cpp Wed Jan 04 10:49:09 2012 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,279 +0,0 @@ -/* - * Copyright (c) 2011, 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. - */ - -#include "precompiled.hpp" -#include "graal/graalVMExits.hpp" - -// this is a *global* handle -jobject VMExits::_compilerPermObject = NULL; -jobject VMExits::_vmExitsPermObject = NULL; -jobject VMExits::_vmExitsPermKlass = NULL; - -KlassHandle VMExits::vmExitsKlass() { - if (JNIHandles::resolve(_vmExitsPermKlass) == NULL) { - klassOop result = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_VMExits(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(result, "Couldn't find class com.sun.hotspot.graal.VMExits"); - _vmExitsPermKlass = JNIHandles::make_global(result); - } - return KlassHandle((klassOop)JNIHandles::resolve_non_null(_vmExitsPermKlass)); -} - -Handle VMExits::compilerInstance() { - if (JNIHandles::resolve(_compilerPermObject) == NULL) { - KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.graal.CompilerImpl"); - - JavaValue result(T_OBJECT); - JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::getInstance_name(), vmSymbols::getInstance_signature(), Thread::current()); - check_pending_exception("Couldn't get Compiler"); - _compilerPermObject = JNIHandles::make_global((oop) result.get_jobject()); - } - return Handle(JNIHandles::resolve_non_null(_compilerPermObject)); -} - -Handle VMExits::instance() { - if (JNIHandles::resolve(_vmExitsPermObject) == NULL) { - KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_Compiler(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.Compiler"); - - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.set_receiver(compilerInstance()); - JavaCalls::call_interface(&result, compilerKlass, vmSymbols::getVMExits_name(), vmSymbols::getVMExits_signature(), &args, Thread::current()); - check_pending_exception("Couldn't get VMExits"); - _vmExitsPermObject = JNIHandles::make_global((oop) result.get_jobject()); - } - return Handle(JNIHandles::resolve_non_null(_vmExitsPermObject)); -} - -void VMExits::initializeCompiler() { - KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.graal.CompilerImpl"); - - JavaValue result(T_VOID); - JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::initialize_name(), vmSymbols::void_method_signature(), Thread::current()); - check_pending_exception("Couldn't initialize compiler"); -} - -jboolean VMExits::setOption(Handle option) { - assert(!option.is_null(), ""); - KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.HotSpotOptions"); - - Thread* THREAD = Thread::current(); - JavaValue result(T_BOOLEAN); - JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD); - check_pending_exception("Error while calling setOption"); - return result.get_jboolean(); -} - -void VMExits::setDefaultOptions() { - KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.HotSpotOptions"); - - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD); - check_pending_exception("Error while calling setDefaultOptions"); -} - -void VMExits::compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking) { - assert(!hotspot_method.is_null(), "just checking"); - Thread* THREAD = Thread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(hotspot_method); - args.push_int(entry_bci); - args.push_int(blocking); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); - check_pending_exception("Error while calling compileMethod"); -} - -void VMExits::shutdownCompiler() { - if (_compilerPermObject != NULL) { - HandleMark hm; - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(instance()); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::shutdownCompiler_name(), vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling shutdownCompiler"); - - JNIHandles::destroy_global(_compilerPermObject); - JNIHandles::destroy_global(_vmExitsPermObject); - JNIHandles::destroy_global(_vmExitsPermKlass); - - _compilerPermObject = NULL; - _vmExitsPermObject = NULL; - _vmExitsPermKlass = NULL; - } -} - -void VMExits::startCompiler() { - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(instance()); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::startCompiler_name(), vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling startCompiler"); -} - -void VMExits::bootstrap() { - JavaThread* THREAD = JavaThread::current(); - JavaValue result(T_VOID); - JavaCallArguments args; - args.push_oop(instance()); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::bootstrap_name(), vmSymbols::void_method_signature(), &args, THREAD); - check_pending_exception("Error while calling boostrap"); -} - -oop VMExits::createRiMethodResolved(jlong vmId, Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_long(vmId); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodResolved_name(), vmSymbols::createRiMethodResolved_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiMethodResolved"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(name); - args.push_oop(signature); - args.push_oop(holder); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodUnresolved_name(), vmSymbols::createRiMethodUnresolved_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiMethodUnresolved"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS) { - assert(!holder.is_null(), "just checking"); - assert(!name.is_null(), "just checking"); - assert(!type.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(holder); - args.push_oop(name); - args.push_oop(type); - args.push_int(index); - args.push_int(flags); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiField_name(), vmSymbols::createRiField_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiField"); - assert(result.get_type() == T_OBJECT, "just checking"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiType(jlong vmId, Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_long(vmId); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiType_name(), vmSymbols::createRiType_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiType"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiTypePrimitive(int basic_type, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_int(basic_type); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypePrimitive_name(), vmSymbols::createRiTypePrimitive_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiTypePrimitive"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiTypeUnresolved(Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypeUnresolved_name(), vmSymbols::createRiTypeUnresolved_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiTypeUnresolved"); - return (oop) result.get_jobject(); -} - -oop VMExits::createRiSignature(Handle name, TRAPS) { - assert(!name.is_null(), "just checking"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(name); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiSignature_name(), vmSymbols::createRiSignature_signature(), &args, THREAD); - check_pending_exception("Error while calling createRiSignature"); - return (oop) result.get_jobject(); -} - -oop VMExits::createCiConstant(Handle kind, jlong value, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_oop(kind()); - args.push_long(value); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstant_name(), vmSymbols::createCiConstant_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantFloat"); - return (oop) result.get_jobject(); - -} - -oop VMExits::createCiConstantFloat(jfloat value, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_float(value); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantFloat_name(), vmSymbols::createCiConstantFloat_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantFloat"); - return (oop) result.get_jobject(); - -} - -oop VMExits::createCiConstantDouble(jdouble value, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - args.push_oop(instance()); - args.push_double(value); - JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantDouble_name(), vmSymbols::createCiConstantDouble_signature(), &args, THREAD); - check_pending_exception("Error while calling createCiConstantDouble"); - return (oop) result.get_jobject(); -} - -oop VMExits::createCiConstantObject(Handle object, TRAPS) { - JavaValue result(T_OBJECT); - JavaCallArguments args; - KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current()); - JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::createCiConstantObject_signature(), object, THREAD); - check_pending_exception("Error while calling CiConstant.forObject"); - return (oop) result.get_jobject(); -} - diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalVMExits.hpp --- a/src/share/vm/graal/graalVMExits.hpp Wed Jan 04 10:49:09 2012 -0800 +++ b/src/share/vm/graal/graalVMExits.hpp Wed Jan 04 20:59:11 2012 +0100 @@ -29,7 +29,7 @@ #include "runtime/jniHandles.hpp" #include "runtime/javaCalls.hpp" -class VMExits : public AllStatic { +class VMToCompiler : public AllStatic { private: static jobject _compilerPermObject; diff -r 35b05867c94a -r 5c80ccb80036 src/share/vm/graal/graalVMToCompiler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalVMToCompiler.cpp Wed Jan 04 20:59:11 2012 +0100 @@ -0,0 +1,279 @@ +/* + * Copyright (c) 2011, 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. + */ + +#include "precompiled.hpp" +#include "graal/graalVMToCompiler.hpp" + +// this is a *global* handle +jobject VMToCompiler::_compilerPermObject = NULL; +jobject VMToCompiler::_vmExitsPermObject = NULL; +jobject VMToCompiler::_vmExitsPermKlass = NULL; + +KlassHandle VMToCompiler::vmExitsKlass() { + if (JNIHandles::resolve(_vmExitsPermKlass) == NULL) { + klassOop result = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_VMExits(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(result, "Couldn't find class com.oracle.max.graal.hotspot.bridge.VMToCompiler"); + _vmExitsPermKlass = JNIHandles::make_global(result); + } + return KlassHandle((klassOop)JNIHandles::resolve_non_null(_vmExitsPermKlass)); +} + +Handle VMToCompiler::compilerInstance() { + if (JNIHandles::resolve(_compilerPermObject) == NULL) { + KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.graal.CompilerImpl"); + + JavaValue result(T_OBJECT); + JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::getInstance_name(), vmSymbols::getInstance_signature(), Thread::current()); + check_pending_exception("Couldn't get Compiler"); + _compilerPermObject = JNIHandles::make_global((oop) result.get_jobject()); + } + return Handle(JNIHandles::resolve_non_null(_compilerPermObject)); +} + +Handle VMToCompiler::instance() { + if (JNIHandles::resolve(_vmExitsPermObject) == NULL) { + KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_Compiler(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.Compiler"); + + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.set_receiver(compilerInstance()); + JavaCalls::call_interface(&result, compilerKlass, vmSymbols::getVMExits_name(), vmSymbols::getVMExits_signature(), &args, Thread::current()); + check_pending_exception("Couldn't get VMExits"); + _vmExitsPermObject = JNIHandles::make_global((oop) result.get_jobject()); + } + return Handle(JNIHandles::resolve_non_null(_vmExitsPermObject)); +} + +void VMToCompiler::initializeCompiler() { + KlassHandle compilerImplKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_CompilerImpl(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerImplKlass(), "Couldn't find class com.sun.hotspot.graal.CompilerImpl"); + + JavaValue result(T_VOID); + JavaCalls::call_static(&result, compilerImplKlass, vmSymbols::initialize_name(), vmSymbols::void_method_signature(), Thread::current()); + check_pending_exception("Couldn't initialize compiler"); +} + +jboolean VMToCompiler::setOption(Handle option) { + assert(!option.is_null(), ""); + KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.HotSpotOptions"); + + Thread* THREAD = Thread::current(); + JavaValue result(T_BOOLEAN); + JavaCalls::call_static(&result, compilerKlass, vmSymbols::setOption_name(), vmSymbols::setOption_signature(), option, THREAD); + check_pending_exception("Error while calling setOption"); + return result.get_jboolean(); +} + +void VMToCompiler::setDefaultOptions() { + KlassHandle compilerKlass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_hotspot_graal_HotSpotOptions(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + check_not_null(compilerKlass(), "Couldn't find class com.sun.hotspot.graal.HotSpotOptions"); + + Thread* THREAD = Thread::current(); + JavaValue result(T_VOID); + JavaCalls::call_static(&result, compilerKlass, vmSymbols::setDefaultOptions_name(), vmSymbols::void_method_signature(), THREAD); + check_pending_exception("Error while calling setDefaultOptions"); +} + +void VMToCompiler::compileMethod(Handle hotspot_method, int entry_bci, jboolean blocking) { + assert(!hotspot_method.is_null(), "just checking"); + Thread* THREAD = Thread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(hotspot_method); + args.push_int(entry_bci); + args.push_int(blocking); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::compileMethod_name(), vmSymbols::compileMethod_signature(), &args, THREAD); + check_pending_exception("Error while calling compileMethod"); +} + +void VMToCompiler::shutdownCompiler() { + if (_compilerPermObject != NULL) { + HandleMark hm; + JavaThread* THREAD = JavaThread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(instance()); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::shutdownCompiler_name(), vmSymbols::void_method_signature(), &args, THREAD); + check_pending_exception("Error while calling shutdownCompiler"); + + JNIHandles::destroy_global(_compilerPermObject); + JNIHandles::destroy_global(_vmExitsPermObject); + JNIHandles::destroy_global(_vmExitsPermKlass); + + _compilerPermObject = NULL; + _vmExitsPermObject = NULL; + _vmExitsPermKlass = NULL; + } +} + +void VMToCompiler::startCompiler() { + JavaThread* THREAD = JavaThread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(instance()); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::startCompiler_name(), vmSymbols::void_method_signature(), &args, THREAD); + check_pending_exception("Error while calling startCompiler"); +} + +void VMToCompiler::bootstrap() { + JavaThread* THREAD = JavaThread::current(); + JavaValue result(T_VOID); + JavaCallArguments args; + args.push_oop(instance()); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::bootstrap_name(), vmSymbols::void_method_signature(), &args, THREAD); + check_pending_exception("Error while calling boostrap"); +} + +oop VMToCompiler::createRiMethodResolved(jlong vmId, Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_long(vmId); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodResolved_name(), vmSymbols::createRiMethodResolved_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiMethodResolved"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createRiMethodUnresolved(Handle name, Handle signature, Handle holder, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(name); + args.push_oop(signature); + args.push_oop(holder); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiMethodUnresolved_name(), vmSymbols::createRiMethodUnresolved_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiMethodUnresolved"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createRiField(Handle holder, Handle name, Handle type, int index, int flags, TRAPS) { + assert(!holder.is_null(), "just checking"); + assert(!name.is_null(), "just checking"); + assert(!type.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(holder); + args.push_oop(name); + args.push_oop(type); + args.push_int(index); + args.push_int(flags); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiField_name(), vmSymbols::createRiField_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiField"); + assert(result.get_type() == T_OBJECT, "just checking"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createRiType(jlong vmId, Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_long(vmId); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiType_name(), vmSymbols::createRiType_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiType"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createRiTypePrimitive(int basic_type, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_int(basic_type); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypePrimitive_name(), vmSymbols::createRiTypePrimitive_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiTypePrimitive"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createRiTypeUnresolved(Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiTypeUnresolved_name(), vmSymbols::createRiTypeUnresolved_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiTypeUnresolved"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createRiSignature(Handle name, TRAPS) { + assert(!name.is_null(), "just checking"); + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(name); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createRiSignature_name(), vmSymbols::createRiSignature_signature(), &args, THREAD); + check_pending_exception("Error while calling createRiSignature"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createCiConstant(Handle kind, jlong value, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_oop(kind()); + args.push_long(value); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstant_name(), vmSymbols::createCiConstant_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantFloat"); + return (oop) result.get_jobject(); + +} + +oop VMToCompiler::createCiConstantFloat(jfloat value, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_float(value); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantFloat_name(), vmSymbols::createCiConstantFloat_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantFloat"); + return (oop) result.get_jobject(); + +} + +oop VMToCompiler::createCiConstantDouble(jdouble value, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + args.push_oop(instance()); + args.push_double(value); + JavaCalls::call_interface(&result, vmExitsKlass(), vmSymbols::createCiConstantDouble_name(), vmSymbols::createCiConstantDouble_signature(), &args, THREAD); + check_pending_exception("Error while calling createCiConstantDouble"); + return (oop) result.get_jobject(); +} + +oop VMToCompiler::createCiConstantObject(Handle object, TRAPS) { + JavaValue result(T_OBJECT); + JavaCallArguments args; + KlassHandle klass = SystemDictionary::resolve_or_null(vmSymbols::com_sun_cri_ci_CiConstant(), SystemDictionary::java_system_loader(), NULL, Thread::current()); + JavaCalls::call_static(&result, klass(), vmSymbols::forObject_name(), vmSymbols::createCiConstantObject_signature(), object, THREAD); + check_pending_exception("Error while calling CiConstant.forObject"); + return (oop) result.get_jobject(); +} +