# HG changeset patch # User Doug Simon # Date 1358280692 -3600 # Node ID d0fbdf2f7a0ed49790a57bf66dd1256ccbdabf31 # Parent 36474f315a8a7cb425a5b0fdacc72010632ad75c added com.sun.crypto.provider.CipherBlockChaining intrinsifications diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRuntime.java Tue Jan 15 21:11:32 2013 +0100 @@ -38,6 +38,8 @@ import static com.oracle.graal.hotspot.nodes.VerifyOopStubCall.*; import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.DecryptBlockStubCall.*; import static com.oracle.graal.hotspot.snippets.AESCryptSubstitutions.EncryptBlockStubCall.*; +import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.DecryptAESCryptStubCall.*; +import static com.oracle.graal.hotspot.snippets.CipherBlockChainingSubstitutions.EncryptAESCryptStubCall.*; import static com.oracle.graal.lir.amd64.AMD64Call.*; import com.oracle.graal.api.code.*; @@ -154,6 +156,24 @@ /* arg0: in */ carg(0, word), /* arg1: out */ carg(1, word), /* arg2: key */ carg(2, word)); + + addRuntimeCall(ENCRYPT, config.cipherBlockChainingEncryptAESCryptStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: in */ carg(0, word), + /* arg1: out */ carg(1, word), + /* arg2: key */ carg(2, word), + /* arg3: r */ carg(3, word), + /* arg4: inLength */ carg(4, Kind.Int)); + + addRuntimeCall(DECRYPT, config.cipherBlockChainingDecryptAESCryptStub, + /* temps */ null, + /* ret */ ret(Kind.Void), + /* arg0: in */ carg(0, word), + /* arg1: out */ carg(1, word), + /* arg2: key */ carg(2, word), + /* arg3: r */ carg(3, word), + /* arg4: inLength */ carg(4, Kind.Int)); } @Override diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotSnippetInstaller.java Tue Jan 15 21:11:32 2013 +0100 @@ -49,12 +49,14 @@ return; } } - } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class) { + } else if (substituteMethod.getDeclaringClass() == AESCryptSubstitutions.class || substituteMethod.getDeclaringClass() == CipherBlockChainingSubstitutions.class) { if (!config.useAESIntrinsics) { return; } assert config.aescryptEncryptBlockStub != 0L; assert config.aescryptDecryptBlockStub != 0L; + assert config.cipherBlockChainingEncryptAESCryptStub != 0L; + assert config.cipherBlockChainingDecryptAESCryptStub != 0L; } super.installSubstitution(originalMethod, substituteMethod); } diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotVMConfig.java Tue Jan 15 21:11:32 2013 +0100 @@ -338,6 +338,8 @@ public long identityHashCodeStub; public long aescryptEncryptBlockStub; public long aescryptDecryptBlockStub; + public long cipherBlockChainingEncryptAESCryptStub; + public long cipherBlockChainingDecryptAESCryptStub; public int deoptReasonNullCheck; public int deoptReasonRangeCheck; diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/bridge/VMToCompilerImpl.java Tue Jan 15 21:11:32 2013 +0100 @@ -23,7 +23,7 @@ package com.oracle.graal.hotspot.bridge; -import static com.oracle.graal.graph.FieldIntrospection.*; +import static com.oracle.graal.graph.UnsafeAccess.*; import java.io.*; import java.lang.reflect.*; diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotRuntime.java Tue Jan 15 21:11:32 2013 +0100 @@ -322,8 +322,9 @@ if (GraalOptions.IntrinsifyClassMethods) { installer.installSubstitutions(ClassSubstitutions.class); } - if (GraalOptions.IntrinsifyAESCryptMethods) { + if (GraalOptions.IntrinsifyAESMethods) { installer.installSubstitutions(AESCryptSubstitutions.class); + installer.installSubstitutions(CipherBlockChainingSubstitutions.class); } if (GraalOptions.IntrinsifyArrayCopy) { installer.installSnippets(ArrayCopySnippets.class); diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/AESCryptSubstitutions.java Tue Jan 15 21:11:32 2013 +0100 @@ -44,13 +44,16 @@ @ClassSubstitution(className = "com.sun.crypto.provider.AESCrypt") public class AESCryptSubstitutions { - private static final long kOffset; + static final long kOffset; + static final Class AESCryptClass; + static { try { // Need to use launcher class path as com.sun.crypto.provider.AESCrypt // is normally not on the boot class path ClassLoader cl = Launcher.getLauncher().getClassLoader(); - kOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.AESCrypt", true, cl).getDeclaredField("K")); + AESCryptClass = Class.forName("com.sun.crypto.provider.AESCrypt", true, cl); + kOffset = UnsafeAccess.unsafe.objectFieldOffset(AESCryptClass.getDeclaredField("K")); } catch (Exception ex) { throw new GraalInternalError(ex); } diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/snippets/CipherBlockChainingSubstitutions.java Tue Jan 15 21:11:32 2013 +0100 @@ -0,0 +1,152 @@ +/* + * Copyright (c) 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.graal.hotspot.snippets; + +import static com.oracle.graal.hotspot.snippets.HotSpotSnippetUtils.*; +import sun.misc.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.RuntimeCallTarget.Descriptor; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.gen.*; +import com.oracle.graal.compiler.target.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.hotspot.nodes.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.type.*; +import com.oracle.graal.snippets.*; +import com.oracle.graal.snippets.ClassSubstitution.MethodSubstitution; +import com.oracle.graal.snippets.Snippet.Fold; +import com.oracle.graal.word.*; + +/** + * Substitutions for {@code com.sun.crypto.provider.CipherBlockChaining} methods. + */ +@ClassSubstitution(className = "com.sun.crypto.provider.CipherBlockChaining") +public class CipherBlockChainingSubstitutions { + + private static final long embeddedCipherOffset; + private static final long rOffset; + static { + try { + // Need to use launcher class path as com.sun.crypto.provider.AESCrypt + // is normally not on the boot class path + ClassLoader cl = Launcher.getLauncher().getClassLoader(); + embeddedCipherOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.FeedbackCipher", true, cl).getDeclaredField("embeddedCipher")); + rOffset = UnsafeAccess.unsafe.objectFieldOffset(Class.forName("com.sun.crypto.provider.CipherBlockChaining", true, cl).getDeclaredField("r")); + } catch (Exception ex) { + throw new GraalInternalError(ex); + } + } + + @Fold + private static Class getAESCryptClass() { + return AESCryptSubstitutions.AESCryptClass; + } + + @MethodSubstitution(isStatic = false) + static void encrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset)); + if (getAESCryptClass().isInstance(embeddedCipher)) { + Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + EncryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength); + } else { + encrypt(rcvr, in, inOffset, inLength, out, outOffset); + } + } + + @MethodSubstitution(isStatic = false) + static void decrypt(Object rcvr, byte[] in, int inOffset, int inLength, byte[] out, int outOffset) { + Object embeddedCipher = Word.fromObject(rcvr).readObject(Word.unsigned(embeddedCipherOffset)); + if (in != out && getAESCryptClass().isInstance(embeddedCipher)) { + Word kAddr = Word.fromObject(embeddedCipher).readWord(Word.unsigned(AESCryptSubstitutions.kOffset)).add(arrayBaseOffset(Kind.Byte)); + Word rAddr = Word.unsigned(GetObjectAddressNode.get(rcvr)).readWord(Word.unsigned(rOffset)).add(arrayBaseOffset(Kind.Byte)); + Word inAddr = Word.unsigned(GetObjectAddressNode.get(in) + arrayBaseOffset(Kind.Byte) + inOffset); + Word outAddr = Word.unsigned(GetObjectAddressNode.get(out) + arrayBaseOffset(Kind.Byte) + outOffset); + DecryptAESCryptStubCall.call(inAddr, outAddr, kAddr, rAddr, inLength); + } else { + decrypt(rcvr, in, inOffset, inLength, out, outOffset); + } + } + + public static class EncryptAESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode in; + @Input private final ValueNode out; + @Input private final ValueNode key; + @Input private final ValueNode r; + @Input private final ValueNode inLength; + + public static final Descriptor ENCRYPT = new Descriptor("encrypt", false, void.class, Word.class, Word.class, Word.class, Word.class, int.class); + + public EncryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) { + super(StampFactory.forVoid()); + this.in = in; + this.out = out; + this.key = key; + this.r = r; + this.inLength = inLength; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(ENCRYPT); + gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength)); + } + + @NodeIntrinsic + public static native void call(Word in, Word out, Word key, Word r, int inLength); + } + + public static class DecryptAESCryptStubCall extends FixedWithNextNode implements LIRGenLowerable { + + @Input private final ValueNode in; + @Input private final ValueNode out; + @Input private final ValueNode key; + @Input private final ValueNode r; + @Input private final ValueNode inLength; + + public static final Descriptor DECRYPT = new Descriptor("decrypt", false, void.class, Word.class, Word.class, Word.class, Word.class, int.class); + + public DecryptAESCryptStubCall(ValueNode in, ValueNode out, ValueNode key, ValueNode r, ValueNode inLength) { + super(StampFactory.forVoid()); + this.in = in; + this.out = out; + this.key = key; + this.r = r; + this.inLength = inLength; + } + + @Override + public void generate(LIRGenerator gen) { + RuntimeCallTarget stub = gen.getRuntime().lookupRuntimeCall(DECRYPT); + gen.emitCall(stub, stub.getCallingConvention(), false, gen.operand(in), gen.operand(out), gen.operand(key), gen.operand(r), gen.operand(inLength)); + } + + @NodeIntrinsic + public static native void call(Word in, Word out, Word key, Word r, int inLength); + } +} diff -r 36474f315a8a -r d0fbdf2f7a0e graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java --- a/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Jan 15 21:08:13 2013 +0100 +++ b/graal/com.oracle.graal.phases/src/com/oracle/graal/phases/GraalOptions.java Tue Jan 15 21:11:32 2013 +0100 @@ -208,7 +208,7 @@ public static boolean IntrinsifyThreadMethods = true; public static boolean IntrinsifyUnsafeMethods = true; public static boolean IntrinsifyMathMethods = true; - public static boolean IntrinsifyAESCryptMethods = true; + public static boolean IntrinsifyAESMethods = true; /** * Counts the various paths taken through snippets. diff -r 36474f315a8a -r d0fbdf2f7a0e src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Tue Jan 15 21:08:13 2013 +0100 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Tue Jan 15 21:11:32 2013 +0100 @@ -736,6 +736,8 @@ set_long("logPrintfStub", VmIds::addStub(GraalRuntime::entry_for(GraalRuntime::graal_log_printf_id))); set_long("aescryptEncryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_encryptBlock())); set_long("aescryptDecryptBlockStub", VmIds::addStub(StubRoutines::aescrypt_decryptBlock())); + set_long("cipherBlockChainingEncryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_encryptAESCrypt())); + set_long("cipherBlockChainingDecryptAESCryptStub", VmIds::addStub(StubRoutines::cipherBlockChaining_decryptAESCrypt())); set_int("deoptReasonNone", Deoptimization::Reason_none); set_int("deoptReasonNullCheck", Deoptimization::Reason_null_check);