27 import java.io.IOException; |
27 import java.io.IOException; |
28 import java.security.MessageDigest; |
28 import java.security.MessageDigest; |
29 import java.security.NoSuchAlgorithmException; |
29 import java.security.NoSuchAlgorithmException; |
30 import java.util.Arrays; |
30 import java.util.Arrays; |
31 |
31 |
32 import jdk.vm.ci.common.JVMCIError; |
|
33 import jdk.vm.ci.meta.ResolvedJavaMethod; |
32 import jdk.vm.ci.meta.ResolvedJavaMethod; |
34 import jdk.vm.ci.meta.ResolvedJavaType; |
33 import jdk.vm.ci.meta.ResolvedJavaType; |
35 import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding; |
34 import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding; |
36 |
35 |
37 /** |
36 /** |
38 * Implements a {@link SpeculationReasonEncoding} that {@linkplain #getByteArray() produces} a byte |
37 * Implements a {@link SpeculationReasonEncoding} that {@linkplain #getByteArray() produces} a byte |
39 * array. Data is added via a {@link DataOutputStream}. When producing the final byte array, if the |
38 * array. Data is added via a {@link DataOutputStream}. When producing the final byte array, if the |
40 * total length of data exceeds the length of a SHA-1 digest, then a SHA-1 digest of the data is |
39 * total length of data exceeds the length of a SHA-1 digest and a SHA-1 digest algorithm is |
41 * produced instead. |
40 * available, then a SHA-1 digest of the data is produced instead. |
42 */ |
41 */ |
43 final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements SpeculationReasonEncoding { |
42 final class HotSpotSpeculationEncoding extends ByteArrayOutputStream implements SpeculationReasonEncoding { |
44 |
43 |
45 private DataOutputStream dos = new DataOutputStream(this); |
44 private DataOutputStream dos = new DataOutputStream(this); |
46 private byte[] result; |
45 private byte[] result; |
150 } |
149 } |
151 return false; |
150 return false; |
152 } |
151 } |
153 |
152 |
154 /** |
153 /** |
155 * Prototype SHA1 digest that is cloned before use. |
154 * Prototype SHA1 digest. |
156 */ |
155 */ |
157 private static final MessageDigest SHA1 = getSHA1(); |
156 private static final MessageDigest SHA1; |
158 private static final int SHA1_LENGTH = SHA1.getDigestLength(); |
157 |
159 |
158 /** |
160 private static MessageDigest getSHA1() { |
159 * Cloning the prototype is quicker than calling {@link MessageDigest#getInstance(String)} every |
161 try { |
160 * time. |
162 MessageDigest sha1 = MessageDigest.getInstance("SHA-1"); |
161 */ |
|
162 private static final boolean SHA1_IS_CLONEABLE; |
|
163 private static final int SHA1_LENGTH; |
|
164 |
|
165 static { |
|
166 MessageDigest sha1 = null; |
|
167 boolean sha1IsCloneable = false; |
|
168 try { |
|
169 sha1 = MessageDigest.getInstance("SHA-1"); |
163 sha1.clone(); |
170 sha1.clone(); |
164 return sha1; |
171 sha1IsCloneable = true; |
165 } catch (CloneNotSupportedException | NoSuchAlgorithmException e) { |
172 } catch (NoSuchAlgorithmException e) { |
166 // Should never happen given that SHA-1 is mandated in a |
173 // Should never happen given that SHA-1 is mandated in a |
167 // compliant Java platform implementation. |
174 // compliant Java platform implementation. However, be |
168 throw new JVMCIError("Expect a cloneable implementation of a SHA-1 message digest to be available", e); |
175 // conservative and fall back to not using a digest. |
169 } |
176 } catch (CloneNotSupportedException e) { |
|
177 } |
|
178 SHA1 = sha1; |
|
179 SHA1_IS_CLONEABLE = sha1IsCloneable; |
|
180 SHA1_LENGTH = SHA1 == null ? 20 : SHA1.getDigestLength(); |
170 } |
181 } |
171 |
182 |
172 /** |
183 /** |
173 * Gets the final encoded byte array and closes this encoding such that any further attempts to |
184 * Gets the final encoded byte array and closes this encoding such that any further attempts to |
174 * update it result in an {@link IllegalArgumentException}. |
185 * update it result in an {@link IllegalArgumentException}. |
175 */ |
186 */ |
176 byte[] getByteArray() { |
187 byte[] getByteArray() { |
177 if (result == null) { |
188 if (result == null) { |
178 if (count > SHA1_LENGTH) { |
189 if (SHA1 != null && count > SHA1_LENGTH) { |
179 try { |
190 try { |
180 MessageDigest md = (MessageDigest) SHA1.clone(); |
191 MessageDigest md = SHA1_IS_CLONEABLE ? (MessageDigest) SHA1.clone() : MessageDigest.getInstance("SHA-1"); |
181 md.update(buf, 0, count); |
192 md.update(buf, 0, count); |
182 result = md.digest(); |
193 result = md.digest(); |
183 } catch (CloneNotSupportedException e) { |
194 } catch (CloneNotSupportedException | NoSuchAlgorithmException e) { |
184 throw new InternalError(e); |
195 throw new InternalError(e); |
185 } |
196 } |
186 } else { |
197 } else { |
187 if (buf.length == count) { |
198 if (buf.length == count) { |
188 // No need to copy the byte array |
199 // No need to copy the byte array |