From e55eebc5ed578e1bf8558f68dd35297d8189810b Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Mon, 14 Apr 2014 21:02:31 +0000 Subject: [PATCH 01/91] 8037846: Ensure streaming of input cipher streams Reviewed-by: xuelei, valeriep --- .../share/classes/javax/crypto/CipherInputStream.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java b/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java index f9be4611d83..0930f9d6426 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java +++ b/jdk/src/java.base/share/classes/javax/crypto/CipherInputStream.java @@ -107,9 +107,10 @@ public class CipherInputStream extends FilterInputStream { done = true; try { obuffer = cipher.doFinal(); + } catch (IllegalBlockSizeException | BadPaddingException e) { + obuffer = null; + throw new IOException(e); } - catch (IllegalBlockSizeException e) {obuffer = null;} - catch (BadPaddingException e) {obuffer = null;} if (obuffer == null) return -1; else { @@ -120,7 +121,10 @@ public class CipherInputStream extends FilterInputStream { } try { obuffer = cipher.update(ibuffer, 0, readin); - } catch (IllegalStateException e) {obuffer = null;}; + } catch (IllegalStateException e) { + obuffer = null; + throw e; + } ostart = 0; if (obuffer == null) ofinish = 0; @@ -302,6 +306,7 @@ public class CipherInputStream extends FilterInputStream { } } catch (BadPaddingException | IllegalBlockSizeException ex) { + throw new IOException(ex); } ostart = 0; ofinish = 0; From 1d8cb90952f7a6f9ccdaa7f77dc10eaa1c46f3a2 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 21 Apr 2014 11:08:30 -0700 Subject: [PATCH 02/91] 8036936: Use local locales Made sure cache key is cleare on GC invocation Reviewed-by: okutsu --- .../classes/sun/util/locale/BaseLocale.java | 90 ++++++++++--------- .../sun/util/locale/LocaleObjectCache.java | 4 +- 2 files changed, 53 insertions(+), 41 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 137fd82f7dd..2f4da3d5960 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -31,6 +31,7 @@ */ package sun.util.locale; +import java.lang.ref.SoftReference; import java.util.StringJoiner; @@ -151,11 +152,11 @@ public final class BaseLocale { return h; } - private static final class Key implements Comparable { - private final String lang; - private final String scrt; - private final String regn; - private final String vart; + private static final class Key { + private final SoftReference lang; + private final SoftReference scrt; + private final SoftReference regn; + private final SoftReference vart; private final boolean normalized; private final int hash; @@ -167,10 +168,10 @@ public final class BaseLocale { assert language.intern() == language && region.intern() == region; - lang = language; - scrt = ""; - regn = region; - vart = ""; + lang = new SoftReference<>(language); + scrt = new SoftReference<>(""); + regn = new SoftReference<>(region); + vart = new SoftReference<>(""); this.normalized = true; int h = language.hashCode(); @@ -191,40 +192,40 @@ public final class BaseLocale { String variant, boolean normalized) { int h = 0; if (language != null) { - lang = language; + lang = new SoftReference<>(language); int len = language.length(); for (int i = 0; i < len; i++) { h = 31*h + LocaleUtils.toLower(language.charAt(i)); } } else { - lang = ""; + lang = new SoftReference<>(""); } if (script != null) { - scrt = script; + scrt = new SoftReference<>(script); int len = script.length(); for (int i = 0; i < len; i++) { h = 31*h + LocaleUtils.toLower(script.charAt(i)); } } else { - scrt = ""; + scrt = new SoftReference<>(""); } if (region != null) { - regn = region; + regn = new SoftReference<>(region); int len = region.length(); for (int i = 0; i < len; i++) { h = 31*h + LocaleUtils.toLower(region.charAt(i)); } } else { - regn = ""; + regn = new SoftReference<>(""); } if (variant != null) { - vart = variant; + vart = new SoftReference<>(variant); int len = variant.length(); for (int i = 0; i < len; i++) { h = 31*h + variant.charAt(i); } } else { - vart = ""; + vart = new SoftReference<>(""); } hash = h; this.normalized = normalized; @@ -232,28 +233,31 @@ public final class BaseLocale { @Override public boolean equals(Object obj) { - return (this == obj) || - (obj instanceof Key) - && this.hash == ((Key)obj).hash - && LocaleUtils.caseIgnoreMatch(((Key)obj).lang, this.lang) - && LocaleUtils.caseIgnoreMatch(((Key)obj).scrt, this.scrt) - && LocaleUtils.caseIgnoreMatch(((Key)obj).regn, this.regn) - && ((Key)obj).vart.equals(vart); // variant is case sensitive in JDK! - } + if (this == obj) { + return true; + } - @Override - public int compareTo(Key other) { - int res = LocaleUtils.caseIgnoreCompare(this.lang, other.lang); - if (res == 0) { - res = LocaleUtils.caseIgnoreCompare(this.scrt, other.scrt); - if (res == 0) { - res = LocaleUtils.caseIgnoreCompare(this.regn, other.regn); - if (res == 0) { - res = this.vart.compareTo(other.vart); + if (obj instanceof Key && this.hash == ((Key)obj).hash) { + String tl = this.lang.get(); + String ol = ((Key)obj).lang.get(); + if (tl != null && ol != null && + LocaleUtils.caseIgnoreMatch(ol, tl)) { + String ts = this.scrt.get(); + String os = ((Key)obj).scrt.get(); + if (ts != null && os != null && + LocaleUtils.caseIgnoreMatch(os, ts)) { + String tr = this.regn.get(); + String or = ((Key)obj).regn.get(); + if (tr != null && or != null && + LocaleUtils.caseIgnoreMatch(or, tr)) { + String tv = this.vart.get(); + String ov = ((Key)obj).vart.get(); + return (ov != null && ov.equals(tv)); + } } } } - return res; + return false; } @Override @@ -266,10 +270,10 @@ public final class BaseLocale { return key; } - String lang = LocaleUtils.toLowerString(key.lang).intern(); - String scrt = LocaleUtils.toTitleString(key.scrt).intern(); - String regn = LocaleUtils.toUpperString(key.regn).intern(); - String vart = key.vart.intern(); // preserve upper/lower cases + String lang = LocaleUtils.toLowerString(key.lang.get()).intern(); + String scrt = LocaleUtils.toTitleString(key.scrt.get()).intern(); + String regn = LocaleUtils.toUpperString(key.regn.get()).intern(); + String vart = key.vart.get().intern(); // preserve upper/lower cases return new Key(lang, scrt, regn, vart, true); } @@ -282,12 +286,18 @@ public final class BaseLocale { @Override protected Key normalizeKey(Key key) { + assert key.lang.get() != null && + key.scrt.get() != null && + key.regn.get() != null && + key.vart.get() != null; + return Key.normalize(key); } @Override protected BaseLocale createObject(Key key) { - return new BaseLocale(key.lang, key.scrt, key.regn, key.vart); + return new BaseLocale(key.lang.get(), key.scrt.get(), + key.regn.get(), key.vart.get()); } } } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java b/jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java index 88920aaf50c..eae1480882b 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/LocaleObjectCache.java @@ -57,8 +57,10 @@ public abstract class LocaleObjectCache { value = entry.get(); } if (value == null) { - key = normalizeKey(key); V newVal = createObject(key); + // make sure key is normalized *after* the object creation + // so that newVal is assured to be created from a valid key. + key = normalizeKey(key); if (key == null || newVal == null) { // subclass must return non-null key/value object return null; From 9cba51fbc5aba121d8809e5d91a7b185832197d0 Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Tue, 22 Apr 2014 00:43:56 +0000 Subject: [PATCH 03/91] 8037066: Secure transport layer Reviewed-by: weijun, ahgross, asmotrak, mbankal --- .../sun/security/ssl/ClientHandshaker.java | 193 +++++++++++++++++- .../classes/sun/security/ssl/Handshaker.java | 13 +- .../sun/security/ssl/SSLSessionImpl.java | 26 ++- 3 files changed, 223 insertions(+), 9 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java index 5c3abbcdab5..5108528f283 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ClientHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,8 @@ import java.security.spec.ECParameterSpec; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; +import java.security.cert.CertificateParsingException; +import javax.security.auth.x500.X500Principal; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; @@ -89,11 +91,65 @@ final class ClientHandshaker extends Handshaker { private final static boolean enableSNIExtension = Debug.getBooleanProperty("jsse.enableSNIExtension", true); + /* + * Allow unsafe server certificate change? + * + * Server certificate change during SSL/TLS renegotiation may be considered + * unsafe, as described in the Triple Handshake attacks: + * + * https://secure-resumption.com/tlsauth.pdf + * + * Endpoint identification (See + * SSLParameters.getEndpointIdentificationAlgorithm()) is a pretty nice + * guarantee that the server certificate change in renegotiation is legal. + * However, endpoing identification is only enabled for HTTPS and LDAP + * over SSL/TLS by default. It is not enough to protect SSL/TLS + * connections other than HTTPS and LDAP. + * + * The renegotiation indication extension (See RFC 5764) is a pretty + * strong guarantee that the endpoints on both client and server sides + * are identical on the same connection. However, the Triple Handshake + * attacks can bypass this guarantee if there is a session-resumption + * handshake between the initial full handshake and the renegotiation + * full handshake. + * + * Server certificate change may be unsafe and should be restricted if + * endpoint identification is not enabled and the previous handshake is + * a session-resumption abbreviated initial handshake, unless the + * identities represented by both certificates can be regraded as the + * same (See isIdentityEquivalent()). + * + * Considering the compatibility impact and the actual requirements to + * support server certificate change in practice, the system property, + * jdk.tls.allowUnsafeServerCertChange, is used to define whether unsafe + * server certificate change in renegotiation is allowed or not. The + * default value of the system property is "false". To mitigate the + * compactibility impact, applications may want to set the system + * property to "true" at their own risk. + * + * If the value of the system property is "false", server certificate + * change in renegotiation after a session-resumption abbreviated initial + * handshake is restricted (See isIdentityEquivalent()). + * + * If the system property is set to "true" explicitly, the restriction on + * server certificate change in renegotiation is disabled. + */ + private final static boolean allowUnsafeServerCertChange = + Debug.getBooleanProperty("jdk.tls.allowUnsafeServerCertChange", false); + private List requestedServerNames = Collections.emptyList(); private boolean serverNamesAccepted = false; + /* + * the reserved server certificate chain in previous handshaking + * + * The server certificate chain is only reserved if the previous + * handshake is a session-resumption abbreviated initial handshake. + */ + private X509Certificate[] reservedServerCerts = null; + /* * Constructors */ @@ -555,14 +611,19 @@ final class ClientHandshaker extends Handshaker { // we wanted to resume, but the server refused session = null; if (!enableNewSession) { - throw new SSLException - ("New session creation is disabled"); + throw new SSLException("New session creation is disabled"); } } } if (resumingSession && session != null) { setHandshakeSessionSE(session); + // Reserve the handshake state if this is a session-resumption + // abbreviated initial handshake. + if (isInitialHandshake) { + session.setAsSessionResumption(true); + } + return; } @@ -1063,6 +1124,13 @@ final class ClientHandshaker extends Handshaker { serverVerifyData = mesg.getVerifyData(); } + /* + * Reset the handshake state if this is not an initial handshake. + */ + if (!isInitialHandshake) { + session.setAsSessionResumption(false); + } + /* * OK, it verified. If we're doing the fast handshake, add that * "Finished" message to the hash of handshake messages, then send @@ -1161,8 +1229,23 @@ final class ClientHandshaker extends Handshaker { System.out.println("%% No cached client session"); } } - if ((session != null) && (session.isRejoinable() == false)) { - session = null; + if (session != null) { + // If unsafe server certificate change is not allowed, reserve + // current server certificates if the previous handshake is a + // session-resumption abbreviated initial handshake. + if (!allowUnsafeServerCertChange && session.isSessionResumption()) { + try { + // If existing, peer certificate chain cannot be null. + reservedServerCerts = + (X509Certificate[])session.getPeerCertificates(); + } catch (SSLPeerUnverifiedException puve) { + // Maybe not certificate-based, ignore the exception. + } + } + + if (!session.isRejoinable()) { + session = null; + } } if (session != null) { @@ -1331,9 +1414,28 @@ final class ClientHandshaker extends Handshaker { } X509Certificate[] peerCerts = mesg.getCertificateChain(); if (peerCerts.length == 0) { - fatalSE(Alerts.alert_bad_certificate, - "empty certificate chain"); + fatalSE(Alerts.alert_bad_certificate, "empty certificate chain"); } + + // Allow server certificate change in client side during renegotiation + // after a session-resumption abbreviated initial handshake? + // + // DO NOT need to check allowUnsafeServerCertChange here. We only + // reserve server certificates when allowUnsafeServerCertChange is + // flase. + if (reservedServerCerts != null) { + // It is not necessary to check the certificate update if endpoint + // identification is enabled. + String identityAlg = getEndpointIdentificationAlgorithmSE(); + if ((identityAlg == null || identityAlg.length() == 0) && + !isIdentityEquivalent(peerCerts[0], reservedServerCerts[0])) { + + fatalSE(Alerts.alert_bad_certificate, + "server certificate change is restricted " + + "during renegotiation"); + } + } + // ask the trust manager to verify the chain X509TrustManager tm = sslContext.getX509TrustManager(); try { @@ -1370,4 +1472,81 @@ final class ClientHandshaker extends Handshaker { } session.setPeerCertificates(peerCerts); } + + /* + * Whether the certificates can represent the same identity? + * + * The certificates can be used to represent the same identity: + * 1. If the subject alternative names of IP address are present in + * both certificates, they should be identical; otherwise, + * 2. if the subject alternative names of DNS name are present in + * both certificates, they should be identical; otherwise, + * 3. if the subject fields are present in both certificates, the + * certificate subjects and issuers should be identical. + */ + private static boolean isIdentityEquivalent(X509Certificate thisCert, + X509Certificate prevCert) { + if (thisCert.equals(prevCert)) { + return true; + } + + // check the iPAddress field in subjectAltName extension + Object thisIPAddress = getSubjectAltName(thisCert, 7); // 7: iPAddress + Object prevIPAddress = getSubjectAltName(prevCert, 7); + if (thisIPAddress != null && prevIPAddress!= null) { + // only allow the exactly match + return Objects.equals(thisIPAddress, prevIPAddress); + } + + // check the dNSName field in subjectAltName extension + Object thisDNSName = getSubjectAltName(thisCert, 2); // 2: dNSName + Object prevDNSName = getSubjectAltName(prevCert, 2); + if (thisDNSName != null && prevDNSName!= null) { + // only allow the exactly match + return Objects.equals(thisDNSName, prevDNSName); + } + + // check the certificate subject and issuer + X500Principal thisSubject = thisCert.getSubjectX500Principal(); + X500Principal prevSubject = prevCert.getSubjectX500Principal(); + X500Principal thisIssuer = thisCert.getIssuerX500Principal(); + X500Principal prevIssuer = prevCert.getIssuerX500Principal(); + if (!thisSubject.getName().isEmpty() && + !prevSubject.getName().isEmpty() && + thisSubject.equals(prevSubject) && + thisIssuer.equals(prevIssuer)) { + return true; + } + + return false; + } + + /* + * Returns the subject alternative name of the specified type in the + * subjectAltNames extension of a certificate. + */ + private static Object getSubjectAltName(X509Certificate cert, int type) { + Collection> subjectAltNames; + + try { + subjectAltNames = cert.getSubjectAlternativeNames(); + } catch (CertificateParsingException cpe) { + if (debug != null && Debug.isOn("handshake")) { + System.out.println( + "Attempt to obtain subjectAltNames extension failed!"); + } + return null; + } + + if (subjectAltNames != null) { + for (List subjectAltName : subjectAltNames) { + int subjectAltNameType = (Integer)subjectAltName.get(0); + if (subjectAltNameType == type) { + return subjectAltName.get(1); + } + } + } + + return null; + } } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java index bea8608e6ff..80c2a518c1b 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/Handshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -359,6 +359,17 @@ abstract class Handshaker { } } + String getEndpointIdentificationAlgorithmSE() { + SSLParameters paras; + if (conn != null) { + paras = conn.getSSLParameters(); + } else { + paras = engine.getSSLParameters(); + } + + return paras.getEndpointIdentificationAlgorithm(); + } + private void setVersionSE(ProtocolVersion protocolVersion) { if (conn != null) { conn.setVersion(protocolVersion); diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java index 6cb4170d34f..b5f304b6b97 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,6 +114,14 @@ final class SSLSessionImpl extends ExtendedSSLSession { private Principal peerPrincipal; private Principal localPrincipal; + /* + * Is the session currently re-established with a session-resumption + * abbreviated initial handshake? + * + * Note that currently we only set this variable in client side. + */ + private boolean isSessionResumption = false; + /* * We count session creations, eventually for statistical data but * also since counters make shorter debugging IDs than the big ones @@ -324,6 +332,22 @@ final class SSLSessionImpl extends ExtendedSSLSession { } } + /** + * Return true if the session is currently re-established with a + * session-resumption abbreviated initial handshake. + */ + boolean isSessionResumption() { + return isSessionResumption; + } + + /** + * Resets whether the session is re-established with a session-resumption + * abbreviated initial handshake. + */ + void setAsSessionResumption(boolean flag) { + isSessionResumption = flag; + } + /** * Returns the name of the cipher suite in use on this session */ From 62383e4a21c4eb80b11675523d86194b4a546abe Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 22 Apr 2014 14:07:45 -0700 Subject: [PATCH 04/91] 8035781: Improve equality for annotations Reviewed-by: jfranck, abuckley, ahgross, dmeetry --- .../AnnotationInvocationHandler.java | 113 ++++++++++++++++-- 1 file changed, 104 insertions(+), 9 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java index 6e73de70d52..120fe7aac16 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java +++ b/jdk/src/java.base/share/classes/sun/reflect/annotation/AnnotationInvocationHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.lang.annotation.*; import java.lang.reflect.*; import java.io.Serializable; import java.util.*; -import java.lang.annotation.*; import java.security.AccessController; import java.security.PrivilegedAction; @@ -45,6 +44,11 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { private final Map memberValues; AnnotationInvocationHandler(Class type, Map memberValues) { + Class[] superInterfaces = type.getInterfaces(); + if (!type.isAnnotation() || + superInterfaces.length != 1 || + superInterfaces[0] != java.lang.annotation.Annotation.class) + throw new AnnotationFormatError("Attempt to create proxy for a non-annotation type."); this.type = type; this.memberValues = memberValues; } @@ -57,13 +61,17 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { if (member.equals("equals") && paramTypes.length == 1 && paramTypes[0] == Object.class) return equalsImpl(args[0]); - assert paramTypes.length == 0; - if (member.equals("toString")) + if (paramTypes.length != 0) + throw new AssertionError("Too many parameters for an annotation method"); + + switch(member) { + case "toString": return toStringImpl(); - if (member.equals("hashCode")) + case "hashCode": return hashCodeImpl(); - if (member.equals("annotationType")) + case "annotationType": return type; + } // Handle annotation member accessors Object result = memberValues.get(member); @@ -129,7 +137,7 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { * Implementation of dynamicProxy.toString() */ private String toStringImpl() { - StringBuffer result = new StringBuffer(128); + StringBuilder result = new StringBuilder(128); result.append('@'); result.append(type.getName()); result.append('('); @@ -277,6 +285,7 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { new PrivilegedAction() { public Method[] run() { final Method[] mm = type.getDeclaredMethods(); + validateAnnotationMethods(mm); AccessibleObject.setAccessible(mm, true); return mm; } @@ -286,6 +295,94 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { } private transient volatile Method[] memberMethods = null; + /** + * Validates that a method is structurally appropriate for an + * annotation type. As of Java SE 8, annotation types cannot + * contain static methods and the declared methods of an + * annotation type must take zero arguments and there are + * restrictions on the return type. + */ + private void validateAnnotationMethods(Method[] memberMethods) { + /* + * Specification citations below are from JLS + * 9.6.1. Annotation Type Elements + */ + boolean valid = true; + for(Method method : memberMethods) { + /* + * "By virtue of the AnnotationTypeElementDeclaration + * production, a method declaration in an annotation type + * declaration cannot have formal parameters, type + * parameters, or a throws clause. + * + * "By virtue of the AnnotationTypeElementModifier + * production, a method declaration in an annotation type + * declaration cannot be default or static." + */ + if (method.getModifiers() != (Modifier.PUBLIC | Modifier.ABSTRACT) || + method.isDefault() || + method.getParameterCount() != 0 || + method.getExceptionTypes().length != 0) { + valid = false; + break; + } + + /* + * "It is a compile-time error if the return type of a + * method declared in an annotation type is not one of the + * following: a primitive type, String, Class, any + * parameterized invocation of Class, an enum type + * (section 8.9), an annotation type, or an array type + * (chapter 10) whose element type is one of the preceding + * types." + */ + Class returnType = method.getReturnType(); + if (returnType.isArray()) { + returnType = returnType.getComponentType(); + if (returnType.isArray()) { // Only single dimensional arrays + valid = false; + break; + } + } + + if (!((returnType.isPrimitive() && returnType != void.class) || + returnType == java.lang.String.class || + returnType == java.lang.Class.class || + returnType.isEnum() || + returnType.isAnnotation())) { + valid = false; + break; + } + + /* + * "It is a compile-time error if any method declared in an + * annotation type has a signature that is + * override-equivalent to that of any public or protected + * method declared in class Object or in the interface + * java.lang.annotation.Annotation." + * + * The methods in Object or Annotation meeting the other + * criteria (no arguments, contrained return type, etc.) + * above are: + * + * String toString() + * int hashCode() + * Class annotationType() + */ + String methodName = method.getName(); + if ((methodName.equals("toString") && returnType == java.lang.String.class) || + (methodName.equals("hashCode") && returnType == int.class) || + (methodName.equals("annotationType") && returnType == java.lang.Class.class)) { + valid = false; + break; + } + } + if (valid) + return; + else + throw new AnnotationFormatError("Malformed method on an annotation type"); + } + /** * Implementation of dynamicProxy.hashCode() */ @@ -330,7 +427,6 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); - // Check to make sure that types have not evolved incompatibly AnnotationType annotationType = null; @@ -343,7 +439,6 @@ class AnnotationInvocationHandler implements InvocationHandler, Serializable { Map> memberTypes = annotationType.memberTypes(); - // If there are annotation members without values, that // situation is handled by the invoke method. for (Map.Entry memberValue : memberValues.entrySet()) { From 5ce941b14301dfda807965e95fb501c4eb9eea42 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Wed, 23 Apr 2014 09:06:22 -1000 Subject: [PATCH 05/91] 8037326: VerifyAccess.isMemberAccessible() has incorrect access check Reviewed-by: jrose, twisti, ahgross --- .../classes/sun/invoke/util/VerifyAccess.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java index a95aefbafb1..fc870fc9403 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyAccess.java @@ -102,19 +102,24 @@ public class VerifyAccess { case PUBLIC: return true; // already checked above case PROTECTED: + assert !defc.isInterface(); // protected members aren't allowed in interfaces if ((allowedModes & PROTECTED_OR_PACKAGE_ALLOWED) != 0 && isSamePackage(defc, lookupClass)) return true; if ((allowedModes & PROTECTED) == 0) return false; + // Protected members are accessible by subclasses, which does not include interfaces. + // Interfaces are types, not classes. They should not have access to + // protected members in j.l.Object, even though it is their superclass. if ((mods & STATIC) != 0 && !isRelatedClass(refc, lookupClass)) return false; if ((allowedModes & PROTECTED) != 0 && - isSuperClass(defc, lookupClass)) + isSubClass(lookupClass, defc)) return true; return false; case PACKAGE_ONLY: // That is, zero. Unmarked member is package-only access. + assert !defc.isInterface(); // package-private members aren't allowed in interfaces return ((allowedModes & PACKAGE_ALLOWED) != 0 && isSamePackage(defc, lookupClass)); case PRIVATE: @@ -129,12 +134,13 @@ public class VerifyAccess { static boolean isRelatedClass(Class refc, Class lookupClass) { return (refc == lookupClass || - refc.isAssignableFrom(lookupClass) || - lookupClass.isAssignableFrom(refc)); + isSubClass(refc, lookupClass) || + isSubClass(lookupClass, refc)); } - static boolean isSuperClass(Class defc, Class lookupClass) { - return defc.isAssignableFrom(lookupClass); + static boolean isSubClass(Class lookupClass, Class defc) { + return defc.isAssignableFrom(lookupClass) && + !lookupClass.isInterface(); // interfaces are types, not classes. } static int getClassModifiers(Class c) { From d124a839cec2e8247eec1353324e138fe029f186 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Thu, 2 Oct 2014 11:36:44 -0700 Subject: [PATCH 06/91] 8059299: assert(adr_type != NULL) failed: expecting TypeKlassPtr Use top() for dead paths when initializing Phi node of exceptions klasses in Parse::catch_inline_exceptions(). Reviewed-by: jrose, vlivanov --- hotspot/src/share/vm/opto/doCall.cpp | 14 +++- hotspot/test/TEST.groups | 2 +- .../exceptions/CatchInlineExceptions.java | 81 +++++++++++++++++++ 3 files changed, 92 insertions(+), 5 deletions(-) create mode 100644 hotspot/test/compiler/exceptions/CatchInlineExceptions.java diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index 62eb88460f1..813d9450fc3 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -802,10 +802,16 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) { // each arm of the Phi. If I know something clever about the exceptions // I'm loading the class from, I can replace the LoadKlass with the // klass constant for the exception oop. - if( ex_node->is_Phi() ) { - ex_klass_node = new PhiNode( ex_node->in(0), TypeKlassPtr::OBJECT ); - for( uint i = 1; i < ex_node->req(); i++ ) { - Node* p = basic_plus_adr( ex_node->in(i), ex_node->in(i), oopDesc::klass_offset_in_bytes() ); + if (ex_node->is_Phi()) { + ex_klass_node = new PhiNode(ex_node->in(0), TypeKlassPtr::OBJECT); + for (uint i = 1; i < ex_node->req(); i++) { + Node* ex_in = ex_node->in(i); + if (ex_in == top() || ex_in == NULL) { + // This path was not taken. + ex_klass_node->init_req(i, top()); + continue; + } + Node* p = basic_plus_adr(ex_in, ex_in, oopDesc::klass_offset_in_bytes()); Node* k = _gvn.transform( LoadKlassNode::make(_gvn, immutable_memory(), p, TypeInstPtr::KLASS, TypeKlassPtr::OBJECT) ); ex_klass_node->init_req( i, k ); } diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index 6ad554b58d8..a73ae8e5f5a 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -440,7 +440,7 @@ hotspot_compiler_3 = \ compiler/codegen/ \ compiler/cpuflags/RestoreMXCSR.java \ compiler/EscapeAnalysis/ \ - compiler/exceptions/TestRecursiveReplacedException.java \ + compiler/exceptions/ \ compiler/floatingpoint/ModNaN.java \ compiler/gcbarriers/G1CrashTest.java \ compiler/inlining/ \ diff --git a/hotspot/test/compiler/exceptions/CatchInlineExceptions.java b/hotspot/test/compiler/exceptions/CatchInlineExceptions.java new file mode 100644 index 00000000000..01be927cf7b --- /dev/null +++ b/hotspot/test/compiler/exceptions/CatchInlineExceptions.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8059299 + * @summary assert(adr_type != NULL) failed: expecting TypeKlassPtr + * @run main/othervm -Xbatch CatchInlineExceptions + */ + +class Exception1 extends Exception {}; +class Exception2 extends Exception {}; + +public class CatchInlineExceptions { + private static int counter0; + private static int counter1; + private static int counter2; + private static int counter; + + static void foo(int i) throws Exception { + if ((i & 1023) == 2) { + counter0++; + throw new Exception2(); + } + } + + static void test(int i) throws Exception { + try { + foo(i); + } + catch (Exception e) { + if (e instanceof Exception1) { + counter1++; + } else if (e instanceof Exception2) { + counter2++; + } + counter++; + throw e; + } + } + + public static void main(String[] args) throws Throwable { + for (int i = 0; i < 15000; i++) { + try { + test(i); + } catch (Exception e) { + // expected + } + } + if (counter1 != 0) { + throw new RuntimeException("Failed: counter1(" + counter1 + ") != 0"); + } + if (counter2 != counter) { + throw new RuntimeException("Failed: counter2(" + counter2 + ") != counter0(" + counter0 + ")"); + } + if (counter2 != counter) { + throw new RuntimeException("Failed: counter2(" + counter2 + ") != counter(" + counter + ")"); + } + System.out.println("TEST PASSED"); + } +} From 3263a62bb4fbb74af2731c20cc0d84bedd6cff92 Mon Sep 17 00:00:00 2001 From: Goetz Lindenmaier Date: Thu, 2 Oct 2014 09:32:53 +0200 Subject: [PATCH 07/91] 8059592: Recent bugfixes in ppc64 port Reviewed-by: kvn --- hotspot/make/aix/makefiles/fastdebug.make | 1 - hotspot/src/cpu/ppc/vm/assembler_ppc.hpp | 117 +++++++++++++++++- .../src/cpu/ppc/vm/assembler_ppc.inline.hpp | 52 ++++++++ .../src/cpu/ppc/vm/globalDefinitions_ppc.hpp | 2 + hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp | 1 - hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp | 1 - hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp | 14 +-- hotspot/src/cpu/ppc/vm/ppc.ad | 58 +++++---- hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp | 6 +- .../src/cpu/ppc/vm/templateTable_ppc_64.cpp | 4 - .../vm/prefetch_linux_ppc.inline.hpp | 2 +- 11 files changed, 207 insertions(+), 51 deletions(-) diff --git a/hotspot/make/aix/makefiles/fastdebug.make b/hotspot/make/aix/makefiles/fastdebug.make index 40d792002e6..33bf50940b9 100644 --- a/hotspot/make/aix/makefiles/fastdebug.make +++ b/hotspot/make/aix/makefiles/fastdebug.make @@ -67,7 +67,6 @@ MAPFILE = $(GAMMADIR)/make/aix/makefiles/mapfile-vers-debug # not justified. LFLAGS_QIPA= -G_SUFFIX = _g VERSION = optimized SYSDEFS += -DASSERT -DFASTDEBUG PICFLAGS = DEFAULT diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp index 0c8cf435aea..7d9aecb310f 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.hpp @@ -268,8 +268,35 @@ class Assembler : public AbstractAssembler { ISEL_OPCODE = (31u << OPCODE_SHIFT | 15u << 1), - MTLR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1 | 8 << SPR_0_4_SHIFT), - MFLR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1 | 8 << SPR_0_4_SHIFT), + // Special purpose registers + MTSPR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1), + MFSPR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1), + + MTXER_OPCODE = (MTSPR_OPCODE | 1 << SPR_0_4_SHIFT), + MFXER_OPCODE = (MFSPR_OPCODE | 1 << SPR_0_4_SHIFT), + + MTDSCR_OPCODE = (MTSPR_OPCODE | 3 << SPR_0_4_SHIFT), + MFDSCR_OPCODE = (MFSPR_OPCODE | 3 << SPR_0_4_SHIFT), + + MTLR_OPCODE = (MTSPR_OPCODE | 8 << SPR_0_4_SHIFT), + MFLR_OPCODE = (MFSPR_OPCODE | 8 << SPR_0_4_SHIFT), + + MTCTR_OPCODE = (MTSPR_OPCODE | 9 << SPR_0_4_SHIFT), + MFCTR_OPCODE = (MFSPR_OPCODE | 9 << SPR_0_4_SHIFT), + + MTTFHAR_OPCODE = (MTSPR_OPCODE | 128 << SPR_0_4_SHIFT), + MFTFHAR_OPCODE = (MFSPR_OPCODE | 128 << SPR_0_4_SHIFT), + MTTFIAR_OPCODE = (MTSPR_OPCODE | 129 << SPR_0_4_SHIFT), + MFTFIAR_OPCODE = (MFSPR_OPCODE | 129 << SPR_0_4_SHIFT), + MTTEXASR_OPCODE = (MTSPR_OPCODE | 130 << SPR_0_4_SHIFT), + MFTEXASR_OPCODE = (MFSPR_OPCODE | 130 << SPR_0_4_SHIFT), + MTTEXASRU_OPCODE = (MTSPR_OPCODE | 131 << SPR_0_4_SHIFT), + MFTEXASRU_OPCODE = (MFSPR_OPCODE | 131 << SPR_0_4_SHIFT), + + MTVRSAVE_OPCODE = (MTSPR_OPCODE | 256 << SPR_0_4_SHIFT), + MFVRSAVE_OPCODE = (MFSPR_OPCODE | 256 << SPR_0_4_SHIFT), + + MFTB_OPCODE = (MFSPR_OPCODE | 268 << SPR_0_4_SHIFT), MTCRF_OPCODE = (31u << OPCODE_SHIFT | 144u << 1), MFCR_OPCODE = (31u << OPCODE_SHIFT | 19u << 1), @@ -291,9 +318,6 @@ class Assembler : public AbstractAssembler { // CTR-related opcodes BCCTR_OPCODE = (19u << OPCODE_SHIFT | 528u << 1), - MTCTR_OPCODE = (31u << OPCODE_SHIFT | 467u << 1 | 9 << SPR_0_4_SHIFT), - MFCTR_OPCODE = (31u << OPCODE_SHIFT | 339u << 1 | 9 << SPR_0_4_SHIFT), - LWZ_OPCODE = (32u << OPCODE_SHIFT), LWZX_OPCODE = (31u << OPCODE_SHIFT | 23u << 1), @@ -585,6 +609,37 @@ class Assembler : public AbstractAssembler { MTVSCR_OPCODE = (4u << OPCODE_SHIFT | 1604u ), MFVSCR_OPCODE = (4u << OPCODE_SHIFT | 1540u ), + // AES (introduced with Power 8) + VCIPHER_OPCODE = (4u << OPCODE_SHIFT | 1288u), + VCIPHERLAST_OPCODE = (4u << OPCODE_SHIFT | 1289u), + VNCIPHER_OPCODE = (4u << OPCODE_SHIFT | 1352u), + VNCIPHERLAST_OPCODE = (4u << OPCODE_SHIFT | 1353u), + VSBOX_OPCODE = (4u << OPCODE_SHIFT | 1480u), + + // SHA (introduced with Power 8) + VSHASIGMAD_OPCODE = (4u << OPCODE_SHIFT | 1730u), + VSHASIGMAW_OPCODE = (4u << OPCODE_SHIFT | 1666u), + + // Vector Binary Polynomial Multiplication (introduced with Power 8) + VPMSUMB_OPCODE = (4u << OPCODE_SHIFT | 1032u), + VPMSUMD_OPCODE = (4u << OPCODE_SHIFT | 1224u), + VPMSUMH_OPCODE = (4u << OPCODE_SHIFT | 1096u), + VPMSUMW_OPCODE = (4u << OPCODE_SHIFT | 1160u), + + // Vector Permute and Xor (introduced with Power 8) + VPERMXOR_OPCODE = (4u << OPCODE_SHIFT | 45u), + + // Transactional Memory instructions (introduced with Power 8) + TBEGIN_OPCODE = (31u << OPCODE_SHIFT | 654u << 1), + TEND_OPCODE = (31u << OPCODE_SHIFT | 686u << 1), + TABORT_OPCODE = (31u << OPCODE_SHIFT | 910u << 1), + TABORTWC_OPCODE = (31u << OPCODE_SHIFT | 782u << 1), + TABORTWCI_OPCODE = (31u << OPCODE_SHIFT | 846u << 1), + TABORTDC_OPCODE = (31u << OPCODE_SHIFT | 814u << 1), + TABORTDCI_OPCODE = (31u << OPCODE_SHIFT | 878u << 1), + TSR_OPCODE = (31u << OPCODE_SHIFT | 750u << 1), + TCHECK_OPCODE = (31u << OPCODE_SHIFT | 718u << 1), + // Icache and dcache related instructions DCBA_OPCODE = (31u << OPCODE_SHIFT | 758u << 1), DCBZ_OPCODE = (31u << OPCODE_SHIFT | 1014u << 1), @@ -1420,6 +1475,25 @@ class Assembler : public AbstractAssembler { inline void mcrf( ConditionRegister crd, ConditionRegister cra); inline void mtcr( Register s); + // Special purpose registers + // Exception Register + inline void mtxer(Register s1); + inline void mfxer(Register d); + // Vector Register Save Register + inline void mtvrsave(Register s1); + inline void mfvrsave(Register d); + // Timebase + inline void mftb(Register d); + // Introduced with Power 8: + // Data Stream Control Register + inline void mtdscr(Register s1); + inline void mfdscr(Register d ); + // Transactional Memory Registers + inline void mftfhar(Register d); + inline void mftfiar(Register d); + inline void mftexasr(Register d); + inline void mftexasru(Register d); + // PPC 1, section 2.4.1 Branch Instructions inline void b( address a, relocInfo::relocType rt = relocInfo::none); inline void b( Label& L); @@ -1860,6 +1934,39 @@ class Assembler : public AbstractAssembler { inline void mtvscr( VectorRegister b); inline void mfvscr( VectorRegister d); + // AES (introduced with Power 8) + inline void vcipher( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vcipherlast( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vncipher( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vncipherlast(VectorRegister d, VectorRegister a, VectorRegister b); + inline void vsbox( VectorRegister d, VectorRegister a); + + // SHA (introduced with Power 8) + // Not yet implemented. + + // Vector Binary Polynomial Multiplication (introduced with Power 8) + inline void vpmsumb( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpmsumd( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpmsumh( VectorRegister d, VectorRegister a, VectorRegister b); + inline void vpmsumw( VectorRegister d, VectorRegister a, VectorRegister b); + + // Vector Permute and Xor (introduced with Power 8) + inline void vpermxor( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c); + + // Transactional Memory instructions (introduced with Power 8) + inline void tbegin_(); // R=0 + inline void tbeginrot_(); // R=1 Rollback-Only Transaction + inline void tend_(); // A=0 + inline void tendall_(); // A=1 + inline void tabort_(Register a); + inline void tabortwc_(int t, Register a, Register b); + inline void tabortwci_(int t, Register a, int si); + inline void tabortdc_(int t, Register a, Register b); + inline void tabortdci_(int t, Register a, int si); + inline void tsuspend_(); // tsr with L=0 + inline void tresume_(); // tsr with L=1 + inline void tcheck(int f); + // The following encoders use r0 as second operand. These instructions // read r0 as '0'. inline void lwzx( Register d, Register s2); diff --git a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp index 87db4bff89d..b4a7370994d 100644 --- a/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp +++ b/hotspot/src/cpu/ppc/vm/assembler_ppc.inline.hpp @@ -312,6 +312,25 @@ inline void Assembler::mcrf( ConditionRegister crd, ConditionRegister cra) { emit_int32(MCRF_OPCODE | bf(crd) | bfa(cra)); } inline void Assembler::mtcr( Register s) { Assembler::mtcrf(0xff, s); } +// Special purpose registers +// Exception Register +inline void Assembler::mtxer(Register s1) { emit_int32(MTXER_OPCODE | rs(s1)); } +inline void Assembler::mfxer(Register d ) { emit_int32(MFXER_OPCODE | rt(d)); } +// Vector Register Save Register +inline void Assembler::mtvrsave(Register s1) { emit_int32(MTVRSAVE_OPCODE | rs(s1)); } +inline void Assembler::mfvrsave(Register d ) { emit_int32(MFVRSAVE_OPCODE | rt(d)); } +// Timebase +inline void Assembler::mftb(Register d ) { emit_int32(MFTB_OPCODE | rt(d)); } +// Introduced with Power 8: +// Data Stream Control Register +inline void Assembler::mtdscr(Register s1) { emit_int32(MTDSCR_OPCODE | rs(s1)); } +inline void Assembler::mfdscr(Register d ) { emit_int32(MFDSCR_OPCODE | rt(d)); } +// Transactional Memory Registers +inline void Assembler::mftfhar(Register d ) { emit_int32(MFTFHAR_OPCODE | rt(d)); } +inline void Assembler::mftfiar(Register d ) { emit_int32(MFTFIAR_OPCODE | rt(d)); } +inline void Assembler::mftexasr(Register d ) { emit_int32(MFTEXASR_OPCODE | rt(d)); } +inline void Assembler::mftexasru(Register d ) { emit_int32(MFTEXASRU_OPCODE | rt(d)); } + // SAP JVM 2006-02-13 PPC branch instruction. // PPC 1, section 2.4.1 Branch Instructions inline void Assembler::b( address a, relocInfo::relocType rt) { emit_data(BXX_OPCODE| li(disp( intptr_t(a), intptr_t(pc()))) |aa(0)|lk(0), rt); } @@ -735,6 +754,39 @@ inline void Assembler::vsrah( VectorRegister d, VectorRegister a, VectorRegist inline void Assembler::mtvscr( VectorRegister b) { emit_int32( MTVSCR_OPCODE | vrb(b)); } inline void Assembler::mfvscr( VectorRegister d) { emit_int32( MFVSCR_OPCODE | vrt(d)); } +// AES (introduced with Power 8) +inline void Assembler::vcipher( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCIPHER_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vcipherlast( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VCIPHERLAST_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vncipher( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNCIPHER_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vncipherlast(VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VNCIPHERLAST_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vsbox( VectorRegister d, VectorRegister a) { emit_int32( VSBOX_OPCODE | vrt(d) | vra(a) ); } + +// SHA (introduced with Power 8) +// Not yet implemented. + +// Vector Binary Polynomial Multiplication (introduced with Power 8) +inline void Assembler::vpmsumb( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMB_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpmsumd( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMD_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpmsumh( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMH_OPCODE | vrt(d) | vra(a) | vrb(b)); } +inline void Assembler::vpmsumw( VectorRegister d, VectorRegister a, VectorRegister b) { emit_int32( VPMSUMW_OPCODE | vrt(d) | vra(a) | vrb(b)); } + +// Vector Permute and Xor (introduced with Power 8) +inline void Assembler::vpermxor( VectorRegister d, VectorRegister a, VectorRegister b, VectorRegister c) { emit_int32( VPMSUMW_OPCODE | vrt(d) | vra(a) | vrb(b) | vrc(c)); } + +// Transactional Memory instructions (introduced with Power 8) +inline void Assembler::tbegin_() { emit_int32( TBEGIN_OPCODE | rc(1)); } +inline void Assembler::tbeginrot_() { emit_int32( TBEGIN_OPCODE | /*R=1*/ 1u << (31-10) | rc(1)); } +inline void Assembler::tend_() { emit_int32( TEND_OPCODE | rc(1)); } +inline void Assembler::tendall_() { emit_int32( TEND_OPCODE | /*A=1*/ 1u << (31-6) | rc(1)); } +inline void Assembler::tabort_(Register a) { emit_int32( TABORT_OPCODE | ra(a) | rc(1)); } +inline void Assembler::tabortwc_(int t, Register a, Register b) { emit_int32( TABORTWC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); } +inline void Assembler::tabortwci_(int t, Register a, int si) { emit_int32( TABORTWCI_OPCODE | to(t) | ra(a) | sh1620(si) | rc(1)); } +inline void Assembler::tabortdc_(int t, Register a, Register b) { emit_int32( TABORTDC_OPCODE | to(t) | ra(a) | rb(b) | rc(1)); } +inline void Assembler::tabortdci_(int t, Register a, int si) { emit_int32( TABORTDCI_OPCODE | to(t) | ra(a) | sh1620(si) | rc(1)); } +inline void Assembler::tsuspend_() { emit_int32( TSR_OPCODE | rc(1)); } +inline void Assembler::tresume_() { emit_int32( TSR_OPCODE | /*L=1*/ 1u << (31-10) | rc(1)); } +inline void Assembler::tcheck(int f) { emit_int32( TCHECK_OPCODE | bf(f)); } + // ra0 version inline void Assembler::lwzx( Register d, Register s2) { emit_int32( LWZX_OPCODE | rt(d) | rb(s2));} inline void Assembler::lwz( Register d, int si16 ) { emit_int32( LWZ_OPCODE | rt(d) | d1(si16));} diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp index 4cd5efdd4c3..bd8bef477da 100644 --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -37,6 +37,8 @@ const int StackAlignmentInBytes = 16; // signatures accordingly. const bool CCallingConventionRequiresIntsAsLongs = true; +#define SUPPORTS_NATIVE_CX8 + // The PPC CPUs are NOT multiple-copy-atomic. #define CPU_NOT_MULTIPLE_COPY_ATOMIC diff --git a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp index 91decd076e7..6c89a18c03b 100644 --- a/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/interp_masm_ppc_64.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" -#include "asm/assembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "interp_masm_ppc_64.hpp" #include "interpreter/interpreterRuntime.hpp" diff --git a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp index d64da8ea17a..be85db68c82 100644 --- a/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/interpreter_ppc.cpp @@ -24,7 +24,6 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "interpreter/bytecodeHistogram.hpp" #include "interpreter/interpreter.hpp" diff --git a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp index 4366af19626..1b98de177dc 100644 --- a/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/macroAssembler_ppc.cpp @@ -2366,7 +2366,7 @@ void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, Register Rnew_v #endif // INCLUDE_ALL_GCS // Values for last_Java_pc, and last_Java_sp must comply to the rules -// in frame_ppc64.hpp. +// in frame_ppc.hpp. void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) { // Always set last_Java_pc and flags first because once last_Java_sp // is visible has_last_Java_frame is true and users will look at the @@ -2493,6 +2493,7 @@ int MacroAssembler::instr_size_for_decode_klass_not_null() { } void MacroAssembler::decode_klass_not_null(Register dst, Register src) { + assert(dst != R0, "Dst reg may not be R0, as R0 is used here."); if (src == noreg) src = dst; Register shifted_src = src; if (Universe::narrow_klass_shift() != 0 || @@ -2527,14 +2528,11 @@ void MacroAssembler::load_klass_with_trap_null_check(Register dst, Register src) void MacroAssembler::reinit_heapbase(Register d, Register tmp) { if (Universe::heap() != NULL) { - if (Universe::narrow_oop_base() == NULL) { - Assembler::xorr(R30, R30, R30); - } else { - load_const(R30, Universe::narrow_ptrs_base(), tmp); - } + load_const_optimized(R30, Universe::narrow_ptrs_base(), tmp); } else { - load_const(R30, Universe::narrow_ptrs_base_addr(), tmp); - ld(R30, 0, R30); + // Heap not yet allocated. Load indirectly. + int simm16_offset = load_const_optimized(R30, Universe::narrow_ptrs_base_addr(), tmp, true); + ld(R30, simm16_offset, R30); } } diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index ab2d535bbc9..d68749c8ca1 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -1249,6 +1249,7 @@ EmitCallOffsets emit_call_with_trampoline_stub(MacroAssembler &_masm, address en // Emit the trampoline stub which will be related to the branch-and-link below. CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, offsets.insts_call_instruction_offset); + if (Compile::current()->env()->failing()) { return offsets; } // Code cache may be full. __ relocate(rtype); } @@ -1410,7 +1411,7 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { while (bang_offset <= bang_end) { // Need at least one stack bang at end of shadow zone. - // Again I had to copy code, this time from assembler_ppc64.cpp, + // Again I had to copy code, this time from assembler_ppc.cpp, // bang_stack_with_offset - see there for comments. // Stack grows down, caller passes positive offset. @@ -2000,7 +2001,7 @@ void MachUEPNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { // Inline_cache contains a klass. Register ic_klass = as_Register(Matcher::inline_cache_reg_encode()); - Register receiver_klass = R0; // tmp + Register receiver_klass = R12_scratch2; // tmp assert_different_registers(ic_klass, receiver_klass, R11_scratch1, R3_ARG1); assert(R11_scratch1 == R11, "need prologue scratch register"); @@ -3484,6 +3485,7 @@ encode %{ // Emit the trampoline stub which will be related to the branch-and-link below. CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); + if (Compile::current()->env()->failing()) { return; } // Code cache may be full. __ relocate(_optimized_virtual ? relocInfo::opt_virtual_call_type : relocInfo::static_call_type); } @@ -3527,6 +3529,7 @@ encode %{ // Emit the trampoline stub which will be related to the branch-and-link below. CallStubImpl::emit_trampoline_stub(_masm, entry_point_toc_offset, start_offset); + if (ra_->C->env()->failing()) { return; } // Code cache may be full. assert(_optimized_virtual, "methodHandle call should be a virtual call"); __ relocate(relocInfo::opt_virtual_call_type); } @@ -3577,9 +3580,7 @@ encode %{ const address entry_point_const = __ address_constant(entry_point, RelocationHolder::none); const int entry_point_const_toc_offset = __ offset_to_method_toc(entry_point_const); CallStubImpl::emit_trampoline_stub(_masm, entry_point_const_toc_offset, __ offset()); - - if (ra_->C->env()->failing()) - return; + if (ra_->C->env()->failing()) { return; } // Code cache may be full. // Build relocation at call site with ic position as data. assert((_load_ic_hi_node != NULL && _load_ic_node == NULL) || @@ -5638,19 +5639,6 @@ instruct loadNKlass(iRegNdst dst, memory mem) %{ ins_pipe(pipe_class_memory); %} -//// Load compressed klass and decode it if narrow_klass_shift == 0. -//// TODO: will narrow_klass_shift ever be 0? -//instruct decodeNKlass2Klass(iRegPdst dst, memory mem) %{ -// match(Set dst (DecodeNKlass (LoadNKlass mem))); -// predicate(false /* TODO: PPC port Universe::narrow_klass_shift() == 0*); -// ins_cost(MEMORY_REF_COST); -// -// format %{ "LWZ $dst, $mem \t// DecodeNKlass (unscaled)" %} -// size(4); -// ins_encode( enc_lwz(dst, mem) ); -// ins_pipe(pipe_class_memory); -//%} - // Load Klass Pointer instruct loadKlass(iRegPdst dst, memoryAlg4 mem) %{ match(Set dst (LoadKlass mem)); @@ -6070,11 +6058,15 @@ instruct loadConN_Ex(iRegNdst dst, immN src) %{ %} %} -instruct loadConNKlass_hi(iRegNdst dst, immNKlass src) %{ +// We have seen a safepoint between the hi and lo parts, and this node was handled +// as an oop. Therefore this needs a match rule so that build_oop_map knows this is +// not a narrow oop. +instruct loadConNKlass_hi(iRegNdst dst, immNKlass_NM src) %{ + match(Set dst src); effect(DEF dst, USE src); ins_cost(DEFAULT_COST); - format %{ "LIS $dst, $src \t// narrow oop hi" %} + format %{ "LIS $dst, $src \t// narrow klass hi" %} size(4); ins_encode %{ // TODO: PPC port $archOpcode(ppc64Opcode_addis); @@ -6084,6 +6076,21 @@ instruct loadConNKlass_hi(iRegNdst dst, immNKlass src) %{ ins_pipe(pipe_class_default); %} +// As loadConNKlass_hi this must be recognized as narrow klass, not oop! +instruct loadConNKlass_mask(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ + match(Set dst src1); + effect(TEMP src2); + ins_cost(DEFAULT_COST); + + format %{ "MASK $dst, $src2, 0xFFFFFFFF" %} // mask + size(4); + ins_encode %{ + // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); + __ clrldi($dst$$Register, $src2$$Register, 0x20); + %} + ins_pipe(pipe_class_default); +%} + // This needs a match rule so that build_oop_map knows this is // not a narrow oop. instruct loadConNKlass_lo(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ @@ -6091,10 +6098,10 @@ instruct loadConNKlass_lo(iRegNdst dst, immNKlass_NM src1, iRegNsrc src2) %{ effect(TEMP src2); ins_cost(DEFAULT_COST); - format %{ "ADDI $dst, $src1, $src2 \t// narrow oop lo" %} + format %{ "ORI $dst, $src1, $src2 \t// narrow klass lo" %} size(4); ins_encode %{ - // TODO: PPC port $archOpcode(ppc64Opcode_addi); + // TODO: PPC port $archOpcode(ppc64Opcode_ori); intptr_t Csrc = Klass::encode_klass((Klass *)$src1$$constant); assert(__ oop_recorder() != NULL, "this assembler needs an OopRecorder"); int klass_index = __ oop_recorder()->find_index((Klass *)$src1$$constant); @@ -6125,10 +6132,11 @@ instruct loadConNKlass_Ex(iRegNdst dst, immNKlass src) %{ MachNode *m2 = m1; if (!Assembler::is_uimm((jlong)Klass::encode_klass((Klass *)op_src->constant()), 31)) { // Value might be 1-extended. Mask out these bits. - m2 = new clearMs32bNode(); + m2 = new loadConNKlass_maskNode(); m2->add_req(NULL, m1); m2->_opnds[0] = op_dst; - m2->_opnds[1] = op_dst; + m2->_opnds[1] = op_src; + m2->_opnds[2] = op_dst; ra_->set_pair(m2->_idx, ra_->get_reg_second(this), ra_->get_reg_first(this)); nodes->push(m2); } @@ -6973,7 +6981,7 @@ instruct encodePKlass_32GAligned(iRegNdst dst, iRegPsrc src) %{ size(4); ins_encode %{ // TODO: PPC port $archOpcode(ppc64Opcode_rldicl); - __ rldicl($dst$$Register, $src$$Register, 64-Universe::narrow_oop_shift(), 32); + __ rldicl($dst$$Register, $src$$Register, 64-Universe::narrow_klass_shift(), 32); %} ins_pipe(pipe_class_default); %} diff --git a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp index 290a4be01b0..0f8c752cacc 100644 --- a/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/stubGenerator_ppc.cpp @@ -24,7 +24,6 @@ */ #include "precompiled.hpp" -#include "asm/assembler.hpp" #include "asm/macroAssembler.inline.hpp" #include "interpreter/interpreter.hpp" #include "nativeInst_ppc.hpp" @@ -39,9 +38,6 @@ #include "runtime/stubCodeGenerator.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/top.hpp" -#ifdef COMPILER2 -#include "opto/runtime.hpp" -#endif #include "runtime/thread.inline.hpp" #define __ _masm-> @@ -216,7 +212,7 @@ class StubGenerator: public StubCodeGenerator { { BLOCK_COMMENT("Call frame manager or native entry."); // Call frame manager or native entry. - Register r_new_arg_entry = R14; // PPC_state; + Register r_new_arg_entry = R14; assert_different_registers(r_new_arg_entry, r_top_of_arguments_addr, r_arg_method, r_arg_thread); diff --git a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp index 663c5744095..f0c7097abbd 100644 --- a/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp +++ b/hotspot/src/cpu/ppc/vm/templateTable_ppc_64.cpp @@ -353,7 +353,6 @@ void TemplateTable::ldc(bool wide) { __ sldi(Rscratch1, Rscratch1, LogBytesPerWord); __ cmpdi(CCR0, Rscratch2, JVM_CONSTANT_Integer); __ bne(CCR0, notInt); - __ isync(); // Order load of constant wrt. tags. __ lwax(R17_tos, Rcpool, Rscratch1); __ push(itos); __ b(exit); @@ -365,7 +364,6 @@ void TemplateTable::ldc(bool wide) { __ cmpdi(CCR0, Rscratch2, JVM_CONSTANT_Float); __ asm_assert_eq("unexpected type", 0x8765); #endif - __ isync(); // Order load of constant wrt. tags. __ lfsx(F15_ftos, Rcpool, Rscratch1); __ push(ftos); @@ -424,13 +422,11 @@ void TemplateTable::ldc2_w() { // Check out Conversions.java for an example. // Also ConstantPool::header_size() is 20, which makes it very difficult // to double-align double on the constant pool. SG, 11/7/97 - __ isync(); // Order load of constant wrt. tags. __ lfdx(F15_ftos, Rcpool, Rindex); __ push(dtos); __ b(Lexit); __ bind(Llong); - __ isync(); // Order load of constant wrt. tags. __ ldx(R17_tos, Rcpool, Rindex); __ push(ltos); diff --git a/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp index c14df6ef9d3..c3b880f87ac 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/prefetch_linux_ppc.inline.hpp @@ -47,4 +47,4 @@ inline void Prefetch::write(void *loc, intx interval) { ); } -#endif // OS_CPU_LINUX_PPC_VM_PREFETCH_LINUX_OJDKPPC_HPP +#endif // OS_CPU_LINUX_PPC_VM_PREFETCH_LINUX_PPC_INLINE_HPP From 0ba49695491589e57839eb44852e1941b3f32bd5 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Thu, 2 Oct 2014 17:13:31 +0400 Subject: [PATCH 08/91] 8059595: Verifier::verify is wasting time before is_eligible_for_verification check Do the check earlier. Reviewed-by: hseigel, kamg --- hotspot/src/share/vm/classfile/verifier.cpp | 73 +++++++++++---------- 1 file changed, 38 insertions(+), 35 deletions(-) diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 36ec76d6e5d..877eebd0e0b 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -98,6 +98,14 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul HandleMark hm; ResourceMark rm(THREAD); + if (!is_eligible_for_verification(klass, should_verify_class)) { + return true; + } + + // If the class should be verified, first see if we can use the split + // verifier. If not, or if verification fails and FailOverToOldVerifier + // is set, then call the inference verifier. + Symbol* exception_name = NULL; const size_t message_buffer_len = klass->name()->utf8_length() + 1024; char* message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len); @@ -105,47 +113,42 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul const char* klassName = klass->external_name(); bool can_failover = FailOverToOldVerifier && - klass->major_version() < NOFAILOVER_MAJOR_VERSION; + klass->major_version() < NOFAILOVER_MAJOR_VERSION; - // If the class should be verified, first see if we can use the split - // verifier. If not, or if verification fails and FailOverToOldVerifier - // is set, then call the inference verifier. - if (is_eligible_for_verification(klass, should_verify_class)) { - if (TraceClassInitialization) { - tty->print_cr("Start class verification for: %s", klassName); - } - if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) { - ClassVerifier split_verifier(klass, THREAD); - split_verifier.verify_class(THREAD); - exception_name = split_verifier.result(); - if (can_failover && !HAS_PENDING_EXCEPTION && - (exception_name == vmSymbols::java_lang_VerifyError() || - exception_name == vmSymbols::java_lang_ClassFormatError())) { - if (TraceClassInitialization || VerboseVerification) { - tty->print_cr( - "Fail over class verification to old verifier for: %s", klassName); - } - exception_name = inference_verify( - klass, message_buffer, message_buffer_len, THREAD); + if (TraceClassInitialization) { + tty->print_cr("Start class verification for: %s", klassName); + } + if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) { + ClassVerifier split_verifier(klass, THREAD); + split_verifier.verify_class(THREAD); + exception_name = split_verifier.result(); + if (can_failover && !HAS_PENDING_EXCEPTION && + (exception_name == vmSymbols::java_lang_VerifyError() || + exception_name == vmSymbols::java_lang_ClassFormatError())) { + if (TraceClassInitialization || VerboseVerification) { + tty->print_cr( + "Fail over class verification to old verifier for: %s", klassName); } - if (exception_name != NULL) { - exception_message = split_verifier.exception_message(); - } - } else { exception_name = inference_verify( - klass, message_buffer, message_buffer_len, THREAD); + klass, message_buffer, message_buffer_len, THREAD); } + if (exception_name != NULL) { + exception_message = split_verifier.exception_message(); + } + } else { + exception_name = inference_verify( + klass, message_buffer, message_buffer_len, THREAD); + } - if (TraceClassInitialization || VerboseVerification) { - if (HAS_PENDING_EXCEPTION) { - tty->print("Verification for %s has", klassName); - tty->print_cr(" exception pending %s ", - InstanceKlass::cast(PENDING_EXCEPTION->klass())->external_name()); - } else if (exception_name != NULL) { - tty->print_cr("Verification for %s failed", klassName); - } - tty->print_cr("End class verification for: %s", klassName); + if (TraceClassInitialization || VerboseVerification) { + if (HAS_PENDING_EXCEPTION) { + tty->print("Verification for %s has", klassName); + tty->print_cr(" exception pending %s ", + InstanceKlass::cast(PENDING_EXCEPTION->klass())->external_name()); + } else if (exception_name != NULL) { + tty->print_cr("Verification for %s failed", klassName); } + tty->print_cr("End class verification for: %s", klassName); } if (HAS_PENDING_EXCEPTION) { From 90200446c1fc1fea38479a9381ef7dbf676a0a6f Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 2 Oct 2014 16:31:44 -0400 Subject: [PATCH 09/91] 8047736: Remove JVM_GetClassLoader as no longer used Remove this function from hotspot. It's already removed from the JDK. Reviewed-by: mchung, fparain, ctornqvi --- hotspot/make/aix/makefiles/mapfile-vers-debug | 1 - hotspot/make/aix/makefiles/mapfile-vers-product | 1 - hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug | 1 - .../make/bsd/makefiles/mapfile-vers-darwin-product | 1 - hotspot/make/bsd/makefiles/mapfile-vers-debug | 1 - hotspot/make/bsd/makefiles/mapfile-vers-product | 1 - hotspot/make/linux/makefiles/mapfile-vers-debug | 1 - hotspot/make/linux/makefiles/mapfile-vers-product | 1 - hotspot/make/solaris/makefiles/mapfile-vers | 1 - hotspot/src/share/vm/prims/jvm.cpp | 11 ----------- hotspot/src/share/vm/prims/jvm.h | 3 --- 11 files changed, 23 deletions(-) diff --git a/hotspot/make/aix/makefiles/mapfile-vers-debug b/hotspot/make/aix/makefiles/mapfile-vers-debug index 613e26bd880..49beedda9ed 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-debug +++ b/hotspot/make/aix/makefiles/mapfile-vers-debug @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/make/aix/makefiles/mapfile-vers-product b/hotspot/make/aix/makefiles/mapfile-vers-product index 0b8a040c74a..8adbf613849 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-product +++ b/hotspot/make/aix/makefiles/mapfile-vers-product @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug index 7f7f00036fe..adf6616885a 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug @@ -115,7 +115,6 @@ _JVM_GetClassDeclaredMethods _JVM_GetClassFieldsCount _JVM_GetClassInterfaces - _JVM_GetClassLoader _JVM_GetClassMethodsCount _JVM_GetClassModifiers _JVM_GetClassName diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product index 7f7f00036fe..adf6616885a 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product @@ -115,7 +115,6 @@ _JVM_GetClassDeclaredMethods _JVM_GetClassFieldsCount _JVM_GetClassInterfaces - _JVM_GetClassLoader _JVM_GetClassMethodsCount _JVM_GetClassModifiers _JVM_GetClassName diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index f7d88125ab5..6c79e8b9b75 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index f7d88125ab5..6c79e8b9b75 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index f7d88125ab5..6c79e8b9b75 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index f7d88125ab5..6c79e8b9b75 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index 9bf34ff8305..51cb3f9657b 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -117,7 +117,6 @@ SUNWprivate_1.1 { JVM_GetClassDeclaredMethods; JVM_GetClassFieldsCount; JVM_GetClassInterfaces; - JVM_GetClassLoader; JVM_GetClassMethodsCount; JVM_GetClassModifiers; JVM_GetClassName; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index 1a51e80e00e..fa02d67b4a7 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1073,17 +1073,6 @@ JVM_ENTRY(jobjectArray, JVM_GetClassInterfaces(JNIEnv *env, jclass cls)) JVM_END -JVM_ENTRY(jobject, JVM_GetClassLoader(JNIEnv *env, jclass cls)) - JVMWrapper("JVM_GetClassLoader"); - if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(cls))) { - return NULL; - } - Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); - oop loader = k->class_loader(); - return JNIHandles::make_local(env, loader); -JVM_END - - JVM_QUICK_ENTRY(jboolean, JVM_IsInterface(JNIEnv *env, jclass cls)) JVMWrapper("JVM_IsInterface"); oop mirror = JNIHandles::resolve_non_null(cls); diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index 72278843ab2..c1aa8080cd3 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -462,9 +462,6 @@ JVM_GetClassName(JNIEnv *env, jclass cls); JNIEXPORT jobjectArray JNICALL JVM_GetClassInterfaces(JNIEnv *env, jclass cls); -JNIEXPORT jobject JNICALL -JVM_GetClassLoader(JNIEnv *env, jclass cls); - JNIEXPORT jboolean JNICALL JVM_IsInterface(JNIEnv *env, jclass cls); From c39454ae56e4bf02589612944e7862e4779a9912 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Fri, 3 Oct 2014 13:34:46 -0700 Subject: [PATCH 10/91] 8059621: JVM crashes with "unexpected index type" assert in LIRGenerator::do_UnsafeGetRaw Get types from LIR instructions instead of HIR Reviewed-by: kvn --- hotspot/src/share/vm/c1/c1_LIRGenerator.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 3515a322477..2beb72a60f1 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -2069,14 +2069,14 @@ void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) { LIR_Opr base_op = base.result(); LIR_Opr index_op = idx.result(); #ifndef _LP64 - if (x->base()->type()->tag() == longTag) { + if (base_op->type() == T_LONG) { base_op = new_register(T_INT); __ convert(Bytecodes::_l2i, base.result(), base_op); } if (x->has_index()) { - if (x->index()->type()->tag() == longTag) { + if (index_op->type() == T_LONG) { LIR_Opr long_index_op = index_op; - if (x->index()->type()->is_constant()) { + if (index_op->is_constant()) { long_index_op = new_register(T_LONG); __ move(index_op, long_index_op); } @@ -2091,14 +2091,14 @@ void LIRGenerator::do_UnsafeGetRaw(UnsafeGetRaw* x) { assert(!x->has_index() || index_op->type() == T_INT, "index should be an int"); #else if (x->has_index()) { - if (x->index()->type()->tag() == intTag) { - if (!x->index()->type()->is_constant()) { + if (index_op->type() == T_INT) { + if (!index_op->is_constant()) { index_op = new_register(T_LONG); __ convert(Bytecodes::_i2l, idx.result(), index_op); } } else { - assert(x->index()->type()->tag() == longTag, "must be"); - if (x->index()->type()->is_constant()) { + assert(index_op->type() == T_LONG, "must be"); + if (index_op->is_constant()) { index_op = new_register(T_LONG); __ move(idx.result(), index_op); } @@ -2179,12 +2179,12 @@ void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) { LIR_Opr index_op = idx.result(); #ifndef _LP64 - if (x->base()->type()->tag() == longTag) { + if (base_op->type() == T_LONG) { base_op = new_register(T_INT); __ convert(Bytecodes::_l2i, base.result(), base_op); } if (x->has_index()) { - if (x->index()->type()->tag() == longTag) { + if (index_op->type() == T_LONG) { index_op = new_register(T_INT); __ convert(Bytecodes::_l2i, idx.result(), index_op); } @@ -2194,7 +2194,7 @@ void LIRGenerator::do_UnsafePutRaw(UnsafePutRaw* x) { assert(!x->has_index() || (index_op->type() == T_INT && !index_op->is_constant()), "index should be an non-constant int"); #else if (x->has_index()) { - if (x->index()->type()->tag() == intTag) { + if (index_op->type() == T_INT) { index_op = new_register(T_LONG); __ convert(Bytecodes::_i2l, idx.result(), index_op); } From db57351f4352dda9fbfd8c59d1943e760c84b83b Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Fri, 3 Oct 2014 13:56:18 -0700 Subject: [PATCH 11/91] 8046607: Code cleanup: PerfMemory::backing_store_filename() should be removed Removed PerfMemory::backing_store_filename() API since it is not used anywhere. Reviewed-by: sla, hseigel --- hotspot/src/os/aix/vm/perfMemory_aix.cpp | 4 ---- hotspot/src/os/bsd/vm/perfMemory_bsd.cpp | 4 ---- hotspot/src/os/linux/vm/perfMemory_linux.cpp | 4 ---- hotspot/src/os/solaris/vm/perfMemory_solaris.cpp | 4 ---- hotspot/src/os/windows/vm/perfMemory_windows.cpp | 4 ---- hotspot/src/share/vm/runtime/perfMemory.hpp | 3 --- 6 files changed, 23 deletions(-) diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index a30919c70df..36644f0f679 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -1020,7 +1020,3 @@ void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { unmap_shared(addr, bytes); } - -char* PerfMemory::backing_store_filename() { - return backing_store_file_name; -} diff --git a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp index 2737fe38ce1..631366e2944 100644 --- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp +++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp @@ -1043,7 +1043,3 @@ void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { unmap_shared(addr, bytes); } - -char* PerfMemory::backing_store_filename() { - return backing_store_file_name; -} diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp index 2eef5da69f9..6d92575563e 100644 --- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp +++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp @@ -1049,7 +1049,3 @@ void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { unmap_shared(addr, bytes); } - -char* PerfMemory::backing_store_filename() { - return backing_store_file_name; -} diff --git a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp index 2d279af0c2b..7f956338e6b 100644 --- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp +++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp @@ -1068,7 +1068,3 @@ void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { unmap_shared(addr, bytes); } - -char* PerfMemory::backing_store_filename() { - return backing_store_file_name; -} diff --git a/hotspot/src/os/windows/vm/perfMemory_windows.cpp b/hotspot/src/os/windows/vm/perfMemory_windows.cpp index e1b59253e82..edbd0bf622d 100644 --- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp +++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp @@ -1846,7 +1846,3 @@ void PerfMemory::detach(char* addr, size_t bytes, TRAPS) { remove_file_mapping(addr); } } - -char* PerfMemory::backing_store_filename() { - return sharedmem_fileName; -} diff --git a/hotspot/src/share/vm/runtime/perfMemory.hpp b/hotspot/src/share/vm/runtime/perfMemory.hpp index 18a2efd2f55..07e119ef8f8 100644 --- a/hotspot/src/share/vm/runtime/perfMemory.hpp +++ b/hotspot/src/share/vm/runtime/perfMemory.hpp @@ -155,9 +155,6 @@ class PerfMemory : AllStatic { } } - // filename of backing store or NULL if none. - static char* backing_store_filename(); - // returns the complete file path of hsperfdata. // the caller is expected to free the allocated memory. static char* get_perfdata_file_path(); From 4c1c76ae4f3e4ee82c59ed53ee9c5639ed63f2e3 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Mon, 6 Oct 2014 07:58:50 +0200 Subject: [PATCH 12/91] 8059559: SIGSEGV at CodeHeap::allocate(unsigned int, bool) Create the non-profiled code heap if TieredStopAtLevel=0 is set because we compile method handle intrinsics. Reviewed-by: kvn --- hotspot/src/share/vm/code/codeCache.cpp | 3 +-- .../codecache/CheckSegmentedCodeCache.java | 21 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index a2653d10b43..b21604f8549 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -254,8 +254,7 @@ bool CodeCache::heap_available(int code_blob_type) { if (!SegmentedCodeCache) { // No segmentation: use a single code heap return (code_blob_type == CodeBlobType::All); - } else if ((Arguments::mode() == Arguments::_int) || - (TieredStopAtLevel == CompLevel_none)) { + } else if (Arguments::mode() == Arguments::_int) { // Interpreter only: we don't need any method code heaps return (code_blob_type == CodeBlobType::NonNMethod); } else if (TieredCompilation && (TieredStopAtLevel > CompLevel_simple)) { diff --git a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java index 5ed11c21233..06330d840b6 100644 --- a/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java +++ b/hotspot/test/compiler/codecache/CheckSegmentedCodeCache.java @@ -38,22 +38,26 @@ public class CheckSegmentedCodeCache { private static void verifySegmentedCodeCache(ProcessBuilder pb, boolean enabled) throws Exception { OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); if (enabled) { try { // Non-nmethod code heap should be always available with the segmented code cache out.shouldContain(NON_METHOD); } catch (RuntimeException e) { - // TieredCompilation is disabled in a client VM - out.shouldContain("TieredCompilation is disabled in this release."); + // Check if TieredCompilation is disabled (in a client VM) + if(!out.getOutput().contains("TieredCompilation is disabled in this release.")) { + // Code cache is not segmented + throw new RuntimeException("No code cache segmentation."); + } } } else { out.shouldNotContain(NON_METHOD); } - out.shouldHaveExitValue(0); } private static void verifyCodeHeapNotExists(ProcessBuilder pb, String... heapNames) throws Exception { OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); for (String name : heapNames) { out.shouldNotContain(name); } @@ -86,6 +90,10 @@ public class CheckSegmentedCodeCache { "-XX:ReservedCodeCacheSize=240m", "-XX:+PrintCodeCache", "-version"); verifySegmentedCodeCache(pb, true); + pb = ProcessTools.createJavaProcessBuilder("-XX:+TieredCompilation", + "-XX:ReservedCodeCacheSize=400m", + "-XX:+PrintCodeCache", "-version"); + verifySegmentedCodeCache(pb, true); // Always enabled if SegmentedCodeCache is set pb = ProcessTools.createJavaProcessBuilder("-XX:+SegmentedCodeCache", @@ -100,12 +108,13 @@ public class CheckSegmentedCodeCache { "-Xint", "-XX:+PrintCodeCache", "-version"); verifyCodeHeapNotExists(pb, PROFILED, NON_PROFILED); + + // If we stop compilation at CompLevel_none or CompLevel_simple we + // don't need a profiled code heap. pb = ProcessTools.createJavaProcessBuilder("-XX:+SegmentedCodeCache", "-XX:TieredStopAtLevel=0", "-XX:+PrintCodeCache", "-version"); - verifyCodeHeapNotExists(pb, PROFILED, NON_PROFILED); - - // If we stop compilation at CompLevel_simple + verifyCodeHeapNotExists(pb, PROFILED); pb = ProcessTools.createJavaProcessBuilder("-XX:+SegmentedCodeCache", "-XX:TieredStopAtLevel=1", "-XX:+PrintCodeCache", "-version"); From 18eb46eb952e27dc60e74d01f4eb0db6005986ad Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Mon, 6 Oct 2014 10:11:13 +0200 Subject: [PATCH 13/91] 8059466: Force young GC to initiate marking cycle when stat update is requested Enable yc to be forced for stat update. Reviewed-by: mgerdin, jcoomes --- .../src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp | 1 + .../src/share/vm/gc_implementation/g1/vm_operations_g1.cpp | 5 +++-- hotspot/src/share/vm/gc_interface/gcCause.cpp | 3 ++- hotspot/src/share/vm/gc_interface/gcCause.hpp | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index f6aad1c81c6..133e2094f63 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2343,6 +2343,7 @@ bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) { case GCCause::_gc_locker: return GCLockerInvokesConcurrent; case GCCause::_java_lang_system_gc: return ExplicitGCInvokesConcurrent; case GCCause::_g1_humongous_allocation: return true; + case GCCause::_update_allocation_context_stats_inc: return true; default: return false; } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp index c3847e0da4e..9b50ae6af53 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp @@ -95,8 +95,9 @@ void VM_G1IncCollectionPause::doit() { assert(!_should_initiate_conc_mark || ((_gc_cause == GCCause::_gc_locker && GCLockerInvokesConcurrent) || (_gc_cause == GCCause::_java_lang_system_gc && ExplicitGCInvokesConcurrent) || - _gc_cause == GCCause::_g1_humongous_allocation), - "only a GC locker, a System.gc() or a hum allocation induced GC should start a cycle"); + _gc_cause == GCCause::_g1_humongous_allocation || + _gc_cause == GCCause::_update_allocation_context_stats_inc), + "only a GC locker, a System.gc(), stats update or a hum allocation induced GC should start a cycle"); if (_word_size > 0) { // An allocation has been requested. So, try to do that first. diff --git a/hotspot/src/share/vm/gc_interface/gcCause.cpp b/hotspot/src/share/vm/gc_interface/gcCause.cpp index ff9402507c5..4778d8aa45a 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.cpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp @@ -54,7 +54,8 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _wb_young_gc: return "WhiteBox Initiated Young GC"; - case _update_allocation_context_stats: + case _update_allocation_context_stats_inc: + case _update_allocation_context_stats_full: return "Update Allocation Context Stats"; case _no_gc: diff --git a/hotspot/src/share/vm/gc_interface/gcCause.hpp b/hotspot/src/share/vm/gc_interface/gcCause.hpp index 25b55d2f6c5..4af99f1cf7e 100644 --- a/hotspot/src/share/vm/gc_interface/gcCause.hpp +++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp @@ -47,7 +47,8 @@ class GCCause : public AllStatic { _heap_inspection, _heap_dump, _wb_young_gc, - _update_allocation_context_stats, + _update_allocation_context_stats_inc, + _update_allocation_context_stats_full, /* implementation independent, but reserved for GC use */ _no_gc, From 82171aa7abc81058ba571a4ed424d6a99c1aab05 Mon Sep 17 00:00:00 2001 From: Albert Noll Date: Mon, 6 Oct 2014 06:51:37 -0700 Subject: [PATCH 14/91] 8059331: Print additional information for the assert in Compile::start() Add additional output that shows the failure reason Reviewed-by: kvn --- hotspot/src/share/vm/opto/compile.cpp | 10 ++++++++-- hotspot/src/share/vm/opto/compile.hpp | 15 +++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 1e3a6fc7b73..0163dce638c 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -1153,12 +1153,18 @@ void Compile::init_start(StartNode* s) { assert(s == start(), ""); } +/** + * Return the 'StartNode'. We must not have a pending failure, since the ideal graph + * can be in an inconsistent state, i.e., we can get segmentation faults when traversing + * the ideal graph. + */ StartNode* Compile::start() const { - assert(!failing(), ""); + assert (!failing(), err_msg_res("Must not have pending failure. Reason is: %s", failure_reason())); for (DUIterator_Fast imax, i = root()->fast_outs(imax); i < imax; i++) { Node* start = root()->fast_out(i); - if( start->is_Start() ) + if (start->is_Start()) { return start->as_Start(); + } } fatal("Did not find Start node!"); return NULL; diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 3dfda2b285f..2ac023235a9 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -707,12 +707,15 @@ class Compile : public Phase { void sort_expensive_nodes(); // Compilation environment. - Arena* comp_arena() { return &_comp_arena; } - ciEnv* env() const { return _env; } - CompileLog* log() const { return _log; } - bool failing() const { return _env->failing() || _failure_reason != NULL; } - const char* failure_reason() { return _failure_reason; } - bool failure_reason_is(const char* r) { return (r==_failure_reason) || (r!=NULL && _failure_reason!=NULL && strcmp(r, _failure_reason)==0); } + Arena* comp_arena() { return &_comp_arena; } + ciEnv* env() const { return _env; } + CompileLog* log() const { return _log; } + bool failing() const { return _env->failing() || _failure_reason != NULL; } + const char* failure_reason() const { return (_env->failing()) ? _env->failure_reason() : _failure_reason; } + + bool failure_reason_is(const char* r) const { + return (r == _failure_reason) || (r != NULL && _failure_reason != NULL && strcmp(r, _failure_reason) == 0); + } void record_failure(const char* reason); void record_method_not_compilable(const char* reason, bool all_tiers = false) { From 6d1c35615acfef2824aa38e8afcfb9c7baa46c26 Mon Sep 17 00:00:00 2001 From: Marcus Larsson Date: Tue, 7 Oct 2014 14:54:53 +0200 Subject: [PATCH 15/91] 8058298: Separate heap region iterator claim values from the data structures iterated over Reviewed-by: tschatzl, brutisso --- .../gc_implementation/g1/concurrentMark.cpp | 102 +++------- .../gc_implementation/g1/g1CollectedHeap.cpp | 186 +++--------------- .../gc_implementation/g1/g1CollectedHeap.hpp | 42 +--- .../g1/g1CollectorPolicy.cpp | 22 +-- .../vm/gc_implementation/g1/g1EvacFailure.hpp | 19 +- .../vm/gc_implementation/g1/g1RemSet.cpp | 8 +- .../vm/gc_implementation/g1/g1RemSet.hpp | 6 +- .../vm/gc_implementation/g1/heapRegion.cpp | 14 +- .../vm/gc_implementation/g1/heapRegion.hpp | 22 --- .../g1/heapRegionManager.cpp | 55 ++++-- .../g1/heapRegionManager.hpp | 35 +++- 11 files changed, 157 insertions(+), 354 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 8666c7a1583..755525123df 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -1683,6 +1683,8 @@ protected: int _failures; bool _verbose; + HeapRegionClaimer _hrclaimer; + public: G1ParVerifyFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, @@ -1692,19 +1694,8 @@ public: _actual_region_bm(region_bm), _actual_card_bm(card_bm), _expected_region_bm(expected_region_bm), _expected_card_bm(expected_card_bm), _failures(0), _verbose(false), - _n_workers(0) { + _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { assert(VerifyDuringGC, "don't call this otherwise"); - - // Use the value already set as the number of active threads - // in the call to run_task(). - if (G1CollectedHeap::use_parallel_gc_threads()) { - assert( _g1h->workers()->active_workers() > 0, - "Should have been previously set"); - _n_workers = _g1h->workers()->active_workers(); - } else { - _n_workers = 1; - } - assert(_expected_card_bm->size() == _actual_card_bm->size(), "sanity"); assert(_expected_region_bm->size() == _actual_region_bm->size(), "sanity"); @@ -1721,10 +1712,7 @@ public: _verbose); if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate_chunked(&verify_cl, - worker_id, - _n_workers, - HeapRegion::VerifyCountClaimValue); + _g1h->heap_region_par_iterate(&verify_cl, worker_id, &_hrclaimer); } else { _g1h->heap_region_iterate(&verify_cl); } @@ -1813,22 +1801,14 @@ protected: BitMap* _actual_card_bm; uint _n_workers; + HeapRegionClaimer _hrclaimer; public: G1ParFinalCountTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm) : AbstractGangTask("G1 final counting"), _g1h(g1h), _cm(_g1h->concurrent_mark()), _actual_region_bm(region_bm), _actual_card_bm(card_bm), - _n_workers(0) { - // Use the value already set as the number of active threads - // in the call to run_task(). - if (G1CollectedHeap::use_parallel_gc_threads()) { - assert( _g1h->workers()->active_workers() > 0, - "Should have been previously set"); - _n_workers = _g1h->workers()->active_workers(); - } else { - _n_workers = 1; - } + _n_workers(_g1h->workers()->active_workers()), _hrclaimer(_n_workers) { } void work(uint worker_id) { @@ -1839,10 +1819,7 @@ public: _actual_card_bm); if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate_chunked(&final_update_cl, - worker_id, - _n_workers, - HeapRegion::FinalCountClaimValue); + _g1h->heap_region_par_iterate(&final_update_cl, worker_id, &_hrclaimer); } else { _g1h->heap_region_iterate(&final_update_cl); } @@ -1929,12 +1906,12 @@ protected: size_t _max_live_bytes; size_t _freed_bytes; FreeRegionList* _cleanup_list; + HeapRegionClaimer _hrclaimer; public: - G1ParNoteEndTask(G1CollectedHeap* g1h, - FreeRegionList* cleanup_list) : - AbstractGangTask("G1 note end"), _g1h(g1h), - _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list) { } + G1ParNoteEndTask(G1CollectedHeap* g1h, FreeRegionList* cleanup_list, uint n_workers) : + AbstractGangTask("G1 note end"), _g1h(g1h), _max_live_bytes(0), _freed_bytes(0), _cleanup_list(cleanup_list), _hrclaimer(n_workers) { + } void work(uint worker_id) { double start = os::elapsedTime(); @@ -1943,9 +1920,7 @@ public: G1NoteEndOfConcMarkClosure g1_note_end(_g1h, &local_cleanup_list, &hrrs_cleanup_task); if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate_chunked(&g1_note_end, worker_id, - _g1h->workers()->active_workers(), - HeapRegion::NoteEndClaimValue); + _g1h->heap_region_par_iterate(&g1_note_end, worker_id, &_hrclaimer); } else { _g1h->heap_region_iterate(&g1_note_end); } @@ -1991,16 +1966,16 @@ protected: G1RemSet* _g1rs; BitMap* _region_bm; BitMap* _card_bm; + HeapRegionClaimer _hrclaimer; + public: - G1ParScrubRemSetTask(G1CollectedHeap* g1h, - BitMap* region_bm, BitMap* card_bm) : - AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), - _region_bm(region_bm), _card_bm(card_bm) { } + G1ParScrubRemSetTask(G1CollectedHeap* g1h, BitMap* region_bm, BitMap* card_bm, uint n_workers) : + AbstractGangTask("G1 ScrubRS"), _g1rs(g1h->g1_rem_set()), _region_bm(region_bm), _card_bm(card_bm), _hrclaimer(n_workers) { + } void work(uint worker_id) { if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1rs->scrub_par(_region_bm, _card_bm, worker_id, - HeapRegion::ScrubRemSetClaimValue); + _g1rs->scrub_par(_region_bm, _card_bm, worker_id, &_hrclaimer); } else { _g1rs->scrub(_region_bm, _card_bm); } @@ -2043,9 +2018,6 @@ void ConcurrentMark::cleanup() { G1ParFinalCountTask g1_par_count_task(g1h, &_region_bm, &_card_bm); if (G1CollectedHeap::use_parallel_gc_threads()) { - assert(g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue), - "sanity check"); - g1h->set_par_threads(); n_workers = g1h->n_par_threads(); assert(g1h->n_par_threads() == n_workers, @@ -2053,9 +2025,6 @@ void ConcurrentMark::cleanup() { g1h->workers()->run_task(&g1_par_count_task); // Done with the parallel phase so reset to 0. g1h->set_par_threads(0); - - assert(g1h->check_heap_region_claim_values(HeapRegion::FinalCountClaimValue), - "sanity check"); } else { n_workers = 1; g1_par_count_task.work(0); @@ -2080,9 +2049,6 @@ void ConcurrentMark::cleanup() { g1h->workers()->run_task(&g1_par_verify_task); // Done with the parallel phase so reset to 0. g1h->set_par_threads(0); - - assert(g1h->check_heap_region_claim_values(HeapRegion::VerifyCountClaimValue), - "sanity check"); } else { g1_par_verify_task.work(0); } @@ -2108,14 +2074,11 @@ void ConcurrentMark::cleanup() { g1h->reset_gc_time_stamp(); // Note end of marking in all heap regions. - G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list); + G1ParNoteEndTask g1_par_note_end_task(g1h, &_cleanup_list, n_workers); if (G1CollectedHeap::use_parallel_gc_threads()) { g1h->set_par_threads((int)n_workers); g1h->workers()->run_task(&g1_par_note_end_task); g1h->set_par_threads(0); - - assert(g1h->check_heap_region_claim_values(HeapRegion::NoteEndClaimValue), - "sanity check"); } else { g1_par_note_end_task.work(0); } @@ -2132,15 +2095,11 @@ void ConcurrentMark::cleanup() { // regions. if (G1ScrubRemSets) { double rs_scrub_start = os::elapsedTime(); - G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm); + G1ParScrubRemSetTask g1_par_scrub_rs_task(g1h, &_region_bm, &_card_bm, n_workers); if (G1CollectedHeap::use_parallel_gc_threads()) { g1h->set_par_threads((int)n_workers); g1h->workers()->run_task(&g1_par_scrub_rs_task); g1h->set_par_threads(0); - - assert(g1h->check_heap_region_claim_values( - HeapRegion::ScrubRemSetClaimValue), - "sanity check"); } else { g1_par_scrub_rs_task.work(0); } @@ -3288,6 +3247,7 @@ protected: BitMap* _cm_card_bm; uint _max_worker_id; int _active_workers; + HeapRegionClaimer _hrclaimer; public: G1AggregateCountDataTask(G1CollectedHeap* g1h, @@ -3295,18 +3255,18 @@ public: BitMap* cm_card_bm, uint max_worker_id, int n_workers) : - AbstractGangTask("Count Aggregation"), - _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), - _max_worker_id(max_worker_id), - _active_workers(n_workers) { } + AbstractGangTask("Count Aggregation"), + _g1h(g1h), _cm(cm), _cm_card_bm(cm_card_bm), + _max_worker_id(max_worker_id), + _active_workers(n_workers), + _hrclaimer(_active_workers) { + } void work(uint worker_id) { AggregateCountDataHRClosure cl(_g1h, _cm_card_bm, _max_worker_id); if (G1CollectedHeap::use_parallel_gc_threads()) { - _g1h->heap_region_par_iterate_chunked(&cl, worker_id, - _active_workers, - HeapRegion::AggregateCountClaimValue); + _g1h->heap_region_par_iterate(&cl, worker_id, &_hrclaimer); } else { _g1h->heap_region_iterate(&cl); } @@ -3323,15 +3283,9 @@ void ConcurrentMark::aggregate_count_data() { _max_worker_id, n_workers); if (G1CollectedHeap::use_parallel_gc_threads()) { - assert(_g1h->check_heap_region_claim_values(HeapRegion::InitialClaimValue), - "sanity check"); _g1h->set_par_threads(n_workers); _g1h->workers()->run_task(&g1_par_agg_task); _g1h->set_par_threads(0); - - assert(_g1h->check_heap_region_claim_values(HeapRegion::AggregateCountClaimValue), - "sanity check"); - _g1h->reset_heap_region_claim_values(); } else { g1_par_agg_task.work(0); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 133e2094f63..bec4fd63b83 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -90,8 +90,8 @@ size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; // Notes on implementation of parallelism in different tasks. // -// G1ParVerifyTask uses heap_region_par_iterate_chunked() for parallelism. -// The number of GC workers is passed to heap_region_par_iterate_chunked(). +// G1ParVerifyTask uses heap_region_par_iterate() for parallelism. +// The number of GC workers is passed to heap_region_par_iterate(). // It does use run_task() which sets _n_workers in the task. // G1ParTask executes g1_process_roots() -> // SharedHeap::process_roots() which calls eventually to @@ -1215,17 +1215,15 @@ public: class ParRebuildRSTask: public AbstractGangTask { G1CollectedHeap* _g1; + HeapRegionClaimer _hrclaimer; + public: - ParRebuildRSTask(G1CollectedHeap* g1) - : AbstractGangTask("ParRebuildRSTask"), - _g1(g1) - { } + ParRebuildRSTask(G1CollectedHeap* g1) : + AbstractGangTask("ParRebuildRSTask"), _g1(g1), _hrclaimer(g1->workers()->active_workers()) {} void work(uint worker_id) { RebuildRSOutOfRegionClosure rebuild_rs(_g1, worker_id); - _g1->heap_region_par_iterate_chunked(&rebuild_rs, worker_id, - _g1->workers()->active_workers(), - HeapRegion::RebuildRSClaimValue); + _g1->heap_region_par_iterate(&rebuild_rs, worker_id, &_hrclaimer); } }; @@ -1455,8 +1453,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, set_par_threads(n_workers); ParRebuildRSTask rebuild_rs_task(this); - assert(check_heap_region_claim_values( - HeapRegion::InitialClaimValue), "sanity check"); assert(UseDynamicNumberOfGCThreads || workers()->active_workers() == workers()->total_workers(), "Unless dynamic should use total workers"); @@ -1466,9 +1462,6 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, set_par_threads(workers()->active_workers()); workers()->run_task(&rebuild_rs_task); set_par_threads(0); - assert(check_heap_region_claim_values( - HeapRegion::RebuildRSClaimValue), "sanity check"); - reset_heap_region_claim_values(); } else { RebuildRSOutOfRegionClosure rebuild_rs(this); heap_region_iterate(&rebuild_rs); @@ -2634,111 +2627,12 @@ void G1CollectedHeap::heap_region_iterate(HeapRegionClosure* cl) const { } void -G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl, - uint worker_id, - uint num_workers, - jint claim_value) const { - _hrm.par_iterate(cl, worker_id, num_workers, claim_value); +G1CollectedHeap::heap_region_par_iterate(HeapRegionClosure* cl, + uint worker_id, + HeapRegionClaimer *hrclaimer) const { + _hrm.par_iterate(cl, worker_id, hrclaimer); } -class ResetClaimValuesClosure: public HeapRegionClosure { -public: - bool doHeapRegion(HeapRegion* r) { - r->set_claim_value(HeapRegion::InitialClaimValue); - return false; - } -}; - -void G1CollectedHeap::reset_heap_region_claim_values() { - ResetClaimValuesClosure blk; - heap_region_iterate(&blk); -} - -void G1CollectedHeap::reset_cset_heap_region_claim_values() { - ResetClaimValuesClosure blk; - collection_set_iterate(&blk); -} - -#ifdef ASSERT -// This checks whether all regions in the heap have the correct claim -// value. I also piggy-backed on this a check to ensure that the -// humongous_start_region() information on "continues humongous" -// regions is correct. - -class CheckClaimValuesClosure : public HeapRegionClosure { -private: - jint _claim_value; - uint _failures; - HeapRegion* _sh_region; - -public: - CheckClaimValuesClosure(jint claim_value) : - _claim_value(claim_value), _failures(0), _sh_region(NULL) { } - bool doHeapRegion(HeapRegion* r) { - if (r->claim_value() != _claim_value) { - gclog_or_tty->print_cr("Region " HR_FORMAT ", " - "claim value = %d, should be %d", - HR_FORMAT_PARAMS(r), - r->claim_value(), _claim_value); - ++_failures; - } - if (!r->is_humongous()) { - _sh_region = NULL; - } else if (r->is_starts_humongous()) { - _sh_region = r; - } else if (r->is_continues_humongous()) { - if (r->humongous_start_region() != _sh_region) { - gclog_or_tty->print_cr("Region " HR_FORMAT ", " - "HS = "PTR_FORMAT", should be "PTR_FORMAT, - HR_FORMAT_PARAMS(r), - r->humongous_start_region(), - _sh_region); - ++_failures; - } - } - return false; - } - uint failures() { return _failures; } -}; - -bool G1CollectedHeap::check_heap_region_claim_values(jint claim_value) { - CheckClaimValuesClosure cl(claim_value); - heap_region_iterate(&cl); - return cl.failures() == 0; -} - -class CheckClaimValuesInCSetHRClosure: public HeapRegionClosure { -private: - jint _claim_value; - uint _failures; - -public: - CheckClaimValuesInCSetHRClosure(jint claim_value) : - _claim_value(claim_value), _failures(0) { } - - uint failures() { return _failures; } - - bool doHeapRegion(HeapRegion* hr) { - assert(hr->in_collection_set(), "how?"); - assert(!hr->is_humongous(), "H-region in CSet"); - if (hr->claim_value() != _claim_value) { - gclog_or_tty->print_cr("CSet Region " HR_FORMAT ", " - "claim value = %d, should be %d", - HR_FORMAT_PARAMS(hr), - hr->claim_value(), _claim_value); - _failures += 1; - } - return false; - } -}; - -bool G1CollectedHeap::check_cset_heap_region_claim_values(jint claim_value) { - CheckClaimValuesInCSetHRClosure cl(claim_value); - collection_set_iterate(&cl); - return cl.failures() == 0; -} -#endif // ASSERT - // Clear the cached CSet starting regions and (more importantly) // the time stamps. Called when we reset the GC time stamp. void G1CollectedHeap::clear_cset_start_regions() { @@ -3252,19 +3146,21 @@ public: class G1ParVerifyTask: public AbstractGangTask { private: - G1CollectedHeap* _g1h; - VerifyOption _vo; - bool _failures; + G1CollectedHeap* _g1h; + VerifyOption _vo; + bool _failures; + HeapRegionClaimer _hrclaimer; public: // _vo == UsePrevMarking -> use "prev" marking information, // _vo == UseNextMarking -> use "next" marking information, // _vo == UseMarkWord -> use mark word from object header. G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) : - AbstractGangTask("Parallel verify task"), - _g1h(g1h), - _vo(vo), - _failures(false) { } + AbstractGangTask("Parallel verify task"), + _g1h(g1h), + _vo(vo), + _failures(false), + _hrclaimer(g1h->workers()->active_workers()) {} bool failures() { return _failures; @@ -3273,9 +3169,7 @@ public: void work(uint worker_id) { HandleMark hm; VerifyRegionClosure blk(true, _vo); - _g1h->heap_region_par_iterate_chunked(&blk, worker_id, - _g1h->workers()->active_workers(), - HeapRegion::ParVerifyClaimValue); + _g1h->heap_region_par_iterate(&blk, worker_id, &_hrclaimer); if (blk.failures()) { _failures = true; } @@ -3317,8 +3211,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { if (!silent) { gclog_or_tty->print("HeapRegions "); } if (GCParallelVerificationEnabled && ParallelGCThreads > 1) { - assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), - "sanity check"); G1ParVerifyTask task(this, vo); assert(UseDynamicNumberOfGCThreads || @@ -3332,15 +3224,6 @@ void G1CollectedHeap::verify(bool silent, VerifyOption vo) { failures = true; } - // Checks that the expected amount of parallel work was done. - // The implication is that n_workers is > 0. - assert(check_heap_region_claim_values(HeapRegion::ParVerifyClaimValue), - "sanity check"); - - reset_heap_region_claim_values(); - - assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), - "sanity check"); } else { VerifyRegionClosure blk(false, vo); heap_region_iterate(&blk); @@ -3927,8 +3810,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } assert(check_young_list_well_formed(), "young list should be well formed"); - assert(check_heap_region_claim_values(HeapRegion::InitialClaimValue), - "sanity check"); // Don't dynamically change the number of GC threads this early. A value of // 0 is used to indicate serial work. When parallel work is done, @@ -4289,26 +4170,12 @@ void G1CollectedHeap::finalize_for_evac_failure() { } void G1CollectedHeap::remove_self_forwarding_pointers() { - assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity"); - double remove_self_forwards_start = os::elapsedTime(); + set_par_threads(); G1ParRemoveSelfForwardPtrsTask rsfp_task(this); - - if (G1CollectedHeap::use_parallel_gc_threads()) { - set_par_threads(); - workers()->run_task(&rsfp_task); - set_par_threads(0); - } else { - rsfp_task.work(0); - } - - assert(check_cset_heap_region_claim_values(HeapRegion::ParEvacFailureClaimValue), "sanity"); - - // Reset the claim values in the regions in the collection set. - reset_cset_heap_region_claim_values(); - - assert(check_cset_heap_region_claim_values(HeapRegion::InitialClaimValue), "sanity"); + workers()->run_task(&rsfp_task); + set_par_threads(0); // Now restore saved marks, if any. assert(_objs_with_preserved_marks.size() == @@ -5949,11 +5816,6 @@ void G1CollectedHeap::evacuate_collection_set(EvacuationInfo& evacuation_info) { purge_code_root_memory(); - if (g1_policy()->during_initial_mark_pause()) { - // Reset the claim values set during marking the strong code roots - reset_heap_region_claim_values(); - } - finalize_for_evac_failure(); if (evacuation_failed()) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index bcc0419bf76..4f6d064fe9a 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -211,6 +211,7 @@ class G1CollectedHeap : public SharedHeap { friend class G1FreeHumongousRegionClosure; // Other related classes. friend class G1MarkSweep; + friend class HeapRegionClaimer; private: // The one and only G1CollectedHeap, so static functions can find it. @@ -1377,38 +1378,15 @@ public: inline HeapWord* bottom_addr_for_region(uint index) const; - // Divide the heap region sequence into "chunks" of some size (the number - // of regions divided by the number of parallel threads times some - // overpartition factor, currently 4). Assumes that this will be called - // in parallel by ParallelGCThreads worker threads with distinct worker - // ids in the range [0..max(ParallelGCThreads-1, 1)], that all parallel - // calls will use the same "claim_value", and that that claim value is - // different from the claim_value of any heap region before the start of - // the iteration. Applies "blk->doHeapRegion" to each of the regions, by - // attempting to claim the first region in each chunk, and, if - // successful, applying the closure to each region in the chunk (and - // setting the claim value of the second and subsequent regions of the - // chunk.) For now requires that "doHeapRegion" always returns "false", - // i.e., that a closure never attempt to abort a traversal. - void heap_region_par_iterate_chunked(HeapRegionClosure* cl, - uint worker_id, - uint num_workers, - jint claim_value) const; - - // It resets all the region claim values to the default. - void reset_heap_region_claim_values(); - - // Resets the claim values of regions in the current - // collection set to the default. - void reset_cset_heap_region_claim_values(); - -#ifdef ASSERT - bool check_heap_region_claim_values(jint claim_value); - - // Same as the routine above but only checks regions in the - // current collection set. - bool check_cset_heap_region_claim_values(jint claim_value); -#endif // ASSERT + // Iterate over the heap regions in parallel. Assumes that this will be called + // in parallel by ParallelGCThreads worker threads with distinct worker ids + // in the range [0..max(ParallelGCThreads-1, 1)]. Applies "blk->doHeapRegion" + // to each of the regions, by attempting to claim the region using the + // HeapRegionClaimer and, if successful, applying the closure to the claimed + // region. + void heap_region_par_iterate(HeapRegionClosure* cl, + uint worker_id, + HeapRegionClaimer* hrclaimer) const; // Clear the cached cset start regions and (more importantly) // the time stamps. Called when we reset the GC time stamp. diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index a2f33d12c38..1cf1b178afe 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -1598,19 +1598,17 @@ class ParKnownGarbageTask: public AbstractGangTask { CollectionSetChooser* _hrSorted; uint _chunk_size; G1CollectedHeap* _g1; + HeapRegionClaimer _hrclaimer; + public: - ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size) : - AbstractGangTask("ParKnownGarbageTask"), - _hrSorted(hrSorted), _chunk_size(chunk_size), - _g1(G1CollectedHeap::heap()) { } + ParKnownGarbageTask(CollectionSetChooser* hrSorted, uint chunk_size, uint n_workers) : + AbstractGangTask("ParKnownGarbageTask"), + _hrSorted(hrSorted), _chunk_size(chunk_size), + _g1(G1CollectedHeap::heap()), _hrclaimer(n_workers) {} void work(uint worker_id) { ParKnownGarbageHRClosure parKnownGarbageCl(_hrSorted, _chunk_size); - - // Back to zero for the claim value. - _g1->heap_region_par_iterate_chunked(&parKnownGarbageCl, worker_id, - _g1->workers()->active_workers(), - HeapRegion::InitialClaimValue); + _g1->heap_region_par_iterate(&parKnownGarbageCl, worker_id, &_hrclaimer); } }; @@ -1641,12 +1639,8 @@ G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) { } _collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(), WorkUnit); - ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, - (int) WorkUnit); + ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser, WorkUnit, (uint) no_of_gc_threads); _g1->workers()->run_task(&parKnownGarbageTask); - - assert(_g1->check_heap_region_claim_values(HeapRegion::InitialClaimValue), - "sanity check"); } else { KnownGarbageClosure knownGarbagecl(_collectionSetChooser); _g1->heap_region_iterate(&knownGarbagecl); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp index 28c57b4fcd4..96c675f42ec 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp @@ -177,16 +177,18 @@ class RemoveSelfForwardPtrHRClosure: public HeapRegionClosure { G1CollectedHeap* _g1h; ConcurrentMark* _cm; uint _worker_id; + HeapRegionClaimer* _hrclaimer; DirtyCardQueue _dcq; UpdateRSetDeferred _update_rset_cl; public: RemoveSelfForwardPtrHRClosure(G1CollectedHeap* g1h, - uint worker_id) : - _g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq), - _worker_id(worker_id), _cm(_g1h->concurrent_mark()) { - } + uint worker_id, + HeapRegionClaimer* hrclaimer) : + _g1h(g1h), _dcq(&g1h->dirty_card_queue_set()), _update_rset_cl(g1h, &_dcq), + _worker_id(worker_id), _cm(_g1h->concurrent_mark()), _hrclaimer(hrclaimer) { + } bool doHeapRegion(HeapRegion *hr) { bool during_initial_mark = _g1h->g1_policy()->during_initial_mark_pause(); @@ -195,7 +197,7 @@ public: assert(!hr->is_humongous(), "sanity"); assert(hr->in_collection_set(), "bad CS"); - if (hr->claimHeapRegion(HeapRegion::ParEvacFailureClaimValue)) { + if (_hrclaimer->claim_region(hr->hrm_index())) { if (hr->evacuation_failed()) { RemoveSelfForwardPtrObjClosure rspc(_g1h, _cm, hr, &_update_rset_cl, during_initial_mark, @@ -233,14 +235,15 @@ public: class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask { protected: G1CollectedHeap* _g1h; + HeapRegionClaimer _hrclaimer; public: G1ParRemoveSelfForwardPtrsTask(G1CollectedHeap* g1h) : - AbstractGangTask("G1 Remove Self-forwarding Pointers"), - _g1h(g1h) { } + AbstractGangTask("G1 Remove Self-forwarding Pointers"), _g1h(g1h), + _hrclaimer(g1h->workers()->active_workers()) {} void work(uint worker_id) { - RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id); + RemoveSelfForwardPtrHRClosure rsfp_cl(_g1h, worker_id, &_hrclaimer); HeapRegion* hr = _g1h->start_cset_region_for_worker(worker_id); _g1h->collection_set_iterate_from(hr, &rsfp_cl); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp index 02433dbc550..a24b5a8069e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp @@ -425,13 +425,9 @@ void G1RemSet::scrub(BitMap* region_bm, BitMap* card_bm) { _g1->heap_region_iterate(&scrub_cl); } -void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, - uint worker_num, int claim_val) { +void G1RemSet::scrub_par(BitMap* region_bm, BitMap* card_bm, uint worker_num, HeapRegionClaimer *hrclaimer) { ScrubRSClosure scrub_cl(region_bm, card_bm); - _g1->heap_region_par_iterate_chunked(&scrub_cl, - worker_num, - n_workers(), - claim_val); + _g1->heap_region_par_iterate(&scrub_cl, worker_num, hrclaimer); } G1TriggerClosure::G1TriggerClosure() : diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp index a6823dfdc14..73c79172361 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp @@ -128,10 +128,10 @@ public: void scrub(BitMap* region_bm, BitMap* card_bm); // Like the above, but assumes is called in parallel: "worker_num" is the - // parallel thread id of the current thread, and "claim_val" is the - // value that should be used to claim heap regions. + // parallel thread id of the current thread, and "hrclaimer" is the shared + // HeapRegionClaimer that should be used to claim heap regions. void scrub_par(BitMap* region_bm, BitMap* card_bm, - uint worker_num, int claim_val); + uint worker_num, HeapRegionClaimer* hrclaimer); // Refine the card corresponding to "card_ptr". // If check_for_refs_into_cset is true, a true result is returned diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index bb549aa5625..55e74c6669c 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -217,7 +217,6 @@ void HeapRegion::hr_clear(bool par, bool clear_space, bool locked) { } else { hrrs->clear(); } - _claimed = InitialClaimValue; } zero_marked_bytes(); @@ -294,17 +293,6 @@ void HeapRegion::clear_humongous() { _humongous_start_region = NULL; } -bool HeapRegion::claimHeapRegion(jint claimValue) { - jint current = _claimed; - if (current != claimValue) { - jint res = Atomic::cmpxchg(claimValue, &_claimed, current); - if (res == current) { - return true; - } - } - return false; -} - HeapRegion::HeapRegion(uint hrm_index, G1BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr) : @@ -314,7 +302,7 @@ HeapRegion::HeapRegion(uint hrm_index, _humongous_start_region(NULL), _in_collection_set(false), _next_in_special_set(NULL), - _claimed(InitialClaimValue), _evacuation_failed(false), + _evacuation_failed(false), _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0), _next_young_region(NULL), _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 74f32bcee4e..916726e48a0 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -254,9 +254,6 @@ class HeapRegion: public G1OffsetTableContigSpace { HeapRegionSetBase* _containing_set; #endif // ASSERT - // For parallel heapRegion traversal. - jint _claimed; - // We use concurrent marking to determine the amount of live data // in each heap region. size_t _prev_marked_bytes; // Bytes known to be live via last completed marking. @@ -336,19 +333,6 @@ class HeapRegion: public G1OffsetTableContigSpace { // up once during initialization time. static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size); - enum ClaimValues { - InitialClaimValue = 0, - FinalCountClaimValue = 1, - NoteEndClaimValue = 2, - ScrubRemSetClaimValue = 3, - ParVerifyClaimValue = 4, - RebuildRSClaimValue = 5, - ParEvacFailureClaimValue = 6, - AggregateCountClaimValue = 7, - VerifyCountClaimValue = 8, - ParMarkRootClaimValue = 9 - }; - // All allocated blocks are occupied by objects in a HeapRegion bool block_is_obj(const HeapWord* p) const; @@ -691,12 +675,6 @@ class HeapRegion: public G1OffsetTableContigSpace { return (HeapWord *) obj >= next_top_at_mark_start(); } - // For parallel heapRegion traversal. - bool claimHeapRegion(int claimValue); - jint claim_value() { return _claimed; } - // Use this carefully: only when you're sure no one is claiming... - void set_claim_value(int claimValue) { _claimed = claimValue; } - // Returns the "evacuation_failed" property of the region. bool evacuation_failed() { return _evacuation_failed; } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp index a88c4b355cf..5de9dbcce98 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.cpp @@ -260,20 +260,17 @@ uint HeapRegionManager::find_unavailable_from_idx(uint start_idx, uint* res_idx) return num_regions; } -uint HeapRegionManager::start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const { - return num_regions * worker_i / num_workers; -} - -void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const { - const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length); +void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const { + const uint start_index = hrclaimer->start_region_for_worker(worker_id); // Every worker will actually look at all regions, skipping over regions that // are currently not committed. // This also (potentially) iterates over regions newly allocated during GC. This // is no problem except for some extra work. - for (uint count = 0; count < _allocated_heapregions_length; count++) { - const uint index = (start_index + count) % _allocated_heapregions_length; - assert(0 <= index && index < _allocated_heapregions_length, "sanity"); + const uint n_regions = hrclaimer->n_regions(); + for (uint count = 0; count < n_regions; count++) { + const uint index = (start_index + count) % n_regions; + assert(0 <= index && index < n_regions, "sanity"); // Skip over unavailable regions if (!is_available(index)) { continue; @@ -282,11 +279,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint // We'll ignore "continues humongous" regions (we'll process them // when we come across their corresponding "start humongous" // region) and regions already claimed. - if (r->claim_value() == claim_value || r->is_continues_humongous()) { + if (hrclaimer->is_region_claimed(index) || r->is_continues_humongous()) { continue; } // OK, try to claim it - if (!r->claimHeapRegion(claim_value)) { + if (!hrclaimer->claim_region(index)) { continue; } // Success! @@ -306,13 +303,11 @@ void HeapRegionManager::par_iterate(HeapRegionClosure* blk, uint worker_id, uint assert(chr->humongous_start_region() == r, err_msg("Must work on humongous continuation of the original start region " PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr))); - assert(chr->claim_value() != claim_value, + assert(!hrclaimer->is_region_claimed(ch_index), "Must not have been claimed yet because claiming of humongous continuation first claims the start region"); - bool claim_result = chr->claimHeapRegion(claim_value); - // We should always be able to claim it; no one else should - // be trying to claim this region. - guarantee(claim_result, "We should always be able to claim the is_continues_humongous part of the humongous object"); + // There's no need to actually claim the continues humongous region, but we can do it in an assert as an extra precaution. + assert(hrclaimer->claim_region(ch_index), "We should always be able to claim the continuesHumongous part of the humongous object"); bool res2 = blk->doHeapRegion(chr); if (res2) { @@ -445,3 +440,31 @@ void HeapRegionManager::verify_optional() { } #endif // PRODUCT +HeapRegionClaimer::HeapRegionClaimer(uint n_workers) : + _n_workers(n_workers), _n_regions(G1CollectedHeap::heap()->_hrm._allocated_heapregions_length), _claims(NULL) { + assert(n_workers > 0, "Need at least one worker."); + _claims = NEW_C_HEAP_ARRAY(uint, _n_regions, mtGC); + memset(_claims, Unclaimed, sizeof(*_claims) * _n_regions); +} + +HeapRegionClaimer::~HeapRegionClaimer() { + if (_claims != NULL) { + FREE_C_HEAP_ARRAY(uint, _claims, mtGC); + } +} + +uint HeapRegionClaimer::start_region_for_worker(uint worker_id) const { + assert(worker_id < _n_workers, "Invalid worker_id."); + return _n_regions * worker_id / _n_workers; +} + +bool HeapRegionClaimer::is_region_claimed(uint region_index) const { + assert(region_index < _n_regions, "Invalid index."); + return _claims[region_index] == Claimed; +} + +bool HeapRegionClaimer::claim_region(uint region_index) { + assert(region_index < _n_regions, "Invalid index."); + uint old_val = Atomic::cmpxchg(Claimed, &_claims[region_index], Unclaimed); + return old_val == Unclaimed; +} diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp index 7f96df4b2b2..f94d20a5cf4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionManager.hpp @@ -31,6 +31,7 @@ class HeapRegion; class HeapRegionClosure; +class HeapRegionClaimer; class FreeRegionList; class G1HeapRegionTable : public G1BiasedMappedArray { @@ -66,6 +67,7 @@ class G1HeapRegionTable : public G1BiasedMappedArray { class HeapRegionManager: public CHeapObj { friend class VMStructs; + friend class HeapRegionClaimer; G1HeapRegionTable _regions; @@ -99,9 +101,6 @@ class HeapRegionManager: public CHeapObj { // Notify other data structures about change in the heap layout. void update_committed_space(HeapWord* old_end, HeapWord* new_end); - // Calculate the starting region for each worker during parallel iteration so - // that they do not all start from the same region. - uint start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const; // Find a contiguous set of empty or uncommitted regions of length num and return // the index of the first region or G1_NO_HRM_INDEX if the search was unsuccessful. @@ -223,7 +222,7 @@ public: // terminating the iteration early if doHeapRegion() returns true. void iterate(HeapRegionClosure* blk) const; - void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const; + void par_iterate(HeapRegionClosure* blk, uint worker_id, HeapRegionClaimer* hrclaimer) const; // Uncommit up to num_regions_to_remove regions that are completely free. // Return the actual number of uncommitted regions. @@ -235,5 +234,33 @@ public: void verify_optional() PRODUCT_RETURN; }; +// The HeapRegionClaimer is used during parallel iteration over heap regions, +// allowing workers to claim heap regions, gaining exclusive rights to these regions. +class HeapRegionClaimer : public StackObj { + uint _n_workers; + uint _n_regions; + uint* _claims; + + static const uint Unclaimed = 0; + static const uint Claimed = 1; + + public: + HeapRegionClaimer(uint n_workers); + ~HeapRegionClaimer(); + + inline uint n_regions() const { + return _n_regions; + } + + // Calculate the starting region for given worker so + // that they do not all start from the same region. + uint start_region_for_worker(uint worker_id) const; + + // Check if region has been claimed with this HRClaimer. + bool is_region_claimed(uint region_index) const; + + // Claim the given region, returns true if successfully claimed. + bool claim_region(uint region_index); +}; #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONMANAGER_HPP From 3ed02be10e68612ebdb5e8058a6259af314e9435 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Wed, 8 Oct 2014 09:23:18 +0200 Subject: [PATCH 16/91] 8059735: make_not_entrant_or_zombie sees zombies Make sure nmethod is not set to zombie state twice by sweeper and safepoint code. Reviewed-by: kvn, anoll, mgerdin --- hotspot/src/share/vm/runtime/sweeper.cpp | 26 ++++++++++++++++-------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp index ab1c113138e..cecb8ff08a1 100644 --- a/hotspot/src/share/vm/runtime/sweeper.cpp +++ b/hotspot/src/share/vm/runtime/sweeper.cpp @@ -540,17 +540,25 @@ int NMethodSweeper::process_nmethod(nmethod *nm) { // If there are no current activations of this method on the // stack we can safely convert it to a zombie method if (nm->can_not_entrant_be_converted()) { - if (PrintMethodFlushing && Verbose) { - tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); - } // Clear ICStubs to prevent back patching stubs of zombie or unloaded // nmethods during the next safepoint (see ICStub::finalize). - MutexLocker cl(CompiledIC_lock); - nm->clear_ic_stubs(); - // Code cache state change is tracked in make_zombie() - nm->make_zombie(); - _zombified_count++; - SWEEP(nm); + { + MutexLocker cl(CompiledIC_lock); + nm->clear_ic_stubs(); + } + // Acquiring the CompiledIC_lock may block for a safepoint and set the + // nmethod to zombie (see 'CodeCache::make_marked_nmethods_zombies'). + // Check if nmethod is still non-entrant at this point. + if (nm->is_not_entrant()) { + if (PrintMethodFlushing && Verbose) { + tty->print_cr("### Nmethod %3d/" PTR_FORMAT " (not entrant) being made zombie", nm->compile_id(), nm); + } + // Code cache state change is tracked in make_zombie() + nm->make_zombie(); + _zombified_count++; + SWEEP(nm); + } + assert(nm->is_zombie(), "nmethod must be zombie"); } else { // Still alive, clean up its inline caches MutexLocker cl(CompiledIC_lock); From edc10143cb71052df6b6dc2ff8dd23f0a12a976f Mon Sep 17 00:00:00 2001 From: Lois Foltan Date: Wed, 7 May 2014 19:38:22 +0400 Subject: [PATCH 17/91] 8036805: Correct linker method lookup Correct handling of array of primitive type qualifiers during field and method resolution. Reviewed-by: acorn, hseigel, ahgross --- .../src/share/vm/interpreter/linkResolver.cpp | 52 ++++++++++++------- hotspot/src/share/vm/oops/arrayKlass.cpp | 7 +++ hotspot/src/share/vm/oops/arrayKlass.hpp | 4 ++ hotspot/src/share/vm/oops/klass.cpp | 9 ++++ hotspot/src/share/vm/oops/klass.hpp | 2 + 5 files changed, 54 insertions(+), 20 deletions(-) diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index 6fbb3bfa6f1..5bf368a1765 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -246,6 +246,12 @@ void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle kl // Ignore overpasses so statics can be found during resolution Method* result_oop = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); + if (klass->oop_is_array()) { + // Only consider klass and super klass for arrays + result = methodHandle(THREAD, result_oop); + return; + } + // JDK 8, JVMS 5.4.3.4: Interface method resolution should // ignore static and non-public methods of java.lang.Object, // like clone, finalize, registerNatives. @@ -290,6 +296,11 @@ void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, Klass result = methodHandle(THREAD, super_klass->uncached_lookup_method(name, signature, Klass::normal)); } + if (klass->oop_is_array()) { + // Only consider klass and super klass for arrays + return; + } + if (result.is_null()) { Array* default_methods = InstanceKlass::cast(klass())->default_methods(); if (default_methods != NULL) { @@ -545,7 +556,7 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res // 2. lookup method in resolved klass and its super klasses lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, false, CHECK); - if (resolved_method.is_null()) { // not found in the class hierarchy + if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // not found in the class hierarchy // 3. lookup method in all the interfaces implemented by the resolved klass lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); @@ -558,16 +569,16 @@ void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle res CLEAR_PENDING_EXCEPTION; } } + } - if (resolved_method.is_null()) { - // 4. method lookup failed - ResourceMark rm(THREAD); - THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature), - nested_exception); - } + if (resolved_method.is_null()) { + // 4. method lookup failed + ResourceMark rm(THREAD); + THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + method_name, + method_signature), + nested_exception); } // 5. access checks, access checking may be turned off when calling from within the VM. @@ -633,17 +644,18 @@ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, // JDK8: also look for static methods lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, true, CHECK); - if (resolved_method.is_null()) { + if (resolved_method.is_null() && !resolved_klass->oop_is_array()) { // lookup method in all the super-interfaces lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); - if (resolved_method.is_null()) { - // no method found - ResourceMark rm(THREAD); - THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), - Method::name_and_sig_as_C_string(resolved_klass(), - method_name, - method_signature)); - } + } + + if (resolved_method.is_null()) { + // no method found + ResourceMark rm(THREAD); + THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(resolved_klass(), + method_name, + method_signature)); } if (check_access) { @@ -775,7 +787,7 @@ void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass } // Resolve instance field - KlassHandle sel_klass(THREAD, InstanceKlass::cast(resolved_klass())->find_field(field, sig, &fd)); + KlassHandle sel_klass(THREAD, resolved_klass->find_field(field, sig, &fd)); // check if field exists; i.e., if a klass containing the field def has been selected if (sel_klass.is_null()) { ResourceMark rm(THREAD); diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index 21de8cb42cf..740ae166adf 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -64,6 +64,13 @@ oop ArrayKlass::multi_allocate(int rank, jint* sizes, TRAPS) { return NULL; } +// find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined +Klass* ArrayKlass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { + // There are no fields in an array klass but look to the super class (Object) + assert(super(), "super klass must be present"); + return super()->find_field(name, sig, fd); +} + Method* ArrayKlass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { // There are no methods in an array klass but the super class (Object) has some assert(super(), "super klass must be present"); diff --git a/hotspot/src/share/vm/oops/arrayKlass.hpp b/hotspot/src/share/vm/oops/arrayKlass.hpp index 39ae5768aaf..248fde0373a 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.hpp +++ b/hotspot/src/share/vm/oops/arrayKlass.hpp @@ -28,6 +28,7 @@ #include "memory/universe.hpp" #include "oops/klass.hpp" +class fieldDescriptor; class klassVtable; // ArrayKlass is the abstract baseclass for all array classes @@ -77,6 +78,9 @@ class ArrayKlass: public Klass { virtual oop multi_allocate(int rank, jint* sizes, TRAPS); objArrayOop allocate_arrayArray(int n, int length, TRAPS); + // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined + Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; + // Lookup operations Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 810c8d729cd..bdd4839be46 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -130,6 +130,15 @@ bool Klass::compute_is_subtype_of(Klass* k) { return is_subclass_of(k); } +Klass* Klass::find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { +#ifdef ASSERT + tty->print_cr("Error: find_field called on a klass oop." + " Likely error: reflection method does not correctly" + " wrap return value in a mirror object."); +#endif + ShouldNotReachHere(); + return NULL; +} Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const { #ifdef ASSERT diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 5af2104e594..fd7691462f3 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -62,6 +62,7 @@ class ClassLoaderData; class klassVtable; class ParCompactionManager; class KlassSizeStats; +class fieldDescriptor; class Klass : public Metadata { friend class VMStructs; @@ -411,6 +412,7 @@ protected: virtual void initialize(TRAPS); // lookup operation for MethodLookupCache friend class MethodLookupCache; + virtual Klass* find_field(Symbol* name, Symbol* signature, fieldDescriptor* fd) const; virtual Method* uncached_lookup_method(Symbol* name, Symbol* signature, MethodLookupMode mode) const; public: Method* lookup_method(Symbol* name, Symbol* signature) const { From 6037f786bb1c4e4101a3a54bca0a7581591b2fe0 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Thu, 8 May 2014 21:09:57 +0400 Subject: [PATCH 18/91] 8041529: Better parameterization of parameter lists Reviewed-by: twisti, ahgross --- .../java.base/share/classes/java/lang/invoke/MethodType.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java index 3eab50e26ea..00e0a046efe 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java @@ -727,7 +727,7 @@ class MethodType implements java.io.Serializable { * @return the parameter types (as an immutable list) */ public List> parameterList() { - return Collections.unmodifiableList(Arrays.asList(ptypes)); + return Collections.unmodifiableList(Arrays.asList(ptypes.clone())); } /*non-public*/ Class lastParameterType() { From 3e5a530aff8642d44ef252eb804e080843588ad3 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 22 Jul 2014 16:24:48 +0400 Subject: [PATCH 19/91] 8015256: Better class accessibility Improve protection domain check in forName() Reviewed-by: mchung, acorn, jdn --- .../share/classes/java/lang/Class.java | 23 +++++++++++-------- jdk/src/java.base/share/native/include/jvm.h | 13 +++++++++++ .../java.base/share/native/libjava/Class.c | 5 ++-- 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index 2179ee809f5..5c03b975326 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -262,8 +262,8 @@ public final class Class implements java.io.Serializable, @CallerSensitive public static Class forName(String className) throws ClassNotFoundException { - return forName0(className, true, - ClassLoader.getClassLoader(Reflection.getCallerClass())); + Class caller = Reflection.getCallerClass(); + return forName0(className, true, ClassLoader.getClassLoader(caller), caller); } @@ -333,22 +333,27 @@ public final class Class implements java.io.Serializable, ClassLoader loader) throws ClassNotFoundException { - if (sun.misc.VM.isSystemDomainLoader(loader)) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - ClassLoader ccl = ClassLoader.getClassLoader(Reflection.getCallerClass()); + Class caller = null; + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + // Reflective call to get caller class is only needed if a security manager + // is present. Avoid the overhead of making this call otherwise. + caller = Reflection.getCallerClass(); + if (sun.misc.VM.isSystemDomainLoader(loader)) { + ClassLoader ccl = ClassLoader.getClassLoader(caller); if (!sun.misc.VM.isSystemDomainLoader(ccl)) { sm.checkPermission( SecurityConstants.GET_CLASSLOADER_PERMISSION); } } } - return forName0(name, initialize, loader); + return forName0(name, initialize, loader, caller); } - /** Called after security checks have been made. */ + /** Called after security check for system loader access checks have been made. */ private static native Class forName0(String name, boolean initialize, - ClassLoader loader) + ClassLoader loader, + Class caller) throws ClassNotFoundException; /** diff --git a/jdk/src/java.base/share/native/include/jvm.h b/jdk/src/java.base/share/native/include/jvm.h index f3ac9286cdc..26f988a2b58 100644 --- a/jdk/src/java.base/share/native/include/jvm.h +++ b/jdk/src/java.base/share/native/include/jvm.h @@ -385,6 +385,19 @@ JVM_ResolveClass(JNIEnv *env, jclass cls); JNIEXPORT jclass JNICALL JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); +/* + * Find a class from a given class loader. Throws ClassNotFoundException. + * name: name of class + * init: whether initialization is done + * loader: class loader to look up the class. This may not be the same as the caller's + * class loader. + * caller: initiating class. The initiating class may be null when a security + * manager is not installed. + */ +JNIEXPORT jclass JNICALL +JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init, + jobject loader, jclass caller); + /* * Find a class from a given class loader. Throw ClassNotFoundException * or NoClassDefFoundError depending on the value of the last diff --git a/jdk/src/java.base/share/native/libjava/Class.c b/jdk/src/java.base/share/native/libjava/Class.c index 98726d38ebd..ae759514a79 100644 --- a/jdk/src/java.base/share/native/libjava/Class.c +++ b/jdk/src/java.base/share/native/libjava/Class.c @@ -93,7 +93,7 @@ Java_java_lang_Class_registerNatives(JNIEnv *env, jclass cls) JNIEXPORT jclass JNICALL Java_java_lang_Class_forName0(JNIEnv *env, jclass this, jstring classname, - jboolean initialize, jobject loader) + jboolean initialize, jobject loader, jclass caller) { char *clname; jclass cls = 0; @@ -131,8 +131,7 @@ Java_java_lang_Class_forName0(JNIEnv *env, jclass this, jstring classname, goto done; } - cls = JVM_FindClassFromClassLoader(env, clname, initialize, - loader, JNI_FALSE); + cls = JVM_FindClassFromCaller(env, clname, initialize, loader, caller); done: if (clname != buf) { From 70ef26d4d0fefcd5cd1aee8f63043753b2c4a97b Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Mon, 12 May 2014 10:18:51 -0400 Subject: [PATCH 20/91] 8038364: Use certificate exceptions correctly Reviewed-by: vinnie, skoivu --- .../security/cert/CertificateRevokedException.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java b/jdk/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java index a545627061a..8c1f0664023 100644 --- a/jdk/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java +++ b/jdk/src/java.base/share/classes/java/security/cert/CertificateRevokedException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,6 +84,8 @@ public class CertificateRevokedException extends CertificateException { * @throws NullPointerException if {@code revocationDate}, * {@code reason}, {@code authority}, or * {@code extensions} is {@code null} + * @throws ClassCastException if {@code extensions} contains an incorrectly + * typed key or value */ public CertificateRevokedException(Date revocationDate, CRLReason reason, X500Principal authority, Map extensions) { @@ -94,7 +96,10 @@ public class CertificateRevokedException extends CertificateException { this.revocationDate = new Date(revocationDate.getTime()); this.reason = reason; this.authority = authority; - this.extensions = new HashMap(extensions); + // make sure Map only contains correct types + this.extensions = Collections.checkedMap(new HashMap<>(), + String.class, Extension.class); + this.extensions.putAll(extensions); } /** @@ -172,7 +177,8 @@ public class CertificateRevokedException extends CertificateException { public String getMessage() { return "Certificate has been revoked, reason: " + reason + ", revocation date: " + revocationDate - + ", authority: " + authority + ", extensions: " + extensions; + + ", authority: " + authority + ", extension OIDs: " + + extensions.keySet(); } /** From 14363dbaab1b4365367e96c7ce1ff125fc25ce1e Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 14 May 2014 15:40:39 +0200 Subject: [PATCH 21/91] 8041564: Improved management of logger resources Reviewed-by: skoivu, mchung, igerasim --- .../share/classes/java/util/logging/Logger.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java index ae4c1e46baf..fc4101f20f4 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1937,6 +1937,9 @@ public class Logger { } setCallersClassLoaderRef(callersClass); + if (isSystemLogger && getCallersClassLoader() != null) { + checkPermission(); + } if (findResourceBundle(name, true) == null) { // We've failed to find an expected ResourceBundle. // unset the caller's ClassLoader since we were unable to find the @@ -2170,11 +2173,13 @@ public class Logger { return trb; } final String rbName = isSystemLogger - ? trb.resourceBundleName + // ancestor of a system logger is expected to be a system logger. + // ignore resource bundle name if it's not. + ? (target.isSystemLogger ? trb.resourceBundleName : null) : target.getResourceBundleName(); if (rbName != null) { return LoggerBundle.get(rbName, - findResourceBundle(rbName, true)); + findResourceBundle(rbName, true)); } target = isSystemLogger ? target.parent : target.getParent(); } From 91823dc0c8428ec5edd9628314b2e9913891e7d9 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 22 May 2014 12:28:27 -0700 Subject: [PATCH 22/91] 8041540: Better use of pages in font processing Reviewed-by: srl, bae, mschoene --- .../layout/ContextualSubstSubtables.cpp | 98 +++++++++++++------ 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualSubstSubtables.cpp b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualSubstSubtables.cpp index 3707efdfb4f..14906145e54 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualSubstSubtables.cpp +++ b/jdk/src/java.desktop/share/native/libfontmanager/layout/ContextualSubstSubtables.cpp @@ -243,12 +243,22 @@ le_uint32 ContextualSubstitutionFormat1Subtable::process(const LETableReference le_uint16 srSetCount = SWAPW(subRuleSetCount); if (coverageIndex < srSetCount) { + LEReferenceToArrayOf subRuleSetTableOffsetArrayRef(base, success, + &subRuleSetTableOffsetArray[coverageIndex], 1); + if (LE_FAILURE(success)) { + return 0; + } Offset subRuleSetTableOffset = SWAPW(subRuleSetTableOffsetArray[coverageIndex]); LEReferenceTo subRuleSetTable(base, success, (const SubRuleSetTable *) ((char *) this + subRuleSetTableOffset)); le_uint16 subRuleCount = SWAPW(subRuleSetTable->subRuleCount); le_int32 position = glyphIterator->getCurrStreamPosition(); + LEReferenceToArrayOf subRuleTableOffsetArrayRef(base, success, + subRuleSetTable->subRuleTableOffsetArray, subRuleCount); + if (LE_FAILURE(success)) { + return 0; + } for (le_uint16 subRule = 0; subRule < subRuleCount; subRule += 1) { Offset subRuleTableOffset = SWAPW(subRuleSetTable->subRuleTableOffsetArray[subRule]); @@ -301,34 +311,44 @@ le_uint32 ContextualSubstitutionFormat2Subtable::process(const LETableReference glyphIterator->getCurrGlyphID(), success); - if (setClass < scSetCount && subClassSetTableOffsetArray[setClass] != 0) { - Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]); - LEReferenceTo - subClassSetTable(base, success, (const SubClassSetTable *) ((char *) this + subClassSetTableOffset)); - le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount); - le_int32 position = glyphIterator->getCurrStreamPosition(); + if (setClass < scSetCount) { + LEReferenceToArrayOf + subClassSetTableOffsetArrayRef(base, success, subClassSetTableOffsetArray, setClass); + if (LE_FAILURE(success)) { return 0; } + if (subClassSetTableOffsetArray[setClass] != 0) { - for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) { - Offset subClassRuleTableOffset = - SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]); - LEReferenceTo - subClassRuleTable(subClassSetTable, success, subClassRuleTableOffset); - le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1; - le_uint16 substCount = SWAPW(subClassRuleTable->substCount); - - LEReferenceToArrayOf classArray(base, success, subClassRuleTable->classArray, matchCount+1); - - if (LE_FAILURE(success)) { return 0; } - if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) { - LEReferenceToArrayOf - substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount); - - applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); - - return matchCount + 1; + Offset subClassSetTableOffset = SWAPW(subClassSetTableOffsetArray[setClass]); + LEReferenceTo + subClassSetTable(base, success, (const SubClassSetTable *) ((char *) this + subClassSetTableOffset)); + le_uint16 subClassRuleCount = SWAPW(subClassSetTable->subClassRuleCount); + le_int32 position = glyphIterator->getCurrStreamPosition(); + LEReferenceToArrayOf + subClassRuleTableOffsetArrayRef(base, success, subClassSetTable->subClassRuleTableOffsetArray, subClassRuleCount); + if (LE_FAILURE(success)) { + return 0; } + for (le_uint16 scRule = 0; scRule < subClassRuleCount; scRule += 1) { + Offset subClassRuleTableOffset = + SWAPW(subClassSetTable->subClassRuleTableOffsetArray[scRule]); + LEReferenceTo + subClassRuleTable(subClassSetTable, success, subClassRuleTableOffset); + le_uint16 matchCount = SWAPW(subClassRuleTable->glyphCount) - 1; + le_uint16 substCount = SWAPW(subClassRuleTable->substCount); - glyphIterator->setCurrStreamPosition(position); + LEReferenceToArrayOf classArray(base, success, subClassRuleTable->classArray, matchCount+1); + + if (LE_FAILURE(success)) { return 0; } + if (matchGlyphClasses(classArray, matchCount, glyphIterator, classDefinitionTable, success)) { + LEReferenceToArrayOf + substLookupRecordArray(base, success, (const SubstitutionLookupRecord *) &subClassRuleTable->classArray[matchCount], substCount); + + applySubstitutionLookups(lookupProcessor, substLookupRecordArray, substCount, glyphIterator, fontInstance, position, success); + + return matchCount + 1; + } + + glyphIterator->setCurrStreamPosition(position); + } } } @@ -442,13 +462,22 @@ le_uint32 ChainingContextualSubstitutionFormat1Subtable::process(const LETableRe le_uint16 srSetCount = SWAPW(chainSubRuleSetCount); if (coverageIndex < srSetCount) { + LEReferenceToArrayOf + chainSubRuleSetTableOffsetArrayRef(base, success, chainSubRuleSetTableOffsetArray, coverageIndex); + if (LE_FAILURE(success)) { + return 0; + } Offset chainSubRuleSetTableOffset = SWAPW(chainSubRuleSetTableOffsetArray[coverageIndex]); LEReferenceTo chainSubRuleSetTable(base, success, (const ChainSubRuleSetTable *) ((char *) this + chainSubRuleSetTableOffset)); le_uint16 chainSubRuleCount = SWAPW(chainSubRuleSetTable->chainSubRuleCount); le_int32 position = glyphIterator->getCurrStreamPosition(); GlyphIterator tempIterator(*glyphIterator, emptyFeatureList); - + LEReferenceToArrayOf + chainSubRuleTableOffsetArrayRef(base, success, chainSubRuleSetTable->chainSubRuleTableOffsetArray, chainSubRuleCount); + if (LE_FAILURE(success)) { + return 0; + } for (le_uint16 subRule = 0; subRule < chainSubRuleCount; subRule += 1) { Offset chainSubRuleTableOffset = SWAPW(chainSubRuleSetTable->chainSubRuleTableOffsetArray[subRule]); @@ -530,6 +559,11 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LETableRe le_int32 setClass = inputClassDefinitionTable->getGlyphClass(inputClassDefinitionTable, glyphIterator->getCurrGlyphID(), success); + LEReferenceToArrayOf + chainSubClassSetTableOffsetArrayRef(base, success, chainSubClassSetTableOffsetArray, setClass); + if (LE_FAILURE(success)) { + return 0; + } if (setClass < scSetCount && chainSubClassSetTableOffsetArray[setClass] != 0) { Offset chainSubClassSetTableOffset = SWAPW(chainSubClassSetTableOffsetArray[setClass]); @@ -538,7 +572,11 @@ le_uint32 ChainingContextualSubstitutionFormat2Subtable::process(const LETableRe le_uint16 chainSubClassRuleCount = SWAPW(chainSubClassSetTable->chainSubClassRuleCount); le_int32 position = glyphIterator->getCurrStreamPosition(); GlyphIterator tempIterator(*glyphIterator, emptyFeatureList); - + LEReferenceToArrayOf + chainSubClassRuleTableOffsetArrayRef(base, success, chainSubClassSetTable->chainSubClassRuleTableOffsetArray, chainSubClassRuleCount); + if (LE_FAILURE(success)) { + return 0; + } for (le_uint16 scRule = 0; scRule < chainSubClassRuleCount; scRule += 1) { Offset chainSubClassRuleTableOffset = SWAPW(chainSubClassSetTable->chainSubClassRuleTableOffsetArray[scRule]); @@ -603,12 +641,14 @@ le_uint32 ChainingContextualSubstitutionFormat3Subtable::process(const LETableRe } le_uint16 backtrkGlyphCount = SWAPW(backtrackGlyphCount); + LEReferenceToArrayOf backtrackGlyphArrayRef(base, success, backtrackCoverageTableOffsetArray, backtrkGlyphCount); + if (LE_FAILURE(success)) { + return 0; + } le_uint16 inputGlyphCount = (le_uint16) SWAPW(backtrackCoverageTableOffsetArray[backtrkGlyphCount]); LEReferenceToArrayOf inputCoverageTableOffsetArray(base, success, &backtrackCoverageTableOffsetArray[backtrkGlyphCount + 1], inputGlyphCount+2); // offset if (LE_FAILURE(success)) { return 0; } const le_uint16 lookaheadGlyphCount = (le_uint16) SWAPW(inputCoverageTableOffsetArray[inputGlyphCount]); - - if( LE_FAILURE(success)) { return 0; } LEReferenceToArrayOf lookaheadCoverageTableOffsetArray(base, success, inputCoverageTableOffsetArray.getAlias(inputGlyphCount + 1, success), lookaheadGlyphCount+2); if( LE_FAILURE(success) ) { return 0; } From f97c6a8a967258a654d0bcab6287b58865a11dac Mon Sep 17 00:00:00 2001 From: Petr Pchelko Date: Fri, 23 May 2014 10:56:42 +0400 Subject: [PATCH 23/91] 8041545: Better validation of generated rasters Reviewed-by: prr, serb, bae, skoivu --- .../share/classes/sun/awt/image/BytePackedRaster.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java index bd3835d5184..3e60f193ac2 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/image/BytePackedRaster.java @@ -1408,10 +1408,10 @@ public class BytePackedRaster extends SunWritableRaster { } } - int lastbit = (dataBitOffset - + (height-1) * scanlineStride * 8 - + (width-1) * pixelBitStride - + pixelBitStride - 1); + long lastbit = (long) dataBitOffset + + (long) (height - 1) * (long) scanlineStride * 8 + + (long) (width - 1) * (long) pixelBitStride + + (long) pixelBitStride - 1; if (lastbit < 0 || lastbit / 8 >= data.length) { throw new RasterFormatException("raster dimensions overflow " + "array bounds"); From 91bc3af39256625034b4ff73cac6c08c5f00e406 Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Tue, 27 May 2014 08:56:59 -0400 Subject: [PATCH 24/91] 8038908: Make Signature more robust Reviewed-by: valeriep, skoivu, asmotrak --- .../classes/java/security/Signature.java | 42 +++++++++++++++---- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/security/Signature.java b/jdk/src/java.base/share/classes/java/security/Signature.java index 60a7e01b6c9..738cf84ef5e 100644 --- a/jdk/src/java.base/share/classes/java/security/Signature.java +++ b/jdk/src/java.base/share/classes/java/security/Signature.java @@ -604,9 +604,13 @@ public abstract class Signature extends SignatureSpi { * @return the number of bytes placed into {@code outbuf}. * * @exception SignatureException if this signature object is not - * initialized properly, if this signature algorithm is unable to - * process the input data provided, or if {@code len} is less - * than the actual signature length. + * initialized properly, if this signature algorithm is unable to + * process the input data provided, or if {@code len} is less + * than the actual signature length. + * @exception IllegalArgumentException if {@code outbuf} is {@code null}, + * or {@code offset} or {@code len} is less than 0, or the sum of + * {@code offset} and {@code len} is greater than the length of + * {@code outbuf}. * * @since 1.2 */ @@ -615,6 +619,9 @@ public abstract class Signature extends SignatureSpi { if (outbuf == null) { throw new IllegalArgumentException("No output buffer given"); } + if (offset < 0 || len < 0) { + throw new IllegalArgumentException("offset or len is less than 0"); + } if (outbuf.length - offset < len) { throw new IllegalArgumentException ("Output buffer too small for specified offset and length"); @@ -683,9 +690,16 @@ public abstract class Signature extends SignatureSpi { public final boolean verify(byte[] signature, int offset, int length) throws SignatureException { if (state == VERIFY) { - if ((signature == null) || (offset < 0) || (length < 0) || - (length > signature.length - offset)) { - throw new IllegalArgumentException("Bad arguments"); + if (signature == null) { + throw new IllegalArgumentException("signature is null"); + } + if (offset < 0 || length < 0) { + throw new IllegalArgumentException + ("offset or length is less than 0"); + } + if (signature.length - offset < length) { + throw new IllegalArgumentException + ("signature too small for specified offset and length"); } return engineVerify(signature, offset, length); @@ -733,11 +747,25 @@ public abstract class Signature extends SignatureSpi { * @param len the number of bytes to use, starting at offset. * * @exception SignatureException if this signature object is not - * initialized properly. + * initialized properly. + * @exception IllegalArgumentException if {@code data} is {@code null}, + * or {@code off} or {@code len} is less than 0, or the sum of + * {@code off} and {@code len} is greater than the length of + * {@code data}. */ public final void update(byte[] data, int off, int len) throws SignatureException { if (state == SIGN || state == VERIFY) { + if (data == null) { + throw new IllegalArgumentException("data is null"); + } + if (off < 0 || len < 0) { + throw new IllegalArgumentException("off or len is less than 0"); + } + if (data.length - off < len) { + throw new IllegalArgumentException + ("data too small for specified offset and length"); + } engineUpdate(data, off, len); } else { throw new SignatureException("object not initialized for " From be3dc19daeacc4e5fac376c6bceaba47df00de92 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 28 May 2014 14:51:24 +0100 Subject: [PATCH 25/91] 8039509: Wrap sockets more thoroughly Reviewed-by: chegar, alanb --- jdk/make/mapfiles/libnet/mapfile-vers | 2 + .../net/AbstractPlainDatagramSocketImpl.java | 4 + .../classes/java/net/DatagramSocket.java | 42 ++++++++- .../classes/java/net/DatagramSocketImpl.java | 6 ++ .../sun/nio/ch/DatagramChannelImpl.java | 19 ++++ .../libnet/AbstractPlainDatagramSocketImpl.c | 89 +++++++++++++++++++ .../libnet/AbstractPlainDatagramSocketImpl.c | 82 +++++++++++++++++ 7 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 jdk/src/java.base/unix/native/libnet/AbstractPlainDatagramSocketImpl.c create mode 100644 jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers index ab621a923a8..168d38d8ee3 100644 --- a/jdk/make/mapfiles/libnet/mapfile-vers +++ b/jdk/make/mapfiles/libnet/mapfile-vers @@ -28,6 +28,8 @@ SUNWprivate_1.1 { global: JNI_OnLoad; + Java_java_net_AbstractPlainDatagramSocketImpl_init; + Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable; Java_java_net_PlainSocketImpl_socketListen; Java_java_net_PlainDatagramSocketImpl_getTTL; Java_java_net_PlainDatagramSocketImpl_init; diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index a557299798b..0ffe37f8d9f 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -68,6 +68,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl return null; } }); + init(); } /** @@ -362,4 +363,7 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl protected boolean nativeConnectDisabled() { return connectDisabled; } + + native int dataAvailable(); + private static native void init(); } diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java index c9cf26f0b1f..c047b3cf6a4 100644 --- a/jdk/src/java.base/share/classes/java/net/DatagramSocket.java +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocket.java @@ -85,6 +85,17 @@ class DatagramSocket implements java.io.Closeable { */ boolean oldImpl = false; + /** + * Set when a socket is ST_CONNECTED until we are certain + * that any packets which might have been received prior + * to calling connect() but not read by the application + * have been read. During this time we check the source + * address of all packets received to be sure they are from + * the connected destination. Other packets are read but + * silently dropped. + */ + private boolean explicitFilter = false; + private int bytesLeftToFilter; /* * Connection state: * ST_NOT_CONNECTED = socket not connected @@ -144,6 +155,15 @@ class DatagramSocket implements java.io.Closeable { // socket is now connected by the impl connectState = ST_CONNECTED; + // Do we need to filter some packets? + int avail = getImpl().dataAvailable(); + if (avail == -1) { + throw new SocketException(); + } + explicitFilter = avail > 0; + if (explicitFilter) { + bytesLeftToFilter = getReceiveBufferSize(); + } } catch (SocketException se) { // connection will be emulated by DatagramSocket @@ -492,6 +512,7 @@ class DatagramSocket implements java.io.Closeable { connectedAddress = null; connectedPort = -1; connectState = ST_NOT_CONNECTED; + explicitFilter = false; } } @@ -750,10 +771,12 @@ class DatagramSocket implements java.io.Closeable { } // end of while } } - if (connectState == ST_CONNECTED_NO_IMPL) { + if ((connectState == ST_CONNECTED_NO_IMPL) || explicitFilter) { // We have to do the filtering the old fashioned way since // the native impl doesn't support connect or the connect - // via the impl failed. + // via the impl failed, or .. "explicitFilter" may be set when + // a socket is connected via the impl, for a period of time + // when packets from other sources might be queued on socket. boolean stop = false; while (!stop) { InetAddress peekAddress = null; @@ -772,8 +795,12 @@ class DatagramSocket implements java.io.Closeable { if ((!connectedAddress.equals(peekAddress)) || (connectedPort != peekPort)) { // throw the packet away and silently continue - DatagramPacket tmp = new DatagramPacket(new byte[1], 1); + DatagramPacket tmp = new DatagramPacket( + new byte[1024], 1024); getImpl().receive(tmp); + if (explicitFilter) { + bytesLeftToFilter -= tmp.getLength(); + } } else { stop = true; } @@ -782,6 +809,15 @@ class DatagramSocket implements java.io.Closeable { // If the security check succeeds, or the datagram is // connected then receive the packet getImpl().receive(p); + if (explicitFilter) { + bytesLeftToFilter -= p.getLength(); + if (bytesLeftToFilter <= 0) { + explicitFilter = false; + } else { + // break out of filter, if there is no more data queued + explicitFilter = getImpl().dataAvailable() > 0; + } + } } } diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java index 50d5369f66d..2abaaf9a237 100644 --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java @@ -63,6 +63,12 @@ public abstract class DatagramSocketImpl implements SocketOptions { return socket; } + int dataAvailable() { + // default impl returns zero, which disables the calling + // functionality + return 0; + } + /** * Creates a datagram socket. * @exception SocketException if there is an error in the diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index a34286bddb4..b9fd16eae29 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -740,6 +740,25 @@ class DatagramChannelImpl // set or refresh local address localAddress = Net.localAddress(fd); + + // flush any packets already received. + boolean blocking = false; + synchronized (blockingLock()) { + try { + blocking = isBlocking(); + ByteBuffer tmpBuf = ByteBuffer.allocate(100); + if (blocking) { + configureBlocking(false); + } + do { + tmpBuf.clear(); + } while (read(tmpBuf) > 0); + } finally { + if (blocking) { + configureBlocking(true); + } + } + } } } } diff --git a/jdk/src/java.base/unix/native/libnet/AbstractPlainDatagramSocketImpl.c b/jdk/src/java.base/unix/native/libnet/AbstractPlainDatagramSocketImpl.c new file mode 100644 index 00000000000..075fffc5176 --- /dev/null +++ b/jdk/src/java.base/unix/native/libnet/AbstractPlainDatagramSocketImpl.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 +#include + +#ifdef __solaris__ +#include +#include + +#ifndef BSD_COMP +#define BSD_COMP +#endif + +#endif + +#include + +#include "jvm.h" +#include "jni_util.h" +#include "net_util.h" + +#include "java_net_AbstractPlainDatagramSocketImpl.h" + +static jfieldID IO_fd_fdID; + +static jfieldID apdsi_fdID; + + +/* + * Class: java_net_AbstractPlainDatagramSocketImpl + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { + + apdsi_fdID = (*env)->GetFieldID(env, cls, "fd", + "Ljava/io/FileDescriptor;"); + CHECK_NULL(apdsi_fdID); + + IO_fd_fdID = NET_GetFileDescriptorID(env); +} + +/* + * Class: java_net_AbstractPlainDatagramSocketImpl + * Method: dataAvailable + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable +(JNIEnv *env, jobject this) { + int fd, retval; + + jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID); + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return -1; + } + fd = (*env)->GetIntField(env, fdObj, IO_fd_fdID); + + if (ioctl(fd, FIONREAD, &retval) < 0) { + return -1; + } + return retval; +} diff --git a/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c new file mode 100644 index 00000000000..7244e664c9e --- /dev/null +++ b/jdk/src/java.base/windows/native/libnet/AbstractPlainDatagramSocketImpl.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 +#include + +#include "jvm.h" +#include "jni_util.h" +#include "net_util.h" + +#include "java_net_AbstractPlainDatagramSocketImpl.h" + +static jfieldID IO_fd_fdID; + +static jfieldID apdsi_fdID; + + +/* + * Class: java_net_AbstractPlainDatagramSocketImpl + * Method: init + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) { + + apdsi_fdID = (*env)->GetFieldID(env, cls, "fd", + "Ljava/io/FileDescriptor;"); + CHECK_NULL(apdsi_fdID); + + IO_fd_fdID = NET_GetFileDescriptorID(env); + CHECK_NULL(IO_fd_fdID); + + JNU_CHECK_EXCEPTION(env); +} + +/* + * Class: java_net_AbstractPlainDatagramSocketImpl + * Method: dataAvailable + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_java_net_AbstractPlainDatagramSocketImpl_dataAvailable +(JNIEnv *env, jobject this) { + SOCKET fd; + int retval; + + jobject fdObj = (*env)->GetObjectField(env, this, apdsi_fdID); + + if (IS_NULL(fdObj)) { + JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", + "Socket closed"); + return -1; + } + fd = (SOCKET)(*env)->GetIntField(env, fdObj, IO_fd_fdID); + + if (ioctlsocket(fd, FIONREAD, &retval) < 0) { + return -1; + } + return retval; +} + From 7d730f7819cf1a1472f1b85921ff88bc9f85495e Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Fri, 30 May 2014 16:09:49 +0400 Subject: [PATCH 26/91] 8042609: Limit splashiness of splash images Reviewed-by: mschoene, serb --- .../native/libsplashscreen/splashscreen_sys.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c b/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c index 6bbfd517db8..3c1fe7f5091 100644 --- a/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c +++ b/jdk/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,6 +213,14 @@ SplashPaint(Splash * splash, HDC hdc) void SplashRedrawWindow(Splash * splash) { + if (!SplashIsStillLooping(splash)) { + KillTimer(splash->hWnd, 0); + } + + if (splash->currentFrame < 0) { + return; + } + SplashUpdateScreenData(splash); if (splash->isLayered) { BLENDFUNCTION bf; @@ -303,9 +311,6 @@ SplashRedrawWindow(Splash * splash) time = 0; SetTimer(splash->hWnd, 0, time, NULL); } - else { - KillTimer(splash->hWnd, 0); - } } void SplashReconfigureNow(Splash * splash) { From 7bd17413f23754f03c5706ab0e261c4bd5e76764 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 14 Oct 2014 13:10:50 -0700 Subject: [PATCH 27/91] 8015256: Better class accessibility Improve protection domain check in forName() Reviewed-by: mchung, acorn, jdn --- hotspot/make/aix/makefiles/mapfile-vers-debug | 1 + .../make/aix/makefiles/mapfile-vers-product | 1 + .../bsd/makefiles/mapfile-vers-darwin-debug | 1 + .../bsd/makefiles/mapfile-vers-darwin-product | 1 + hotspot/make/bsd/makefiles/mapfile-vers-debug | 1 + .../make/bsd/makefiles/mapfile-vers-product | 1 + .../make/linux/makefiles/mapfile-vers-debug | 1 + .../make/linux/makefiles/mapfile-vers-product | 1 + hotspot/make/solaris/makefiles/mapfile-vers | 1 + hotspot/src/share/vm/prims/jvm.cpp | 46 ++++++++++++++++++- hotspot/src/share/vm/prims/jvm.h | 13 ++++++ 11 files changed, 66 insertions(+), 2 deletions(-) diff --git a/hotspot/make/aix/makefiles/mapfile-vers-debug b/hotspot/make/aix/makefiles/mapfile-vers-debug index 49beedda9ed..6557af2e313 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-debug +++ b/hotspot/make/aix/makefiles/mapfile-vers-debug @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/make/aix/makefiles/mapfile-vers-product b/hotspot/make/aix/makefiles/mapfile-vers-product index 8adbf613849..f1b93ad37b3 100644 --- a/hotspot/make/aix/makefiles/mapfile-vers-product +++ b/hotspot/make/aix/makefiles/mapfile-vers-product @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug index adf6616885a..60ec58b0229 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-debug @@ -82,6 +82,7 @@ _JVM_EnableCompiler _JVM_Exit _JVM_FillInStackTrace + _JVM_FindClassFromCaller _JVM_FindClassFromClass _JVM_FindClassFromClassLoader _JVM_FindClassFromBootLoader diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product index adf6616885a..60ec58b0229 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-darwin-product @@ -82,6 +82,7 @@ _JVM_EnableCompiler _JVM_Exit _JVM_FillInStackTrace + _JVM_FindClassFromCaller _JVM_FindClassFromClass _JVM_FindClassFromClassLoader _JVM_FindClassFromBootLoader diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-debug b/hotspot/make/bsd/makefiles/mapfile-vers-debug index 6c79e8b9b75..e60cc7d6fcc 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-debug +++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/make/bsd/makefiles/mapfile-vers-product b/hotspot/make/bsd/makefiles/mapfile-vers-product index 6c79e8b9b75..e60cc7d6fcc 100644 --- a/hotspot/make/bsd/makefiles/mapfile-vers-product +++ b/hotspot/make/bsd/makefiles/mapfile-vers-product @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-debug b/hotspot/make/linux/makefiles/mapfile-vers-debug index 6c79e8b9b75..e60cc7d6fcc 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-debug +++ b/hotspot/make/linux/makefiles/mapfile-vers-debug @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/make/linux/makefiles/mapfile-vers-product b/hotspot/make/linux/makefiles/mapfile-vers-product index 6c79e8b9b75..e60cc7d6fcc 100644 --- a/hotspot/make/linux/makefiles/mapfile-vers-product +++ b/hotspot/make/linux/makefiles/mapfile-vers-product @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/make/solaris/makefiles/mapfile-vers b/hotspot/make/solaris/makefiles/mapfile-vers index 51cb3f9657b..35078f1241a 100644 --- a/hotspot/make/solaris/makefiles/mapfile-vers +++ b/hotspot/make/solaris/makefiles/mapfile-vers @@ -84,6 +84,7 @@ SUNWprivate_1.1 { JVM_EnableCompiler; JVM_Exit; JVM_FillInStackTrace; + JVM_FindClassFromCaller; JVM_FindClassFromClass; JVM_FindClassFromClassLoader; JVM_FindClassFromBootLoader; diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index fa02d67b4a7..0d6b682404e 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -805,6 +805,7 @@ JVM_ENTRY(jclass, JVM_FindClassFromBootLoader(JNIEnv* env, return (jclass) JNIHandles::make_local(env, k->java_mirror()); JVM_END +// Not used; JVM_FindClassFromCaller replaces this. JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, jboolean init, jobject loader, jboolean throwError)) @@ -831,6 +832,42 @@ JVM_ENTRY(jclass, JVM_FindClassFromClassLoader(JNIEnv* env, const char* name, return result; JVM_END +// Find a class with this name in this loader, using the caller's protection domain. +JVM_ENTRY(jclass, JVM_FindClassFromCaller(JNIEnv* env, const char* name, + jboolean init, jobject loader, + jclass caller)) + JVMWrapper2("JVM_FindClassFromCaller %s throws ClassNotFoundException", name); + // Java libraries should ensure that name is never null... + if (name == NULL || (int)strlen(name) > Symbol::max_length()) { + // It's impossible to create this class; the name cannot fit + // into the constant pool. + THROW_MSG_0(vmSymbols::java_lang_ClassNotFoundException(), name); + } + + TempNewSymbol h_name = SymbolTable::new_symbol(name, CHECK_NULL); + + oop loader_oop = JNIHandles::resolve(loader); + oop from_class = JNIHandles::resolve(caller); + oop protection_domain = NULL; + // If loader is null, shouldn't call ClassLoader.checkPackageAccess; otherwise get + // NPE. Put it in another way, the bootstrap class loader has all permission and + // thus no checkPackageAccess equivalence in the VM class loader. + // The caller is also passed as NULL by the java code if there is no security + // manager to avoid the performance cost of getting the calling class. + if (from_class != NULL && loader_oop != NULL) { + protection_domain = java_lang_Class::as_Klass(from_class)->protection_domain(); + } + + Handle h_loader(THREAD, loader_oop); + Handle h_prot(THREAD, protection_domain); + jclass result = find_class_from_class_loader(env, h_name, init, h_loader, + h_prot, false, THREAD); + + if (TraceClassResolution && result != NULL) { + trace_class_resolution(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(result))); + } + return result; +JVM_END JVM_ENTRY(jclass, JVM_FindClassFromClass(JNIEnv *env, const char *name, jboolean init, jclass from)) @@ -3921,10 +3958,15 @@ JNIEXPORT void JNICALL JVM_RawMonitorExit(void *mon) { // Shared JNI/JVM entry points ////////////////////////////////////////////////////////////// -jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, Handle loader, Handle protection_domain, jboolean throwError, TRAPS) { +jclass find_class_from_class_loader(JNIEnv* env, Symbol* name, jboolean init, + Handle loader, Handle protection_domain, + jboolean throwError, TRAPS) { // Security Note: // The Java level wrapper will perform the necessary security check allowing - // us to pass the NULL as the initiating class loader. + // us to pass the NULL as the initiating class loader. The VM is responsible for + // the checkPackageAccess relative to the initiating class loader via the + // protection_domain. The protection_domain is passed as NULL by the java code + // if there is no security manager in 3-arg Class.forName(). Klass* klass = SystemDictionary::resolve_or_fail(name, loader, protection_domain, throwError != 0, CHECK_NULL); KlassHandle klass_handle(THREAD, klass); diff --git a/hotspot/src/share/vm/prims/jvm.h b/hotspot/src/share/vm/prims/jvm.h index c1aa8080cd3..52fd28fc4e1 100644 --- a/hotspot/src/share/vm/prims/jvm.h +++ b/hotspot/src/share/vm/prims/jvm.h @@ -419,6 +419,19 @@ JVM_FindClassFromClassLoader(JNIEnv *env, const char *name, jboolean init, JNIEXPORT jclass JNICALL JVM_FindClassFromBootLoader(JNIEnv *env, const char *name); +/* + * Find a class from a given class loader. Throws ClassNotFoundException. + * name: name of class + * init: whether initialization is done + * loader: class loader to look up the class. This may not be the same as the caller's + * class loader. + * caller: initiating class. The initiating class may be null when a security + * manager is not installed. + */ +JNIEXPORT jclass JNICALL +JVM_FindClassFromCaller(JNIEnv *env, const char *name, jboolean init, + jobject loader, jclass caller); + /* * Find a class from a given class. */ From f203dcbfbf4153b12262b6834969a2ff516742cd Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Tue, 22 Jul 2014 16:16:51 +0400 Subject: [PATCH 28/91] 8036533: Method for correct defaults 8036156: Limit default method hierarchy Fix protected access checks Reviewed-by: coleenp, lfoltan, acorn, ahgross --- .../src/share/vm/classfile/stackMapFrame.cpp | 10 +++++----- .../src/share/vm/classfile/stackMapFrame.hpp | 6 +++--- .../share/vm/classfile/verificationType.cpp | 16 ++++++++++------ .../share/vm/classfile/verificationType.hpp | 10 +++++++--- hotspot/src/share/vm/classfile/verifier.cpp | 18 +++++++++--------- hotspot/src/share/vm/runtime/reflection.cpp | 3 ++- 6 files changed, 36 insertions(+), 27 deletions(-) diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.cpp b/hotspot/src/share/vm/classfile/stackMapFrame.cpp index 9cb1d307a52..1332a081c76 100644 --- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp +++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp @@ -148,7 +148,7 @@ int StackMapFrame::is_assignable_to( VerificationType* from, VerificationType* to, int32_t len, TRAPS) const { int32_t i = 0; for (i = 0; i < len; i++) { - if (!to[i].is_assignable_from(from[i], verifier(), THREAD)) { + if (!to[i].is_assignable_from(from[i], verifier(), false, THREAD)) { break; } } @@ -245,7 +245,7 @@ VerificationType StackMapFrame::pop_stack_ex(VerificationType type, TRAPS) { } VerificationType top = _stack[--_stack_size]; bool subtype = type.is_assignable_from( - top, verifier(), CHECK_(VerificationType::bogus_type())); + top, verifier(), false, CHECK_(VerificationType::bogus_type())); if (!subtype) { verifier()->verify_error( ErrorContext::bad_type(_offset, stack_top_ctx(), @@ -265,7 +265,7 @@ VerificationType StackMapFrame::get_local( return VerificationType::bogus_type(); } bool subtype = type.is_assignable_from(_locals[index], - verifier(), CHECK_(VerificationType::bogus_type())); + verifier(), false, CHECK_(VerificationType::bogus_type())); if (!subtype) { verifier()->verify_error( ErrorContext::bad_type(_offset, @@ -288,14 +288,14 @@ void StackMapFrame::get_local_2( "get long/double overflows locals"); return; } - bool subtype = type1.is_assignable_from(_locals[index], verifier(), CHECK); + bool subtype = type1.is_assignable_from(_locals[index], verifier(), false, CHECK); if (!subtype) { verifier()->verify_error( ErrorContext::bad_type(_offset, TypeOrigin::local(index, this), TypeOrigin::implicit(type1)), "Bad local variable type"); } else { - subtype = type2.is_assignable_from(_locals[index + 1], verifier(), CHECK); + subtype = type2.is_assignable_from(_locals[index + 1], verifier(), false, CHECK); if (!subtype) { /* Unreachable? All local store routines convert a split long or double * into a TOP during the store. So we should never end up seeing an diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/hotspot/src/share/vm/classfile/stackMapFrame.hpp index 53582c1673c..24cbae330bb 100644 --- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp +++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp @@ -234,7 +234,7 @@ class StackMapFrame : public ResourceObj { if (_stack_size != 0) { VerificationType top = _stack[_stack_size - 1]; bool subtype = type.is_assignable_from( - top, verifier(), CHECK_(VerificationType::bogus_type())); + top, verifier(), false, CHECK_(VerificationType::bogus_type())); if (subtype) { --_stack_size; return top; @@ -249,9 +249,9 @@ class StackMapFrame : public ResourceObj { assert(type2.is_long() || type2.is_double(), "must be long/double_2"); if (_stack_size >= 2) { VerificationType top1 = _stack[_stack_size - 1]; - bool subtype1 = type1.is_assignable_from(top1, verifier(), CHECK); + bool subtype1 = type1.is_assignable_from(top1, verifier(), false, CHECK); VerificationType top2 = _stack[_stack_size - 2]; - bool subtype2 = type2.is_assignable_from(top2, verifier(), CHECK); + bool subtype2 = type2.is_assignable_from(top2, verifier(), false, CHECK); if (subtype1 && subtype2) { _stack_size -= 2; return; diff --git a/hotspot/src/share/vm/classfile/verificationType.cpp b/hotspot/src/share/vm/classfile/verificationType.cpp index 561618bdebe..120d9a37d62 100644 --- a/hotspot/src/share/vm/classfile/verificationType.cpp +++ b/hotspot/src/share/vm/classfile/verificationType.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,8 @@ VerificationType VerificationType::from_tag(u1 tag) { } bool VerificationType::is_reference_assignable_from( - const VerificationType& from, ClassVerifier* context, TRAPS) const { + const VerificationType& from, ClassVerifier* context, + bool from_field_is_protected, TRAPS) const { instanceKlassHandle klass = context->current_class(); if (from.is_null()) { // null is assignable to any reference @@ -62,9 +63,11 @@ bool VerificationType::is_reference_assignable_from( Handle(THREAD, klass->protection_domain()), true, CHECK_false); KlassHandle this_class(THREAD, obj); - if (this_class->is_interface()) { - // We treat interfaces as java.lang.Object, including - // java.lang.Cloneable and java.io.Serializable + if (this_class->is_interface() && (!from_field_is_protected || + from.name() != vmSymbols::java_lang_Object())) { + // If we are not trying to access a protected field or method in + // java.lang.Object then we treat interfaces as java.lang.Object, + // including java.lang.Cloneable and java.io.Serializable. return true; } else if (from.is_object()) { Klass* from_class = SystemDictionary::resolve_or_fail( @@ -76,7 +79,8 @@ bool VerificationType::is_reference_assignable_from( VerificationType comp_this = get_component(context, CHECK_false); VerificationType comp_from = from.get_component(context, CHECK_false); if (!comp_this.is_bogus() && !comp_from.is_bogus()) { - return comp_this.is_assignable_from(comp_from, context, CHECK_false); + return comp_this.is_assignable_from(comp_from, context, + from_field_is_protected, CHECK_false); } } return false; diff --git a/hotspot/src/share/vm/classfile/verificationType.hpp b/hotspot/src/share/vm/classfile/verificationType.hpp index 16266477ec1..43bd79e21b1 100644 --- a/hotspot/src/share/vm/classfile/verificationType.hpp +++ b/hotspot/src/share/vm/classfile/verificationType.hpp @@ -265,7 +265,8 @@ class VerificationType VALUE_OBJ_CLASS_SPEC { // is assignable to another. Returns true if one can assign 'from' to // this. bool is_assignable_from( - const VerificationType& from, ClassVerifier* context, TRAPS) const { + const VerificationType& from, ClassVerifier* context, + bool from_field_is_protected, TRAPS) const { if (equals(from) || is_bogus()) { return true; } else { @@ -286,7 +287,9 @@ class VerificationType VALUE_OBJ_CLASS_SPEC { return from.is_integer(); default: if (is_reference() && from.is_reference()) { - return is_reference_assignable_from(from, context, CHECK_false); + return is_reference_assignable_from(from, context, + from_field_is_protected, + CHECK_false); } else { return false; } @@ -308,7 +311,8 @@ class VerificationType VALUE_OBJ_CLASS_SPEC { private: bool is_reference_assignable_from( - const VerificationType&, ClassVerifier*, TRAPS) const; + const VerificationType&, ClassVerifier*, bool from_field_is_protected, + TRAPS) const; }; #endif // SHARE_VM_CLASSFILE_VERIFICATIONTYPE_HPP diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 877eebd0e0b..92dfb14f9dc 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -1721,7 +1721,7 @@ void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_da VerificationType throwable = VerificationType::reference_type(vmSymbols::java_lang_Throwable()); bool is_subclass = throwable.is_assignable_from( - catch_type, this, CHECK_VERIFY(this)); + catch_type, this, false, CHECK_VERIFY(this)); if (!is_subclass) { // 4286534: should throw VerifyError according to recent spec change verify_error(ErrorContext::bad_type(handler_pc, @@ -2174,7 +2174,7 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, stack_object_type = current_type(); } is_assignable = target_class_type.is_assignable_from( - stack_object_type, this, CHECK_VERIFY(this)); + stack_object_type, this, false, CHECK_VERIFY(this)); if (!is_assignable) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), @@ -2201,7 +2201,7 @@ void ClassVerifier::verify_field_instructions(RawBytecodeStream* bcs, // It's protected access, check if stack object is assignable to // current class. is_assignable = current_type().is_assignable_from( - stack_object_type, this, CHECK_VERIFY(this)); + stack_object_type, this, true, CHECK_VERIFY(this)); if (!is_assignable) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), @@ -2475,7 +2475,7 @@ void ClassVerifier::verify_invoke_init( instanceKlassHandle mh(THREAD, m->method_holder()); if (m->is_protected() && !mh->is_same_class_package(_klass())) { bool assignable = current_type().is_assignable_from( - objectref_type, this, CHECK_VERIFY(this)); + objectref_type, this, true, CHECK_VERIFY(this)); if (!assignable) { verify_error(ErrorContext::bad_type(bci, TypeOrigin::cp(new_class_index, objectref_type), @@ -2646,11 +2646,11 @@ void ClassVerifier::verify_invoke_instructions( bool have_imr_indirect = cp->tag_at(index).value() == JVM_CONSTANT_InterfaceMethodref; if (!current_class()->is_anonymous()) { subtype = ref_class_type.is_assignable_from( - current_type(), this, CHECK_VERIFY(this)); + current_type(), this, false, CHECK_VERIFY(this)); } else { VerificationType host_klass_type = VerificationType::reference_type(current_class()->host_klass()->name()); - subtype = ref_class_type.is_assignable_from(host_klass_type, this, CHECK_VERIFY(this)); + subtype = ref_class_type.is_assignable_from(host_klass_type, this, false, CHECK_VERIFY(this)); // If invokespecial of IMR, need to recheck for same or // direct interface relative to the host class @@ -2694,7 +2694,7 @@ void ClassVerifier::verify_invoke_instructions( VerificationType top = current_frame->pop_stack(CHECK_VERIFY(this)); VerificationType hosttype = VerificationType::reference_type(current_class()->host_klass()->name()); - bool subtype = hosttype.is_assignable_from(top, this, CHECK_VERIFY(this)); + bool subtype = hosttype.is_assignable_from(top, this, false, CHECK_VERIFY(this)); if (!subtype) { verify_error( ErrorContext::bad_type(current_frame->offset(), current_frame->stack_top_ctx(), @@ -2719,7 +2719,7 @@ void ClassVerifier::verify_invoke_instructions( // It's protected access, check if stack object is // assignable to current class. bool is_assignable = current_type().is_assignable_from( - stack_object_type, this, CHECK_VERIFY(this)); + stack_object_type, this, true, CHECK_VERIFY(this)); if (!is_assignable) { if (ref_class_type.name() == vmSymbols::java_lang_Object() && stack_object_type.is_array() @@ -2902,7 +2902,7 @@ void ClassVerifier::verify_return_value( "Method expects a return value"); return; } - bool match = return_type.is_assignable_from(type, this, CHECK_VERIFY(this)); + bool match = return_type.is_assignable_from(type, this, false, CHECK_VERIFY(this)); if (!match) { verify_error(ErrorContext::bad_type(bci, current_frame->stack_top_ctx(), TypeOrigin::signature(return_type)), diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index 42c9ed3e8ef..c6cb79ce7a4 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -507,7 +507,8 @@ bool Reflection::verify_field_access(Klass* current_class, if (access.is_protected()) { if (!protected_restriction) { // See if current_class (or outermost host class) is a subclass of field_class - if (host_class->is_subclass_of(field_class)) { + // An interface may not access protected members of j.l.Object + if (!host_class->is_interface() && host_class->is_subclass_of(field_class)) { if (access.is_static() || // static fields are ok, see 6622385 current_class == resolved_class || field_class == resolved_class || From 9f06aa633c74aacdb826bea0b8f804c3cbae11e1 Mon Sep 17 00:00:00 2001 From: Harold Seigel Date: Fri, 30 May 2014 13:23:27 -0400 Subject: [PATCH 29/91] 8041717: Issue with class file parser Add better checking for bad values. Reviewed-by: coleenp, lfoltan, mschoene --- hotspot/src/share/vm/classfile/classFileParser.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 8b3ef37d590..0f2f8d590c4 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -2859,6 +2859,11 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(u4 attribute_b "bootstrap_method_index %u has bad constant type in class file %s", bootstrap_method_index, CHECK); + + guarantee_property((operand_fill_index + 1 + argument_count) < operands->length(), + "Invalid BootstrapMethods num_bootstrap_methods or num_bootstrap_arguments value in class file %s", + CHECK); + operands->at_put(operand_fill_index++, bootstrap_method_index); operands->at_put(operand_fill_index++, argument_count); @@ -2875,8 +2880,6 @@ void ClassFileParser::parse_classfile_bootstrap_methods_attribute(u4 attribute_b } } - assert(ConstantPool::operand_array_length(operands) == attribute_array_length, "correct decode"); - u1* current_end = cfs->current(); guarantee_property(current_end == current_start + attribute_byte_length, "Bad length on BootstrapMethods in class file %s", From 52d7b541a6413c6c88b8b95461d974edd1f72d00 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 5 Jun 2014 18:46:37 +0200 Subject: [PATCH 30/91] 8042797: Avoid strawberries in LogRecord Reviewed-by: mchung, skoivu, igerasim --- .../share/classes/java/util/logging/LogRecord.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java b/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java index bfc05201ebc..1ea4d72008d 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java @@ -509,7 +509,13 @@ public class LogRecord implements java.io.Serializable { // If necessary, try to regenerate the resource bundle. if (resourceBundleName != null) { try { - resourceBundle = ResourceBundle.getBundle(resourceBundleName); + // use system class loader to ensure the ResourceBundle + // instance is a different instance than null loader uses + final ResourceBundle bundle = + ResourceBundle.getBundle(resourceBundleName, + Locale.getDefault(), + ClassLoader.getSystemClassLoader()); + resourceBundle = bundle; } catch (MissingResourceException ex) { // This is not a good place to throw an exception, // so we simply leave the resourceBundle null. From 38479150516d0f851b1f4a1bea410de11ca2614b Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Wed, 11 Jun 2014 16:25:59 -0400 Subject: [PATCH 31/91] 8038913: Bolster XML support Reviewed-by: xuelei, skoivu --- .../apache/xml/internal/security/Init.java | 72 +++++++++++-------- .../security/algorithms/JCEMapper.java | 7 ++ .../algorithms/SignatureAlgorithm.java | 13 +++- .../internal/security/c14n/Canonicalizer.java | 9 ++- .../keys/keyresolver/KeyResolver.java | 13 ++++ .../security/transforms/Transform.java | 7 ++ .../internal/security/utils/ElementProxy.java | 3 + .../internal/security/utils/JavaUtils.java | 22 ++++++ .../xml/internal/security/utils/XMLUtils.java | 12 ++++ .../utils/resolver/ResourceResolver.java | 13 ++++ 10 files changed, 136 insertions(+), 35 deletions(-) diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java index 6176370878a..5f3b9f53c8f 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/Init.java @@ -25,6 +25,8 @@ package com.sun.org.apache.xml.internal.security; import java.io.InputStream; import java.security.AccessController; import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.List; @@ -35,6 +37,7 @@ import javax.xml.parsers.DocumentBuilderFactory; import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithm; import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; +import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.keys.keyresolver.KeyResolver; import com.sun.org.apache.xml.internal.security.transforms.Transform; import com.sun.org.apache.xml.internal.security.utils.ElementProxy; @@ -118,43 +121,50 @@ public class Init { log.log(java.util.logging.Level.FINE, "Registering default algorithms"); } try { - // - // Bind the default prefixes - // - ElementProxy.registerDefaultPrefixes(); + AccessController.doPrivileged(new PrivilegedExceptionAction(){ + @Override public Void run() throws XMLSecurityException { + // + // Bind the default prefixes + // + ElementProxy.registerDefaultPrefixes(); - // - // Set the default Transforms - // - Transform.registerDefaultAlgorithms(); + // + // Set the default Transforms + // + Transform.registerDefaultAlgorithms(); - // - // Set the default signature algorithms - // - SignatureAlgorithm.registerDefaultAlgorithms(); + // + // Set the default signature algorithms + // + SignatureAlgorithm.registerDefaultAlgorithms(); - // - // Set the default JCE algorithms - // - JCEMapper.registerDefaultAlgorithms(); + // + // Set the default JCE algorithms + // + JCEMapper.registerDefaultAlgorithms(); - // - // Set the default c14n algorithms - // - Canonicalizer.registerDefaultAlgorithms(); + // + // Set the default c14n algorithms + // + Canonicalizer.registerDefaultAlgorithms(); - // - // Register the default resolvers - // - ResourceResolver.registerDefaultResolvers(); + // + // Register the default resolvers + // + ResourceResolver.registerDefaultResolvers(); - // - // Register the default key resolvers - // - KeyResolver.registerDefaultResolvers(); - } catch (Exception ex) { - log.log(java.util.logging.Level.SEVERE, ex.getMessage(), ex); - ex.printStackTrace(); + // + // Register the default key resolvers + // + KeyResolver.registerDefaultResolvers(); + + return null; + } + }); + } catch (PrivilegedActionException ex) { + XMLSecurityException xse = (XMLSecurityException)ex.getException(); + log.log(java.util.logging.Level.SEVERE, xse.getMessage(), xse); + xse.printStackTrace(); } } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java index 6001e510532..3656f248848 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java @@ -27,6 +27,7 @@ import java.util.concurrent.ConcurrentHashMap; import com.sun.org.apache.xml.internal.security.encryption.XMLCipher; import com.sun.org.apache.xml.internal.security.signature.XMLSignature; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Element; @@ -49,8 +50,11 @@ public class JCEMapper { * * @param id * @param algorithm + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the JCE algorithm */ public static void register(String id, Algorithm algorithm) { + JavaUtils.checkRegisterPermission(); algorithmsMap.put(id, algorithm); } @@ -296,8 +300,11 @@ public class JCEMapper { /** * Sets the default Provider for obtaining the security algorithms * @param provider the default providerId. + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the JCE provider */ public static void setProviderId(String provider) { + JavaUtils.checkRegisterPermission(); providerName = provider; } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java index 6e94f4b16d9..253e35ca864 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java @@ -37,6 +37,7 @@ import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.signature.XMLSignature; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; import com.sun.org.apache.xml.internal.security.utils.Constants; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -314,18 +315,21 @@ public class SignatureAlgorithm extends Algorithm { } /** - * Registers implementing class of the Transform algorithm with algorithmURI + * Registers implementing class of the SignatureAlgorithm with algorithmURI * - * @param algorithmURI algorithmURI URI representation of Transform algorithm. + * @param algorithmURI algorithmURI URI representation of SignatureAlgorithm. * @param implementingClass implementingClass the implementing class of * {@link SignatureAlgorithmSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered * @throws XMLSignatureException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the signature algorithm */ @SuppressWarnings("unchecked") public static void register(String algorithmURI, String implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, XMLSignatureException { + JavaUtils.checkRegisterPermission(); if (log.isLoggable(java.util.logging.Level.FINE)) { log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); } @@ -352,15 +356,18 @@ public class SignatureAlgorithm extends Algorithm { /** * Registers implementing class of the Transform algorithm with algorithmURI * - * @param algorithmURI algorithmURI URI representation of Transform algorithm. + * @param algorithmURI algorithmURI URI representation of SignatureAlgorithm. * @param implementingClass implementingClass the implementing class of * {@link SignatureAlgorithmSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI is already registered * @throws XMLSignatureException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the signature algorithm */ public static void register(String algorithmURI, Class implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, XMLSignatureException { + JavaUtils.checkRegisterPermission(); if (log.isLoggable(java.util.logging.Level.FINE)) { log.log(java.util.logging.Level.FINE, "Try to register " + algorithmURI + " " + implementingClass); } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java index 2f0b31f5ed4..ae33b72c91d 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/Canonicalizer.java @@ -41,6 +41,7 @@ import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicaliz import com.sun.org.apache.xml.internal.security.c14n.implementations.Canonicalizer20010315WithComments; import com.sun.org.apache.xml.internal.security.c14n.implementations.CanonicalizerPhysical; import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -142,10 +143,13 @@ public class Canonicalizer { * @param algorithmURI * @param implementingClass * @throws AlgorithmAlreadyRegisteredException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the canonicalizer */ @SuppressWarnings("unchecked") public static void register(String algorithmURI, String implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException { + JavaUtils.checkRegisterPermission(); // check whether URI is already registered Class registeredClass = canonicalizerHash.get(algorithmURI); @@ -166,9 +170,12 @@ public class Canonicalizer { * @param algorithmURI * @param implementingClass * @throws AlgorithmAlreadyRegisteredException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the canonicalizer */ - public static void register(String algorithmURI, Class implementingClass) + public static void register(String algorithmURI, Class implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException { + JavaUtils.checkRegisterPermission(); // check whether URI is already registered Class registeredClass = canonicalizerHash.get(algorithmURI); diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java index fe541ff044f..e8622d938b6 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/KeyResolver.java @@ -42,6 +42,7 @@ import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509SKIResolver; import com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations.X509SubjectNameResolver; import com.sun.org.apache.xml.internal.security.keys.storage.StorageResolver; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -175,9 +176,12 @@ public class KeyResolver { * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void register(String className, boolean globalResolver) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + JavaUtils.checkRegisterPermission(); KeyResolverSpi keyResolverSpi = (KeyResolverSpi) Class.forName(className).newInstance(); keyResolverSpi.setGlobalResolver(globalResolver); @@ -195,8 +199,11 @@ public class KeyResolver { * * @param className * @param globalResolver Whether the KeyResolverSpi is a global resolver or not + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void registerAtStart(String className, boolean globalResolver) { + JavaUtils.checkRegisterPermission(); KeyResolverSpi keyResolverSpi = null; Exception ex = null; try { @@ -228,11 +235,14 @@ public class KeyResolver { * * @param keyResolverSpi a KeyResolverSpi instance to register * @param start whether to register the KeyResolverSpi at the start of the list or not + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void register( KeyResolverSpi keyResolverSpi, boolean start ) { + JavaUtils.checkRegisterPermission(); KeyResolver resolver = new KeyResolver(keyResolverSpi); if (start) { resolverVector.add(0, resolver); @@ -254,9 +264,12 @@ public class KeyResolver { * @throws InstantiationException * @throws IllegalAccessException * @throws ClassNotFoundException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the key resolver */ public static void registerClassNames(List classNames) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + JavaUtils.checkRegisterPermission(); List keyResolverList = new ArrayList(classNames.size()); for (String className : classNames) { KeyResolverSpi keyResolverSpi = diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java index 37d67ba9f24..3fc1d21bb9c 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java @@ -46,6 +46,7 @@ import com.sun.org.apache.xml.internal.security.transforms.implementations.Trans import com.sun.org.apache.xml.internal.security.transforms.implementations.TransformXSLT; import com.sun.org.apache.xml.internal.security.utils.Constants; import com.sun.org.apache.xml.internal.security.utils.HelperNodeList; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import com.sun.org.apache.xml.internal.security.utils.SignatureElementProxy; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import org.w3c.dom.Document; @@ -181,11 +182,14 @@ public final class Transform extends SignatureElementProxy { * class of {@link TransformSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI * is already registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the transform */ @SuppressWarnings("unchecked") public static void register(String algorithmURI, String implementingClass) throws AlgorithmAlreadyRegisteredException, ClassNotFoundException, InvalidTransformException { + JavaUtils.checkRegisterPermission(); // are we already registered? Class transformSpi = transformSpiHash.get(algorithmURI); if (transformSpi != null) { @@ -206,9 +210,12 @@ public final class Transform extends SignatureElementProxy { * class of {@link TransformSpi} * @throws AlgorithmAlreadyRegisteredException if specified algorithmURI * is already registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register the transform */ public static void register(String algorithmURI, Class implementingClass) throws AlgorithmAlreadyRegisteredException { + JavaUtils.checkRegisterPermission(); // are we already registered? Class transformSpi = transformSpiHash.get(algorithmURI); if (transformSpi != null) { diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java index ac7a53eba4f..fe8bdb1f1d6 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/ElementProxy.java @@ -468,9 +468,12 @@ public abstract class ElementProxy { * @param namespace * @param prefix * @throws XMLSecurityException + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the default prefix */ public static void setDefaultPrefix(String namespace, String prefix) throws XMLSecurityException { + JavaUtils.checkRegisterPermission(); if (prefixMappings.containsValue(prefix)) { String storedPrefix = prefixMappings.get(namespace); if (!storedPrefix.equals(prefix)) { diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java index 99b2d1f77e1..80c582fe8e2 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/JavaUtils.java @@ -28,6 +28,7 @@ import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.security.SecurityPermission; /** * A collection of different, general-purpose methods for JAVA-specific things @@ -39,6 +40,10 @@ public class JavaUtils { private static java.util.logging.Logger log = java.util.logging.Logger.getLogger(JavaUtils.class.getName()); + private static final SecurityPermission REGISTER_PERMISSION = + new SecurityPermission( + "com.sun.org.apache.xml.internal.security.register"); + private JavaUtils() { // we don't allow instantiation } @@ -146,6 +151,23 @@ public class JavaUtils { return retBytes; } + /** + * Throws a {@code SecurityException} if a security manager is installed + * and the caller is not allowed to register an implementation of an + * algorithm, transform, or other security sensitive XML Signature function. + * + * @throws SecurityException if a security manager is installed and the + * caller has not been granted the + * {@literal "com.sun.org.apache.xml.internal.security.register"} + * {@code SecurityPermission} + */ + public static void checkRegisterPermission() { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(REGISTER_PERMISSION); + } + } + /** * Converts an ASN.1 DSA value to a XML Signature DSA Value. * diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java index b73e5e8a5ec..3463dc75fec 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/XMLUtils.java @@ -80,32 +80,44 @@ public class XMLUtils { /** * Set the prefix for the digital signature namespace * @param prefix the new prefix for the digital signature namespace + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setDsPrefix(String prefix) { + JavaUtils.checkRegisterPermission(); dsPrefix = prefix; } /** * Set the prefix for the digital signature 1.1 namespace * @param prefix the new prefix for the digital signature 1.1 namespace + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setDs11Prefix(String prefix) { + JavaUtils.checkRegisterPermission(); ds11Prefix = prefix; } /** * Set the prefix for the encryption namespace * @param prefix the new prefix for the encryption namespace + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setXencPrefix(String prefix) { + JavaUtils.checkRegisterPermission(); xencPrefix = prefix; } /** * Set the prefix for the encryption namespace 1.1 * @param prefix the new prefix for the encryption namespace 1.1 + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to set the prefix */ public static void setXenc11Prefix(String prefix) { + JavaUtils.checkRegisterPermission(); xenc11Prefix = prefix; } diff --git a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java index 7570a019064..012d2fb8bc4 100644 --- a/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java +++ b/jdk/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/resolver/ResourceResolver.java @@ -27,6 +27,7 @@ import java.util.List; import java.util.Map; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; +import com.sun.org.apache.xml.internal.security.utils.JavaUtils; import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverDirectHTTP; import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverFragment; import com.sun.org.apache.xml.internal.security.utils.resolver.implementations.ResolverLocalFilesystem; @@ -199,9 +200,12 @@ public class ResourceResolver { * the class cannot be registered. * * @param className the name of the ResourceResolverSpi class to be registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ @SuppressWarnings("unchecked") public static void register(String className) { + JavaUtils.checkRegisterPermission(); try { Class resourceResolverClass = (Class) Class.forName(className); @@ -216,9 +220,12 @@ public class ResourceResolver { * list. This method logs a warning if the class cannot be registered. * * @param className the name of the ResourceResolverSpi class to be registered + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ @SuppressWarnings("unchecked") public static void registerAtStart(String className) { + JavaUtils.checkRegisterPermission(); try { Class resourceResolverClass = (Class) Class.forName(className); @@ -233,8 +240,11 @@ public class ResourceResolver { * cannot be registered. * @param className * @param start + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ public static void register(Class className, boolean start) { + JavaUtils.checkRegisterPermission(); try { ResourceResolverSpi resourceResolverSpi = className.newInstance(); register(resourceResolverSpi, start); @@ -250,8 +260,11 @@ public class ResourceResolver { * cannot be registered. * @param resourceResolverSpi * @param start + * @throws SecurityException if a security manager is installed and the + * caller does not have permission to register a resource resolver */ public static void register(ResourceResolverSpi resourceResolverSpi, boolean start) { + JavaUtils.checkRegisterPermission(); synchronized(resolverList) { if (start) { resolverList.add(0, new ResourceResolver(resourceResolverSpi)); From a71432a188c552ce65507962abab8156ddbf724e Mon Sep 17 00:00:00 2001 From: Zhengyu Gu Date: Mon, 16 Jun 2014 10:23:46 -0400 Subject: [PATCH 32/91] 8038903: More native monitor monitoring Moved ntive monitor monitoring flags to experimental Reviewed-by: acorn, hseigel, mschoene --- hotspot/src/share/vm/runtime/globals.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 7d5a99a20c4..d2952060e8d 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -1177,11 +1177,11 @@ class CommandLineFlags { "When true prevents OS-level spurious, or premature, wakeups " \ "from Object.wait (Ignored for Windows)") \ \ - product(intx, NativeMonitorTimeout, -1, "(Unstable)") \ + experimental(intx, NativeMonitorTimeout, -1, "(Unstable)") \ \ - product(intx, NativeMonitorFlags, 0, "(Unstable)") \ + experimental(intx, NativeMonitorFlags, 0, "(Unstable)") \ \ - product(intx, NativeMonitorSpinLimit, 20, "(Unstable)") \ + experimental(intx, NativeMonitorSpinLimit, 20, "(Unstable)") \ \ develop(bool, UsePthreads, false, \ "Use pthread-based instead of libthread-based synchronization " \ From cc10c541608b5f927e25f2367a69a3c87bad4e73 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 24 Jun 2014 10:03:46 -0700 Subject: [PATCH 33/91] 8035162: Service printing service Reviewed-by: bae, jgodinez, mschoene --- .../java.desktop/unix/classes/sun/print/CUPSPrinter.java | 8 ++++---- .../unix/classes/sun/print/IPPPrintService.java | 8 ++++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java index 6d1b54e32f3..c1f0423b2b1 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java @@ -136,7 +136,7 @@ public class CUPSPrinter { /** * Returns array of MediaSizeNames derived from PPD. */ - public MediaSizeName[] getMediaSizeNames() { + MediaSizeName[] getMediaSizeNames() { initMedia(); return cupsMediaSNames; } @@ -145,7 +145,7 @@ public class CUPSPrinter { /** * Returns array of Custom MediaSizeNames derived from PPD. */ - public CustomMediaSizeName[] getCustomMediaSizeNames() { + CustomMediaSizeName[] getCustomMediaSizeNames() { initMedia(); return cupsCustomMediaSNames; } @@ -157,7 +157,7 @@ public class CUPSPrinter { /** * Returns array of MediaPrintableArea derived from PPD. */ - public MediaPrintableArea[] getMediaPrintableArea() { + MediaPrintableArea[] getMediaPrintableArea() { initMedia(); return cupsMediaPrintables; } @@ -165,7 +165,7 @@ public class CUPSPrinter { /** * Returns array of MediaTrays derived from PPD. */ - public MediaTray[] getMediaTrays() { + MediaTray[] getMediaTrays() { initMedia(); return cupsMediaTrays; } diff --git a/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java b/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java index 22cc7bb48bf..698cd429bda 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/IPPPrintService.java @@ -1002,7 +1002,9 @@ public class IPPPrintService implements PrintService, SunPrinterJobService { public synchronized Class[] getSupportedAttributeCategories() { if (supportedCats != null) { - return supportedCats; + Class [] copyCats = new Class[supportedCats.length]; + System.arraycopy(supportedCats, 0, copyCats, 0, copyCats.length); + return copyCats; } initAttributes(); @@ -1065,7 +1067,9 @@ public class IPPPrintService implements PrintService, SunPrinterJobService { supportedCats = new Class[catList.size()]; catList.toArray(supportedCats); - return supportedCats; + Class[] copyCats = new Class[supportedCats.length]; + System.arraycopy(supportedCats, 0, copyCats, 0, copyCats.length); + return copyCats; } From 47d69e2546d005b5d170671e62a6553f389504ee Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 24 Jun 2014 14:00:01 -0700 Subject: [PATCH 34/91] 8044274: Proper property processing Reviewed-by: okutsu --- .../classes/java/util/ResourceBundle.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java index 151f1fd560a..3b8d06e01a7 100644 --- a/jdk/src/java.base/share/classes/java/util/ResourceBundle.java +++ b/jdk/src/java.base/share/classes/java/util/ResourceBundle.java @@ -2646,7 +2646,10 @@ public abstract class ResourceBundle { } catch (ClassNotFoundException e) { } } else if (format.equals("java.properties")) { - final String resourceName = toResourceName(bundleName, "properties"); + final String resourceName = toResourceName0(bundleName, "properties"); + if (resourceName == null) { + return bundle; + } final ClassLoader classLoader = loader; final boolean reloadFlag = reload; InputStream stream = null; @@ -2800,7 +2803,10 @@ public abstract class ResourceBundle { } boolean result = false; try { - String resourceName = toResourceName(toBundleName(baseName, locale), format); + String resourceName = toResourceName0(toBundleName(baseName, locale), format); + if (resourceName == null) { + return result; + } URL url = loader.getResource(resourceName); if (url != null) { long lastModified = 0; @@ -2934,6 +2940,15 @@ public abstract class ResourceBundle { sb.append(bundleName.replace('.', '/')).append('.').append(suffix); return sb.toString(); } + + private String toResourceName0(String bundleName, String suffix) { + // application protocol check + if (bundleName.contains("://")) { + return null; + } else { + return toResourceName(bundleName, suffix); + } + } } private static class SingleFormatControl extends Control { From 5ef677511773ec611615b7de26ff4b3f68c8e848 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 7 Aug 2014 12:57:23 -0700 Subject: [PATCH 35/91] 8048025: Ensure cache consistency To support zip entry with null character(s) embedded Reviewed-by: alanb, weijun --- .../java.base/share/native/libzip/ZipFile.c | 8 +--- .../java.base/share/native/libzip/zip_util.c | 44 +++++++++++++++---- .../java.base/share/native/libzip/zip_util.h | 4 +- 3 files changed, 41 insertions(+), 15 deletions(-) diff --git a/jdk/src/java.base/share/native/libzip/ZipFile.c b/jdk/src/java.base/share/native/libzip/ZipFile.c index 4604d8ff229..1649021c477 100644 --- a/jdk/src/java.base/share/native/libzip/ZipFile.c +++ b/jdk/src/java.base/share/native/libzip/ZipFile.c @@ -174,11 +174,7 @@ Java_java_util_zip_ZipFile_getEntry(JNIEnv *env, jclass cls, jlong zfile, } (*env)->GetByteArrayRegion(env, name, 0, ulen, (jbyte *)path); path[ulen] = '\0'; - if (addSlash == JNI_FALSE) { - ze = ZIP_GetEntry(zip, path, 0); - } else { - ze = ZIP_GetEntry(zip, path, (jint)ulen); - } + ze = ZIP_GetEntry2(zip, path, (jint)ulen, addSlash); if (path != buf) { free(path); } @@ -271,7 +267,7 @@ Java_java_util_zip_ZipFile_getEntryBytes(JNIEnv *env, switch (type) { case java_util_zip_ZipFile_JZENTRY_NAME: if (ze->name != 0) { - len = (int)strlen(ze->name); + len = (int)ze->nlen; // Unlike for extra and comment, we never return null for // an (extremely rarely seen) empty name if ((jba = (*env)->NewByteArray(env, len)) == NULL) diff --git a/jdk/src/java.base/share/native/libzip/zip_util.c b/jdk/src/java.base/share/native/libzip/zip_util.c index a072e6624c4..b172cde3172 100644 --- a/jdk/src/java.base/share/native/libzip/zip_util.c +++ b/jdk/src/java.base/share/native/libzip/zip_util.c @@ -1021,6 +1021,7 @@ newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint) if ((ze->name = malloc(nlen + 1)) == NULL) goto Catch; memcpy(ze->name, cen + CENHDR, nlen); ze->name[nlen] = '\0'; + ze->nlen = nlen; if (elen > 0) { char *extra = cen + CENHDR + nlen; @@ -1118,7 +1119,34 @@ ZIP_FreeEntry(jzfile *jz, jzentry *ze) jzentry * ZIP_GetEntry(jzfile *zip, char *name, jint ulen) { - unsigned int hsh = hash(name); + if (ulen == 0) { + return ZIP_GetEntry2(zip, name, strlen(name), JNI_FALSE); + } + return ZIP_GetEntry2(zip, name, ulen, JNI_TRUE); +} + +jboolean equals(char* name1, int len1, char* name2, int len2) { + if (len1 != len2) { + return JNI_FALSE; + } + while (len1-- > 0) { + if (*name1++ != *name2++) { + return JNI_FALSE; + } + } + return JNI_TRUE; +} + +/* + * Returns the zip entry corresponding to the specified name, or + * NULL if not found. + * This method supports embedded null character in "name", use ulen + * for the length of "name". + */ +jzentry * +ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash) +{ + unsigned int hsh = hashN(name, ulen); jint idx; jzentry *ze = 0; @@ -1139,7 +1167,7 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) /* Check the cached entry first */ ze = zip->cache; - if (ze && strcmp(ze->name,name) == 0) { + if (ze && equals(ze->name, ze->nlen, name, ulen)) { /* Cache hit! Remove and return the cached entry. */ zip->cache = 0; ZIP_Unlock(zip); @@ -1165,7 +1193,7 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) * we keep searching. */ ze = newEntry(zip, zc, ACCESS_RANDOM); - if (ze && strcmp(ze->name, name)==0) { + if (ze && equals(ze->name, ze->nlen, name, ulen)) { break; } if (ze != 0) { @@ -1184,8 +1212,8 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) break; } - /* If no real length was passed in, we are done */ - if (ulen == 0) { + /* If no need to try appending slash, we are done */ + if (!addSlash) { break; } @@ -1195,11 +1223,11 @@ ZIP_GetEntry(jzfile *zip, char *name, jint ulen) } /* Add slash and try once more */ - name[ulen] = '/'; - name[ulen+1] = '\0'; + name[ulen++] = '/'; + name[ulen] = '\0'; hsh = hash_append(hsh, '/'); idx = zip->table[hsh % zip->tablelen]; - ulen = 0; + addSlash = JNI_FALSE; } Finally: diff --git a/jdk/src/java.base/share/native/libzip/zip_util.h b/jdk/src/java.base/share/native/libzip/zip_util.h index a4aaf83823b..a64668cd6d9 100644 --- a/jdk/src/java.base/share/native/libzip/zip_util.h +++ b/jdk/src/java.base/share/native/libzip/zip_util.h @@ -154,6 +154,7 @@ * - If pos <= 0 then it is the position of entry LOC header. * If pos > 0 then it is the position of entry data. * pos should not be accessed directly, but only by ZIP_GetEntryDataOffset. + * - entry name may include embedded null character, use nlen for length */ typedef struct jzentry { /* Zip file entry */ @@ -166,6 +167,7 @@ typedef struct jzentry { /* Zip file entry */ jbyte *extra; /* optional extra data */ jlong pos; /* position of LOC header or entry data */ jint flag; /* general purpose flag */ + jint nlen; /* length of the entry name */ } jzentry; /* @@ -269,5 +271,5 @@ void ZIP_Unlock(jzfile *zip); jint ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len); void ZIP_FreeEntry(jzfile *zip, jzentry *ze); jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry); - +jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash); #endif /* !_ZIP_H_ */ From 21f7f36b9e2375908c246c86268271bd2b067369 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Thu, 14 Aug 2014 21:46:27 -0400 Subject: [PATCH 36/91] 8044269: Analysis of archive files Add checksum verification. Reviewed-by: iklam, dholmes, mschoene --- jdk/make/lib/CoreLibraries.gmk | 2 +- jdk/src/java.base/share/native/libzip/CRC32.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index 852879f09ee..6e17ae0634a 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -224,7 +224,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBZIP, \ $(call SET_SHARED_LIBRARY_ORIGIN) \ $(EXPORT_ZIP_FUNCS), \ LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \ - -export:ZIP_ReadEntry -export:ZIP_GetNextEntry jvm.lib \ + -export:ZIP_ReadEntry -export:ZIP_GetNextEntry -export:ZIP_CRC32 jvm.lib \ $(WIN_JAVA_LIB), \ LDFLAGS_SUFFIX_linux := -ljvm -ljava $(LIBZ), \ LDFLAGS_SUFFIX_solaris := -ljvm -ljava $(LIBZ) -lc, \ diff --git a/jdk/src/java.base/share/native/libzip/CRC32.c b/jdk/src/java.base/share/native/libzip/CRC32.c index e9185b5fb1b..b03b2b9c53c 100644 --- a/jdk/src/java.base/share/native/libzip/CRC32.c +++ b/jdk/src/java.base/share/native/libzip/CRC32.c @@ -54,7 +54,8 @@ Java_java_util_zip_CRC32_updateBytes(JNIEnv *env, jclass cls, jint crc, return crc; } -JNIEXPORT jint ZIP_CRC32(jint crc, const jbyte *buf, jint len) +JNIEXPORT jint JNICALL +ZIP_CRC32(jint crc, const jbyte *buf, jint len) { return crc32(crc, (Bytef*)buf, len); } From d0992c807171c949d8497364e2767391c674cff2 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Tue, 23 Sep 2014 15:52:40 +0400 Subject: [PATCH 37/91] 8049346: [TESTBUG] fix the @run line of the test: jdk/test/java/awt/Focus/SortingFTP/JDK8048887.java Reviewed-by: serb, alexsch --- jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java b/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java index 72f0ada7d5b..01287068e8c 100644 --- a/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java +++ b/jdk/test/java/awt/Focus/SortingFPT/JDK8048887.java @@ -26,7 +26,7 @@ @bug 8048887 @summary Tests SortingFTP for an exception caused by the tim-sort algo. @author anton.tarasov: area=awt.focus - @run main JDK8040632 + @run main JDK8048887 */ import javax.swing.JFrame; From af478a97f475d5fdcb0cae563745535f986d90b7 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 23 Sep 2014 16:05:05 +0400 Subject: [PATCH 38/91] 8058858: JRE 8u20 crashes while using Japanese IM on Windows Reviewed-by: azvegint, alexsch --- .../java.desktop/windows/native/libawt/windows/awt_Component.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp index 6988fb9703a..91bcef69383 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp @@ -3936,7 +3936,6 @@ void AwtComponent::SendInputMethodEvent(jint id, jstring text, DASSERT(stringCls); CHECK_NULL(stringCls); clauseReading = env->NewObjectArray(cClause, stringCls, NULL); - env->DeleteLocalRef(stringCls); DASSERT(clauseReading); CHECK_NULL(clauseReading); for (int i=0; iSetObjectArrayElement(clauseReading, i, rgClauseReading[i]); From fa2dc1108045261d360d534fd16e26ceee31476f Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Tue, 23 Sep 2014 20:17:56 +0400 Subject: [PATCH 39/91] 8058739: The test case failed as "ERROR in native method: ReleasePrimitiveArrayCritical: failed bounds check" Reviewed-by: prr, serb --- .../windows/native/libawt/java2d/windows/GDIRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp index 643d64d09a0..36991f415cb 100644 --- a/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp @@ -670,7 +670,7 @@ Java_sun_java2d_windows_GDIRenderer_doFillPoly if (ypoints != NULL) { pPoints = TransformPoly(xpoints, ypoints, transx, transy, tmpPts, &npoints, FALSE, FALSE); - env->ReleasePrimitiveArrayCritical(ypointsarray, xpoints, JNI_ABORT); + env->ReleasePrimitiveArrayCritical(ypointsarray, ypoints, JNI_ABORT); } env->ReleasePrimitiveArrayCritical(xpointsarray, xpoints, JNI_ABORT); } From 1f7d2ae35ca0400cacdc5b4e155d850d26612a2d Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 23 Sep 2014 07:13:34 +0400 Subject: [PATCH 40/91] 8041734: JFrame in full screen mode leaves empty workspace after close Reviewed-by: azvegint, alexsch --- .../sun/lwawt/macosx/CPlatformWindow.java | 3 +++ .../classes/sun/lwawt/macosx/CWrapper.java | 18 ++++++++++++++++++ .../macosx/native/libawt_lwawt/awt/CWrapper.m | 17 +++++++++++++++++ 3 files changed, 38 insertions(+) diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index 5af2cdfe1d0..0a381941ede 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -567,7 +567,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo CWrapper.NSWindow.makeKeyWindow(nsWindowPtr); } } else { + // immediately hide the window CWrapper.NSWindow.orderOut(nsWindowPtr); + // process the close + CWrapper.NSWindow.close(nsWindowPtr); } } else { // otherwise, put it in a proper z-order diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWrapper.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWrapper.java index f0fec624d8d..516b8de1550 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWrapper.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CWrapper.java @@ -54,8 +54,26 @@ final class CWrapper { static native void orderFront(long window); static native void orderFrontRegardless(long window); static native void orderWindow(long window, int ordered, long relativeTo); + + /** + * Removes the window from the screen. + * + * @param window the pointer of the NSWindow + */ static native void orderOut(long window); + /** + * Removes the window from the screen and releases it. According to + * documentation this method should be similar to {@link #orderOut}, + * because we use ReleasedWhenClosed:NO, so the window shouldn't be + * released. But the close method works differently, for example it + * close the space if the window was in the full screen via + * {@link CPlatformWindow#toggleFullScreen()}. + * + * @param window the pointer of the NSWindow + */ + static native void close(long window); + static native void addChildWindow(long parent, long child, int ordered); static native void removeChildWindow(long parent, long child); diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m index bf0d6b2fccd..bb14ef5ae84 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/CWrapper.m @@ -173,6 +173,23 @@ JNF_COCOA_ENTER(env); JNF_COCOA_EXIT(env); } +/* + * Class: sun_lwawt_macosx_CWrapper$NSWindow + * Method: close + * Signature: (J)V + */ +JNIEXPORT void JNICALL +Java_sun_lwawt_macosx_CWrapper_00024NSWindow_close + (JNIEnv *env, jclass cls, jlong windowPtr) +{ +JNF_COCOA_ENTER(env); + NSWindow *window = (NSWindow *)jlong_to_ptr(windowPtr); + [ThreadUtilities performOnMainThreadWaiting:NO block:^(){ + [window close]; + }]; +JNF_COCOA_EXIT(env); +} + /* * Class: sun_lwawt_macosx_CWrapper$NSWindow * Method: orderFrontRegardless From 4325c3fbec3098cb5008e2d42395e26eec2917de Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 23 Sep 2014 15:48:16 -0700 Subject: [PATCH 41/91] 8017773: OpenJDK7 returns incorrect TrueType font metrics Reviewed-by: prr, bae --- .../native/libfontmanager/freetypeScaler.c | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c b/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c index 12371110af7..af5b76e5381 100644 --- a/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c +++ b/jdk/src/java.desktop/share/native/libfontmanager/freetypeScaler.c @@ -425,7 +425,6 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative( jobject metrics; jfloat ax, ay, dx, dy, bx, by, lx, ly, mx, my; jfloat f0 = 0.0; - FT_Pos bmodifier = 0; FTScalerContext *context = (FTScalerContext*) jlong_to_ptr(pScalerContext); FTScalerInfo *scalerInfo = @@ -458,43 +457,38 @@ Java_sun_font_FreetypeFontScaler_getFontMetricsNative( So, we have to do adust them explicitly and stay consistent with what freetype does to outlines. */ - /* For bolding glyphs are not just widened. Height is also changed - (see ftsynth.c). - - TODO: In vertical direction we could do better job and adjust metrics - proportionally to glyoh shape. */ - if (context->doBold) { - bmodifier = FT_MulFix( - scalerInfo->face->units_per_EM, - scalerInfo->face->size->metrics.y_scale)/24; - } - /**** Note: only some metrics are affected by styling ***/ + /* See https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=657854 */ +#define FT_MulFixFloatShift6(a, b) (((float) (a)) * ((float) (b)) / 65536.0 / 64.0) + + /* + * See FreeType source code: src/base/ftobjs.c ft_recompute_scaled_metrics() + * http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1659 + */ /* ascent */ ax = 0; - ay = -(jfloat) FT26Dot6ToFloat(FT_MulFix( - ((jlong) scalerInfo->face->ascender + bmodifier/2), + ay = -(jfloat) (FT_MulFixFloatShift6( + ((jlong) scalerInfo->face->ascender), (jlong) scalerInfo->face->size->metrics.y_scale)); /* descent */ dx = 0; - dy = -(jfloat) FT26Dot6ToFloat(FT_MulFix( - ((jlong) scalerInfo->face->descender + bmodifier/2), + dy = -(jfloat) (FT_MulFixFloatShift6( + ((jlong) scalerInfo->face->descender), (jlong) scalerInfo->face->size->metrics.y_scale)); /* baseline */ bx = by = 0; /* leading */ lx = 0; - ly = (jfloat) FT26Dot6ToFloat(FT_MulFix( - (jlong) scalerInfo->face->height + bmodifier, + ly = (jfloat) (FT_MulFixFloatShift6( + (jlong) scalerInfo->face->height, (jlong) scalerInfo->face->size->metrics.y_scale)) + ay - dy; /* max advance */ mx = (jfloat) FT26Dot6ToFloat( scalerInfo->face->size->metrics.max_advance + - 2*bmodifier + OBLIQUE_MODIFIER(scalerInfo->face->size->metrics.height)); my = 0; From c65f81d72602081a8380aeba64b3ffc618452984 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 24 Sep 2014 15:23:19 +0400 Subject: [PATCH 42/91] 6329748: Invalid/old variable name - newModel in setModel method in JTable class Reviewed-by: prr, alexsch --- .../share/classes/javax/swing/JTable.java | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java index 5e2d595403e..d38a5813f95 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java @@ -3688,17 +3688,17 @@ public class JTable extends JComponent implements TableModelListener, Scrollable // /** - * Sets the data model for this table to newModel and registers + * Sets the data model for this table to {@code dataModel} and registers * with it for listener notifications from the new data model. * - * @param dataModel the new data source for this table - * @exception IllegalArgumentException if newModel is null - * @see #getModel + * @param dataModel the new data source for this table + * @throws IllegalArgumentException if {@code dataModel} is {@code null} + * @see #getModel * @beaninfo * bound: true * description: The model that is the source of the data for this view. */ - public void setModel(TableModel dataModel) { + public void setModel(final TableModel dataModel) { if (dataModel == null) { throw new IllegalArgumentException("Cannot set a null TableModel"); } @@ -3721,29 +3721,30 @@ public class JTable extends JComponent implements TableModelListener, Scrollable } /** - * Returns the TableModel that provides the data displayed by this - * JTable. + * Returns the {@code TableModel} that provides the data displayed by this + * {@code JTable}. * - * @return the TableModel that provides the data displayed by this JTable - * @see #setModel + * @return the {@code TableModel} that provides the data displayed by this + * {@code JTable} + * @see #setModel */ public TableModel getModel() { return dataModel; } /** - * Sets the column model for this table to newModel and registers - * for listener notifications from the new column model. Also sets - * the column model of the JTableHeader to columnModel. + * Sets the column model for this table to {@code columnModel} and registers + * for listener notifications from the new column model. Also sets the + * column model of the {@code JTableHeader} to {@code columnModel}. * - * @param columnModel the new data source for this table - * @exception IllegalArgumentException if columnModel is null - * @see #getColumnModel + * @param columnModel the new data source for this table + * @throws IllegalArgumentException if {@code columnModel} is {@code null} + * @see #getColumnModel * @beaninfo * bound: true * description: The object governing the way columns appear in the view. */ - public void setColumnModel(TableColumnModel columnModel) { + public void setColumnModel(final TableColumnModel columnModel) { if (columnModel == null) { throw new IllegalArgumentException("Cannot set a null ColumnModel"); } @@ -3766,54 +3767,55 @@ public class JTable extends JComponent implements TableModelListener, Scrollable } /** - * Returns the TableColumnModel that contains all column information + * Returns the {@code TableColumnModel} that contains all column information * of this table. * - * @return the object that provides the column state of the table - * @see #setColumnModel + * @return the object that provides the column state of the table + * @see #setColumnModel */ public TableColumnModel getColumnModel() { return columnModel; } /** - * Sets the row selection model for this table to newModel + * Sets the row selection model for this table to {@code selectionModel} * and registers for listener notifications from the new selection model. * - * @param newModel the new selection model - * @exception IllegalArgumentException if newModel is null - * @see #getSelectionModel + * @param selectionModel the new selection model + * @throws IllegalArgumentException if {@code selectionModel} is + * {@code null} + * @see #getSelectionModel * @beaninfo * bound: true * description: The selection model for rows. */ - public void setSelectionModel(ListSelectionModel newModel) { - if (newModel == null) { + public void setSelectionModel(final ListSelectionModel selectionModel) { + if (selectionModel == null) { throw new IllegalArgumentException("Cannot set a null SelectionModel"); } - ListSelectionModel oldModel = selectionModel; + ListSelectionModel oldModel = this.selectionModel; - if (newModel != oldModel) { + if (selectionModel != oldModel) { if (oldModel != null) { oldModel.removeListSelectionListener(this); } - selectionModel = newModel; - newModel.addListSelectionListener(this); + this.selectionModel = selectionModel; + selectionModel.addListSelectionListener(this); - firePropertyChange("selectionModel", oldModel, newModel); + firePropertyChange("selectionModel", oldModel, selectionModel); repaint(); } } /** - * Returns the ListSelectionModel that is used to maintain row + * Returns the {@code ListSelectionModel} that is used to maintain row * selection state. * - * @return the object that provides row selection state, null - * if row selection is not allowed - * @see #setSelectionModel + * @return the object that provides row selection state, {@code null} if row + * selection is not allowed + * @see #setSelectionModel */ public ListSelectionModel getSelectionModel() { return selectionModel; From c8fc432f84ee91469fad81bda2add4dcfbc71903 Mon Sep 17 00:00:00 2001 From: Anton Tarasov Date: Wed, 24 Sep 2014 15:36:11 +0400 Subject: [PATCH 43/91] 8058870: Mac: JFXPanel deadlocks in jnlp mode Reviewed-by: serb, alexsch --- .../share/classes/javax/swing/JComponent.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java index 17cbf60100b..735ca0b72de 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -56,6 +56,7 @@ import java.io.ObjectInputStream; import java.io.IOException; import java.io.ObjectInputValidation; import java.io.InvalidObjectException; +import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.border.*; import javax.swing.event.*; @@ -354,7 +355,8 @@ public abstract class JComponent extends Container implements Serializable, private static final int AUTOSCROLLS_SET = 25; private static final int FOCUS_TRAVERSAL_KEYS_FORWARD_SET = 26; private static final int FOCUS_TRAVERSAL_KEYS_BACKWARD_SET = 27; - private static final int REVALIDATE_RUNNABLE_SCHEDULED = 28; + + private transient AtomicBoolean revalidateRunnableScheduled = new AtomicBoolean(false); /** * Temporary rectangles. @@ -4901,16 +4903,11 @@ public abstract class JComponent extends Container implements Serializable, // To avoid a flood of Runnables when constructing GUIs off // the EDT, a flag is maintained as to whether or not // a Runnable has been scheduled. - synchronized(this) { - if (getFlag(REVALIDATE_RUNNABLE_SCHEDULED)) { - return; - } - setFlag(REVALIDATE_RUNNABLE_SCHEDULED, true); + if (revalidateRunnableScheduled.getAndSet(true)) { + return; } SunToolkit.executeOnEventHandlerThread(this, () -> { - synchronized(JComponent.this) { - setFlag(REVALIDATE_RUNNABLE_SCHEDULED, false); - } + revalidateRunnableScheduled.set(false); revalidate(); }); } @@ -5567,6 +5564,7 @@ public abstract class JComponent extends Container implements Serializable, ToolTipManager.sharedInstance().registerComponent(this); } setWriteObjCounter(this, (byte)0); + revalidateRunnableScheduled = new AtomicBoolean(false); } From 1095cd42dad6458acadc6c57362c288cdaa79589 Mon Sep 17 00:00:00 2001 From: Jonathan Lu Date: Thu, 25 Sep 2014 14:33:03 +0800 Subject: [PATCH 44/91] 8058930: GraphicsEnvironment.getHeadlessProperty() does not work for AIX platform Reviewed-by: serb --- .../classes/java/awt/GraphicsEnvironment.java | 3 +- .../TestDetectHeadless.java | 32 +++++++++++++ .../TestDetectHeadless/TestDetectHeadless.sh | 47 +++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.java create mode 100644 jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.sh diff --git a/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java b/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java index 77e053a27f2..88638a1ecd1 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java +++ b/jdk/src/java.desktop/share/classes/java/awt/GraphicsEnvironment.java @@ -182,7 +182,8 @@ public abstract class GraphicsEnvironment { "SunOS".equals(osName) || "FreeBSD".equals(osName) || "NetBSD".equals(osName) || - "OpenBSD".equals(osName)) && + "OpenBSD".equals(osName) || + "AIX".equals(osName)) && (System.getenv("DISPLAY") == null)); } } diff --git a/jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.java b/jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.java new file mode 100644 index 00000000000..79897765568 --- /dev/null +++ b/jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * Portions Copyright (c) 2014 IBM Corporation + */ + +public class TestDetectHeadless { + public static void main(String[] args) throws Exception { + Class.forName("javax.swing.plaf.basic.BasicInternalFrameTitlePane"); + } +} diff --git a/jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.sh b/jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.sh new file mode 100644 index 00000000000..6642efa5bd2 --- /dev/null +++ b/jdk/test/java/awt/GraphicsEnvironment/TestDetectHeadless/TestDetectHeadless.sh @@ -0,0 +1,47 @@ +#!/bin/sh + +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# +# Portions Copyright (c) 2014 IBM Corporation +# + +# @test +# @bug 8058930 +# @summary java.awt.GraphicsEnvironment.getHeadlessProperty() does not work for AIX +# +# @build TestDetectHeadless +# @run shell TestDetectHeadless.sh + +OS=`uname -s` +case "$OS" in + Windows* | CYGWIN* ) + echo "Passed"; exit 0 ;; + * ) unset DISPLAY ;; +esac + +${TESTJAVA}/bin/java ${TESTVMOPTS} \ + -cp ${TESTCLASSES} TestDetectHeadless + +exit $? From f4d35341ded97c05e13cb58007dcaaad49f64199 Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Thu, 25 Sep 2014 15:57:37 +0400 Subject: [PATCH 45/91] 8058473: "Comparison method violates its general contract" when using Clipboard Reviewed-by: serb, bae --- .../sun/datatransfer/DataFlavorUtil.java | 9 ++ .../DataFlavorComparatorTest1.java | 115 ++++++++++++++++++ 2 files changed, 124 insertions(+) create mode 100644 jdk/test/sun/awt/datatransfer/DataFlavorComparatorTest1.java diff --git a/jdk/src/java.desktop/share/classes/sun/datatransfer/DataFlavorUtil.java b/jdk/src/java.desktop/share/classes/sun/datatransfer/DataFlavorUtil.java index a5198ddb8d6..d7f9c2763cc 100644 --- a/jdk/src/java.desktop/share/classes/sun/datatransfer/DataFlavorUtil.java +++ b/jdk/src/java.desktop/share/classes/sun/datatransfer/DataFlavorUtil.java @@ -581,6 +581,15 @@ public class DataFlavorUtil { return comp; } + // Next prefer text types + if (flavor1.isFlavorTextType()) { + return 1; + } + + if (flavor2.isFlavorTextType()) { + return -1; + } + // Next, look for application/x-java-* types. Prefer unknown // MIME types because if the user provides his own data flavor, // it will likely be the most descriptive one. diff --git a/jdk/test/sun/awt/datatransfer/DataFlavorComparatorTest1.java b/jdk/test/sun/awt/datatransfer/DataFlavorComparatorTest1.java new file mode 100644 index 00000000000..86ecd481322 --- /dev/null +++ b/jdk/test/sun/awt/datatransfer/DataFlavorComparatorTest1.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 8058473 + @summary "Comparison method violates its general contract" when using Clipboard + Ensure that DataFlavorComparator conforms to Comparator contract + @author Anton Nashatyrev + @run main DataFlavorComparatorTest1 +*/ +import sun.datatransfer.DataFlavorUtil; + +import java.awt.datatransfer.DataFlavor; +import java.util.Comparator; + +public class DataFlavorComparatorTest1 { + + public static void main(String[] args) throws Exception { + String[] mimes = new String[] { + "text/plain", + "text/plain; charset=unicode", + "text/plain; charset=cp1251", + "text/plain; charset=unicode; class=java.io.InputStream", + "text/plain; charset=unicode; class=java.io.Serializable", + "text/plain; charset=unicode; class=java.lang.Object", + "text/plain; class=java.lang.String", + "text/plain; class=java.io.Reader", + "text/plain; class=java.lang.Object", + "text/html", + "text/html; charset=unicode", + "text/html; charset=cp1251", + "text/html; charset=unicode; class=java.io.InputStream", + "text/html; charset=unicode; class=java.io.Serializable", + "text/html; charset=unicode; class=java.lang.Object", + "text/html; class=java.lang.String", + "text/html; class=java.io.Reader", + "text/html; class=java.lang.Object", + "text/unknown", + "text/unknown; charset=unicode", + "text/unknown; charset=cp1251", + "text/unknown; charset=unicode; class=java.io.InputStream", + "text/unknown; charset=unicode; class=java.io.Serializable", + "text/unknown; charset=unicode; class=java.lang.Object", + "text/unknown; class=java.lang.String", + "text/unknown; class=java.io.Reader", + "text/unknown; class=java.lang.Object", + "application/unknown; class=java.io.InputStream", + "application/unknown; class=java.lang.Object", + "application/unknown", + "application/x-java-jvm-local-objectref; class=java.io.InputStream", + "application/x-java-jvm-local-objectref; class=java.lang.Object", + "application/x-java-jvm-local-objectref", + "unknown/flavor", + "unknown/flavor; class=java.io.InputStream", + "unknown/flavor; class=java.lang.Object", + }; + + DataFlavor[] flavors = new DataFlavor[mimes.length]; + for (int i = 0; i < flavors.length; i++) { + flavors[i] = new DataFlavor(mimes[i]); + } + + testComparator(DataFlavorUtil.getDataFlavorComparator(), flavors); + + System.out.println("Passed."); + } + + private static void testComparator(Comparator cmp, DataFlavor[] flavs) + throws ClassNotFoundException { + + for (DataFlavor x: flavs) { + for (DataFlavor y: flavs) { + if (Math.signum(cmp.compare(x,y)) != -Math.signum(cmp.compare(y,x))) { + throw new RuntimeException("Antisymmetry violated: " + x + ", " + y); + } + if (cmp.compare(x,y) == 0 && !x.equals(y)) { + throw new RuntimeException("Equals rule violated: " + x + ", " + y); + } + for (DataFlavor z: flavs) { + if (cmp.compare(x,y) == 0) { + if (Math.signum(cmp.compare(x, z)) != Math.signum(cmp.compare(y, z))) { + throw new RuntimeException("Transitivity (1) violated: " + x + ", " + y + ", " + z); + } + } else { + if (Math.signum(cmp.compare(x, y)) == Math.signum(cmp.compare(y, z))) { + if (Math.signum(cmp.compare(x, y)) != Math.signum(cmp.compare(x, z))) { + throw new RuntimeException("Transitivity (2) violated: " + x + ", " + y + ", " + z); + } + } + } + } + } + } + } +} From ebc6607b656e617087e62020f670141854b4fefa Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Fri, 26 Sep 2014 18:43:44 +0400 Subject: [PATCH 46/91] 8051857: OperationTimedOut exception inside from XToolkit.syncNativeQueue call Reviewed-by: alexsch, serb --- .../unix/native/common/awt/awt_util.h | 2 ++ .../unix/native/libawt_xawt/xawt/XlibWrapper.c | 17 ++++++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/jdk/src/java.desktop/unix/native/common/awt/awt_util.h b/jdk/src/java.desktop/unix/native/common/awt/awt_util.h index dd0be228269..87089054e46 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/awt_util.h +++ b/jdk/src/java.desktop/unix/native/common/awt/awt_util.h @@ -52,6 +52,8 @@ */ extern XErrorHandler current_native_xerror_handler; +Window get_xawt_root_shell(JNIEnv *env); + #endif /* !HEADLESS */ #ifndef INTERSECTS diff --git a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c index 60298f7c4d3..f1d63185186 100644 --- a/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c +++ b/jdk/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c @@ -2011,10 +2011,14 @@ static Bool exitSecondaryLoop = True; * Toolkit thread to process PropertyNotify or SelectionNotify events. */ static Bool -secondary_loop_event(Display* dpy, XEvent* event, char* arg) { - return (event->type == SelectionNotify || - event->type == SelectionClear || - event->type == PropertyNotify) ? True : False; +secondary_loop_event(Display* dpy, XEvent* event, XPointer xawt_root_window) { + return ( + event->type == SelectionNotify || + event->type == SelectionClear || + event->type == PropertyNotify || + (event->type == ConfigureNotify + && event->xany.window == *(Window*) xawt_root_window) + ) ? True : False; } @@ -2025,8 +2029,11 @@ Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent(JNIEnv *env, jclass clazz, AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); exitSecondaryLoop = False; + Window xawt_root_window = get_xawt_root_shell(env); + while (!exitSecondaryLoop) { - if (XCheckIfEvent((Display*) jlong_to_ptr(display), (XEvent*) jlong_to_ptr(ptr), secondary_loop_event, NULL)) { + if (XCheckIfEvent((Display*) jlong_to_ptr(display), + (XEvent*) jlong_to_ptr(ptr), secondary_loop_event, (XPointer) &xawt_root_window)) { return JNI_TRUE; } timeout = (timeout < AWT_SECONDARY_LOOP_TIMEOUT) ? (timeout << 1) : AWT_SECONDARY_LOOP_TIMEOUT; From 4ba0786cc0ce224d95c45ccf93595c364285b61d Mon Sep 17 00:00:00 2001 From: Anton Nashatyrev Date: Tue, 30 Sep 2014 14:51:33 +0400 Subject: [PATCH 47/91] 8056914: Right Click Menu for Paste not showing after upgrading to java 7 Reviewed-by: serb, bae --- .../native/libawt/windows/awt_TextArea.cpp | 214 +----------------- .../native/libawt/windows/awt_TextArea.h | 21 -- .../libawt/windows/awt_TextComponent.cpp | 204 ++++++++++++++++- .../native/libawt/windows/awt_TextComponent.h | 24 ++ .../native/libawt/windows/awt_TextField.cpp | 8 +- 5 files changed, 229 insertions(+), 242 deletions(-) diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp index 938da4c5d9f..427a0b8e3e8 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.cpp @@ -47,16 +47,12 @@ struct ReplaceTextStruct { jfieldID AwtTextArea::scrollbarVisibilityID; -WNDPROC AwtTextArea::sm_pDefWindowProc = NULL; - /************************************************************************ * AwtTextArea methods */ AwtTextArea::AwtTextArea() { - m_bIgnoreEnChange = FALSE; m_bCanUndo = FALSE; - m_hEditCtrl = NULL; m_lHDeltaAccum = 0; m_lVDeltaAccum = 0; } @@ -67,10 +63,6 @@ AwtTextArea::~AwtTextArea() void AwtTextArea::Dispose() { - if (m_hEditCtrl != NULL) { - VERIFY(::DestroyWindow(m_hEditCtrl)); - m_hEditCtrl = NULL; - } AwtTextComponent::Dispose(); } @@ -91,10 +83,6 @@ void AwtTextArea::EditSetSel(CHARRANGE &cr) { } } -void AwtTextArea::EditGetSel(CHARRANGE &cr) { - SendMessage(EM_EXGETSEL, 0, reinterpret_cast(&cr)); -} - /* Count how many '\n's are there in jStr */ size_t AwtTextArea::CountNewLines(JNIEnv *env, jstring jStr, size_t maxlen) { @@ -149,159 +137,6 @@ AwtTextArea::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { return retValue; } -/* - * This routine is a window procedure for the subclass of the standard edit control - * used to generate context menu. RichEdit controls don't have built-in context menu. - * To implement this functionality we have to create an invisible edit control and - * forward WM_CONTEXTMENU messages from a RichEdit control to this helper edit control. - * While the edit control context menu is active we intercept the message generated in - * response to particular item selection and forward it back to the RichEdit control. - * (See AwtTextArea::WmContextMenu for more details). - */ -LRESULT -AwtTextArea::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { - - static BOOL bContextMenuActive = FALSE; - - LRESULT retValue = 0; - MsgRouting mr = mrDoDefault; - - DASSERT(::IsWindow(::GetParent(hWnd))); - - switch (message) { - case WM_UNDO: - case WM_CUT: - case WM_COPY: - case WM_PASTE: - case WM_CLEAR: - case EM_SETSEL: - if (bContextMenuActive) { - ::SendMessage(::GetParent(hWnd), message, wParam, lParam); - mr = mrConsume; - } - break; - case WM_CONTEXTMENU: - bContextMenuActive = TRUE; - break; - } - - if (mr == mrDoDefault) { - DASSERT(sm_pDefWindowProc != NULL); - retValue = ::CallWindowProc(sm_pDefWindowProc, - hWnd, message, wParam, lParam); - } - - if (message == WM_CONTEXTMENU) { - bContextMenuActive = FALSE; - } - - return retValue; -} - -MsgRouting -AwtTextArea::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { - /* Use the system provided edit control class to generate context menu. */ - if (m_hEditCtrl == NULL) { - DWORD dwStyle = WS_CHILD; - DWORD dwExStyle = 0; - m_hEditCtrl = ::CreateWindowEx(dwExStyle, - L"EDIT", - L"TEXT", - dwStyle, - 0, 0, 0, 0, - GetHWnd(), - reinterpret_cast( - static_cast( - CreateControlID())), - AwtToolkit::GetInstance().GetModuleHandle(), - NULL); - DASSERT(m_hEditCtrl != NULL); - if (sm_pDefWindowProc == NULL) { - sm_pDefWindowProc = (WNDPROC)::GetWindowLongPtr(m_hEditCtrl, - GWLP_WNDPROC); - } - ::SetLastError(0); - INT_PTR ret = ::SetWindowLongPtr(m_hEditCtrl, GWLP_WNDPROC, - (INT_PTR)AwtTextArea::EditProc); - DASSERT(ret != 0 || ::GetLastError() == 0); - } - - /* - * Tricks on the edit control to ensure that its context menu has - * the correct set of enabled items according to the RichEdit state. - */ - ::SetWindowText(m_hEditCtrl, TEXT("TEXT")); - - if (m_bCanUndo == TRUE && SendMessage(EM_CANUNDO)) { - /* Enable 'Undo' item. */ - ::SendMessage(m_hEditCtrl, WM_CHAR, 'A', 0); - } - - { - /* - * Initial selection for the edit control - (0,1). - * This enables 'Cut', 'Copy' and 'Delete' and 'Select All'. - */ - INT nStart = 0; - INT nEnd = 1; - if (SendMessage(EM_SELECTIONTYPE) == SEL_EMPTY) { - /* - * RichEdit selection is empty - clear selection of the edit control. - * This disables 'Cut', 'Copy' and 'Delete'. - */ - nStart = -1; - nEnd = 0; - } else { - - CHARRANGE cr; - EditGetSel(cr); - /* Check if all the text is selected. */ - if (cr.cpMin == 0) { - - int len = ::GetWindowTextLength(GetHWnd()); - if (cr.cpMin == 0 && cr.cpMax >= len) { - /* - * All the text is selected in RichEdit - select all the - * text in the edit control. This disables 'Select All'. - */ - nStart = 0; - nEnd = -1; - } - } - } - ::SendMessage(m_hEditCtrl, EM_SETSEL, (WPARAM)nStart, (LPARAM)nEnd); - } - - /* Disable 'Paste' item if the RichEdit control is read-only. */ - ::SendMessage(m_hEditCtrl, EM_SETREADONLY, - GetStyle() & ES_READONLY ? TRUE : FALSE, 0); - - POINT p; - p.x = xPos; - p.y = yPos; - - /* - * If the context menu is requested with SHIFT+F10 or VK_APPS key, - * we position its top left corner to the center of the RichEdit - * client rect. - */ - if (p.x == -1 && p.y == -1) { - RECT r; - VERIFY(::GetClientRect(GetHWnd(), &r)); - p.x = (r.left + r.right) / 2; - p.y = (r.top + r.bottom) / 2; - VERIFY(::ClientToScreen(GetHWnd(), &p)); - } - - // The context menu steals focus from the proxy. - // So, set the focus-restore flag up. - SetRestoreFocus(TRUE); - ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y)); - SetRestoreFocus(FALSE); - - return mrConsume; -} - MsgRouting AwtTextArea::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) { @@ -313,28 +148,9 @@ AwtTextArea::WmNcHitTest(UINT x, UINT y, LRESULT& retVal) } -MsgRouting -AwtTextArea::WmNotify(UINT notifyCode) -{ - if (notifyCode == EN_CHANGE) { - /* - * Ignore notifications if the text hasn't been changed. - * EN_CHANGE sent on character formatting changes as well. - */ - if (m_bIgnoreEnChange == FALSE) { - m_bCanUndo = TRUE; - DoCallback("valueChanged", "()V"); - } else { - m_bCanUndo = FALSE; - } - } - return mrDoDefault; -} - MsgRouting AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) { - MsgRouting returnVal; /* * RichEdit 1.0 control starts internal message loop if the * left mouse button is pressed while the cursor is not over @@ -486,26 +302,6 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) } delete msg; return mrConsume; - } else if (msg->message == WM_RBUTTONUP || - (msg->message == WM_SYSKEYDOWN && msg->wParam == VK_F10 && - HIBYTE(::GetKeyState(VK_SHIFT)))) { - POINT p; - if (msg->message == WM_RBUTTONUP) { - VERIFY(::GetCursorPos(&p)); - } else { - p.x = -1; - p.y = -1; - } - - if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(), - MAKELPARAM(p.x, p.y))) { - JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - JNU_ThrowInternalError(env, "Message not posted, native event queue may be full."); - env->ExceptionDescribe(); - env->ExceptionClear(); - } - delete msg; - return mrConsume; } else if (msg->message == WM_MOUSEWHEEL) { // 4417236: If there is an old version of RichEd32.dll which // does not provide the mouse wheel scrolling we have to @@ -596,15 +392,7 @@ AwtTextArea::HandleEvent(MSG *msg, BOOL synthetic) // 4417236: end of fix } - /* - * Store the 'synthetic' parameter so that the WM_PASTE security check - * happens only for synthetic events. - */ - m_synthetic = synthetic; - returnVal = AwtComponent::HandleEvent(msg, synthetic); - m_synthetic = FALSE; - - return returnVal; + return AwtTextComponent::HandleEvent(msg, synthetic); } diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h index 931a31937f6..1738e64b8ed 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextArea.h @@ -57,17 +57,11 @@ public: static size_t GetALength(JNIEnv* env, jstring jStr, size_t maxlen); LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - static LRESULT CALLBACK EditProc(HWND hWnd, UINT message, - WPARAM wParam, LPARAM lParam); MsgRouting WmEnable(BOOL fEnabled); - MsgRouting WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos); - MsgRouting WmNotify(UINT notifyCode); MsgRouting WmNcHitTest(UINT x, UINT y, LRESULT &retVal); MsgRouting HandleEvent(MSG *msg, BOOL synthetic); - INLINE void SetIgnoreEnChange(BOOL b) { m_bIgnoreEnChange = b; } - virtual BOOL InheritsNativeMouseWheelBehavior(); virtual void Reshape(int x, int y, int w, int h); @@ -81,22 +75,7 @@ public: protected: void EditSetSel(CHARRANGE &cr); - void EditGetSel(CHARRANGE &cr); private: - // RichEdit 1.0 control generates EN_CHANGE notifications not only - // on text changes, but also on any character formatting change. - // This flag is true when the latter case is detected. - BOOL m_bIgnoreEnChange; - - // RichEdit 1.0 control undoes a character formatting change - // if it is the latest. We don't create our own undo buffer, - // but just prohibit undo in case if the latest operation - // is a formatting change. - BOOL m_bCanUndo; - - HWND m_hEditCtrl; - static WNDPROC sm_pDefWindowProc; - LONG m_lHDeltaAccum; LONG m_lVDeltaAccum; diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp index d96a194f01e..eaa8bca03d4 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.cpp @@ -66,6 +66,8 @@ AwtTextComponent::AwtTextComponent() { m_lLastPos = -1; m_isLFonly = FALSE; m_EOLchecked = FALSE; + m_hEditCtrl = NULL; + m_bIgnoreEnChange = FALSE; // javaEventsMask = 0; // accessibility support } @@ -213,6 +215,16 @@ done: return c; } +void AwtTextComponent::Dispose() +{ + if (m_hEditCtrl != NULL) { + VERIFY(::DestroyWindow(m_hEditCtrl)); + m_hEditCtrl = NULL; + } + AwtComponent::Dispose(); +} + + LRESULT AwtTextComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { @@ -322,7 +334,16 @@ MsgRouting AwtTextComponent::WmNotify(UINT notifyCode) { if (notifyCode == EN_CHANGE) { - DoCallback("valueChanged", "()V"); + /* + * Ignore notifications if the text hasn't been changed. + * EN_CHANGE sent on character formatting changes as well. + */ + if (m_bIgnoreEnChange == FALSE) { + m_bCanUndo = TRUE; + DoCallback("valueChanged", "()V"); + } else { + m_bCanUndo = FALSE; + } } return mrDoDefault; } @@ -337,6 +358,28 @@ AwtTextComponent::HandleEvent(MSG *msg, BOOL synthetic) { MsgRouting returnVal; + if (msg->message == WM_RBUTTONUP || + (msg->message == WM_SYSKEYDOWN && msg->wParam == VK_F10 && + HIBYTE(::GetKeyState(VK_SHIFT)))) { + POINT p; + if (msg->message == WM_RBUTTONUP) { + VERIFY(::GetCursorPos(&p)); + } else { + p.x = -1; + p.y = -1; + } + + if (!::PostMessage(GetHWnd(), WM_CONTEXTMENU, (WPARAM)GetHWnd(), + MAKELPARAM(p.x, p.y))) { + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + JNU_ThrowInternalError(env, "Message not posted, native event queue may be full."); + env->ExceptionDescribe(); + env->ExceptionClear(); + } + delete msg; + return mrConsume; + } + /* * Store the 'synthetic' parameter so that the WM_PASTE security check * happens only for synthetic events. @@ -701,6 +744,10 @@ void AwtTextComponent::SetBackgroundColor(COLORREF c) { SendMessage(EM_SETBKGNDCOLOR, (WPARAM)FALSE, (LPARAM)GetBackgroundColor()); } +void AwtTextComponent::EditGetSel(CHARRANGE &cr) { + SendMessage(EM_EXGETSEL, 0, reinterpret_cast(&cr)); +} + /************************************************************************ * WTextComponentPeer native methods @@ -983,6 +1030,161 @@ AwtTextComponent::OleCallback::GetContextMenu(WORD seltype, } +/* + * This routine is a window procedure for the subclass of the standard edit control + * used to generate context menu. RichEdit controls don't have built-in context menu. + * To implement this functionality we have to create an invisible edit control and + * forward WM_CONTEXTMENU messages from a RichEdit control to this helper edit control. + * While the edit control context menu is active we intercept the message generated in + * response to particular item selection and forward it back to the RichEdit control. + * (See AwtTextArea::WmContextMenu for more details). + */ + +WNDPROC AwtTextComponent::sm_pDefWindowProc = NULL; + +LRESULT +AwtTextComponent::EditProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { + + static BOOL bContextMenuActive = FALSE; + + LRESULT retValue = 0; + MsgRouting mr = mrDoDefault; + + DASSERT(::IsWindow(::GetParent(hWnd))); + + switch (message) { + case WM_UNDO: + case WM_CUT: + case WM_COPY: + case WM_PASTE: + case WM_CLEAR: + case EM_SETSEL: + if (bContextMenuActive) { + ::SendMessage(::GetParent(hWnd), message, wParam, lParam); + mr = mrConsume; + } + break; + case WM_CONTEXTMENU: + bContextMenuActive = TRUE; + break; + } + + if (mr == mrDoDefault) { + DASSERT(sm_pDefWindowProc != NULL); + retValue = ::CallWindowProc(sm_pDefWindowProc, + hWnd, message, wParam, lParam); + } + + if (message == WM_CONTEXTMENU) { + bContextMenuActive = FALSE; + } + + return retValue; +} + +MsgRouting +AwtTextComponent::WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos) { + /* Use the system provided edit control class to generate context menu. */ + if (m_hEditCtrl == NULL) { + DWORD dwStyle = WS_CHILD; + DWORD dwExStyle = 0; + m_hEditCtrl = ::CreateWindowEx(dwExStyle, + L"EDIT", + L"TEXT", + dwStyle, + 0, 0, 0, 0, + GetHWnd(), + reinterpret_cast( + static_cast( + CreateControlID())), + AwtToolkit::GetInstance().GetModuleHandle(), + NULL); + DASSERT(m_hEditCtrl != NULL); + if (sm_pDefWindowProc == NULL) { + sm_pDefWindowProc = (WNDPROC)::GetWindowLongPtr(m_hEditCtrl, + GWLP_WNDPROC); + } + ::SetLastError(0); + INT_PTR ret = ::SetWindowLongPtr(m_hEditCtrl, GWLP_WNDPROC, + (INT_PTR)AwtTextArea::EditProc); + DASSERT(ret != 0 || ::GetLastError() == 0); + } + + /* + * Tricks on the edit control to ensure that its context menu has + * the correct set of enabled items according to the RichEdit state. + */ + ::SetWindowText(m_hEditCtrl, TEXT("TEXT")); + + if (m_bCanUndo == TRUE && SendMessage(EM_CANUNDO)) { + /* Enable 'Undo' item. */ + ::SendMessage(m_hEditCtrl, WM_CHAR, 'A', 0); + } + + { + /* + * Initial selection for the edit control - (0,1). + * This enables 'Cut', 'Copy' and 'Delete' and 'Select All'. + */ + INT nStart = 0; + INT nEnd = 1; + if (SendMessage(EM_SELECTIONTYPE) == SEL_EMPTY) { + /* + * RichEdit selection is empty - clear selection of the edit control. + * This disables 'Cut', 'Copy' and 'Delete'. + */ + nStart = -1; + nEnd = 0; + } else { + + CHARRANGE cr; + EditGetSel(cr); + /* Check if all the text is selected. */ + if (cr.cpMin == 0) { + + int len = ::GetWindowTextLength(GetHWnd()); + if (cr.cpMin == 0 && cr.cpMax >= len) { + /* + * All the text is selected in RichEdit - select all the + * text in the edit control. This disables 'Select All'. + */ + nStart = 0; + nEnd = -1; + } + } + } + ::SendMessage(m_hEditCtrl, EM_SETSEL, (WPARAM)nStart, (LPARAM)nEnd); + } + + /* Disable 'Paste' item if the RichEdit control is read-only. */ + ::SendMessage(m_hEditCtrl, EM_SETREADONLY, + GetStyle() & ES_READONLY ? TRUE : FALSE, 0); + + POINT p; + p.x = xPos; + p.y = yPos; + + /* + * If the context menu is requested with SHIFT+F10 or VK_APPS key, + * we position its top left corner to the center of the RichEdit + * client rect. + */ + if (p.x == -1 && p.y == -1) { + RECT r; + VERIFY(::GetClientRect(GetHWnd(), &r)); + p.x = (r.left + r.right) / 2; + p.y = (r.top + r.bottom) / 2; + VERIFY(::ClientToScreen(GetHWnd(), &p)); + } + + // The context menu steals focus from the proxy. + // So, set the focus-restore flag up. + SetRestoreFocus(TRUE); + ::SendMessage(m_hEditCtrl, WM_CONTEXTMENU, (WPARAM)m_hEditCtrl, MAKELPARAM(p.x, p.y)); + SetRestoreFocus(FALSE); + + return mrConsume; +} // // Accessibility support diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.h b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.h index 356ed641984..2a9eecc4e64 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.h +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextComponent.h @@ -47,6 +47,8 @@ public: static AwtTextComponent* Create(jobject self, jobject parent, BOOL isMultiline); + virtual void Dispose(); + virtual LPCTSTR GetClassName(); LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); @@ -83,6 +85,8 @@ public: MsgRouting HandleEvent(MSG *msg, BOOL synthetic); MsgRouting WmPaste(); + INLINE void SetIgnoreEnChange(BOOL b) { m_bIgnoreEnChange = b; } + virtual BOOL IsFocusingMouseMessage(MSG *pMsg); /* To be fully implemented in a future release @@ -115,11 +119,24 @@ public: INLINE VOID SetEndSelectionPos(LONG lPos) { m_lEndPos = lPos; } INLINE VOID SetLastSelectionPos(LONG lPos) { m_lLastPos = lPos; } + void EditGetSel(CHARRANGE &cr); + // Used to prevent untrusted code from synthesizing a WM_PASTE message // by posting a -V KeyEvent BOOL m_synthetic; LONG EditGetCharFromPos(POINT& pt); + // RichEdit 1.0 control generates EN_CHANGE notifications not only + // on text changes, but also on any character formatting change. + // This flag is true when the latter case is detected. + BOOL m_bIgnoreEnChange; + + // RichEdit 1.0 control undoes a character formatting change + // if it is the latest. We don't create our own undo buffer, + // but just prohibit undo in case if the latest operation + // is a formatting change. + BOOL m_bCanUndo; + /***************************************************************** * Inner class OleCallback declaration. */ @@ -166,6 +183,13 @@ private: static OleCallback sm_oleCallback; + static WNDPROC sm_pDefWindowProc; + HWND m_hEditCtrl; + + static LRESULT CALLBACK EditProc(HWND hWnd, UINT message, + WPARAM wParam, LPARAM lParam); + MsgRouting WmContextMenu(HWND hCtrl, UINT xPos, UINT yPos); + // // Accessibility support // diff --git a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp index b37b5c74596..1c966aaf065 100644 --- a/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp +++ b/jdk/src/java.desktop/windows/native/libawt/windows/awt_TextField.cpp @@ -249,13 +249,7 @@ AwtTextField::HandleEvent(MSG *msg, BOOL synthetic) } } - /* - * Store the 'synthetic' parameter so that the WM_PASTE security check - * happens only for synthetic events. - */ - m_synthetic = synthetic; - returnVal = AwtComponent::HandleEvent(msg, synthetic); - m_synthetic = FALSE; + returnVal = AwtTextComponent::HandleEvent(msg, synthetic); if(systemBeeperEnabled){ SystemParametersInfo(SPI_SETBEEP, 1, NULL, 0); From 7a259eeb29ffbb12a5b694c3a147b311de1be451 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Tue, 30 Sep 2014 17:39:04 +0400 Subject: [PATCH 48/91] 8058115: Some of MidiDeviceProviders do not follow the specification Reviewed-by: prr, azvegint --- .../sound/AbstractMidiDeviceProvider.java | 10 ++- .../com/sun/media/sound/MidiUtils.java | 21 +++++- .../sun/media/sound/RealTimeSequencer.java | 6 +- .../sound/RealTimeSequencerProvider.java | 22 ++---- .../com/sun/media/sound/SoftProvider.java | 18 +++-- .../classes/javax/sound/midi/MidiSystem.java | 30 +++----- .../sound/midi/spi/MidiDeviceProvider.java | 14 ++-- .../midi/MidiDeviceProvider/NullInfo.java | 71 +++++++++++++++++++ .../MidiDeviceProvider/UnsupportedInfo.java | 59 +++++++++++++++ 9 files changed, 186 insertions(+), 65 deletions(-) create mode 100644 jdk/test/javax/sound/midi/MidiDeviceProvider/NullInfo.java create mode 100644 jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java index 3d0d1af514a..8d0003cc987 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDeviceProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,7 @@ public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider { } } - + @Override public final MidiDevice.Info[] getDeviceInfo() { readDeviceInfos(); Info[] infos = getInfoCache(); @@ -126,7 +126,7 @@ public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider { return localArray; } - + @Override public final MidiDevice getDevice(MidiDevice.Info info) { if (info instanceof Info) { readDeviceInfos(); @@ -143,9 +143,7 @@ public abstract class AbstractMidiDeviceProvider extends MidiDeviceProvider { } } } - - throw new IllegalArgumentException("MidiDevice " + info.toString() - + " not supported by this provider."); + throw MidiUtils.unsupportedDevice(info); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java index eecd33fe0b5..40f7cd9f576 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/MidiUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,15 @@ package com.sun.media.sound; -import javax.sound.midi.*; import java.util.ArrayList; +import javax.sound.midi.MetaMessage; +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiMessage; +import javax.sound.midi.Sequence; +import javax.sound.midi.Track; + // TODO: // - define and use a global symbolic constant for 60000000 (see convertTempo) @@ -48,6 +54,17 @@ public final class MidiUtils { private MidiUtils() { } + /** + * Returns an exception which should be thrown if MidiDevice is unsupported. + * + * @param info an info object that describes the desired device + * @return an exception instance + */ + static RuntimeException unsupportedDevice(final MidiDevice.Info info) { + return new IllegalArgumentException(String.format( + "MidiDevice %s not supported by this provider", info)); + } + /** return true if the passed message is Meta End Of Track */ public static boolean isMetaEndOfTrack(MidiMessage midiMsg) { // first check if it is a META message at all diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java index 7252723e776..ea782e811b0 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencer.java @@ -64,7 +64,7 @@ final class RealTimeSequencer extends AbstractMidiDevice /** * All RealTimeSequencers share this info object. */ - static final RealTimeSequencerInfo info = new RealTimeSequencerInfo(); + static final MidiDevice.Info info = new RealTimeSequencerInfo(); private static final Sequencer.SyncMode[] masterSyncModes = { Sequencer.SyncMode.INTERNAL_CLOCK }; @@ -154,7 +154,7 @@ final class RealTimeSequencer extends AbstractMidiDevice /* ****************************** CONSTRUCTOR ****************************** */ - RealTimeSequencer() throws MidiUnavailableException { + RealTimeSequencer(){ super(info); if (Printer.trace) Printer.trace(">> RealTimeSequencer CONSTRUCTOR"); @@ -1088,7 +1088,7 @@ final class RealTimeSequencer extends AbstractMidiDevice private static final String description = "Software sequencer"; private static final String version = "Version 1.0"; - private RealTimeSequencerInfo() { + RealTimeSequencerInfo() { super(name, vendor, description, version); } } // class Info diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java index d2724955a0c..fa5bfa1afbf 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RealTimeSequencerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package com.sun.media.sound; import javax.sound.midi.MidiDevice; -import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.spi.MidiDeviceProvider; /** @@ -36,23 +35,16 @@ import javax.sound.midi.spi.MidiDeviceProvider; */ public final class RealTimeSequencerProvider extends MidiDeviceProvider { - + @Override public MidiDevice.Info[] getDeviceInfo() { - - MidiDevice.Info[] localArray = { RealTimeSequencer.info }; - return localArray; + return new MidiDevice.Info[]{RealTimeSequencer.info}; } - - public MidiDevice getDevice(MidiDevice.Info info) { - if ((info != null) && (!info.equals(RealTimeSequencer.info))) { - return null; - } - - try { + @Override + public MidiDevice getDevice(final MidiDevice.Info info) { + if (RealTimeSequencer.info.equals(info)) { return new RealTimeSequencer(); - } catch (MidiUnavailableException e) { - return null; } + throw MidiUtils.unsupportedDevice(info); } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java index 9fe8ad07390..89d85362539 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,11 +22,10 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.media.sound; -import java.util.Arrays; import javax.sound.midi.MidiDevice; -import javax.sound.midi.MidiDevice.Info; import javax.sound.midi.spi.MidiDeviceProvider; /** @@ -36,17 +35,16 @@ import javax.sound.midi.spi.MidiDeviceProvider; */ public final class SoftProvider extends MidiDeviceProvider { - static final Info softinfo = SoftSynthesizer.info; - private static final Info[] softinfos = {softinfo}; - + @Override public MidiDevice.Info[] getDeviceInfo() { - return Arrays.copyOf(softinfos, softinfos.length); + return new MidiDevice.Info[]{SoftSynthesizer.info}; } - public MidiDevice getDevice(MidiDevice.Info info) { - if (info == softinfo) { + @Override + public MidiDevice getDevice(final MidiDevice.Info info) { + if (SoftSynthesizer.info.equals(info)) { return new SoftSynthesizer(); } - return null; + throw MidiUtils.unsupportedDevice(info); } } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java index 9f790fd0f01..4eee72a9d0a 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java @@ -31,6 +31,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -162,18 +163,11 @@ public class MidiSystem { * of length 0 is returned. */ public static MidiDevice.Info[] getMidiDeviceInfo() { - List allInfos = new ArrayList<>(); - List providers = getMidiDeviceProviders(); - - for(int i = 0; i < providers.size(); i++) { - MidiDeviceProvider provider = providers.get(i); - MidiDevice.Info[] tmpinfo = provider.getDeviceInfo(); - for (int j = 0; j < tmpinfo.length; j++) { - allInfos.add( tmpinfo[j] ); - } + final List allInfos = new ArrayList<>(); + for (final MidiDeviceProvider provider : getMidiDeviceProviders()) { + Collections.addAll(allInfos, provider.getDeviceInfo()); } - MidiDevice.Info[] infosArray = allInfos.toArray(new MidiDevice.Info[0]); - return infosArray; + return allInfos.toArray(new MidiDevice.Info[allInfos.size()]); } /** @@ -187,17 +181,15 @@ public class MidiSystem { * MIDI device installed on the system * @see #getMidiDeviceInfo */ - public static MidiDevice getMidiDevice(MidiDevice.Info info) throws MidiUnavailableException { - List providers = getMidiDeviceProviders(); - - for(int i = 0; i < providers.size(); i++) { - MidiDeviceProvider provider = providers.get(i); + public static MidiDevice getMidiDevice(final MidiDevice.Info info) + throws MidiUnavailableException { + for (final MidiDeviceProvider provider : getMidiDeviceProviders()) { if (provider.isDeviceSupported(info)) { - MidiDevice device = provider.getDevice(info); - return device; + return provider.getDevice(info); } } - throw new IllegalArgumentException("Requested device not installed: " + info); + throw new IllegalArgumentException(String.format( + "Requested device not installed: %s", info)); } /** diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java index b4c95a1ec60..97c9d92b7f0 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiDeviceProvider.java @@ -25,6 +25,8 @@ package javax.sound.midi.spi; +import java.util.Arrays; + import javax.sound.midi.MidiDevice; /** @@ -45,16 +47,8 @@ public abstract class MidiDeviceProvider { * @return {@code true} if the specified device is supported, otherwise * {@code false} */ - public boolean isDeviceSupported(MidiDevice.Info info) { - - MidiDevice.Info infos[] = getDeviceInfo(); - - for(int i=0; i errors = new HashSet<>(); + for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) { + try { + if (mdp.isDeviceSupported(null)) { + throw new RuntimeException("null is supported"); + } + final MidiDevice device = mdp.getDevice(null); + System.err.println("MidiDevice: " + device); + throw new RuntimeException("IllegalArgumentException expected"); + } catch (final IllegalArgumentException e) { + errors.add(e.getMessage()); + } + } + if (errors.size() != 1) { + throw new RuntimeException("Wrong number of messages:" + errors); + } + } +} diff --git a/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java b/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java new file mode 100644 index 00000000000..685a5e8af62 --- /dev/null +++ b/jdk/test/javax/sound/midi/MidiDeviceProvider/UnsupportedInfo.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.sound.midi.MidiDevice; +import javax.sound.midi.MidiSystem; +import javax.sound.midi.spi.MidiDeviceProvider; + +import static java.util.ServiceLoader.load; + +/** + * @test + * @bug 8058115 + * @summary MidiDeviceProvider shouldn't returns incorrect results in case of + * unsupported MidiDevice.Info + * @author Sergey Bylokhov + */ +public final class UnsupportedInfo { + + public static void main(final String[] args) { + final MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo(); + for (final MidiDeviceProvider mdp : load(MidiDeviceProvider.class)) { + for (final MidiDevice.Info info : infos) { + if (mdp.isDeviceSupported(info)) { + if (mdp.getDevice(info) == null) { + throw new RuntimeException("MidiDevice is null"); + } + } else { + try { + mdp.getDevice(info); + throw new RuntimeException( + "IllegalArgumentException expected"); + } catch (final IllegalArgumentException ignored) { + // expected + } + } + } + } + } +} From af1868b9eaf13114c90c1e58efe1e72df0b64a8e Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 3 Oct 2014 11:45:36 -0700 Subject: [PATCH 49/91] 8058892: FILL_ARRAYS and ARRAYS are eagely initialized in MethodHandleImpl Reviewed-by: kvn, shade --- .../java/lang/invoke/MethodHandleImpl.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index d24a1ed5614..934aab15996 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -594,6 +594,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static class Lazy { private static final Class MHI = MethodHandleImpl.class; + private static final MethodHandle[] ARRAYS; + private static final MethodHandle[] FILL_ARRAYS; + static final NamedFunction NF_checkSpreadArgument; static final NamedFunction NF_guardWithCatch; static final NamedFunction NF_throwException; @@ -606,6 +609,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static final MethodHandle MH_arrayIdentity; static { + ARRAYS = makeArrays(); + FILL_ARRAYS = makeFillArrays(); + try { NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); NF_guardWithCatch = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class, @@ -1268,7 +1274,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(mhs.size() == 11); // current number of methods return mhs.toArray(new MethodHandle[MAX_ARITY+1]); } - private static final MethodHandle[] ARRAYS = makeArrays(); // filling versions of the above: // using Integer len instead of int len and no varargs to avoid bootstrapping problems @@ -1315,6 +1320,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; Object a4, Object a5, Object a6, Object a7, Object a8, Object a9) { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } + + private static final int FILL_ARRAYS_COUNT = 11; // current number of fillArray methods + private static MethodHandle[] makeFillArrays() { ArrayList mhs = new ArrayList<>(); mhs.add(null); // there is no empty fill; at least a0 is required @@ -1323,10 +1331,9 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; if (mh == null) break; mhs.add(mh); } - assert(mhs.size() == 11); // current number of methods + assert(mhs.size() == FILL_ARRAYS_COUNT); return mhs.toArray(new MethodHandle[0]); } - private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { Object a = w.makeArray(boxes.length); @@ -1338,15 +1345,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * arguments and returns an Object array of them, as if for varargs. */ static MethodHandle varargsArray(int nargs) { - MethodHandle mh = ARRAYS[nargs]; + MethodHandle mh = Lazy.ARRAYS[nargs]; if (mh != null) return mh; mh = findCollector("array", nargs, Object[].class); if (mh != null) mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); - if (mh != null) return ARRAYS[nargs] = mh; + if (mh != null) return Lazy.ARRAYS[nargs] = mh; mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs); assert(assertCorrectArity(mh, nargs)); mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY); - return ARRAYS[nargs] = mh; + return Lazy.ARRAYS[nargs] = mh; } private static boolean assertCorrectArity(MethodHandle mh, int arity) { @@ -1382,7 +1389,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return mh; } - private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); + private static final int LEFT_ARGS = FILL_ARRAYS_COUNT - 1; private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) * fills a[L]..a[N-1] with corresponding arguments, @@ -1413,7 +1420,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); assert(rightLen > 0); MethodHandle midFill = fillToRight(midLen); // recursive fill - MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] + MethodHandle rightFill = Lazy.FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); assert(rightFill.type().parameterCount() == 1 + rightLen); From ac20afc6be5eb557d577c155eecb6b8e523d83bd Mon Sep 17 00:00:00 2001 From: Phil Race Date: Sun, 5 Oct 2014 10:23:13 -0700 Subject: [PATCH 50/91] 8059219: javax.print.PrintServiceLookup allows to register null service Reviewed-by: bae, jgodinez --- .../javax/print/PrintServiceLookup.java | 2 +- jdk/test/javax/print/RegisterNullService.java | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 jdk/test/javax/print/RegisterNullService.java diff --git a/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java b/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java index 70695a995f8..d15a0146287 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java +++ b/jdk/src/java.desktop/share/classes/javax/print/PrintServiceLookup.java @@ -245,7 +245,7 @@ public abstract class PrintServiceLookup { public static boolean registerService(PrintService service) { synchronized (PrintServiceLookup.class) { - if (service instanceof StreamPrintService) { + if (service == null || service instanceof StreamPrintService) { return false; } ArrayList registeredServices = getRegisteredServices(); diff --git a/jdk/test/javax/print/RegisterNullService.java b/jdk/test/javax/print/RegisterNullService.java new file mode 100644 index 00000000000..f828c394e86 --- /dev/null +++ b/jdk/test/javax/print/RegisterNullService.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8059219 + * @summary Should not be able to register null service. + * @run main RegisterNullService +*/ + +import javax.print.PrintService; +import javax.print.PrintServiceLookup; + +public class RegisterNullService { + public static void main (String [] args) throws RuntimeException { + + boolean registered = PrintServiceLookup.registerService(null); + if (registered) { + throw new RuntimeException("Null service was registered"); + } + PrintService[] services = + PrintServiceLookup.lookupPrintServices(null, null); + for (int i = 0; i < services.length; i++) { + if (services[i] == null) { + throw new RuntimeException("Null service found."); + } + } + } +} From 8848e6168cefca4ec7279e280d96206f6f784680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 7 Oct 2014 15:16:17 +0200 Subject: [PATCH 51/91] 8055662: Update mapfile for libjfr Reviewed-by: egahlin, sla --- jdk/make/mapfiles/libjfr/mapfile-vers | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/jdk/make/mapfiles/libjfr/mapfile-vers b/jdk/make/mapfiles/libjfr/mapfile-vers index dea13dd9864..0bb2cbcb8bc 100644 --- a/jdk/make/mapfiles/libjfr/mapfile-vers +++ b/jdk/make/mapfiles/libjfr/mapfile-vers @@ -10,8 +10,13 @@ SUNWprivate_1.1 { Java_oracle_jrockit_jfr_Process_getpid; Java_oracle_jrockit_jfr_Timing_counterTime; Java_oracle_jrockit_jfr_Timing_init; - Java_oracle_jrockit_jfr_NativeLogger_output0; - Java_oracle_jrockit_jfr_VMJFR_isEnabled; + Java_oracle_jrockit_jfr_Logger_output0; + Java_oracle_jrockit_jfr_JFR_isCommercialFeaturesUnlocked; + Java_oracle_jrockit_jfr_JFR_isStarted; + Java_oracle_jrockit_jfr_JFR_isSupportedInVM; + Java_oracle_jrockit_jfr_JFR_startFlightRecorder; + Java_oracle_jrockit_jfr_JFR_isDisabledOnCommandLine; + Java_oracle_jrockit_jfr_JFR_isEnabled; Java_oracle_jrockit_jfr_VMJFR_options; Java_oracle_jrockit_jfr_VMJFR_init; Java_oracle_jrockit_jfr_VMJFR_addConstPool; @@ -33,7 +38,6 @@ SUNWprivate_1.1 { Java_oracle_jrockit_jfr_VMJFR_setPeriod; Java_oracle_jrockit_jfr_VMJFR_getPeriod; Java_oracle_jrockit_jfr_VMJFR_descriptors; - Java_oracle_jrockit_jfr_VMJFR_redefineClass0; Java_oracle_jrockit_jfr_VMJFR_retransformClasses0; JNI_OnLoad; local: From 067e0eee971d839fa64b46a750288fdfc030b900 Mon Sep 17 00:00:00 2001 From: Alexander Scherbatiy Date: Tue, 7 Oct 2014 18:03:58 +0400 Subject: [PATCH 52/91] 8058305: BadLocationException is not thrown by javax.swing.text.View.getNextVisualPositionFrom() for invalid positions Reviewed-by: serb, azvegint --- .../javax/swing/plaf/basic/BasicTextUI.java | 7 +- .../javax/swing/text/AsyncBoxView.java | 2 +- .../javax/swing/text/CompositeView.java | 8 ++- .../classes/javax/swing/text/GlyphView.java | 2 +- .../share/classes/javax/swing/text/View.java | 2 +- .../NavigationFilter/8058305/bug8058305.java | 70 +++++++++++++++++++ 6 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 jdk/test/javax/swing/text/NavigationFilter/8058305/bug8058305.java diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index 2b23f9c0a0e..961400948c3 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1122,6 +1122,11 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { Position.Bias b, int direction, Position.Bias[] biasRet) throws BadLocationException{ Document doc = editor.getDocument(); + + if (pos < -1 || pos > doc.getLength()) { + throw new BadLocationException("Invalid position", pos); + } + if (doc instanceof AbstractDocument) { ((AbstractDocument)doc).readLock(); } @@ -1594,7 +1599,7 @@ public abstract class BasicTextUI extends TextUI implements ViewFactory { int direction, Position.Bias[] biasRet) throws BadLocationException { - if (pos < -1) { + if (pos < -1 || pos > getDocument().getLength()) { throw new BadLocationException("invalid position", pos); } if( view != null ) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java index a30756c8a05..9c00c5f3f22 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/AsyncBoxView.java @@ -854,7 +854,7 @@ public class AsyncBoxView extends View { int direction, Position.Bias[] biasRet) throws BadLocationException { - if (pos < -1) { + if (pos < -1 || pos > getDocument().getLength()) { throw new BadLocationException("invalid position", pos); } return Utilities.getNextVisualPositionFrom( diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/CompositeView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/CompositeView.java index fa9bf093ab7..b3fcef3338d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/CompositeView.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/CompositeView.java @@ -463,7 +463,7 @@ public abstract class CompositeView extends View { public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) throws BadLocationException { - if (pos < -1) { + if (pos < -1 || pos > getDocument().getLength()) { throw new BadLocationException("invalid position", pos); } Rectangle alloc = getInsideAllocation(a); @@ -723,6 +723,9 @@ public abstract class CompositeView extends View { Shape a, int direction, Position.Bias[] biasRet) throws BadLocationException { + if (pos < -1 || pos > getDocument().getLength()) { + throw new BadLocationException("invalid position", pos); + } return Utilities.getNextVisualPositionFrom( this, pos, b, a, direction, biasRet); } @@ -754,6 +757,9 @@ public abstract class CompositeView extends View { int direction, Position.Bias[] biasRet) throws BadLocationException { + if (pos < -1 || pos > getDocument().getLength()) { + throw new BadLocationException("invalid position", pos); + } return Utilities.getNextVisualPositionFrom( this, pos, b, a, direction, biasRet); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphView.java b/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphView.java index 7e697d7d3de..e374a364cdc 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphView.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/GlyphView.java @@ -900,7 +900,7 @@ public class GlyphView extends View implements TabableView, Cloneable { Position.Bias[] biasRet) throws BadLocationException { - if (pos < -1) { + if (pos < -1 || pos > getDocument().getLength()) { throw new BadLocationException("invalid position", pos); } return painter.getNextVisualPositionFrom(this, pos, b, a, direction, biasRet); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/View.java b/jdk/src/java.desktop/share/classes/javax/swing/text/View.java index cd31266b56f..53b63ce96cf 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/View.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/View.java @@ -500,7 +500,7 @@ public abstract class View implements SwingConstants { public int getNextVisualPositionFrom(int pos, Position.Bias b, Shape a, int direction, Position.Bias[] biasRet) throws BadLocationException { - if (pos < -1) { + if (pos < -1 || pos > getDocument().getLength()) { // -1 is a reserved value, see the code below throw new BadLocationException("Invalid position", pos); } diff --git a/jdk/test/javax/swing/text/NavigationFilter/8058305/bug8058305.java b/jdk/test/javax/swing/text/NavigationFilter/8058305/bug8058305.java new file mode 100644 index 00000000000..9ef696891ba --- /dev/null +++ b/jdk/test/javax/swing/text/NavigationFilter/8058305/bug8058305.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import javax.swing.JFormattedTextField; +import javax.swing.JFrame; +import javax.swing.SwingConstants; +import javax.swing.SwingUtilities; +import javax.swing.text.BadLocationException; +import javax.swing.text.NavigationFilter; +import javax.swing.text.Position; + +/* + * @test + * @bug 8058305 + * @summary BadLocationException is not thrown by + * javax.swing.text.View.getNextVisualPositionFrom() for invalid positions + * @run main bug8058305 + */ +public class bug8058305 { + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(bug8058305::createAndShowGUI); + } + + private static void createAndShowGUI() { + JFrame frame = new JFrame(); + + JFormattedTextField textField = new JFormattedTextField(); + NavigationFilter navigationFilter = new NavigationFilter(); + textField.setText("Test for Tests"); + frame.getContentPane().add(textField); + frame.pack(); + + Position.Bias[] biasRet = {Position.Bias.Forward}; + try { + navigationFilter.getNextVisualPositionFrom(textField, 100, + Position.Bias.Backward, SwingConstants.EAST, biasRet); + throw new RuntimeException("BadLocationException is not thrown!"); + } catch (BadLocationException expectedException) { + } + + frame.setVisible(true); + + try { + navigationFilter.getNextVisualPositionFrom(textField, 200, + Position.Bias.Forward, SwingConstants.WEST, biasRet); + throw new RuntimeException("BadLocationException is not thrown!"); + } catch (BadLocationException expectedException) { + } + } +} From d678e2c0dc877d512e352a99f493605432046005 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Fri, 10 Oct 2014 12:05:32 +0200 Subject: [PATCH 53/91] 8042147: test sun/util/logging/SourceClassName.java failed: Unexpected source: java.util.Currency info The test should allow for the possibility that something else than the test code itself might log during the test. Reviewed-by: lancea --- .../sun/util/logging/SourceClassName.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/jdk/test/sun/util/logging/SourceClassName.java b/jdk/test/sun/util/logging/SourceClassName.java index e662166ab46..886460b7dad 100644 --- a/jdk/test/sun/util/logging/SourceClassName.java +++ b/jdk/test/sun/util/logging/SourceClassName.java @@ -54,7 +54,8 @@ public class SourceClassName { plog.severe("Log message {0} {1}", (Object[]) params); // create a java.util.logging.Logger - // now java.util.logging.Logger should be created for each platform logger + // now java.util.logging.Logger should be created for each platform + // logger Logger logger = Logger.getLogger("test.log.bar"); logger.log(Level.SEVERE, "Log message {0} {1}", params); @@ -82,6 +83,19 @@ public class SourceClassName { record[i++] = line; if (i == 2) { i = 0; + // check log message + if (!record[1].equals(EXPECTED_LOG)) { + // it can sometime happen that some static initializer + // in the system will log an error message - due to e.g. + // some kind of misconfiguration or system settings. + // For instance - somethink like: + // INFO: currency.properties entry for FR ignored + // because the value format is not recognized. + // instead of failing if we get such an unexpected + // message, we will simply print that out. + System.out.println("*** WARNING: Unexpected log: " + record[1]); + continue; + } count++; // check source class name and method String[] ss = record[0].split("\\s+"); @@ -92,10 +106,6 @@ public class SourceClassName { ss[len-2] + " " + ss[len-1]); } - // check log message - if (!record[1].equals(EXPECTED_LOG)) { - throw new RuntimeException("Unexpected log: " + record[1]); - } } } if (count != 3) { From f2913f0270a10cb7b98ef2b78223281af6550e8c Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Fri, 10 Oct 2014 17:59:22 +0530 Subject: [PATCH 54/91] 8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter Reviewed-by: attila, jlaskey --- .../internal/objects/NativeJavaImporter.java | 24 ++++----- .../nashorn/internal/runtime/WithObject.java | 13 +++++ .../runtime/resources/Messages.properties | 1 + nashorn/test/script/basic/JDK-8060101.js | 54 +++++++++++++++++++ 4 files changed, 80 insertions(+), 12 deletions(-) create mode 100644 nashorn/test/script/basic/JDK-8060101.js diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java index d1aa8cb1653..498c263cba6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJavaImporter.java @@ -25,6 +25,7 @@ package jdk.nashorn.internal.objects; +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; import jdk.internal.dynalink.CallSiteDescriptor; @@ -36,9 +37,11 @@ import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.NativeJavaPackage; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; /** @@ -94,33 +97,30 @@ public final class NativeJavaImporter extends ScriptObject { } /** - * "No such property" call placeholder. - * - * This can never be called as we override {@link ScriptObject#noSuchProperty}. We do declare it here as it's a signal - * to {@link jdk.nashorn.internal.runtime.WithObject} that it's worth trying doing a {@code noSuchProperty} on this object. + * "No such property" handler. * * @param self self reference * @param name property name - * @return never returns + * @return value of the missing property */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static Object __noSuchProperty__(final Object self, final Object name) { - throw new AssertionError("__noSuchProperty__ placeholder called"); + if (! (self instanceof NativeJavaImporter)) { + throw typeError("not.a.java.importer", ScriptRuntime.safeToString(self)); + } + return ((NativeJavaImporter)self).createProperty(JSType.toString(name)); } /** - * "No such method call" placeholder - * - * This can never be called as we override {@link ScriptObject#noSuchMethod}. We do declare it here as it's a signal - * to {@link jdk.nashorn.internal.runtime.WithObject} that it's worth trying doing a noSuchProperty on this object. + * "No such method call" handler * * @param self self reference * @param args arguments to method - * @return never returns + * @return never returns always throw TypeError */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static Object __noSuchMethod__(final Object self, final Object... args) { - throw new AssertionError("__noSuchMethod__ placeholder called"); + throw typeError("not.a.function", ScriptRuntime.safeToString(args[0])); } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java index 54ec06f5319..20510dfd36b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/WithObject.java @@ -209,6 +209,19 @@ public final class WithObject extends ScriptObject implements Scope { return super.findProperty(key, deep, start); } + @Override + protected Object invokeNoSuchProperty(final String name, final int programPoint) { + FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true); + if (find != null) { + final Object func = find.getObjectValue(); + if (func instanceof ScriptFunction) { + return ScriptRuntime.apply((ScriptFunction)func, expression, name); + } + } + + return getProto().invokeNoSuchProperty(name, programPoint); + } + @Override public void setSplitState(final int state) { getNonWithParent().setSplitState(state); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties index 056dc87deed..3a161c8d352 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -73,6 +73,7 @@ type.error.strict.getter.setter.poison=In strict mode, "caller", "callee", and " type.error.not.an.object={0} is not an Object type.error.not.a.boolean={0} is not a Boolean type.error.not.a.date={0} is not a Date +type.error.not.a.java.importer={0} is not a JavaImporter object type.error.not.a.number={0} is not a Number type.error.not.a.regexp={0} is not a RegExp type.error.not.a.string={0} is not a String diff --git a/nashorn/test/script/basic/JDK-8060101.js b/nashorn/test/script/basic/JDK-8060101.js new file mode 100644 index 00000000000..617bbccde72 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8060101.js @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8060101: AssertionError: __noSuchProperty__ placeholder called from NativeJavaImporter + * + * @test + * @run + */ + +var constant = 0.50; +var ind = 0.0; + +// make sure callsites are exercised quite a few times +// to induce megamorphic callsite for with/JavaImporter +// combo - which triggered that AssertionError. +for (var i = 0; i < 50; i++) { + var math = new JavaImporter(java.lang.StrictMath); + ind += 10.0; + with (math) { + StrictMath.exp(-constant*ind); + } +} + +for (var i = 0; i < 50; i++) { + var math = new JavaImporter(java.lang.StrictMath); + try { + math.Foo(); + } catch (e) { + if (! (e instanceof TypeError)) { + throw e; + } + } +} From 30f7d127ad410c8a4cbafb98d743ed18c91aab58 Mon Sep 17 00:00:00 2001 From: Konstantin Shefov Date: Fri, 10 Oct 2014 21:28:35 +0400 Subject: [PATCH 55/91] 8058733: [TESTBUG] java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java and LFMultiThreadCachingTest.java failed on some platforms due to java.lang.VirtualMachineError Reviewed-by: darcy, vlivanov --- .../invoke/LFCaching/LambdaFormTestCase.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/jdk/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java b/jdk/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java index 45585b2c4bc..dfdcd15297f 100644 --- a/jdk/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java +++ b/jdk/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java @@ -22,6 +22,8 @@ */ import com.oracle.testlibrary.jsr292.Helper; +import com.sun.management.HotSpotDiagnosticMXBean; +import java.lang.management.ManagementFactory; import java.lang.reflect.Method; import java.util.Collection; import java.util.function.Function; @@ -37,6 +39,8 @@ public abstract class LambdaFormTestCase { private final static String METHOD_HANDLE_CLASS_NAME = "java.lang.invoke.MethodHandle"; private final static String INTERNAL_FORM_METHOD_NAME = "internalForm"; + private static final double ITERATIONS_TO_CODE_CACHE_SIZE_RATIO + = 45 / (128.0 * 1024 * 1024); /** * Reflection link to {@code j.l.i.MethodHandle.internalForm} method. It is @@ -87,7 +91,35 @@ public abstract class LambdaFormTestCase { boolean passed = true; int testCounter = 0; int failCounter = 0; - long iterations = Math.max(1, Helper.TEST_LIMIT / testMethods.size()); + long testCaseNum = testMethods.size(); + long iterations = Math.max(1, Helper.TEST_LIMIT / testCaseNum); + System.out.printf("Number of iterations according to -DtestLimit is %d (%d cases)%n", + iterations, iterations * testCaseNum); + HotSpotDiagnosticMXBean hsDiagBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); + long codeCacheSize = Long.parseLong( + hsDiagBean.getVMOption("ReservedCodeCacheSize").getValue()); + System.out.printf("Code cache size is %d bytes%n", codeCacheSize); + long iterationsByCodeCacheSize = (long) (codeCacheSize + * ITERATIONS_TO_CODE_CACHE_SIZE_RATIO); + long nonProfiledCodeCacheSize = Long.parseLong( + hsDiagBean.getVMOption("NonProfiledCodeHeapSize").getValue()); + System.out.printf("Non-profiled code cache size is %d bytes%n", nonProfiledCodeCacheSize); + long iterationsByNonProfiledCodeCacheSize = (long) (nonProfiledCodeCacheSize + * ITERATIONS_TO_CODE_CACHE_SIZE_RATIO); + System.out.printf("Number of iterations limited by code cache size is %d (%d cases)%n", + iterationsByCodeCacheSize, iterationsByCodeCacheSize * testCaseNum); + System.out.printf("Number of iterations limited by non-profiled code cache size is %d (%d cases)%n", + iterationsByNonProfiledCodeCacheSize, iterationsByNonProfiledCodeCacheSize * testCaseNum); + iterations = Math.min(iterationsByCodeCacheSize, + Math.min(iterations, iterationsByNonProfiledCodeCacheSize)); + if (iterations == 0) { + System.out.println("Warning: code cache size is too small to provide at" + + " least one iteration! Test will try to do one iteration."); + iterations = 1; + } + System.out.printf("Number of iterations is set to %d (%d cases)%n", + iterations, iterations * testCaseNum); + System.out.flush(); for (long i = 0; i < iterations; i++) { System.err.println(String.format("Iteration %d:", i)); for (TestMethods testMethod : testMethods) { From 9b4793ec4c024007d1ed8626605b47b5d20eb6dd Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Sat, 11 Oct 2014 13:24:23 +0100 Subject: [PATCH 56/91] 8058855: Update java.util.zip tests to work with modular image Reviewed-by: dholmes, sherman, alanb --- jdk/test/java/util/zip/InterruptibleZip.java | 24 +++---------------- .../util/zip/ZipFile/FinalizeZipFile.java | 9 ++++--- 2 files changed, 7 insertions(+), 26 deletions(-) diff --git a/jdk/test/java/util/zip/InterruptibleZip.java b/jdk/test/java/util/zip/InterruptibleZip.java index fe2122c6c97..f7e2be4fdfb 100644 --- a/jdk/test/java/util/zip/InterruptibleZip.java +++ b/jdk/test/java/util/zip/InterruptibleZip.java @@ -30,32 +30,14 @@ import java.io.*; import java.util.zip.*; public class InterruptibleZip { - private static String rtJar() { - String bcp = System.getProperty("sun.boot.class.path"); - for (String pathElement : bcp.split(File.pathSeparator)) { - if (pathElement.endsWith(File.separator + "rt.jar") && - new File(pathElement).exists()) { - System.out.println("rtJar="+pathElement); - return pathElement; - } - if (pathElement.endsWith(File.separator + "classes") && - new File(pathElement).isDirectory()) { - System.out.println("rt.jar not available"); - return null; - } - } - throw new Error("Can't find rt.jar or classes directory"); - } public static void main(String[] args) throws Exception { /* Interrupt the current thread. The is.read call below - should continue reading rt.jar. + should continue reading input.jar. */ - String rtJar = rtJar(); - if (rtJar == null) return; Thread.currentThread().interrupt(); - ZipFile zf = new ZipFile(rtJar); - ZipEntry ze = zf.getEntry("java/lang/Object.class"); + ZipFile zf = new ZipFile(new File(System.getProperty("test.src", "."), "input.jar")); + ZipEntry ze = zf.getEntry("Available.java"); InputStream is = zf.getInputStream(ze); byte[] buf = new byte[512]; int n = is.read(buf); diff --git a/jdk/test/java/util/zip/ZipFile/FinalizeZipFile.java b/jdk/test/java/util/zip/ZipFile/FinalizeZipFile.java index 055c05aa72d..74866cac808 100644 --- a/jdk/test/java/util/zip/ZipFile/FinalizeZipFile.java +++ b/jdk/test/java/util/zip/ZipFile/FinalizeZipFile.java @@ -51,12 +51,11 @@ public class FinalizeZipFile { private static void makeGarbage() throws Throwable { final Random rnd = new Random(); - final String javaHome = System.getProperty("java.home"); // Create some ZipFiles. - // Find some .jar files in JDK's lib directory. - final File lib = new File(javaHome, "lib"); - check(lib.isDirectory()); - final File[] jars = lib.listFiles( + // Find some .jar files in test directory. + final File testdir = new File(System.getProperty("test.src", ".")); + check(testdir.isDirectory()); + final File[] jars = testdir.listFiles( new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".jar");}}); From 1a2e64b98b7b9b8358c2b1e0f9d16e93fe6b99ca Mon Sep 17 00:00:00 2001 From: Chris Hegarty Date: Sat, 11 Oct 2014 14:45:27 +0100 Subject: [PATCH 57/91] 8060052: FutureTask; fix underflow when timeout = Long.MIN_VALUE Reviewed-by: martin --- .../java/util/concurrent/FutureTask.java | 81 +++++++++++-------- .../FutureTask/NegativeTimeout.java | 47 +++++++++++ 2 files changed, 94 insertions(+), 34 deletions(-) create mode 100644 jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java index 8a2cb38584f..38bf2c10d5a 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java @@ -163,7 +163,7 @@ public class FutureTask implements RunnableFuture { public boolean cancel(boolean mayInterruptIfRunning) { if (!(state == NEW && - UNSAFE.compareAndSwapInt(this, stateOffset, NEW, + U.compareAndSwapInt(this, STATE, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED))) return false; try { // in case call to interrupt throws exception @@ -173,7 +173,7 @@ public class FutureTask implements RunnableFuture { if (t != null) t.interrupt(); } finally { // final state - UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); + U.putOrderedInt(this, STATE, INTERRUPTED); } } } finally { @@ -227,9 +227,9 @@ public class FutureTask implements RunnableFuture { * @param v the value */ protected void set(V v) { - if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { + if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) { outcome = v; - UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state + U.putOrderedInt(this, STATE, NORMAL); // final state finishCompletion(); } } @@ -245,17 +245,16 @@ public class FutureTask implements RunnableFuture { * @param t the cause of failure */ protected void setException(Throwable t) { - if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) { + if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) { outcome = t; - UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state + U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state finishCompletion(); } } public void run() { if (state != NEW || - !UNSAFE.compareAndSwapObject(this, runnerOffset, - null, Thread.currentThread())) + !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())) return; try { Callable c = callable; @@ -296,8 +295,7 @@ public class FutureTask implements RunnableFuture { */ protected boolean runAndReset() { if (state != NEW || - !UNSAFE.compareAndSwapObject(this, runnerOffset, - null, Thread.currentThread())) + !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread())) return false; boolean ran = false; int s = state; @@ -364,7 +362,7 @@ public class FutureTask implements RunnableFuture { private void finishCompletion() { // assert state > COMPLETING; for (WaitNode q; (q = waiters) != null;) { - if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) { + if (U.compareAndSwapObject(this, WAITERS, q, null)) { for (;;) { Thread t = q.thread; if (t != null) { @@ -391,11 +389,18 @@ public class FutureTask implements RunnableFuture { * * @param timed true if use timed waits * @param nanos time to wait, if timed - * @return state upon completion + * @return state upon completion or at timeout */ private int awaitDone(boolean timed, long nanos) throws InterruptedException { - final long deadline = timed ? System.nanoTime() + nanos : 0L; + // The code below is very delicate, to achieve these goals: + // - call nanoTime exactly once for each call to park + // - if nanos <= 0, return promptly without allocation or nanoTime + // - if nanos == Long.MIN_VALUE, don't underflow + // - if nanos == Long.MAX_VALUE, and nanoTime is non-monotonic + // and we suffer a spurious wakeup, we will do no worse than + // to park-spin for a while + long startTime = 0L; // Special value 0L means not yet parked WaitNode q = null; boolean queued = false; for (;;) { @@ -412,18 +417,30 @@ public class FutureTask implements RunnableFuture { } else if (s == COMPLETING) // cannot time out yet Thread.yield(); - else if (q == null) + else if (q == null) { + if (timed && nanos <= 0L) + return s; q = new WaitNode(); + } else if (!queued) - queued = UNSAFE.compareAndSwapObject(this, waitersOffset, - q.next = waiters, q); + queued = U.compareAndSwapObject(this, WAITERS, + q.next = waiters, q); else if (timed) { - nanos = deadline - System.nanoTime(); - if (nanos <= 0L) { - removeWaiter(q); - return state; + final long parkNanos; + if (startTime == 0L) { // first time + startTime = System.nanoTime(); + if (startTime == 0L) + startTime = 1L; + parkNanos = nanos; + } else { + long elapsed = System.nanoTime() - startTime; + if (elapsed >= nanos) { + removeWaiter(q); + return state; + } + parkNanos = nanos - elapsed; } - LockSupport.parkNanos(this, nanos); + LockSupport.parkNanos(this, parkNanos); } else LockSupport.park(this); @@ -454,8 +471,7 @@ public class FutureTask implements RunnableFuture { if (pred.thread == null) // check for race continue retry; } - else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, - q, s)) + else if (!U.compareAndSwapObject(this, WAITERS, q, s)) continue retry; } break; @@ -464,20 +480,17 @@ public class FutureTask implements RunnableFuture { } // Unsafe mechanics - private static final sun.misc.Unsafe UNSAFE; - private static final long stateOffset; - private static final long runnerOffset; - private static final long waitersOffset; + private static final sun.misc.Unsafe U; + private static final long STATE; + private static final long RUNNER; + private static final long WAITERS; static { try { - UNSAFE = sun.misc.Unsafe.getUnsafe(); + U = sun.misc.Unsafe.getUnsafe(); Class k = FutureTask.class; - stateOffset = UNSAFE.objectFieldOffset - (k.getDeclaredField("state")); - runnerOffset = UNSAFE.objectFieldOffset - (k.getDeclaredField("runner")); - waitersOffset = UNSAFE.objectFieldOffset - (k.getDeclaredField("waiters")); + STATE = U.objectFieldOffset(k.getDeclaredField("state")); + RUNNER = U.objectFieldOffset(k.getDeclaredField("runner")); + WAITERS = U.objectFieldOffset(k.getDeclaredField("waiters")); } catch (Exception e) { throw new Error(e); } diff --git a/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java b/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java new file mode 100644 index 00000000000..2e88fee1cf9 --- /dev/null +++ b/jdk/test/java/util/concurrent/FutureTask/NegativeTimeout.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8060052 + * @summary FutureTask; fix underflow when timeout = Long.MIN_VALUE + * @author Chris Hegarty + */ + +import java.util.concurrent.FutureTask; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; + +// If the bug exists the test will eventually be interrupted by the +// test harness and fail with an InterruptedException, otherwise it +// will throw a TimeoutException almost immediately and return silently. + +public class NegativeTimeout { + public static void main(String[] args) throws Exception { + FutureTask task = new FutureTask<>( () -> { return null; } ); + try { + task.get(Long.MIN_VALUE, TimeUnit.NANOSECONDS); + } catch (TimeoutException success) {} + } +} + From b52b3773e9e1d556f6124dda32219236b38a9d7c Mon Sep 17 00:00:00 2001 From: Felix Yang Date: Mon, 13 Oct 2014 17:55:14 +0800 Subject: [PATCH 58/91] 8048052: Permission tests for setFactory Add RuntimePermission tests for setFactory Reviewed-by: weijun, mullan --- .../SetFactoryPermission.java | 87 +++++++++++++++++++ .../java/net/SetFactoryPermission/policy.fail | 3 + .../net/SetFactoryPermission/policy.success | 4 + 3 files changed, 94 insertions(+) create mode 100644 jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java create mode 100644 jdk/test/java/net/SetFactoryPermission/policy.fail create mode 100644 jdk/test/java/net/SetFactoryPermission/policy.success diff --git a/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java b/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java new file mode 100644 index 00000000000..94779628a05 --- /dev/null +++ b/jdk/test/java/net/SetFactoryPermission/SetFactoryPermission.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8048052 + * @summary Test a series of methods which requires "setFactory" runtime permission + * @run main SetFactoryPermission success + * @run main/othervm/policy=policy.fail SetFactoryPermission fail + * @run main/othervm/policy=policy.success SetFactoryPermission success + */ +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.net.URLConnection; +import java.rmi.server.RMISocketFactory; +import java.security.AccessControlException; + +public class SetFactoryPermission { + static boolean success = false; + + interface Runner { + public void run() throws Exception; + } + + public static void main (String[] args) throws Exception { + if (args.length > 0) { + success = System.getSecurityManager() == null || args[0].equals("success"); + } + + doTest(()->{ + System.out.println("Verify URLConnection.setContentHandlerFactor()"); + URLConnection.setContentHandlerFactory(null); + }); + doTest(()->{ + System.out.println("Verify URL.setURLStreamHandlerFactory()"); + URL.setURLStreamHandlerFactory(null); + }); + doTest(()->{ + System.out.println("Verify ServerSocket.setSocketFactory()"); + ServerSocket.setSocketFactory(null); + }); + doTest(()->{ + System.out.println("Verify Socket.setSocketImplFactory()"); + Socket.setSocketImplFactory(null); + }); + doTest(()->{ + System.out.println("Verify RMISocketFactory.setSocketFactory()"); + RMISocketFactory.setSocketFactory(null); + }); + } + + static void doTest(Runner func) throws Exception { + try { + func.run(); + if (!success) { + throw new RuntimeException("AccessControlException is not thrown. Test failed"); + } + } catch (SecurityException e) { + if (success) { + e.printStackTrace(); + throw new RuntimeException("AccessControlException is thrown unexpectedly. Test failed"); + } + } + } +} diff --git a/jdk/test/java/net/SetFactoryPermission/policy.fail b/jdk/test/java/net/SetFactoryPermission/policy.fail new file mode 100644 index 00000000000..a4c6d11f44f --- /dev/null +++ b/jdk/test/java/net/SetFactoryPermission/policy.fail @@ -0,0 +1,3 @@ +grant { + +}; diff --git a/jdk/test/java/net/SetFactoryPermission/policy.success b/jdk/test/java/net/SetFactoryPermission/policy.success new file mode 100644 index 00000000000..d382afce449 --- /dev/null +++ b/jdk/test/java/net/SetFactoryPermission/policy.success @@ -0,0 +1,4 @@ +grant { + permission java.lang.RuntimePermission "setFactory"; +}; + From 7467e9bd34c51d9062a93dfcf273480243e1bed9 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Mon, 13 Oct 2014 17:35:19 +0100 Subject: [PATCH 59/91] 8060166: javax/management/MBeanInfo/NotificationInfoTest.java fails with modular image Reviewed-by: dfuchs --- .../MBeanInfo/NotificationInfoTest.java | 26 +++---------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java b/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java index 4b45e794a88..8149729deb2 100644 --- a/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java +++ b/jdk/test/javax/management/MBeanInfo/NotificationInfoTest.java @@ -36,7 +36,6 @@ import java.io.*; import java.lang.management.*; import java.lang.reflect.*; import java.net.*; -import java.security.CodeSource; import java.util.*; import java.util.jar.*; import javax.management.*; @@ -83,27 +82,10 @@ public class NotificationInfoTest { System.out.println("Checking platform MBeans..."); checkPlatformMBeans(); - CodeSource cs = - javax.management.MBeanServer.class.getProtectionDomain() - .getCodeSource(); - URL codeBase; - if (cs == null) { - String javaHome = System.getProperty("java.home"); - String[] candidates = {"/lib/rt.jar", "/classes/"}; - codeBase = null; - for (String candidate : candidates) { - File file = new File(javaHome + candidate); - if (file.exists()) { - codeBase = file.toURI().toURL(); - break; - } - } - if (codeBase == null) { - throw new Exception( - "Could not determine codeBase for java.home=" + javaHome); - } - } else - codeBase = cs.getLocation(); + URL codeBase = ClassLoader.getSystemResource("javax/management/MBeanServer.class"); + if (codeBase == null) { + throw new Exception("Could not determine codeBase for " + MBeanServer.class); + } System.out.println(); System.out.println("Looking for standard MBeans..."); From ffe5e6e34c0848c9d8cc906d29ef2ef9d952d551 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Mon, 13 Oct 2014 17:43:17 +0100 Subject: [PATCH 60/91] 8058854: Remove dependency on dt.jar from test/tools/jar/normalize/TestNormal.java Reviewed-by: alanb, ksrini --- .../{jar/normalize => pack200}/TestNormal.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename jdk/test/tools/{jar/normalize => pack200}/TestNormal.java (92%) diff --git a/jdk/test/tools/jar/normalize/TestNormal.java b/jdk/test/tools/pack200/TestNormal.java similarity index 92% rename from jdk/test/tools/jar/normalize/TestNormal.java rename to jdk/test/tools/pack200/TestNormal.java index 7db348c1614..5dfe399c64b 100644 --- a/jdk/test/tools/jar/normalize/TestNormal.java +++ b/jdk/test/tools/pack200/TestNormal.java @@ -42,23 +42,23 @@ public class TestNormal { public static void main(String args[]) throws Exception { Properties p = System.getProperties(); String java_home = p.getProperty("test.jdk"); - String dtjar = java_home + File.separator + "lib" - + File.separator + "dt.jar"; + File testJar = new File("test.jar"); + Utils.jar("cvf", testJar.getName(), Utils.TEST_CLS_DIR.getAbsolutePath()); - File folder = new File("dt"); + File folder = new File("testdir"); if (folder.exists()) { delete(folder); } folder.mkdir(); try { - extractJar(new JarFile(dtjar), folder); - execJavaCommand(java_home, "jar cnf normalized.jar -C dt ."); - execJavaCommand(java_home, "jar cf original.jar -C dt ."); + extractJar(new JarFile(testJar), folder); + execJavaCommand(java_home, "jar cnf normalized.jar -C testdir ."); + execJavaCommand(java_home, "jar cf original.jar -C testdir ."); execJavaCommand(java_home, "pack200 -r repacked.jar original.jar"); compareJars(new JarFile("normalized.jar"), new JarFile("repacked.jar")); } finally { - String[] cleanupList = {"dt", "normalized.jar", "original.jar", "repacked.jar"}; + String[] cleanupList = {"testdir", "normalized.jar", "original.jar", "repacked.jar"}; for (String s : cleanupList) { delete(new File(s)); } From a708737ce9028104149dfc9f4d87e9e7822d4a89 Mon Sep 17 00:00:00 2001 From: Amy Lu Date: Mon, 13 Oct 2014 18:16:29 +0100 Subject: [PATCH 61/91] 8058856: tools/jar/LeadingGarbage.java, introduced in JDK-8058520, fails on Windows Reviewed-by: alanb, martin, sherman --- jdk/test/tools/jar/LeadingGarbage.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/jdk/test/tools/jar/LeadingGarbage.java b/jdk/test/tools/jar/LeadingGarbage.java index 045ebb051c9..f6483346946 100644 --- a/jdk/test/tools/jar/LeadingGarbage.java +++ b/jdk/test/tools/jar/LeadingGarbage.java @@ -30,7 +30,6 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Paths; -import sun.tools.jar.Main; import jdk.testlibrary.OutputAnalyzer; import jdk.testlibrary.ProcessTools; @@ -54,9 +53,9 @@ public class LeadingGarbage { final File leadingGarbageZip = new File("leadingGarbage.zip"); void createFile(File f) throws IOException { - OutputStream fos = new FileOutputStream(f); - fos.write(f.getName().getBytes("UTF-8")); - fos.close(); + try (OutputStream fos = new FileOutputStream(f)) { + fos.write(f.getName().getBytes("UTF-8")); + } } void createFiles() throws IOException { @@ -88,8 +87,9 @@ public class LeadingGarbage { void createZipWithLeadingGarbage() throws Throwable { createNormalZip(); createFile(leadingGarbageZip); - OutputStream fos = new FileOutputStream(leadingGarbageZip, true); - Files.copy(normalZip.toPath(), fos); + try (OutputStream fos = new FileOutputStream(leadingGarbageZip, true)) { + Files.copy(normalZip.toPath(), fos); + } assertTrue(normalZip.length() < leadingGarbageZip.length()); assertTrue(normalZip.delete()); } @@ -111,7 +111,7 @@ public class LeadingGarbage { a.shouldHaveExitValue(0); StringBuilder expected = new StringBuilder(); for (File file : files) - expected.append(file.getName()).append('\n'); + expected.append(file.getName()).append(System.lineSeparator()); a.stdoutShouldMatch(expected.toString()); a.stderrShouldMatch("\\A\\Z"); } From 495821f1b268831890c6b0479480bf48c6dafa4d Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Mon, 13 Oct 2014 14:11:20 -0700 Subject: [PATCH 62/91] 8036951: Xerces Update: XMLSchemaValidator.java and XMLSchemaLoader.java Reviewed-by: lancea --- .../{validation/8037819 => }/TEST.properties | 0 .../8037819/SpecialCaseErrorHandler.java | 66 ------ .../validation/8037819/unparsedEntity.dtd | 3 - .../validation/{8037819 => }/BaseTest.java | 134 ++++++------ .../validation/SpecialCaseErrorHandler.java | 54 +++++ .../javax/xml/jaxp/testng/validation/filelist | 1 + .../jdk8036951/FeaturePropagationTest.java | 196 ++++++++++++++++++ .../RootSimpleTypeDefinitionTest.java | 118 +++++++++++ .../jdk8036951/RootTypeDefinitionTest.java | 114 ++++++++++ .../jdk8036951/Xerces1128doc1Test.java | 95 +++++++++ .../jdk8036951/Xerces1128doc2Test.java | 96 +++++++++ .../{8037819 => jdk8036951}/base.xml | 0 .../{8037819 => jdk8036951}/base.xsd | 0 .../jaxp/testng/validation/jdk8036951/idc.xml | 7 + .../jaxp/testng/validation/jdk8036951/idc.xsd | 41 ++++ .../validation/jdk8036951/simpleType.xml | 2 + .../validation/jdk8036951/xerces1128.xsd | 6 + .../validation/jdk8036951/xerces1128_1.xml | 5 + .../validation/jdk8036951/xerces1128_2.xml | 5 + .../{8037819 => jdk8037819}/BasicTest.java | 3 + .../validation/jdk8037819/BasicTest1.java | 68 ++++++ .../FixedAttrTest.java | 2 + .../IdIdrefCheckingTest.java | 2 + .../IdentityConstraintCheckingTest.java | 2 + .../IgnoreXSITypeTest_A_A.java | 2 + .../IgnoreXSITypeTest_A_C.java | 2 + .../IgnoreXSITypeTest_C_A.java | 2 + .../IgnoreXSITypeTest_C_AC.java | 2 + .../IgnoreXSITypeTest_C_C.java | 2 + .../IgnoreXSITypeTest_C_CA.java | 2 + .../RootTypeDefinitionTest.java | 2 + .../UnparsedEntityCheckingTest.java | 2 + .../UseGrammarPoolOnlyTest_False.java | 2 + .../UseGrammarPoolOnlyTest_True.java | 2 + .../testng/validation/jdk8037819/base.xml | 3 + .../testng/validation/jdk8037819/base.xsd | 74 +++++++ .../{8037819 => jdk8037819}/fixedAttr.xml | 0 .../{8037819 => jdk8037819}/idIdref.xml | 0 .../{8037819 => jdk8037819}/idc.xml | 0 .../{8037819 => jdk8037819}/idc.xsd | 0 .../otherNamespace.xml | 0 .../otherNamespace.xsd | 0 .../validation/jdk8037819/unparsedEntity.dtd | 2 + .../unparsedEntity.xml | 0 .../{8037819 => jdk8037819}/xsitype_A_A.xml | 0 .../{8037819 => jdk8037819}/xsitype_A_C.xml | 0 .../{8037819 => jdk8037819}/xsitype_C_A.xml | 0 .../{8037819 => jdk8037819}/xsitype_C_AC.xml | 0 .../{8037819 => jdk8037819}/xsitype_C_C.xml | 0 .../{8037819 => jdk8037819}/xsitype_C_CA.xml | 0 50 files changed, 977 insertions(+), 142 deletions(-) rename jdk/test/javax/xml/jaxp/testng/{validation/8037819 => }/TEST.properties (100%) delete mode 100644 jdk/test/javax/xml/jaxp/testng/validation/8037819/SpecialCaseErrorHandler.java delete mode 100644 jdk/test/javax/xml/jaxp/testng/validation/8037819/unparsedEntity.dtd rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => }/BaseTest.java (79%) create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/SpecialCaseErrorHandler.java create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/filelist create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/FeaturePropagationTest.java create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootSimpleTypeDefinitionTest.java create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootTypeDefinitionTest.java create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc1Test.java create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc2Test.java rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8036951}/base.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8036951}/base.xsd (100%) create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128.xsd create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/BasicTest.java (97%) create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest1.java rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/FixedAttrTest.java (97%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IdIdrefCheckingTest.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IdentityConstraintCheckingTest.java (99%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IgnoreXSITypeTest_A_A.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IgnoreXSITypeTest_A_C.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IgnoreXSITypeTest_C_A.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IgnoreXSITypeTest_C_AC.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IgnoreXSITypeTest_C_C.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/IgnoreXSITypeTest_C_CA.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/RootTypeDefinitionTest.java (99%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/UnparsedEntityCheckingTest.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/UseGrammarPoolOnlyTest_False.java (98%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/UseGrammarPoolOnlyTest_True.java (97%) create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xml create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xsd rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/fixedAttr.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/idIdref.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/idc.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/idc.xsd (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/otherNamespace.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/otherNamespace.xsd (100%) create mode 100644 jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/unparsedEntity.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/xsitype_A_A.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/xsitype_A_C.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/xsitype_C_A.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/xsitype_C_AC.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/xsitype_C_C.xml (100%) rename jdk/test/javax/xml/jaxp/testng/validation/{8037819 => jdk8037819}/xsitype_C_CA.xml (100%) diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/TEST.properties b/jdk/test/javax/xml/jaxp/testng/TEST.properties similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/TEST.properties rename to jdk/test/javax/xml/jaxp/testng/TEST.properties diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/SpecialCaseErrorHandler.java b/jdk/test/javax/xml/jaxp/testng/validation/8037819/SpecialCaseErrorHandler.java deleted file mode 100644 index e5f236d1907..00000000000 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/SpecialCaseErrorHandler.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import java.util.HashMap; - -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -public class SpecialCaseErrorHandler implements ErrorHandler { - public static final boolean DEBUG = false; - - private HashMap errors; - - public SpecialCaseErrorHandler(String[] specialCases) { - errors = new HashMap<>(); - for (int i = 0; i < specialCases.length; ++i) { - errors.put(specialCases[i], Boolean.FALSE); - } - } - - public void reset() { - errors.keySet().stream().forEach((error) -> { - errors.put(error, Boolean.FALSE); - }); - } - - @Override - public void warning(SAXParseException arg0) throws SAXException { - if (DEBUG) { - System.err.println(arg0.getMessage()); - } - } - - @Override - public void error(SAXParseException arg0) throws SAXException { - if (DEBUG) { - System.err.println(arg0.getMessage()); - } - errors.keySet().stream().filter((error) -> (arg0.getMessage().startsWith(error))).forEach((error) -> { - errors.put(error, Boolean.TRUE); - }); - } - - public void fatalError(SAXParseException arg0) throws SAXException { - throw arg0; - } - - public boolean specialCaseFound(String key) { - return ((Boolean) errors.get(key)).booleanValue(); - } -} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/unparsedEntity.dtd b/jdk/test/javax/xml/jaxp/testng/validation/8037819/unparsedEntity.dtd deleted file mode 100644 index 62484e37cd4..00000000000 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/unparsedEntity.dtd +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/BaseTest.java b/jdk/test/javax/xml/jaxp/testng/validation/BaseTest.java similarity index 79% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/BaseTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/BaseTest.java index 020d3420cd3..63c98ea22da 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/BaseTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/BaseTest.java @@ -1,21 +1,7 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +package validation; import java.io.File; +import java.io.FileNotFoundException; import java.net.URL; import javax.xml.XMLConstants; @@ -37,6 +23,7 @@ import com.sun.org.apache.xerces.internal.xs.ElementPSVI; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration; import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition; +import java.security.Policy; import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -66,33 +53,30 @@ public abstract class BaseTest { protected final static String DOCUMENT_CLASS_NAME = Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_CLASS_NAME_PROPERTY; - protected Schema schema; - protected Validator fValidator; - - protected SpecialCaseErrorHandler fErrorHandler; - - DocumentBuilder builder; - protected Document fDocument; - - protected ElementPSVI fRootNode; - - protected URL fDocumentURL; - protected String documentPath; - protected String fDocumentId; - - static String errMessage; - - int passed = 0, failed = 0; - public static boolean isWindows = false; static { if (System.getProperty("os.name").indexOf("Windows")>-1) { isWindows = true; } }; - public static final String USER_DIR = System.getProperty("user.dir", "."); - public static final String BASE_DIR = System.getProperty("test.src", USER_DIR) - .replaceAll("\\" + System.getProperty("file.separator"), "/"); + + protected Schema schema; + protected Validator fValidator; + + protected SpecialCaseErrorHandler fErrorHandler; + + protected DocumentBuilder builder; + protected Document fDocument; + + protected ElementPSVI fRootNode; + protected URL fDocumentURL; + protected URL fSchemaURL; + + static String errMessage; + + int passed = 0, failed = 0; + private boolean hasSM; + private Policy orig; protected abstract String getSchemaFile(); @@ -103,6 +87,12 @@ public abstract class BaseTest { } protected void setUp() throws Exception { + if (System.getSecurityManager() != null) { + hasSM = true; + System.setSecurityManager(null); + } + + orig = Policy.getPolicy(); DocumentBuilderFactory docFactory = DocumentBuilderFactory .newInstance(); @@ -110,41 +100,46 @@ public abstract class BaseTest { "com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl"); docFactory.setNamespaceAware(true); builder = docFactory.newDocumentBuilder(); + // build the location URL of the document + String filepath = System.getProperty("test.src", "."); + String packageDir = this.getClass().getPackage().getName().replace('.', + '/'); + String documentPath = filepath + "/" + packageDir + "/" + getXMLDocument(); + String schemaPath = filepath + "/" + packageDir + "/" + getSchemaFile(); - documentPath = BASE_DIR + "/" + getXMLDocument(); -System.out.println("documentPath:"+documentPath); if (isWindows) { - fDocumentId = "file:/" + documentPath; + fDocumentURL = new URL("file:/" + documentPath); + fSchemaURL = new URL("file:/" + schemaPath); } else { - fDocumentId = "file:" + documentPath; + fDocumentURL = new URL("file:" + documentPath); + fSchemaURL = new URL("file:" + schemaPath); } - //fDocumentURL = ClassLoader.getSystemResource(documentPath); - //fDocumentURL = getClass().getResource(documentPath); -System.out.println("fDocumentId:"+fDocumentId); -//System.out.println("fDocumentURL.toExternalForm:"+fDocumentURL.toExternalForm()); -/** if (fDocumentURL == null) { throw new FileNotFoundException("Couldn't find xml file for test: " + documentPath); } - fDocument = builder.parse(fDocumentURL.toExternalForm()); - fRootNode = (ElementPSVI) fDocument.getDocumentElement(); - */ + SchemaFactory sf = SchemaFactory .newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); sf.setFeature(USE_GRAMMAR_POOL_ONLY, getUseGrammarPoolOnly()); - String schemaPath = BASE_DIR + "/" + getSchemaFile(); - /** - URL schemaURL = ClassLoader.getSystemResource(schemaPath); - if (schemaURL == null) { + + if (fSchemaURL == null) { throw new FileNotFoundException("Couldn't find schema file for test: " + schemaPath); } - */ - schema = sf.newSchema(new StreamSource(new File(schemaPath))); + schema = sf.newSchema(fSchemaURL); + +// String schemaPath = "./jaxp-ri/src/unit-test/apache/xerces/jdk8037819/" + getSchemaFile(); +// Schema schema = sf.newSchema(new StreamSource(new File(schemaPath))); } protected void tearDown() throws Exception { - fValidator = null; - fDocument = null; + System.setSecurityManager(null); + Policy.setPolicy(orig); + if (hasSM) { + System.setSecurityManager(new SecurityManager()); + } + + builder = null; + schema = null; fRootNode = null; fErrorHandler.reset(); System.out.println("\nNumber of tests passed: " + passed); @@ -157,33 +152,27 @@ System.out.println("fDocumentId:"+fDocumentId); protected void validateDocument() throws Exception { Source source = new DOMSource(fDocument); - source.setSystemId(fDocumentId); + source.setSystemId(fDocumentURL.toExternalForm()); Result result = new DOMResult(fDocument); + fValidator.validate(source, result); } protected void validateFragment() throws Exception { Source source = new DOMSource((Node) fRootNode); - source.setSystemId(fDocumentId); + source.setSystemId(fDocumentURL.toExternalForm()); Result result = new DOMResult((Node) fRootNode); fValidator.validate(source, result); } protected void reset() throws Exception { - try { -System.out.println("new File(documentPath)" + new File(documentPath)); - - fDocument = builder.parse(new File(documentPath)); +// fDocument = builder.parse(new File("./jaxp-ri/src/unit-test/apache/xerces/jdk8037819/" + getXMLDocument())); + fDocument = builder.parse(fDocumentURL.toExternalForm()); fRootNode = (ElementPSVI) fDocument.getDocumentElement(); -System.out.println("fDocument" + fDocument); -System.out.println("fRootNode" + fRootNode); fValidator = schema.newValidator(); fErrorHandler.reset(); fValidator.setErrorHandler(fErrorHandler); fValidator.setFeature(DYNAMIC_VALIDATION, false); - } catch (Exception e) { - e.printStackTrace(); - } } protected PSVIElementNSImpl getChild(int n) { @@ -303,21 +292,21 @@ System.out.println("fRootNode" + fRootNode); success(null); } } - void assertTrue(String msg, boolean value) { + public void assertTrue(String msg, boolean value) { if (!value) { fail(msg); } else { success(null); } } - void assertFalse(String msg, boolean value) { + public void assertFalse(String msg, boolean value) { if (value) { fail(msg); } else { success(null); } } - void fail(String errMsg) { + public void fail(String errMsg) { if (errMessage == null) { errMessage = errMsg; } else { @@ -326,9 +315,8 @@ System.out.println("fRootNode" + fRootNode); failed++; } - void success(String msg) { + public void success(String msg) { passed++; - System.out.println(msg); if (msg != null) { if (msg.length() != 0) { System.out.println(msg); diff --git a/jdk/test/javax/xml/jaxp/testng/validation/SpecialCaseErrorHandler.java b/jdk/test/javax/xml/jaxp/testng/validation/SpecialCaseErrorHandler.java new file mode 100644 index 00000000000..2392cebd9b6 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/SpecialCaseErrorHandler.java @@ -0,0 +1,54 @@ +package validation; + +import java.util.HashMap; +import java.util.Iterator; + +import org.xml.sax.ErrorHandler; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +public class SpecialCaseErrorHandler implements ErrorHandler { + public static final boolean DEBUG = false; + + private HashMap errors; + + public SpecialCaseErrorHandler(String[] specialCases) { + errors = new HashMap(); + for (int i = 0; i < specialCases.length; ++i) { + errors.put(specialCases[i], Boolean.FALSE); + } + } + + public void reset() { + for (Iterator iter = errors.keySet().iterator(); iter.hasNext();) { + String error = (String) iter.next(); + errors.put(error, Boolean.FALSE); + } + } + + public void warning(SAXParseException arg0) throws SAXException { + if (DEBUG) { + System.err.println(arg0.getMessage()); + } + } + + public void error(SAXParseException arg0) throws SAXException { + if (DEBUG) { + System.err.println(arg0.getMessage()); + } + for (Iterator iter = errors.keySet().iterator(); iter.hasNext();) { + String error = (String) iter.next(); + if (arg0.getMessage().startsWith(error)) { + errors.put(error, Boolean.TRUE); + } + } + } + + public void fatalError(SAXParseException arg0) throws SAXException { + throw arg0; + } + + public boolean specialCaseFound(String key) { + return ((Boolean) errors.get(key)).booleanValue(); + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/filelist b/jdk/test/javax/xml/jaxp/testng/validation/filelist new file mode 100644 index 00000000000..48980ad5997 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/filelist @@ -0,0 +1 @@ +jdk8037819/BasicTest1.java diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/FeaturePropagationTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/FeaturePropagationTest.java new file mode 100644 index 00000000000..34ffa6f7e79 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/FeaturePropagationTest.java @@ -0,0 +1,196 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package validation.jdk8036951; + +import java.io.File; +import java.io.FileNotFoundException; +import java.net.URL; +import javax.xml.XMLConstants; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; +import javax.xml.validation.Validator; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import validation.BaseTest; + +/** + * @author Peter McCracken, IBM + * @version $Id$ + */ +public class FeaturePropagationTest extends BaseTest { + + public final String FEATURE_STRING_DEFAULT_FALSE = "http://apache.org/xml/features/honour-all-schemaLocations"; + public final String FEATURE_STRING_DEFAULT_TRUE = "http://apache.org/xml/features/validation/schema-full-checking"; + public final String SECURITY_MANAGER = "http://apache.org/xml/properties/security-manager"; + + public FeaturePropagationTest(String name) { + super(name); + } + + @BeforeClass + protected void setUp() throws Exception { + super.setUp(); + } + + @AfterClass + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Test + public void testPropertyReset() throws Exception { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = makeSchema(factory, null); + Validator validator = schema.newValidator(); + Object beforeReset = validator.getProperty(SECURITY_MANAGER); + validator.setProperty(SECURITY_MANAGER, null); + Object changed = validator.getProperty(SECURITY_MANAGER); + //for JDK, this is changed since by default the security manager is set + assertTrue("Property value should have changed after calling setProperty().", beforeReset != changed); + validator.reset(); + Object afterReset = validator.getProperty(SECURITY_MANAGER); + assertTrue("Property value should be the same after calling reset()", beforeReset == afterReset); + } + + @Test + public void testFeatureReset() throws Exception { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = makeSchema(factory, null); + Validator validator = schema.newValidator(); + validator.setFeature(FEATURE_STRING_DEFAULT_TRUE, false); + validator.setFeature(FEATURE_STRING_DEFAULT_FALSE, true); + validator.reset(); + boolean value = validator.getFeature(FEATURE_STRING_DEFAULT_TRUE); + assertTrue("After reset, value of feature on Validator should be true.", value); + value = validator.getFeature(FEATURE_STRING_DEFAULT_FALSE); + assertFalse("After reset, value of feature on Validator should be false.", value); + } + + @Test + public void testSecureProcessingFeaturePropagationAndReset() throws Exception { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + boolean value; + value = factory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); + //default is true for JDK + //assertFalse("Default value of feature on SchemaFactory should have been false.", value); + assertTrue("Default value of feature on SchemaFactory should have been false.", value); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + Schema schema = makeSchema(factory, null); + Validator validator = schema.newValidator(); + value = validator.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); + assertTrue("Value of feature on Validator should have been true.", value); + validator.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false); + value = validator.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); + assertFalse("Value of feature on Validator should have been false.", value); + validator.reset(); + value = validator.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); + assertTrue("After reset, value of feature on Validator should be true.", value); + } + /* + * Using four basically identical tests to try out the different + * instance classes of Schema. They shouldn't differ, because the relevant + * code is in a common base class. + */ + + @Test + public void testFeaturePropagationNull() throws Exception { + checkFeaturesOnValidator(null); + } + + @Test + public void testFeaturePropagationEmpty() throws Exception { + checkFeaturesOnValidator(new Source[] {}); + } + + @Test + public void testFeaturePropagationSingle() throws Exception { + checkFeaturesOnValidator(new Source[] {makeSource("base.xsd")}); + } + + @Test + public void testFeaturePropagationMultiple() throws Exception { + checkFeaturesOnValidator(new Source[] {makeSource("base.xsd"), makeSource("idc.xsd")}); + } + + private void checkFeaturesOnValidator(Source[] sources) throws Exception { + try { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + Schema schema = makeSchema(factory, sources); + Validator validator = schema.newValidator(); + boolean value; + value = validator.getFeature(FEATURE_STRING_DEFAULT_TRUE); + assertTrue("Default value of feature on Validator should have been true.", value); + value = validator.getFeature(FEATURE_STRING_DEFAULT_FALSE); + assertFalse("Default value of feature on Validator should have been false.", value); + + // checking that the value propagates to the validator + factory.setFeature(FEATURE_STRING_DEFAULT_TRUE, false); + factory.setFeature(FEATURE_STRING_DEFAULT_FALSE, true); + schema = makeSchema(factory, sources); + validator = schema.newValidator(); + value = validator.getFeature(FEATURE_STRING_DEFAULT_TRUE); + assertFalse("Value of feature on Validator should have been false.", value); + value = validator.getFeature(FEATURE_STRING_DEFAULT_FALSE); + assertTrue("Value of feature on Validator should have been true.", value); + + // checking that the validator contains a copy of the features, not a reference + factory.setFeature(FEATURE_STRING_DEFAULT_TRUE, true); + factory.setFeature(FEATURE_STRING_DEFAULT_FALSE, false); + value = validator.getFeature(FEATURE_STRING_DEFAULT_TRUE); + assertFalse("Value of feature on Validator should have stayed false.", value); + value = validator.getFeature(FEATURE_STRING_DEFAULT_FALSE); + assertTrue("Value of feature on Validator should have stayed true.", value); + } + catch (SAXNotRecognizedException e) { + fail(e.getMessage()); + } + catch (SAXNotSupportedException e) { + fail(e.getMessage()); + } + } + + private Schema makeSchema(SchemaFactory factory, Source[] sources) throws SAXException { + if (sources == null) { + return factory.newSchema(); + } + else { + return factory.newSchema(sources); + } + } + + private Source makeSource(String xsd) throws FileNotFoundException { + return new StreamSource(fSchemaURL.toExternalForm()); + } + + @Override + protected String getSchemaFile() { + return "base.xsd"; + } + + @Override + protected String getXMLDocument() { + //not needed + return null; + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootSimpleTypeDefinitionTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootSimpleTypeDefinitionTest.java new file mode 100644 index 00000000000..d55c07f6334 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootSimpleTypeDefinitionTest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package validation.jdk8036951; + +import com.sun.org.apache.xerces.internal.xs.ItemPSVI; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.xml.sax.SAXException; +import validation.BaseTest; + +/** + * @author Peter McCracken, IBM + * @version $Id$ + */ +public class RootSimpleTypeDefinitionTest extends BaseTest { + + private QName typeString; + private QName typeNonNegInt; + + private final static String INVALID_TYPE_ERROR = "cvc-type.3.1.3"; + private final static String MININCLUSIVE_DERIVATION_ERROR = "cvc-minInclusive-valid"; + + protected String getXMLDocument() { + return "simpleType.xml"; + } + + protected String getSchemaFile() { + return "base.xsd"; + } + + protected String[] getRelevantErrorIDs() { + return new String[] { INVALID_TYPE_ERROR, MININCLUSIVE_DERIVATION_ERROR }; + } + + @BeforeClass + protected void setUp() throws Exception { + super.setUp(); + } + + @AfterClass + protected void tearDown() throws Exception { + super.tearDown(); + } + + public RootSimpleTypeDefinitionTest(String name) { + super(name); + // This is a roundabout way of making sure that we're not using an + // interned string (so that == doesn't work) + String ns = "x" + XMLConstants.W3C_XML_SCHEMA_NS_URI; + ns = ns.substring(1); + typeString = new QName(ns, "string", "xsd"); + typeNonNegInt = new QName(ns, "nonNegativeInteger", "xsd"); + } + + @Test + public void testSettingSimpleType() throws Exception { + try { + reset(); + fValidator.setProperty(ROOT_TYPE, typeString); + } catch (SAXException e1) { + fail("Problem setting property: " + e1.getMessage()); + } + + try { + validateDocument(); + } catch (Exception e) { + fail("Validation failed: " + e.getMessage()); + } + + assertValidity(ItemPSVI.VALIDITY_VALID, fRootNode.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, fRootNode + .getValidationAttempted()); + assertElementNull(fRootNode.getElementDeclaration()); + assertTypeName("string", fRootNode.getTypeDefinition().getName()); + } + + @Test + public void testSettingInvalidSimpleType() throws Exception { + try { + reset(); + fValidator.setProperty(ROOT_TYPE, typeNonNegInt); + } catch (SAXException e1) { + fail("Problem setting property: " + e1.getMessage()); + } + + try { + validateDocument(); + } catch (Exception e) { + fail("Validation failed: " + e.getMessage()); + } + + assertError(INVALID_TYPE_ERROR); + assertError(MININCLUSIVE_DERIVATION_ERROR); + assertValidity(ItemPSVI.VALIDITY_INVALID, fRootNode.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, fRootNode + .getValidationAttempted()); + assertElementNull(fRootNode.getElementDeclaration()); + assertTypeName("nonNegativeInteger", fRootNode.getTypeDefinition().getName()); + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootTypeDefinitionTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootTypeDefinitionTest.java new file mode 100644 index 00000000000..9c4c93957c8 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/RootTypeDefinitionTest.java @@ -0,0 +1,114 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package validation.jdk8036951; + + +import com.sun.org.apache.xerces.internal.xs.ElementPSVI; +import com.sun.org.apache.xerces.internal.xs.ItemPSVI; +import javax.xml.XMLConstants; +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.validation.SchemaFactory; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import org.w3c.dom.Document; +import validation.BaseTest; + +/** + * @author Peter McCracken, IBM + * @version $Id$ + */ +public class RootTypeDefinitionTest extends BaseTest { + + private QName unknownType; + private QName typeX; + private QName typeY; + private QName typeZ; + private QName typeOtherNamespace; + + private final static String UNKNOWN_TYPE_ERROR = "cvc-type.1"; + + private final static String INVALID_DERIVATION_ERROR = "cvc-elt.4.3"; + + @BeforeClass + protected void setUp() throws Exception { + super.setUp(); + } + + @AfterClass + protected void tearDown() throws Exception { + super.tearDown(); + } + + protected String getXMLDocument() { + return "base.xml"; + } + + protected String getSchemaFile() { + return "base.xsd"; + } + + protected String[] getRelevantErrorIDs() { + return new String[] { UNKNOWN_TYPE_ERROR, INVALID_DERIVATION_ERROR }; + } + + public RootTypeDefinitionTest(String name) { + super(name); + unknownType = new QName("W"); + typeX = new QName("X"); + typeY = new QName("Y"); + typeZ = new QName("Z"); + typeOtherNamespace = new QName("xslt.unittests", "W", "unit"); + } + + + /** + * XERCESJ-1141 root-type-definition property not read by XMLSchemaValidator during reset() + */ + @Test + public void testUsingDocumentBuilderFactory() throws Exception { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setAttribute(ROOT_TYPE, typeX); + dbf.setAttribute(DOCUMENT_CLASS_NAME,"com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl"); + dbf.setNamespaceAware(true); + dbf.setValidating(false); + + SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + dbf.setSchema(sf.newSchema(fSchemaURL)); + + DocumentBuilder db = dbf.newDocumentBuilder(); + Document document = db.parse(fDocumentURL.toExternalForm()); + ElementPSVI rootNode = (ElementPSVI) document.getDocumentElement(); + + assertValidity(ItemPSVI.VALIDITY_VALID, rootNode.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, rootNode + .getValidationAttempted()); + assertElementNull(rootNode.getElementDeclaration()); + assertTypeName("X", rootNode.getTypeDefinition().getName()); + } + + private void checkDefault() { + assertValidity(ItemPSVI.VALIDITY_VALID, fRootNode.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, fRootNode + .getValidationAttempted()); + assertElementName("A", fRootNode.getElementDeclaration().getName()); + assertTypeName("X", fRootNode.getTypeDefinition().getName()); + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc1Test.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc1Test.java new file mode 100644 index 00000000000..73bb0431317 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc1Test.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package validation.jdk8036951; + + +import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; +import com.sun.org.apache.xerces.internal.xs.ItemPSVI; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import validation.BaseTest; + +public class Xerces1128doc1Test extends BaseTest { + + private final static String UNKNOWN_TYPE_ERROR = "cvc-type.1"; + + private final static String INVALID_DERIVATION_ERROR = "cvc-elt.4.3"; + + @BeforeClass + protected void setUp() throws Exception { + super.setUp(); + } + + @AfterClass + protected void tearDown() throws Exception { + super.tearDown(); + } + + protected String getXMLDocument() { + return "xerces1128_1.xml"; + } + + protected String getSchemaFile() { + return "xerces1128.xsd"; + } + + protected String[] getRelevantErrorIDs() { + return new String[] { UNKNOWN_TYPE_ERROR, INVALID_DERIVATION_ERROR }; + } + + public Xerces1128doc1Test(String name) { + super(name); + } + + + /** + * XERCESJ-1128 values for {validation attempted} property in PSVI + */ + @Test + public void testDocument1() { + try { + reset(); + validateDocument(); + } catch (Exception e) { + fail("Validation failed: " + e.getMessage()); + } + + // default value of the feature is false + checkResult(); + } + + private void checkResult() { + PSVIElementNSImpl child = super.getChild(1); + assertValidity(ItemPSVI.VALIDITY_NOTKNOWN, child.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_NONE, child + .getValidationAttempted()); + assertElementNull(child.getElementDeclaration()); + assertTypeName("anyType", child.getTypeDefinition().getName()); + assertTypeNamespace("http://www.w3.org/2001/XMLSchema", + child.getTypeDefinition().getNamespace()); + + child = super.getChild(2); + assertValidity(ItemPSVI.VALIDITY_VALID, child.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, child + .getValidationAttempted()); + assertElementNull(child.getElementDeclaration()); + assertTypeName("X", child.getTypeDefinition().getName()); + assertTypeNamespaceNull(child.getTypeDefinition().getNamespace()); + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc2Test.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc2Test.java new file mode 100644 index 00000000000..788b63eb674 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/Xerces1128doc2Test.java @@ -0,0 +1,96 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package validation.jdk8036951; + + +import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; +import com.sun.org.apache.xerces.internal.xs.ItemPSVI; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; +import validation.BaseTest; + +public class Xerces1128doc2Test extends BaseTest { + + private final static String UNKNOWN_TYPE_ERROR = "cvc-type.1"; + + private final static String INVALID_DERIVATION_ERROR = "cvc-elt.4.3"; + + @BeforeClass + protected void setUp() throws Exception { + super.setUp(); + } + + @AfterClass + protected void tearDown() throws Exception { + super.tearDown(); + } + + protected String getXMLDocument() { + return "xerces1128_2.xml"; + } + + protected String getSchemaFile() { + return "xerces1128.xsd"; + } + + protected String[] getRelevantErrorIDs() { + return new String[] { UNKNOWN_TYPE_ERROR, INVALID_DERIVATION_ERROR }; + } + + public Xerces1128doc2Test(String name) { + super(name); + } + + + /** + * XERCESJ-1128 values for {validation attempted} property in PSVI + */ + @Test + public void testDocument1() { + try { + reset(); + validateDocument(); + } catch (Exception e) { + fail("Validation failed: " + e.getMessage()); + } + + // default value of the feature is false + checkResult(); + } + + private void checkResult() { + PSVIElementNSImpl child = super.getChild(1); + assertValidity(ItemPSVI.VALIDITY_VALID, child.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, child + .getValidationAttempted()); + assertElementNull(child.getElementDeclaration()); + assertTypeName("X", child.getTypeDefinition().getName()); + assertTypeNamespaceNull(child.getTypeDefinition().getNamespace()); + + child = super.getChild(2); + assertValidity(ItemPSVI.VALIDITY_NOTKNOWN, child.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_NONE, child + .getValidationAttempted()); + assertElementNull(child.getElementDeclaration()); + assertTypeName("anyType", child.getTypeDefinition().getName()); + assertTypeNamespace("http://www.w3.org/2001/XMLSchema", + child.getTypeDefinition().getNamespace()); + + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/base.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/base.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/base.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/base.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/base.xsd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/base.xsd similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/base.xsd rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/base.xsd diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml new file mode 100644 index 00000000000..fcf200955b5 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xml @@ -0,0 +1,7 @@ + + + 1 + 2 + 2 + 3 + \ No newline at end of file diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd new file mode 100644 index 00000000000..90d978310e4 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/idc.xsd @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml new file mode 100644 index 00000000000..26477150162 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/simpleType.xml @@ -0,0 +1,2 @@ + +-12345 \ No newline at end of file diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128.xsd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128.xsd new file mode 100644 index 00000000000..9dce116b426 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128.xsd @@ -0,0 +1,6 @@ + + + + + + diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml new file mode 100644 index 00000000000..c204bb4714c --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_1.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml new file mode 100644 index 00000000000..e6a7c5f7ceb --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8036951/xerces1128_2.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/BasicTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest.java similarity index 97% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/BasicTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest.java index d33e571e28e..e346c8ff3ee 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/BasicTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest.java @@ -15,11 +15,14 @@ * limitations under the License. */ +package validation.jdk8037819; + import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class BasicTest extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest1.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest1.java new file mode 100644 index 00000000000..b6fc97ab748 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/BasicTest1.java @@ -0,0 +1,68 @@ +package validation.jdk8037819; + +import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; +import com.sun.org.apache.xerces.internal.xs.ItemPSVI; +import validation.BaseTest; + +public class BasicTest1 extends BaseTest { + public static void main(String[] args) throws Exception { + BasicTest1 test = new BasicTest1(); + test.setUp(); + test.testSimpleValidation(); + test.testSimpleValidationWithTrivialXSIType(); + test.tearDown(); + } + + protected String getXMLDocument() { + return "base.xml"; + } + + protected String getSchemaFile() { + return "base.xsd"; + } + + public BasicTest1() { + super("BasicTest1"); + } + + protected void setUp() throws Exception { + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSimpleValidation() { + try { + reset(); + validateDocument(); + } catch (Exception e) { + fail("Validation failed: " + e.getMessage()); + } + doValidityAsserts(); + } + + public void testSimpleValidationWithTrivialXSIType() { + try { + reset(); + ((PSVIElementNSImpl) fRootNode).setAttributeNS( + "http://www.w3.org/2001/XMLSchema-instance", "type", "X"); + validateDocument(); + } catch (Exception e) { + fail("Validation failed: " + e.getMessage()); + } + doValidityAsserts(); + } + + private void doValidityAsserts() { + assertValidity(ItemPSVI.VALIDITY_VALID, fRootNode.getValidity()); + assertValidationAttempted(ItemPSVI.VALIDATION_FULL, fRootNode + .getValidationAttempted()); + assertElementName("A", fRootNode.getElementDeclaration().getName()); + assertElementNamespaceNull(fRootNode.getElementDeclaration() + .getNamespace()); + assertTypeName("X", fRootNode.getTypeDefinition().getName()); + assertTypeNamespaceNull(fRootNode.getTypeDefinition().getNamespace()); + } +} diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/FixedAttrTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/FixedAttrTest.java similarity index 97% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/FixedAttrTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/FixedAttrTest.java index e1f31f0d409..2b221fc5d3d 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/FixedAttrTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/FixedAttrTest.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; /** * The purpose of this test is to execute all of the isComparable calls in diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IdIdrefCheckingTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IdIdrefCheckingTest.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IdIdrefCheckingTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IdIdrefCheckingTest.java index 4d0aa31af8f..84536497477 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IdIdrefCheckingTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IdIdrefCheckingTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; @@ -21,6 +22,7 @@ import org.xml.sax.SAXException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; // duplicate IDs // reference to non-existent ID diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IdentityConstraintCheckingTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IdentityConstraintCheckingTest.java similarity index 99% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IdentityConstraintCheckingTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IdentityConstraintCheckingTest.java index 3089f6308ec..2756dea0a8e 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IdentityConstraintCheckingTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IdentityConstraintCheckingTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; @@ -21,6 +22,7 @@ import org.xml.sax.SAXException; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IdentityConstraintCheckingTest extends BaseTest { // These values are unstable, since they're not actually error keys, but diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_A_A.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_A_A.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_A_A.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_A_A.java index 435c0f97069..bef6d245316 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_A_A.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_A_A.java @@ -15,12 +15,14 @@ * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IgnoreXSITypeTest_A_A extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_A_C.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_A_C.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_A_C.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_A_C.java index 4dd172d0de2..7eb3c50ebbe 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_A_C.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_A_C.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IgnoreXSITypeTest_A_C extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_A.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_A.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_A.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_A.java index fb4886e9d04..e431df71720 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_A.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_A.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IgnoreXSITypeTest_C_A extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_AC.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_AC.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_AC.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_AC.java index a98ca85a61e..969813cbd54 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_AC.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_AC.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IgnoreXSITypeTest_C_AC extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_C.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_C.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_C.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_C.java index b2623ac22e4..a99cd8416e0 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_C.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_C.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IgnoreXSITypeTest_C_C extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_CA.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_CA.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_CA.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_CA.java index dc8f4f297d3..d13f535010c 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/IgnoreXSITypeTest_C_CA.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/IgnoreXSITypeTest_C_CA.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class IgnoreXSITypeTest_C_CA extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/RootTypeDefinitionTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/RootTypeDefinitionTest.java similarity index 99% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/RootTypeDefinitionTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/RootTypeDefinitionTest.java index c9db8ad14af..220d445033e 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/RootTypeDefinitionTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/RootTypeDefinitionTest.java @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import javax.xml.namespace.QName; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; @@ -22,6 +23,7 @@ import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class RootTypeDefinitionTest extends BaseTest { private QName unknownType; diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/UnparsedEntityCheckingTest.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UnparsedEntityCheckingTest.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/UnparsedEntityCheckingTest.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UnparsedEntityCheckingTest.java index 5d4faaf367a..c19a11e42eb 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/UnparsedEntityCheckingTest.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UnparsedEntityCheckingTest.java @@ -14,12 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.dom.PSVIElementNSImpl; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class UnparsedEntityCheckingTest extends BaseTest { public static final String UNDECLARED_ENTITY = "UndeclaredEntity"; diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/UseGrammarPoolOnlyTest_False.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UseGrammarPoolOnlyTest_False.java similarity index 98% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/UseGrammarPoolOnlyTest_False.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UseGrammarPoolOnlyTest_False.java index 22c58567688..96249529462 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/UseGrammarPoolOnlyTest_False.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UseGrammarPoolOnlyTest_False.java @@ -14,11 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class UseGrammarPoolOnlyTest_False extends BaseTest { private final static String UNKNOWN_TYPE_ERROR = "cvc-type.1"; diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/UseGrammarPoolOnlyTest_True.java b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UseGrammarPoolOnlyTest_True.java similarity index 97% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/UseGrammarPoolOnlyTest_True.java rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UseGrammarPoolOnlyTest_True.java index 3a41320b71a..e50be070580 100644 --- a/jdk/test/javax/xml/jaxp/testng/validation/8037819/UseGrammarPoolOnlyTest_True.java +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/UseGrammarPoolOnlyTest_True.java @@ -14,11 +14,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +package validation.jdk8037819; import com.sun.org.apache.xerces.internal.xs.ItemPSVI; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; +import validation.BaseTest; public class UseGrammarPoolOnlyTest_True extends BaseTest { diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xml new file mode 100644 index 00000000000..e83adee70f5 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xml @@ -0,0 +1,3 @@ + + + diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xsd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xsd new file mode 100644 index 00000000000..89f59c9f106 --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/base.xsd @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/fixedAttr.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/fixedAttr.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/fixedAttr.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/fixedAttr.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/idIdref.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/idIdref.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/idIdref.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/idIdref.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/idc.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/idc.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/idc.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/idc.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/idc.xsd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/idc.xsd similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/idc.xsd rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/idc.xsd diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/otherNamespace.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/otherNamespace.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/otherNamespace.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/otherNamespace.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/otherNamespace.xsd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/otherNamespace.xsd similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/otherNamespace.xsd rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/otherNamespace.xsd diff --git a/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd new file mode 100644 index 00000000000..bf294d1bf7f --- /dev/null +++ b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.dtd @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/unparsedEntity.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/unparsedEntity.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/unparsedEntity.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_A_A.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_A_A.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_A_A.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_A_A.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_A_C.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_A_C.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_A_C.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_A_C.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_A.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_A.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_A.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_A.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_AC.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_AC.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_AC.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_AC.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_C.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_C.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_C.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_C.xml diff --git a/jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_CA.xml b/jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_CA.xml similarity index 100% rename from jdk/test/javax/xml/jaxp/testng/validation/8037819/xsitype_C_CA.xml rename to jdk/test/javax/xml/jaxp/testng/validation/jdk8037819/xsitype_C_CA.xml From 5468e30603bac9363814d776c26a0bca0a9922e2 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 14 Oct 2014 10:07:44 +0800 Subject: [PATCH 63/91] 8029659: Keytool, print key algorithm of certificate or key entry Reviewed-by: xuelei --- .../sun/security/tools/keytool/Main.java | 30 +++++------- .../sun/security/tools/keytool/Resources.java | 2 +- jdk/test/sun/security/tools/keytool/keyalg.sh | 47 +++++++++++++++++++ 3 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 jdk/test/sun/security/tools/keytool/keyalg.sh diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 51274dc109f..af730ce3361 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -64,6 +64,7 @@ import java.security.cert.X509CRLSelector; import javax.security.auth.x500.X500Principal; import java.util.Base64; +import sun.security.util.KeyUtil; import sun.security.util.ObjectIdentifier; import sun.security.pkcs10.PKCS10; import sun.security.pkcs10.PKCS10Attribute; @@ -1103,8 +1104,13 @@ public final class Main { doChangeKeyPasswd(alias); kssave = true; } else if (command == LIST) { + if (storePass == null + && !KeyStoreUtil.isWindowsKeyStore(storetype)) { + printWarning(); + } + if (alias != null) { - doPrintEntry(alias, out, true); + doPrintEntry(alias, out); } else { doPrintEntries(out); } @@ -1765,15 +1771,9 @@ public final class Main { /** * Prints a single keystore entry. */ - private void doPrintEntry(String alias, PrintStream out, - boolean printWarning) + private void doPrintEntry(String alias, PrintStream out) throws Exception { - if (storePass == null && printWarning - && !KeyStoreUtil.isWindowsKeyStore(storetype)) { - printWarning(); - } - if (keyStore.containsAlias(alias) == false) { MessageFormat form = new MessageFormat (rb.getString("Alias.alias.does.not.exist")); @@ -2090,13 +2090,6 @@ public final class Main { private void doPrintEntries(PrintStream out) throws Exception { - if (storePass == null - && !KeyStoreUtil.isWindowsKeyStore(storetype)) { - printWarning(); - } else { - out.println(); - } - out.println(rb.getString("Keystore.type.") + keyStore.getType()); out.println(rb.getString("Keystore.provider.") + keyStore.getProvider().getName()); @@ -2115,7 +2108,7 @@ public final class Main { for (Enumeration e = keyStore.aliases(); e.hasMoreElements(); ) { String alias = e.nextElement(); - doPrintEntry(alias, out, false); + doPrintEntry(alias, out); if (verbose || rfc) { out.println(rb.getString("NEWLINE")); out.println(rb.getString @@ -2922,6 +2915,7 @@ public final class Main { MessageFormat form = new MessageFormat (rb.getString(".PATTERN.printX509Cert")); + PublicKey pkey = cert.getPublicKey(); Object[] source = {cert.getSubjectDN().toString(), cert.getIssuerDN().toString(), cert.getSerialNumber().toString(16), @@ -2931,7 +2925,9 @@ public final class Main { getCertFingerPrint("SHA1", cert), getCertFingerPrint("SHA-256", cert), cert.getSigAlgName(), - cert.getVersion() + pkey.getAlgorithm(), + KeyUtil.getKeySize(pkey), + cert.getVersion(), }; out.println(form.format(source)); diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java index 80b348ff47e..44e38f74839 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/Resources.java @@ -347,7 +347,7 @@ public class Resources extends java.util.ListResourceBundle { {".RETURN.if.same.as.for.otherAlias.", "\t(RETURN if same as for <{0}>)"}, {".PATTERN.printX509Cert", - "Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t MD5: {5}\n\t SHA1: {6}\n\t SHA256: {7}\n\t Signature algorithm name: {8}\n\t Version: {9}"}, + "Owner: {0}\nIssuer: {1}\nSerial number: {2}\nValid from: {3} until: {4}\nCertificate fingerprints:\n\t MD5: {5}\n\t SHA1: {6}\n\t SHA256: {7}\nSignature algorithm name: {8}\nSubject Public Key Algorithm: {9} ({10,number,#})\nVersion: {11}"}, {"What.is.your.first.and.last.name.", "What is your first and last name?"}, {"What.is.the.name.of.your.organizational.unit.", diff --git a/jdk/test/sun/security/tools/keytool/keyalg.sh b/jdk/test/sun/security/tools/keytool/keyalg.sh new file mode 100644 index 00000000000..ed13bcfe1d4 --- /dev/null +++ b/jdk/test/sun/security/tools/keytool/keyalg.sh @@ -0,0 +1,47 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8029659 +# @summary Keytool, print key algorithm of certificate or key entry +# + +if [ "${TESTJAVA}" = "" ] ; then + JAVAC_CMD=`which javac` + TESTJAVA=`dirname $JAVAC_CMD`/.. +fi + +KS=ks +KEYTOOL="$TESTJAVA/bin/keytool ${TESTTOOLVMOPTS} -keystore ks -storepass changeit -keypass changeit" + +rm $KS 2> /dev/null + +$KEYTOOL -genkeypair -alias ca -dname CN=CA -keyalg EC || exit 1 +$KEYTOOL -genkeypair -alias user -dname CN=User -keyalg RSA -keysize 1024 || exit 2 +$KEYTOOL -certreq -alias user | + $KEYTOOL -gencert -alias ca -rfc -sigalg SHA1withECDSA | + $KEYTOOL -printcert > user.dump || exit 3 + +cat user.dump | grep "Signature algorithm name:" | grep SHA1withECDSA || exit 4 +cat user.dump | grep "Subject Public Key Algorithm:" | grep RSA | grep 1024 || exit 5 + From cd3c6765c2e4269b21db5d994e8ebd268cc3bf19 Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Tue, 14 Oct 2014 10:08:32 +0800 Subject: [PATCH 64/91] 8044215: Unable to initiate SpNego using a S4U2Proxy GSSCredential (Krb5ProxyCredential) Reviewed-by: mullan --- .../share/classes/sun/security/jgss/krb5/Krb5Context.java | 7 +++++-- jdk/test/sun/security/krb5/auto/S4U2proxy.java | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java index 8b1c6def532..4b7b0eeb367 100644 --- a/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java +++ b/jdk/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java @@ -244,8 +244,11 @@ class Krb5Context implements GSSContextSpi { * establishment. */ public final void requestCredDeleg(boolean value) throws GSSException { - if (state == STATE_NEW && isInitiator()) - credDelegState = value; + if (state == STATE_NEW && isInitiator()) { + if (myCred == null || !(myCred instanceof Krb5ProxyCredential)) { + credDelegState = value; + } + } } /** diff --git a/jdk/test/sun/security/krb5/auto/S4U2proxy.java b/jdk/test/sun/security/krb5/auto/S4U2proxy.java index dd7d50c3892..10e565279f0 100644 --- a/jdk/test/sun/security/krb5/auto/S4U2proxy.java +++ b/jdk/test/sun/security/krb5/auto/S4U2proxy.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6355584 + * @bug 6355584 8044215 * @summary Introduce constrained Kerberos delegation * @compile -XDignore.symbol.file S4U2proxy.java * @run main/othervm S4U2proxy krb5 @@ -69,6 +69,10 @@ public class S4U2proxy { Context p = s.delegated(); p.startAsClient(OneKDC.BACKEND, mech); + + // 8044215: requestCredDeleg is useless and harmless + p.x().requestCredDeleg(true); + b.startAsServer(mech); Context.handshake(p, b); From b7065f7ee1ec5619e603768083c370e55f49e19a Mon Sep 17 00:00:00 2001 From: Masayoshi Okutsu Date: Tue, 14 Oct 2014 15:20:41 +0900 Subject: [PATCH 65/91] 8060006: No Russian time zones mapping for Windows Reviewed-by: peytoia, aefimov --- jdk/src/java.base/windows/conf/tzmappings | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/windows/conf/tzmappings b/jdk/src/java.base/windows/conf/tzmappings index 953ea10be7a..0a0b8ad4e0e 100644 --- a/jdk/src/java.base/windows/conf/tzmappings +++ b/jdk/src/java.base/windows/conf/tzmappings @@ -193,5 +193,10 @@ Kaliningrad Standard Time:925,925:RU:Europe/Kaliningrad: Turkey Standard Time:926,926::Asia/Istanbul: Bahia Standard Time:927,927::America/Bahia: Libya Standard Time:928,928:LY:Africa/Tripoli: -Western Brazilian Standard Time:929,929:BR:America/Rio_Branco: -Armenian Standard Time:930,930:AM:Asia/Yerevan: +Belarus Standard Time:929,929:BY:Europe/Minsk: +Line Islands Standard Time:930,930::Pacific/Kiritimati: +Russia Time Zone 10:931,931::Asia/Srednekolymsk: +Russia Time Zone 11:932,932::Asia/Anadyr: +Russia Time Zone 3:933,933::Europe/Samara: +Western Brazilian Standard Time:934,934:BR:America/Rio_Branco: +Armenian Standard Time:935,935:AM:Asia/Yerevan: From 99c9dc1b3256a40a7a7014d3faf7c3bf83409974 Mon Sep 17 00:00:00 2001 From: Jaroslav Bachorik Date: Fri, 10 Oct 2014 14:35:53 +0200 Subject: [PATCH 66/91] 8060120: Improve diagnostic output of StartManagementAgent test Reviewed-by: dfuchs --- .../com/sun/tools/attach/StartManagementAgent.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/jdk/test/com/sun/tools/attach/StartManagementAgent.java b/jdk/test/com/sun/tools/attach/StartManagementAgent.java index 0bfa9d98252..97010bf4139 100644 --- a/jdk/test/com/sun/tools/attach/StartManagementAgent.java +++ b/jdk/test/com/sun/tools/attach/StartManagementAgent.java @@ -53,7 +53,9 @@ public class StartManagementAgent { public static void main(String[] args) throws Throwable { ProcessThread processThread = null; try { + System.out.println("Starting test application"); processThread = RunnerUtil.startApplication(); + System.out.println("Application started"); runTests(processThread.getPid()); } catch (Throwable t) { System.out.println("StartManagementAgent got unexpected exception: " + t); @@ -70,6 +72,7 @@ public class StartManagementAgent { // Try calling with null argument boolean exception = false; try { + System.out.println("Starting management agent with null"); vm.startManagementAgent(null); } catch (NullPointerException e) { exception = true; @@ -86,6 +89,7 @@ public class StartManagementAgent { } p.put("com.sun.management.config.file", f.getAbsolutePath()); try { + System.out.println("Starting management agent with bogus port"); vm.startManagementAgent(p); } catch(AttachOperationFailedException ex) { // We expect parsing of "apa" above to fail, but if the file path @@ -93,6 +97,9 @@ public class StartManagementAgent { if (!ex.getMessage().contains("Invalid com.sun.management.jmxremote.port number")) { throw ex; } + ex.printStackTrace(System.err); + } catch (Throwable t) { + t.printStackTrace(System.err); } } @@ -134,14 +141,19 @@ public class StartManagementAgent { } public static void testLocalAgent(VirtualMachine vm) throws Exception { + System.out.println("Getting VM properties"); Properties agentProps = vm.getAgentProperties(); String address = (String) agentProps.get(LOCAL_CONNECTOR_ADDRESS_PROP); if (address != null) { throw new Exception("Local management agent already started"); } + System.out.println("Starting local agent"); + String result = vm.startLocalManagementAgent(); + System.out.println("Agent started"); + // try to parse the return value as a JMXServiceURL new JMXServiceURL(result); From 4fcc6c8f4f0c42b0c07ec323c87fe88da6b40fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Mon, 13 Oct 2014 17:16:32 +0200 Subject: [PATCH 67/91] 8060011: Concatenating an array and converting it to Java gives wrong result Reviewed-by: lagergren, attila --- .../arrays/DeletedRangeArrayFilter.java | 12 ++-- .../internal/runtime/arrays/IntArrayData.java | 8 +-- .../runtime/arrays/LongArrayData.java | 12 ++-- .../runtime/arrays/NumberArrayData.java | 8 +-- .../runtime/arrays/ObjectArrayData.java | 3 +- .../runtime/arrays/SparseArrayData.java | 2 +- nashorn/test/script/basic/JDK-8060011.js | 58 +++++++++++++++++++ 7 files changed, 81 insertions(+), 22 deletions(-) create mode 100644 nashorn/test/script/basic/JDK-8060011.js diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java index 8732add9348..cd5cadb962e 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java @@ -66,9 +66,9 @@ final class DeletedRangeArrayFilter extends ArrayFilter { public Object[] asObjectArray() { final Object[] value = super.asObjectArray(); - if (lo <= Integer.MAX_VALUE) { - final int intHi = (int)Math.min(hi, Integer.MAX_VALUE); - for (int i = (int)lo; i <= intHi; i++) { + if (lo < Integer.MAX_VALUE) { + final int end = (int)Math.min(hi + 1, Integer.MAX_VALUE); + for (int i = (int)lo; i < end; i++) { value[i] = ScriptRuntime.UNDEFINED; } } @@ -81,9 +81,9 @@ final class DeletedRangeArrayFilter extends ArrayFilter { final Object value = super.asArrayOfType(componentType); final Object undefValue = convertUndefinedValue(componentType); - if (lo <= Integer.MAX_VALUE) { - final int intHi = (int)Math.min(hi, Integer.MAX_VALUE); - for (int i = (int)lo; i <= intHi; i++) { + if (lo < Integer.MAX_VALUE) { + final int end = (int)Math.min(hi + 1, Integer.MAX_VALUE); + for (int i = (int)lo; i < end; i++) { Array.set(value, i, undefValue); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java index 48dd088e01c..fece3a6ef64 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java @@ -73,7 +73,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements { @Override public Object[] asObjectArray() { - return toObjectArray(); + return toObjectArray(true); } @SuppressWarnings("unused") @@ -116,9 +116,9 @@ final class IntArrayData extends ContinuousArrayData implements IntElements { return super.asArrayOfType(componentType); } - private Object[] toObjectArray() { + private Object[] toObjectArray(final boolean trim) { assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[array.length]; + final Object[] oarray = new Object[trim ? (int)length : array.length]; for (int index = 0; index < length; index++) { oarray[index] = Integer.valueOf(array[index]); @@ -158,7 +158,7 @@ final class IntArrayData extends ContinuousArrayData implements IntElements { } private ObjectArrayData convertToObject() { - return new ObjectArrayData(toObjectArray(), (int)length); + return new ObjectArrayData(toObjectArray(false), (int)length); } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java index ad050d69170..31a4484e2ae 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java @@ -67,12 +67,12 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen @Override public Object[] asObjectArray() { - return toObjectArray(array, (int)length); + return toObjectArray(true); } - private static Object[] toObjectArray(final long[] array, final int length) { + private Object[] toObjectArray(final boolean trim) { assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[array.length]; + final Object[] oarray = new Object[trim ? (int)length : array.length]; for (int index = 0; index < length; index++) { oarray[index] = Long.valueOf(array[index]); @@ -89,7 +89,7 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen return super.asArrayOfType(componentType); } - private static double[] toDoubleArray(final long[] array, final int length) { + private double[] toDoubleArray() { assert length <= array.length : "length exceeds internal array size"; final double[] darray = new double[array.length]; @@ -107,9 +107,9 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen } final int len = (int)length; if (type == Double.class) { - return new NumberArrayData(LongArrayData.toDoubleArray(array, len), len); + return new NumberArrayData(toDoubleArray(), len); } - return new ObjectArrayData(LongArrayData.toObjectArray(array, len), len); + return new ObjectArrayData(toObjectArray(false), len); } @Override diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java index b2d843e6fb4..4d27f51df3c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java @@ -66,12 +66,12 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen @Override public Object[] asObjectArray() { - return toObjectArray(array, (int)length); + return toObjectArray(true); } - private static Object[] toObjectArray(final double[] array, final int length) { + private Object[] toObjectArray(final boolean trim) { assert length <= array.length : "length exceeds internal array size"; - final Object[] oarray = new Object[array.length]; + final Object[] oarray = new Object[trim ? (int)length : array.length]; for (int index = 0; index < length; index++) { oarray[index] = Double.valueOf(array[index]); @@ -91,7 +91,7 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen public ArrayData convert(final Class type) { if (type != Double.class && type != Integer.class && type != Long.class) { final int len = (int)length; - return new ObjectArrayData(NumberArrayData.toObjectArray(array, len), len); + return new ObjectArrayData(toObjectArray(false), len); } return this; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java index 8fd1a453077..001ea61c7c8 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java @@ -155,7 +155,8 @@ final class ObjectArrayData extends ContinuousArrayData { @Override public ArrayData setEmpty(final long lo, final long hi) { - Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi, Integer.MAX_VALUE), ScriptRuntime.EMPTY); + // hi parameter is inclusive, but Arrays.fill toIndex parameter is exclusive + Arrays.fill(array, (int)Math.max(lo, 0L), (int)Math.min(hi + 1, Integer.MAX_VALUE), ScriptRuntime.EMPTY); return this; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java index d28b731c44c..ef47345173f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java @@ -78,7 +78,7 @@ class SparseArrayData extends ArrayData { for (final Map.Entry entry : sparseMap.entrySet()) { final long key = entry.getKey(); - if (key <= Integer.MAX_VALUE) { + if (key < Integer.MAX_VALUE) { objArray[(int)key] = entry.getValue(); } else { break; // ascending key order diff --git a/nashorn/test/script/basic/JDK-8060011.js b/nashorn/test/script/basic/JDK-8060011.js new file mode 100644 index 00000000000..7514ff290b6 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8060011.js @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8060011: Concatenating an array and converting it to Java gives wrong result + * + * @test + * @run + */ + + +function compareAsJavaArrays(a1, a2) { + var ja1 = Java.to(a1); + var ja2 = Java.to(a2); + if (ja1.length !== ja2.length) { + throw "different length"; + } + for (var i = 0; i < ja1.length; i++) { + if (ja1[i] !== ja2[i]) { + throw "different element at " + i; + } + } + if (java.util.Arrays.toString(ja1) !== java.util.Arrays.toString(ja2)) { + throw "different string representation"; + } +} + +compareAsJavaArrays([0, 1, 2, 3], + [0].concat([1, 2, 3])); +compareAsJavaArrays([1000000000, 2000000000, 3000000000, 4000000000], + [1000000000].concat([2000000000, 3000000000, 4000000000])); +compareAsJavaArrays([0.5, 1.5, 2.5, 3.5], + [0.5].concat([1.5, 2.5, 3.5])); +compareAsJavaArrays(["0", "1", "2", "3"], + ["0"].concat(["1", "2", "3"])); + + + From 2d6eed916f15524814cd0db806ce35a36654b543 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Mon, 13 Oct 2014 23:38:49 +0530 Subject: [PATCH 68/91] 8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn Reviewed-by: attila, lagergren, hannesw --- .../api/scripting/NashornScriptEngine.java | 28 +----- .../nashorn/api/scripting/ScriptUtils.java | 20 ++-- .../internal/codegen/MethodEmitter.java | 10 +- .../nashorn/internal/objects/NativeJava.java | 6 +- .../linker/JavaAdapterBytecodeGenerator.java | 33 ++++++- .../linker/JavaAdapterClassLoader.java | 3 +- .../runtime/linker/JavaAdapterServices.java | 3 +- .../runtime/linker/NashornBeansLinker.java | 91 ++++++++++++++++--- .../runtime/linker/NashornLinker.java | 2 +- .../runtime/resources/mozilla_compat.js | 4 +- nashorn/test/script/basic/convert.js | 2 +- nashorn/test/script/nosecurity/JDK-8044798.js | 2 + .../scripting/ScriptEngineSecurityTest.java | 36 -------- .../api/scripting/ScriptEngineTest.java | 35 +++++++ 14 files changed, 177 insertions(+), 98 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java index bbf1eecfb49..2f000954815 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngine.java @@ -229,6 +229,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } private T getInterfaceInner(final Object thiz, final Class clazz) { + assert !(thiz instanceof ScriptObject) : "raw ScriptObject not expected here"; + if (clazz == null || !clazz.isInterface()) { throw new IllegalArgumentException(getMessage("interface.class.expected")); } @@ -251,17 +253,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C final ScriptObjectMirror mirror = (ScriptObjectMirror)thiz; realSelf = mirror.getScriptObject(); realGlobal = mirror.getHomeGlobal(); - if (! isOfContext(realGlobal, nashornContext)) { - throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); - } - } else if (thiz instanceof ScriptObject) { - // called from script code. - realSelf = (ScriptObject)thiz; - realGlobal = Context.getGlobal(); - if (realGlobal == null) { - throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); - } - if (! isOfContext(realGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } @@ -368,6 +359,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException { name.getClass(); // null check + assert !(selfObject instanceof ScriptObject) : "raw ScriptObject not expected here"; Global invokeGlobal = null; ScriptObjectMirror selfMirror = null; @@ -377,20 +369,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } invokeGlobal = selfMirror.getHomeGlobal(); - } else if (selfObject instanceof ScriptObject) { - // invokeMethod called from script code - in which case we may get 'naked' ScriptObject - // Wrap it with oldGlobal to make a ScriptObjectMirror for the same. - final Global oldGlobal = Context.getGlobal(); - invokeGlobal = oldGlobal; - if (oldGlobal == null) { - throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); - } - - if (! isOfContext(oldGlobal, nashornContext)) { - throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); - } - - selfMirror = (ScriptObjectMirror)ScriptObjectMirror.wrap(selfObject, oldGlobal); } else if (selfObject == null) { // selfObject is null => global function call final Global ctxtGlobal = getNashornGlobalFrom(context); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java index 4de2cbf5516..b6c4c97e547 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java @@ -75,11 +75,8 @@ public final class ScriptUtils { * @param sync the object to synchronize on * @return a synchronizing wrapper function */ - public static Object makeSynchronizedFunction(final Object func, final Object sync) { - if (func instanceof ScriptFunction) { - return ((ScriptFunction)func).makeSynchronizedFunction(sync); - } - throw typeError("not.a.function", ScriptRuntime.safeToString(func)); + public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { + return func.makeSynchronizedFunction(unwrap(sync)); } /** @@ -88,12 +85,8 @@ public final class ScriptUtils { * @param obj object to be wrapped * @return wrapped object */ - public static Object wrap(final Object obj) { - if (obj instanceof ScriptObject) { - return ScriptObjectMirror.wrap(obj, Context.getGlobal()); - } - - return obj; + public static ScriptObjectMirror wrap(final ScriptObject obj) { + return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal()); } /** @@ -160,14 +153,15 @@ public final class ScriptUtils { } final LinkerServices linker = Bootstrap.getLinkerServices(); - final MethodHandle converter = linker.getTypeConverter(obj.getClass(), clazz); + final Object objToConvert = unwrap(obj); + final MethodHandle converter = linker.getTypeConverter(objToConvert.getClass(), clazz); if (converter == null) { // no supported conversion! throw new UnsupportedOperationException("conversion not supported"); } try { - return converter.invoke(obj); + return converter.invoke(objToConvert); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java index 20914472ce6..2df1ae90b88 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java @@ -98,6 +98,7 @@ import jdk.nashorn.internal.ir.LocalVariableConversion; import jdk.nashorn.internal.ir.RuntimeNode; import jdk.nashorn.internal.ir.Symbol; import jdk.nashorn.internal.ir.TryNode; +import jdk.nashorn.internal.objects.NativeArray; import jdk.nashorn.internal.runtime.ArgumentSetter; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.Debug; @@ -2125,7 +2126,14 @@ public class MethodEmitter implements Emitter { int pos = 0; for (int i = argCount - 1; i >= 0; i--) { - paramTypes[i] = stack.peek(pos++); + Type pt = stack.peek(pos++); + // "erase" specific ScriptObject subtype info - except for NativeArray. + // NativeArray is used for array/List/Deque conversion for Java calls. + if (ScriptObject.class.isAssignableFrom(pt.getTypeClass()) && + !NativeArray.class.isAssignableFrom(pt.getTypeClass())) { + pt = Type.SCRIPT_OBJECT; + } + paramTypes[i] = pt; } final String descriptor = Type.getMethodDescriptor(returnType, paramTypes); for (int i = 0; i < argCount; i++) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java index 4395e081e70..7c6e60a967d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java @@ -90,7 +90,11 @@ public final class NativeJava { */ @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR) public static Object synchronizedFunc(final Object self, final Object func, final Object obj) { - return ScriptUtils.makeSynchronizedFunction(func, obj); + if (func instanceof ScriptFunction) { + return ((ScriptFunction)func).makeSynchronizedFunction(obj); + } + + throw typeError("not.a.function", ScriptRuntime.safeToString(func)); } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java index 44ea184656d..7986b8b4c7c 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java @@ -152,6 +152,7 @@ final class JavaAdapterBytecodeGenerator { static final String SET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE, OBJECT_TYPE); static final String VOID_NOARG_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.VOID_TYPE); + private static final Type SCRIPT_OBJECT_TYPE = Type.getType(ScriptObject.class); private static final Type SCRIPT_FUNCTION_TYPE = Type.getType(ScriptFunction.class); private static final Type STRING_TYPE = Type.getType(String.class); private static final Type METHOD_TYPE_TYPE = Type.getType(MethodType.class); @@ -536,8 +537,8 @@ final class JavaAdapterBytecodeGenerator { final int argLen = originalArgTypes.length; final Type[] newArgTypes = new Type[argLen + 1]; - // Insert ScriptFunction|Object as the last argument to the constructor - final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : OBJECT_TYPE; + // Insert ScriptFunction|ScriptObject as the last argument to the constructor + final Type extraArgumentType = fromFunction ? SCRIPT_FUNCTION_TYPE : SCRIPT_OBJECT_TYPE; newArgTypes[argLen] = extraArgumentType; System.arraycopy(originalArgTypes, 0, newArgTypes, 0, argLen); @@ -588,6 +589,34 @@ final class JavaAdapterBytecodeGenerator { // Initialize converters generateConverterInit(mv, fromFunction); endInitMethod(mv); + + if (! fromFunction) { + newArgTypes[argLen] = OBJECT_TYPE; + final InstructionAdapter mv2 = new InstructionAdapter(cw.visitMethod(ACC_PUBLIC, INIT, + Type.getMethodDescriptor(originalCtorType.getReturnType(), newArgTypes), null, null)); + generateOverridingConstructorWithObjectParam(mv2, ctor, originalCtorType.getDescriptor()); + } + } + + // Object additional param accepting constructor - generated to handle null and undefined value + // for script adapters. This is effectively to throw TypeError on such script adapters. See + // JavaAdapterServices.getHandle as well. + private void generateOverridingConstructorWithObjectParam(final InstructionAdapter mv, final Constructor ctor, final String ctorDescriptor) { + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + final Class[] argTypes = ctor.getParameterTypes(); + int offset = 1; // First arg is at position 1, after this. + for (int i = 0; i < argTypes.length; ++i) { + final Type argType = Type.getType(argTypes[i]); + mv.load(offset, argType); + offset += argType.getSize(); + } + mv.invokespecial(superClassName, INIT, ctorDescriptor, false); + mv.visitVarInsn(ALOAD, offset); + mv.visitInsn(ACONST_NULL); + mv.visitInsn(ACONST_NULL); + mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false); + endInitMethod(mv); } private static void endInitMethod(final InstructionAdapter mv) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java index f5ba8b12c6d..77004978eb7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java @@ -39,6 +39,7 @@ import jdk.nashorn.internal.codegen.DumpBytecode; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptFunction; +import jdk.nashorn.internal.runtime.ScriptObject; /** * This class encapsulates the bytecode of the adapter class and can be used to load it into the JVM as an actual Class. @@ -51,7 +52,7 @@ final class JavaAdapterClassLoader { private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader"); private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT); private static final Collection VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>( - Arrays.asList(JavaAdapterServices.class.getName(), ScriptFunction.class.getName(), JSType.class.getName()))); + Arrays.asList(JavaAdapterServices.class.getName(), ScriptObject.class.getName(), ScriptFunction.class.getName(), JSType.class.getName()))); private final String className; private final byte[] classBytes; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java index ef91f35c097..08e4682181d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java @@ -47,7 +47,6 @@ import jdk.internal.org.objectweb.asm.ClassWriter; import jdk.internal.org.objectweb.asm.Opcodes; import jdk.internal.org.objectweb.asm.Type; import jdk.internal.org.objectweb.asm.commons.InstructionAdapter; -import jdk.nashorn.api.scripting.ScriptUtils; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; @@ -220,7 +219,7 @@ public final class JavaAdapterServices { * @return the filtered return value. */ public static Object exportReturnValue(final Object obj) { - return ScriptUtils.wrap(NashornBeansLinker.exportArgument(obj)); + return NashornBeansLinker.exportArgument(obj, true); } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java index f802e039607..25ba619b7ad 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java @@ -35,17 +35,28 @@ import jdk.internal.dynalink.linker.GuardingDynamicLinker; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.linker.LinkerServices; import jdk.internal.dynalink.support.Lookup; +import jdk.nashorn.api.scripting.ScriptUtils; +import jdk.nashorn.internal.objects.NativeArray; import jdk.nashorn.internal.runtime.ConsString; +import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.options.Options; /** * This linker delegates to a {@code BeansLinker} but passes it a special linker services object that has a modified * {@code asType} method that will ensure that we never pass internal engine objects that should not be externally - * observable (currently only ConsString) to Java APIs, but rather that we flatten it into a String. We can't just add + * observable (currently ConsString and ScriptObject) to Java APIs, but rather that we flatten it into a String. We can't just add * this functionality as custom converters via {@code GuaardingTypeConverterFactory}, since they are not consulted when * the target method handle parameter signature is {@code Object}. */ public class NashornBeansLinker implements GuardingDynamicLinker { + // System property to control whether to wrap ScriptObject->ScriptObjectMirror for + // Object type arguments of Java method calls, field set and array set. + private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true); + private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class); + private static final MethodHandle EXPORT_NATIVE_ARRAY = new Lookup(MethodHandles.lookup()).findOwnStatic("exportNativeArray", Object.class, NativeArray.class); + private static final MethodHandle EXPORT_SCRIPT_OBJECT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportScriptObject", Object.class, ScriptObject.class); + private static final MethodHandle IMPORT_RESULT = new Lookup(MethodHandles.lookup()).findOwnStatic("importResult", Object.class, Object.class); private final BeansLinker beansLinker = new BeansLinker(); @@ -67,8 +78,39 @@ public class NashornBeansLinker implements GuardingDynamicLinker { return delegateLinker.getGuardedInvocation(linkRequest, new NashornBeansLinkerServices(linkerServices)); } - static Object exportArgument(final Object arg) { - return arg instanceof ConsString ? arg.toString() : arg; + @SuppressWarnings("unused") + private static Object exportArgument(final Object arg) { + return exportArgument(arg, MIRROR_ALWAYS); + } + + @SuppressWarnings("unused") + private static Object exportNativeArray(final NativeArray arg) { + return exportArgument(arg, MIRROR_ALWAYS); + } + + @SuppressWarnings("unused") + private static Object exportScriptObject(final ScriptObject arg) { + return exportArgument(arg, MIRROR_ALWAYS); + } + + @SuppressWarnings("unused") + private static Object exportScriptArray(final NativeArray arg) { + return exportArgument(arg, MIRROR_ALWAYS); + } + + static Object exportArgument(final Object arg, final boolean mirrorAlways) { + if (arg instanceof ConsString) { + return arg.toString(); + } else if (mirrorAlways && arg instanceof ScriptObject) { + return ScriptUtils.wrap((ScriptObject)arg); + } else { + return arg; + } + } + + @SuppressWarnings("unused") + private static Object importResult(final Object arg) { + return ScriptUtils.unwrap(arg); } private static class NashornBeansLinkerServices implements LinkerServices { @@ -80,23 +122,50 @@ public class NashornBeansLinker implements GuardingDynamicLinker { @Override public MethodHandle asType(final MethodHandle handle, final MethodType fromType) { - final MethodHandle typed = linkerServices.asType(handle, fromType); - final MethodType handleType = handle.type(); final int paramCount = handleType.parameterCount(); assert fromType.parameterCount() == handleType.parameterCount(); + MethodType newFromType = fromType; MethodHandle[] filters = null; for(int i = 0; i < paramCount; ++i) { - if(shouldConvert(handleType.parameterType(i), fromType.parameterType(i))) { - if(filters == null) { + final MethodHandle filter = argConversionFilter(handleType.parameterType(i), fromType.parameterType(i)); + if (filter != null) { + if (filters == null) { filters = new MethodHandle[paramCount]; } - filters[i] = EXPORT_ARGUMENT; + // "erase" specific type with Object type or else we'll get filter mismatch + newFromType = newFromType.changeParameterType(i, Object.class); + filters[i] = filter; } } - return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed; + final MethodHandle typed = linkerServices.asType(handle, newFromType); + MethodHandle result = filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed; + // Filter Object typed return value for possible ScriptObjectMirror. We convert + // ScriptObjectMirror as ScriptObject (if it is mirror from current global). + if (MIRROR_ALWAYS && areBothObjects(handleType.returnType(), fromType.returnType())) { + result = MethodHandles.filterReturnValue(result, IMPORT_RESULT); + } + + return result; + } + + private static MethodHandle argConversionFilter(final Class handleType, final Class fromType) { + if (handleType == Object.class) { + if (fromType == Object.class) { + return EXPORT_ARGUMENT; + } else if (fromType == NativeArray.class) { + return EXPORT_NATIVE_ARRAY; + } else if (fromType == ScriptObject.class) { + return EXPORT_SCRIPT_OBJECT; + } + } + return null; + } + + private static boolean areBothObjects(final Class handleType, final Class fromType) { + return handleType == Object.class && fromType == Object.class; } @Override @@ -104,10 +173,6 @@ public class NashornBeansLinker implements GuardingDynamicLinker { return Implementation.asTypeLosslessReturn(this, handle, fromType); } - private static boolean shouldConvert(final Class handleType, final Class fromType) { - return handleType == Object.class && fromType == Object.class; - } - @Override public MethodHandle getTypeConverter(final Class sourceType, final Class targetType) { return linkerServices.getTypeConverter(sourceType, targetType); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java index bde01567aa1..75af367f08d 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornLinker.java @@ -292,7 +292,7 @@ final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTyp @SuppressWarnings("unused") private static Object createMirror(final Object obj) { - return ScriptUtils.wrap(obj); + return obj instanceof ScriptObject? ScriptUtils.wrap((ScriptObject)obj) : obj; } private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js index 85e2161c004..6c27e2a6fbc 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/resources/mozilla_compat.js @@ -105,7 +105,7 @@ Object.defineProperty(this, "sync", { if (arguments.length < 1 || arguments.length > 2 ) { throw "sync(function [,object]) parameter count mismatch"; } - return Packages.jdk.nashorn.api.scripting.ScriptUtils.makeSynchronizedFunction(func, syncobj); + return Java.synchronized(func, syncobj); } }); @@ -160,7 +160,7 @@ Object.defineProperty(Object.prototype, "toSource", { configurable: true, enumerable: false, writable: true, value: function(state) { if (! state) { - state = java.util.Collections.newSetFromMap(new java.util.IdentityHashMap()); + state = java.util.Collections.newSetFromMap(new java.util.HashMap()); } if (state.contains(this)) { return "{}"; diff --git a/nashorn/test/script/basic/convert.js b/nashorn/test/script/basic/convert.js index 3a1bca08771..2c87661c74a 100644 --- a/nashorn/test/script/basic/convert.js +++ b/nashorn/test/script/basic/convert.js @@ -42,7 +42,7 @@ print(list); // object to Map obj = { foo: 333, bar: 'hello'}; -var map = ScriptUtils.convert(obj, java.util.Map.class); +var map = ScriptUtils.wrap(obj); print(map instanceof java.util.Map); for (m in map) { print(m + " " + map[m]); diff --git a/nashorn/test/script/nosecurity/JDK-8044798.js b/nashorn/test/script/nosecurity/JDK-8044798.js index c3b6d4cb945..c24edf2181b 100644 --- a/nashorn/test/script/nosecurity/JDK-8044798.js +++ b/nashorn/test/script/nosecurity/JDK-8044798.js @@ -25,6 +25,8 @@ * JDK-8044798: API for debugging Nashorn * * @test + * @option -Dnashorn.mirror.always=false + * @fork * @run */ diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java index 09199a52703..226832e7d82 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java @@ -168,42 +168,6 @@ public class ScriptEngineSecurityTest { } } - @Test - /** - * Check that script can't implement sensitive package interfaces. - */ - public void checkSensitiveInterfaceImplTest() throws ScriptException { - if (System.getSecurityManager() == null) { - // pass vacuously - return; - } - - final ScriptEngineManager m = new ScriptEngineManager(); - final ScriptEngine e = m.getEngineByName("nashorn"); - final Object[] holder = new Object[1]; - e.put("holder", holder); - // put an empty script object into array - e.eval("holder[0] = {}"); - // holder[0] is an object of some subclass of ScriptObject - final Class ScriptObjectClass = holder[0].getClass().getSuperclass(); - final Class PropertyAccessClass = ScriptObjectClass.getInterfaces()[0]; - // implementation methods for PropertyAccess class - e.eval("function set() {}; function get() {}; function getInt(){} " + - "function getDouble(){}; function getLong() {}; " + - "this.delete = function () {}; function has() {}; " + - "function hasOwnProperty() {}"); - - // get implementation of a restricted package interface - try { - log(Objects.toString(((Invocable)e).getInterface((Class)PropertyAccessClass))); - fail("should have thrown SecurityException"); - } catch (final Exception exp) { - if (! (exp instanceof SecurityException)) { - fail("SecurityException expected, got " + exp); - } - } - } - // @bug 8032948: Nashorn linkages awry public static class FakeProxy extends Proxy { public FakeProxy(final InvocationHandler ih) { diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java index 291e8d424c4..124b5a92a80 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java @@ -38,6 +38,7 @@ import java.lang.reflect.Proxy; import java.util.concurrent.Callable; import javax.script.Compilable; import javax.script.CompiledScript; +import javax.script.Invocable; import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; @@ -629,6 +630,40 @@ public class ScriptEngineTest { assertEquals(enumerable, Boolean.FALSE); } + public static class Context { + private Object myobj; + + public void set(Object o) { + myobj = o; + } + + public Object get() { + return myobj; + } + } + + // @bug 8050977: Java8 Javascript Nashorn exception: + // no current Global instance for nashorn + @Test + public void currentGlobalMissingTest() throws Exception { + final ScriptEngineManager manager = new ScriptEngineManager(); + final ScriptEngine e = manager.getEngineByName("nashorn"); + + final Context ctx = new Context(); + e.put("ctx", ctx); + e.eval("var obj = { foo: function(str) { return str.toUpperCase() } }"); + e.eval("ctx.set(obj)"); + final Invocable inv = (Invocable)e; + assertEquals("HELLO", inv.invokeMethod(ctx.get(), "foo", "hello")); + // try object literal + e.eval("ctx.set({ bar: function(str) { return str.toLowerCase() } })"); + assertEquals("hello", inv.invokeMethod(ctx.get(), "bar", "HELLO")); + // try array literal + e.eval("var arr = [ 'hello', 'world' ]"); + e.eval("ctx.set(arr)"); + assertEquals("helloworld", inv.invokeMethod(ctx.get(), "join", "")); + } + private static void checkProperty(final ScriptEngine e, final String name) throws ScriptException { final String value = System.getProperty(name); From c03284412182d24d955ff53b1e54f8a33ef63e29 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Mon, 13 Oct 2014 20:10:14 +0200 Subject: [PATCH 69/91] 8059842: Creating symbols for declared functions shouldn't be a special case Reviewed-by: hannesw, lagergren --- .../internal/codegen/AssignSymbols.java | 34 ++++++++++++------- .../jdk/nashorn/internal/ir/VarNode.java | 8 +++++ 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java index fa2b8a198bd..f83dc9ccdd1 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/AssignSymbols.java @@ -511,16 +511,6 @@ final class AssignSymbols extends NodeVisitor implements Loggabl thisProperties.push(new HashSet()); - if (functionNode.isDeclared()) { - // Can't use lc.getCurrentBlock() as we can have an outermost function in our lexical context that - // is not a program - it is a function being compiled on-demand. - final Iterator blocks = lc.getBlocks(); - if (blocks.hasNext()) { - final IdentNode ident = functionNode.getIdent(); - defineSymbol(blocks.next(), ident.getName(), ident, IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0)); - } - } - // Every function has a body, even the ones skipped on reparse (they have an empty one). We're // asserting this as even for those, enterBlock() must be invoked to correctly process symbols that // are used in them. @@ -532,16 +522,36 @@ final class AssignSymbols extends NodeVisitor implements Loggabl @Override public boolean enterVarNode(final VarNode varNode) { start(varNode); + // Normally, a symbol assigned in a var statement is not live for its RHS. Since we also represent function + // declarations as VarNodes, they are exception to the rule, as they need to have the symbol visible to the + // body of the declared function for self-reference. + if (varNode.isFunctionDeclaration()) { + defineVarIdent(varNode); + } return true; } @Override public Node leaveVarNode(final VarNode varNode) { - final IdentNode ident = varNode.getName(); - defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0)); + if (!varNode.isFunctionDeclaration()) { + defineVarIdent(varNode); + } return super.leaveVarNode(varNode); } + private void defineVarIdent(final VarNode varNode) { + final IdentNode ident = varNode.getName(); + final int flags; + if (varNode.isAnonymousFunctionDeclaration()) { + flags = IS_INTERNAL; + } else if (lc.getCurrentFunction().isProgram()) { + flags = IS_SCOPE; + } else { + flags = 0; + } + defineSymbol(lc.getCurrentBlock(), ident.getName(), ident, varNode.getSymbolFlags() | flags); + } + private Symbol exceptionSymbol() { return newObjectInternal(EXCEPTION_PREFIX); } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java index f9aef826fe6..a8db410042e 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/VarNode.java @@ -272,4 +272,12 @@ public final class VarNode extends Statement implements Assignment { public boolean isFunctionDeclaration() { return init instanceof FunctionNode && ((FunctionNode)init).isDeclared(); } + + /** + * Returns true if this is an anonymous function declaration. + * @return true if this is an anonymous function declaration. + */ + public boolean isAnonymousFunctionDeclaration() { + return isFunctionDeclaration() && ((FunctionNode)init).isAnonymous(); + } } From a891de31140740b036bd75ac5a1c063d3456829a Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Tue, 14 Oct 2014 13:04:56 +0200 Subject: [PATCH 70/91] 8060238: Reports for optimistic test run overwrite those for pessimistic run Reviewed-by: hannesw, lagergren, sundar --- nashorn/make/build.xml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 27ae1b319fc..9e6f5b5558e 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -408,7 +408,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - @@ -431,7 +431,7 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { - @@ -457,9 +457,11 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { + + @@ -467,9 +469,11 @@ grant codeBase "file:/${basedir}/test/script/markdown.js" { + + From fab85d4210cd99e9901a8bbfac85c9a9bdfc32ae Mon Sep 17 00:00:00 2001 From: Andreas Gabrielsson Date: Tue, 14 Oct 2014 15:28:24 +0200 Subject: [PATCH 71/91] 8012518: Reengineer Parser.java to make it play well with the copy-on-write IR Remove the kludges introduced to make the parser work with the copy on write IR. Now everything is done bottom up, finshing node children completely before node parents. The repeated non-functional pattern 'node = node.setSomething(something);' is gone. Resulting code is much more readable, and extensible for future work. The parser is now also consistent with the rest of the stateless copy-on-write world in code generation. Reviewed-by: lagergren, attila, hannesw, shade --- nashorn/.hgignore | 2 + nashorn/bin/runopt.sh | 137 +++++ .../nashorn/api/scripting/ScriptUtils.java | 2 - .../jdk/nashorn/internal/ir/Block.java | 48 +- .../jdk/nashorn/internal/ir/ForNode.java | 61 +-- .../jdk/nashorn/internal/ir/FunctionNode.java | 77 +-- .../jdk/nashorn/internal/ir/LoopNode.java | 5 +- .../classes/jdk/nashorn/internal/ir/Node.java | 22 +- .../jdk/nashorn/internal/ir/WhileNode.java | 12 +- .../jdk/nashorn/internal/ir/WithNode.java | 14 +- .../jdk/nashorn/internal/objects/Global.java | 2 - .../nashorn/internal/objects/NativeError.java | 2 - .../nashorn/internal/objects/NativeJava.java | 2 - .../jdk/nashorn/internal/parser/Parser.java | 487 ++++++++++-------- .../internal/parser/ParserContext.java | 334 ++++++++++++ .../parser/ParserContextBaseNode.java | 109 ++++ .../parser/ParserContextBlockNode.java | 56 ++ .../parser/ParserContextBreakableNode.java | 40 ++ .../parser/ParserContextFunctionNode.java | 197 +++++++ .../parser/ParserContextLabelNode.java | 52 ++ .../parser/ParserContextLoopNode.java | 37 ++ .../internal/parser/ParserContextNode.java | 67 +++ .../parser/ParserContextSwitchNode.java | 36 ++ .../jdk/nashorn/internal/runtime/Context.java | 35 +- 24 files changed, 1466 insertions(+), 370 deletions(-) create mode 100644 nashorn/bin/runopt.sh create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBaseNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBlockNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBreakableNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLabelNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLoopNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextNode.java create mode 100644 nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java diff --git a/nashorn/.hgignore b/nashorn/.hgignore index 02ec40d7e8d..7ee241994a9 100644 --- a/nashorn/.hgignore +++ b/nashorn/.hgignore @@ -26,3 +26,5 @@ jcov2/* test/lib/testng.jar test/script/external/* .project +.externalToolBuilders/* +.settings/* diff --git a/nashorn/bin/runopt.sh b/nashorn/bin/runopt.sh new file mode 100644 index 00000000000..0a61491e624 --- /dev/null +++ b/nashorn/bin/runopt.sh @@ -0,0 +1,137 @@ +#!/bin/sh +# +# Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +########################################################################################### +# This is a helper script to evaluate nashorn with optimistic types +# it produces a flight recording for every run, and uses the best +# known flags for performance for the current configration +########################################################################################### + +# Flags to enable assertions, we need the system assertions too, since +# this script runs Nashorn in the BCP to override any nashorn.jar that might +# reside in your $JAVA_HOME/jre/lib/ext/nashorn.jar +# +ENABLE_ASSERTIONS_FLAGS="-ea -esa" + +# Flags to instrument lambdaform computation, caching, interpretation and compilation +# Default compile threshold for lambdaforms is 30 +# +#LAMBDAFORM_FLAGS="\ +# -Djava.lang.invoke.MethodHandle.COMPILE_THRESHOLD=3 \ +# -Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true \ +# -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true \ +# -Djava.lang.invoke.MethodHandle.TRACE_INTERPRETER=true" + +# Flags to run trusted tests from the Nashorn test suite +# +#TRUSTED_TEST_FLAGS="\ +#-Djava.security.manager \ +#-Djava.security.policy=../build/nashorn.policy -Dnashorn.debug" + +# Testing out new code optimizations using the generic hotspot "new code" parameter +# +#USE_NEW_CODE_FLAGS=-XX:+UnlockDiagnosticVMOptions -XX:+UseNewCode + +# +#-Dnashorn.typeInfo.disabled=false \ +# and for Nashorn options: +# --class-cache-size=0 --persistent-code-cache=false + +# Unique timestamped file name for JFR recordings. For JFR, we also have to +# crank up the stack cutoff depth to 1024, because of ridiculously long lambda form +# stack traces. +# +# It is also recommended that you go into $JAVA_HOME/jre/lib/jfr/default.jfc and +# set the "method-sampling-interval" Normal and Maximum sample time as low as you +# can go (10 ms on most platforms). The default is normally higher. The increased +# sampling overhead is usually negligible for Nashorn runs, but the data is better + +if [ -z $JFR_FILENAME ]; then + JFR_FILENAME="./nashorn_$(date|sed "s/ /_/g"|sed "s/:/_/g").jfr" + echo "Using default JFR filename: ${JFR_FILENAME}..." +fi + +# Flight recorder +# +# see above - already in place, copy the flags down here to disable +ENABLE_FLIGHT_RECORDER_FLAGS="\ + -XX:+UnlockCommercialFeatures \ + -XX:+FlightRecorder \ + -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=$JFR_FILENAME,stackdepth=1024" + +# Type specialization and math intrinsic replacement should be enabled by default in 8u20 and nine, +# keeping this flag around for experimental reasons. Replace + with - to switch it off +# +#ENABLE_TYPE_SPECIALIZATION_FLAGS=-XX:+UseTypeSpeculation + +# Same with math intrinsics. They should be enabled by default in 8u20 and 9, so +# this disables them if needed +# +#DISABLE_MATH_INTRINSICS_FLAGS=-XX:-UseMathExactIntrinsics + +# Add timing to time the compilation phases. +#ENABLE_TIME_FLAGS=--log=time + +# Add ShowHiddenFrames to get lambda form internals on the stack traces +#ENABLE_SHOW_HIDDEN_FRAMES_FLAGS=-XX:+ShowHiddenFrames + +# Add print optoassembly to get an asm dump. This requires 1) a debug build, not product, +# That tired compilation is switched off, for C2 only output and that the number of +# compiler threads is set to 1 for determinsm. +# +#PRINT_ASM_FLAGS=-XX:+PrintOptoAssembly -XX:-TieredCompilation -XX:CICompilerCount=1 \ + +# Tier compile threasholds. Default value is 10. (1-100 is useful for experiments) +#TIER_COMPILATION_THRESHOLD_FLAGS=-XX:IncreaseFirstTierCompileThresholdAt=10 + +# Directory where to look for nashorn.jar in a dist folder. The default is "..", assuming +# that we run the script from the make dir +DIR=.. +NASHORN_JAR=$DIR/dist/nashorn.jar + + +# The built Nashorn jar is placed first in the bootclasspath to override the JDK +# nashorn.jar in $JAVA_HOME/jre/lib/ext. Thus, we also need -esa, as assertions in +# nashorn count as system assertions in this configuration + +# Type profiling default level is 111, 222 adds some compile time, but is faster + +$JAVA_HOME/bin/java \ +$ENABLE_ASSERTIONS_FLAGS \ +$LAMBDAFORM_FLAGS \ +$TRUSTED_FLAGS \ +$USE_NEW_CODE_FLAGS \ +$ENABLE_SHOW_HIDDEN_FRAMES_FLAGS \ +$ENABLE_FLIGHT_RECORDER_FLAGS \ +$ENABLE_TYPE_SPECIALIZATION_FLAGS \ +$TIERED_COMPILATION_THRESOLD_FLAGS \ +$DISABLE_MATH_INTRINSICS_FLAGS \ +$PRINT_ASM_FLAGS \ +-Xbootclasspath/p:$NASHORN_JAR \ +-Xms2G -Xmx2G \ +-XX:TypeProfileLevel=222 \ +-cp $CLASSPATH:../build/test/classes/ \ +jdk.nashorn.tools.Shell $ENABLE_TIME_FLAGS ${@} + + diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java index b6c4c97e547..e6e3915ab29 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java @@ -25,8 +25,6 @@ package jdk.nashorn.api.scripting; -import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; - import java.lang.invoke.MethodHandle; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.linker.LinkerServices; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java index 86a84ca6de8..e3a26893cb5 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Block.java @@ -80,11 +80,12 @@ public class Block extends Node implements BreakableNode, Terminal, Flags /** * Constructor * - * @param token token - * @param finish finish - * @param statements statements + * @param token The first token of the block + * @param finish The index of the last character + * @param flags The flags of the block + * @param statements All statements in the block */ - public Block(final long token, final int finish, final Statement... statements) { + public Block(final long token, final int finish, final int flags, final Statement... statements) { super(token, finish); this.statements = Arrays.asList(statements); @@ -92,29 +93,52 @@ public class Block extends Node implements BreakableNode, Terminal, Flags this.entryLabel = new Label("block_entry"); this.breakLabel = new Label("block_break"); final int len = statements.length; - this.flags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0; + final int terminalFlags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0; + this.flags = terminalFlags | flags; this.conversion = null; } + /** + * Constructs a new block + * + * @param token The first token of the block + * @param finish The index of the last character + * @param statements All statements in the block + */ + public Block(final long token, final int finish, final Statement...statements){ + this(token, finish, 0, statements); + } + + /** + * Constructs a new block + * + * @param token The first token of the block + * @param finish The index of the last character + * @param statements All statements in the block + */ + public Block(final long token, final int finish, final List statements){ + this(token, finish, 0, statements); + } + /** * Constructor * - * @param token token - * @param finish finish - * @param statements statements + * @param token The first token of the block + * @param finish The index of the last character + * @param flags The flags of the block + * @param statements All statements in the block */ - public Block(final long token, final int finish, final List statements) { - this(token, finish, statements.toArray(new Statement[statements.size()])); + public Block(final long token, final int finish, final int flags, final List statements) { + this(token, finish, flags, statements.toArray(new Statement[statements.size()])); } private Block(final Block block, final int finish, final List statements, final int flags, final Map symbols, final LocalVariableConversion conversion) { - super(block); + super(block, finish); this.statements = statements; this.flags = flags; this.symbols = new LinkedHashMap<>(symbols); //todo - symbols have no dependencies on any IR node and can as far as we understand it be shallow copied now this.entryLabel = new Label(block.entryLabel); this.breakLabel = new Label(block.breakLabel); - this.finish = finish; this.conversion = conversion; } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java index 9b4cb6d6e1c..bc864eb68bb 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ForNode.java @@ -54,20 +54,37 @@ public final class ForNode extends LoopNode { private final int flags; + /** + * Constructs a ForNode + * + * @param lineNumber The line number of header + * @param token The for token + * @param finish The last character of the for node + * @param body The body of the for node + * @param flags The flags + */ + public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags){ + this(lineNumber, token, finish, body, flags, null, null, null); + } + /** * Constructor * - * @param lineNumber line number - * @param token token - * @param finish finish - * @param body body - * @param flags flags + * @param lineNumber The line number of header + * @param token The for token + * @param finish The last character of the for node + * @param body The body of the for node + * @param flags The flags + * @param init The initial expression + * @param test The test expression + * @param modify The modify expression */ - public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags) { - super(lineNumber, token, finish, body, false); + public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags, final Expression init, final JoinPredecessorExpression test, final JoinPredecessorExpression modify) { + super(lineNumber, token, finish, body, test, false); this.flags = flags; - this.init = null; - this.modify = null; + this.init = init; + this.modify = modify; + } private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test, @@ -166,16 +183,6 @@ public final class ForNode extends LoopNode { public boolean isForIn() { return (flags & IS_FOR_IN) != 0; } - - /** - * Flag this to be a for in construct - * @param lc lexical context - * @return new for node if changed or existing if not - */ - public ForNode setIsForIn(final LexicalContext lc) { - return setFlags(lc, flags | IS_FOR_IN); - } - /** * Is this a for each construct, known from e.g. Rhino. This will be a for of construct * in ECMAScript 6 @@ -185,15 +192,6 @@ public final class ForNode extends LoopNode { return (flags & IS_FOR_EACH) != 0; } - /** - * Flag this to be a for each construct - * @param lc lexical context - * @return new for node if changed or existing if not - */ - public ForNode setIsForEach(final LexicalContext lc) { - return setFlags(lc, flags | IS_FOR_EACH); - } - /** * If this is a for in or for each construct, there is an iterator symbol * @return the symbol for the iterator to be used, or null if none exists @@ -260,13 +258,6 @@ public final class ForNode extends LoopNode { return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); } - private ForNode setFlags(final LexicalContext lc, final int flags) { - if (this.flags == flags) { - return this; - } - return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); - } - @Override JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) { return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion)); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java index 1bbc7ab0834..ad19f8d53a8 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java @@ -31,7 +31,6 @@ import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALL import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES; - import java.util.Collections; import java.util.EnumSet; import java.util.Iterator; @@ -46,6 +45,7 @@ import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.annotations.Ignore; import jdk.nashorn.internal.ir.annotations.Immutable; import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.parser.Token; import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.Source; @@ -299,12 +299,16 @@ public final class FunctionNode extends LexicalContextExpression implements Flag * @param token token * @param finish finish * @param firstToken first token of the function node (including the function declaration) + * @param lastToken lastToken * @param namespace the namespace * @param ident the identifier * @param name the name of the function * @param parameters parameter list * @param kind kind of function as in {@link FunctionNode.Kind} * @param flags initial flags + * @param body body of the function + * @param state The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR} + * @param endParserState The parser state at the end of the parsing. */ public FunctionNode( final Source source, @@ -312,12 +316,16 @@ public final class FunctionNode extends LexicalContextExpression implements Flag final long token, final int finish, final long firstToken, + final long lastToken, final Namespace namespace, final IdentNode ident, final String name, final List parameters, final FunctionNode.Kind kind, - final int flags) { + final int flags, + final Block body, + final CompilationState state, + final Object endParserState) { super(token, finish); this.source = source; @@ -327,15 +335,15 @@ public final class FunctionNode extends LexicalContextExpression implements Flag this.kind = kind; this.parameters = parameters; this.firstToken = firstToken; - this.lastToken = token; + this.lastToken = lastToken; this.namespace = namespace; - this.compilationState = EnumSet.of(CompilationState.INITIALIZED); + this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state); this.flags = flags; this.compileUnit = null; - this.body = null; + this.body = body; this.thisProperties = 0; this.rootClass = null; - this.endParserState = null; + this.endParserState = endParserState; } private FunctionNode( @@ -439,7 +447,7 @@ public final class FunctionNode extends LexicalContextExpression implements Flag * @return the id */ public int getId() { - return position(); + return isProgram() ? -1: Token.descPosition(firstToken); } /** @@ -902,34 +910,6 @@ public final class FunctionNode extends LexicalContextExpression implements Flag return lastToken; } - /** - * Set the last token for this function's code - * @param lc lexical context - * @param lastToken the last token - * @return function node or a new one if state was changed - */ - public FunctionNode setLastToken(final LexicalContext lc, final long lastToken) { - if (this.lastToken == lastToken) { - return this; - } - return Node.replaceInLexicalContext( - lc, - this, - new FunctionNode( - this, - lastToken, - endParserState, - flags, - name, - returnType, - compileUnit, - compilationState, - body, - parameters, - thisProperties, - rootClass)); - } - /** * Returns the end parser state for this function. * @return the end parser state for this function. @@ -938,33 +918,6 @@ public final class FunctionNode extends LexicalContextExpression implements Flag return endParserState; } - /** - * Set the end parser state for this function. - * @param lc lexical context - * @param endParserState the parser state to set - * @return function node or a new one if state was changed - */ - public FunctionNode setEndParserState(final LexicalContext lc, final Object endParserState) { - if (this.endParserState == endParserState) { - return this; - } - return Node.replaceInLexicalContext( - lc, - this, - new FunctionNode( - this, - lastToken, - endParserState, - flags, - name, - returnType, - compileUnit, - compilationState, - body, - parameters, - thisProperties, rootClass)); - } - /** * Get the name of this function * @return the name diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java index 86ef3cdad49..bfc86a69a43 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/LoopNode.java @@ -53,14 +53,15 @@ public abstract class LoopNode extends BreakableStatement { * @param token token * @param finish finish * @param body loop body + * @param test test * @param controlFlowEscapes controlFlowEscapes */ - protected LoopNode(final int lineNumber, final long token, final int finish, final Block body, final boolean controlFlowEscapes) { + protected LoopNode(final int lineNumber, final long token, final int finish, final Block body, final JoinPredecessorExpression test, final boolean controlFlowEscapes) { super(lineNumber, token, finish, new Label("while_break")); this.continueLabel = new Label("while_continue"); - this.test = null; this.body = body; this.controlFlowEscapes = controlFlowEscapes; + this.test = test; } /** diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java index 37ec4b96a39..861f12a05ff 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/Node.java @@ -39,7 +39,7 @@ public abstract class Node implements Cloneable { protected final int start; /** End of source range. */ - protected int finish; + protected final int finish; /** Token descriptor. */ private final long token; @@ -80,6 +80,18 @@ public abstract class Node implements Cloneable { this.finish = node.finish; } + /** + * Copy constructor that overrides finish + * + * @param node source node + * @param finish Last character + */ + protected Node(final Node node, final int finish) { + this.token = node.token; + this.start = node.start; + this.finish = finish; + } + /** * Is this a loop node? * @@ -151,14 +163,6 @@ public abstract class Node implements Cloneable { return finish; } - /** - * Set finish position for this node in the source string - * @param finish finish - */ - public void setFinish(final int finish) { - this.finish = finish; - } - /** * Get start position for node * @return start position diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java index 0cced567fbc..99bdce87c19 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WhileNode.java @@ -45,9 +45,11 @@ public final class WhileNode extends LoopNode { * @param token token * @param finish finish * @param isDoWhile is this a do while loop? + * @param test test expression + * @param body body of the while loop */ - public WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile) { - super(lineNumber, token, finish, null, false); + public WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile, final JoinPredecessorExpression test, final Block body) { + super(lineNumber, token, finish, body, test, false); this.isDoWhile = isDoWhile; } @@ -55,10 +57,10 @@ public final class WhileNode extends LoopNode { * Internal copy constructor * * @param whileNode while node - * @param test test - * @param body body + * @param test Test expression + * @param body body of the while loop * @param controlFlowEscapes control flow escapes? - * @param conversion TODO + * @param conversion local variable conversion info */ private WhileNode(final WhileNode whileNode, final JoinPredecessorExpression test, final Block body, final boolean controlFlowEscapes, final LocalVariableConversion conversion) { super(whileNode, test, body, controlFlowEscapes, conversion); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WithNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WithNode.java index 0ea52c98bb4..20e319294d2 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WithNode.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/WithNode.java @@ -42,14 +42,16 @@ public final class WithNode extends LexicalContextStatement { /** * Constructor * - * @param lineNumber line number - * @param token token - * @param finish finish + * @param lineNumber Line number of the header + * @param token First token + * @param finish Character index of the last token + * @param expression With expression + * @param body Body of with node */ - public WithNode(final int lineNumber, final long token, final int finish) { + public WithNode(final int lineNumber, final long token, final int finish, final Expression expression, final Block body) { super(lineNumber, token, finish); - this.expression = null; - this.body = null; + this.expression = expression; + this.body = body; } private WithNode(final WithNode node, final Expression expression, final Block body) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java index eb56de0e18f..61d7948f621 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java @@ -561,7 +561,6 @@ public final class Global extends ScriptObject implements Scope { * * @param engine ScriptEngine to initialize */ - @SuppressWarnings("hiding") public void initBuiltinObjects(final ScriptEngine engine) { if (this.builtinObject != null) { // already initialized, just return @@ -1718,7 +1717,6 @@ public final class Global extends ScriptObject implements Scope { return func; } - @SuppressWarnings("hiding") private void init(final ScriptEngine engine) { assert Context.getGlobal() == this : "this global is not set as current"; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java index e1d95ce097f..41ea9a5f4e2 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeError.java @@ -27,7 +27,6 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import jdk.nashorn.api.scripting.NashornException; @@ -131,7 +130,6 @@ public final class NativeError extends ScriptObject { // This is called NativeError, NativeTypeError etc. to // associate a ECMAException with the ECMA Error object. - @SuppressWarnings("unused") static void initException(final ScriptObject self) { // ECMAException constructor has side effects new ECMAException(self, null); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java index 7c6e60a967d..e9a4380dadc 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeJava.java @@ -27,7 +27,6 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; - import java.lang.invoke.MethodHandles; import java.lang.reflect.Array; import java.util.Collection; @@ -36,7 +35,6 @@ import java.util.List; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.support.TypeUtilities; import jdk.nashorn.api.scripting.JSObject; -import jdk.nashorn.api.scripting.ScriptUtils; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java index 3162e184468..32f1df63895 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java @@ -53,7 +53,6 @@ import static jdk.nashorn.internal.parser.TokenType.RPAREN; import static jdk.nashorn.internal.parser.TokenType.SEMICOLON; import static jdk.nashorn.internal.parser.TokenType.TERNARY; import static jdk.nashorn.internal.parser.TokenType.WHILE; - import java.io.Serializable; import java.util.ArrayDeque; import java.util.ArrayList; @@ -71,10 +70,8 @@ import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BaseNode; import jdk.nashorn.internal.ir.BinaryNode; import jdk.nashorn.internal.ir.Block; -import jdk.nashorn.internal.ir.BlockLexicalContext; import jdk.nashorn.internal.ir.BlockStatement; import jdk.nashorn.internal.ir.BreakNode; -import jdk.nashorn.internal.ir.BreakableNode; import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.CaseNode; import jdk.nashorn.internal.ir.CatchNode; @@ -90,9 +87,7 @@ import jdk.nashorn.internal.ir.IfNode; import jdk.nashorn.internal.ir.IndexNode; import jdk.nashorn.internal.ir.JoinPredecessorExpression; import jdk.nashorn.internal.ir.LabelNode; -import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LiteralNode; -import jdk.nashorn.internal.ir.LoopNode; import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.ObjectNode; import jdk.nashorn.internal.ir.PropertyKey; @@ -138,8 +133,8 @@ public class Parser extends AbstractParser implements Loggable { private List functionDeclarations; - private final BlockLexicalContext lc = new BlockLexicalContext(); - private final Deque defaultNames = new ArrayDeque<>(); + private final ParserContext lc; + private final Deque defaultNames; /** Namespace for function names where not explicitly given */ private final Namespace namespace; @@ -187,6 +182,8 @@ public class Parser extends AbstractParser implements Loggable { */ public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int lineOffset, final DebugLogger log) { super(source, errors, strict, lineOffset); + this.lc = new ParserContext(); + this.defaultNames = new ArrayDeque<>(); this.env = env; this.namespace = new Namespace(env.getNamespace()); this.scripting = env._scripting; @@ -344,26 +341,35 @@ public class Parser extends AbstractParser implements Loggable { final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength()); // Set up the function to append elements. - FunctionNode function = newFunctionNode( - functionToken, - new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName()), - new ArrayList(), - FunctionNode.Kind.NORMAL, - functionLine); + final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName()); + final ParserContextFunctionNode function = createParserContextFunctionNode(ident, functionToken, FunctionNode.Kind.NORMAL, functionLine, Collections.emptyList()); + lc.push(function); + + final ParserContextBlockNode body = newBlock(); functionDeclarations = new ArrayList<>(); sourceElements(false); addFunctionDeclarations(function); functionDeclarations = null; + restoreBlock(body); + body.setFlag(Block.NEEDS_SCOPE); + + final Block functionBody = new Block(functionToken, source.getLength() - 1, body.getFlags(), body.getStatements()); + lc.pop(function); + expect(EOF); - function.setFinish(source.getLength() - 1); - function = restoreFunctionNode(function, token); //commit code - function = function.setBody(lc, function.getBody().setNeedsScope(lc)); - - printAST(function); - return function; + final FunctionNode functionNode = createFunctionNode( + function, + functionToken, + ident, + Collections.emptyList(), + FunctionNode.Kind.NORMAL, + functionLine, + functionBody); + printAST(functionNode); + return functionNode; } catch (final Exception e) { handleParseException(e); return null; @@ -444,21 +450,15 @@ loop: * * @return New block. */ - private Block newBlock() { - return lc.push(new Block(token, Token.descPosition(token))); + private ParserContextBlockNode newBlock() { + return lc.push(new ParserContextBlockNode(token)); } - /** - * Set up a new function block. - * - * @param ident Name of function. - * @return New block. - */ - private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List parameters, final FunctionNode.Kind kind, final int functionLine) { + private ParserContextFunctionNode createParserContextFunctionNode(final IdentNode ident, final long functionToken, final FunctionNode.Kind kind, final int functionLine, final List parameters) { // Build function name. final StringBuilder sb = new StringBuilder(); - final FunctionNode parentFunction = lc.getCurrentFunction(); + final ParserContextFunctionNode parentFunction = lc.getCurrentFunction(); if (parentFunction != null && !parentFunction.isProgram()) { sb.append(parentFunction.getName()).append('$'); } @@ -477,25 +477,33 @@ loop: flags |= FunctionNode.IS_PROGRAM; } + final ParserContextFunctionNode functionNode = new ParserContextFunctionNode(functionToken, ident, name, namespace, functionLine, kind, parameters); + functionNode.setFlag(flags); + return functionNode; + } + + private FunctionNode createFunctionNode(final ParserContextFunctionNode function, final long startToken, final IdentNode ident, final List parameters, final FunctionNode.Kind kind, final int functionLine, final Block body){ + final CompilationState state = errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED; // Start new block. final FunctionNode functionNode = new FunctionNode( source, functionLine, - token, - Token.descPosition(token), + body.getToken(), + Token.descPosition(body.getToken()), startToken, + function.getLastToken(), namespace, ident, - name, + function.getName(), parameters, kind, - flags); + function.getFlags(), + body, + state, + function.getEndParserState()); - lc.push(functionNode); - // Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the - // FunctionNode. - newBlock(); + printAST(functionNode); return functionNode; } @@ -503,27 +511,17 @@ loop: /** * Restore the current block. */ - private Block restoreBlock(final Block block) { + private ParserContextBlockNode restoreBlock(final ParserContextBlockNode block) { return lc.pop(block); } - - private FunctionNode restoreFunctionNode(final FunctionNode functionNode, final long lastToken) { - final Block newBody = restoreBlock(lc.getFunctionBody(functionNode)); - - return lc.pop(functionNode). - setBody(lc, newBody). - setLastToken(lc, lastToken). - setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED); - } - /** * Get the statements in a block. * @return Block statements. */ private Block getBlock(final boolean needsBraces) { - // Set up new block. Captures LBRACE. - Block newBlock = newBlock(); + final long blockToken = token; + final ParserContextBlockNode newBlock = newBlock(); try { // Block opening brace. if (needsBraces) { @@ -533,21 +531,18 @@ loop: statementList(); } finally { - newBlock = restoreBlock(newBlock); + restoreBlock(newBlock); } - final int possibleEnd = Token.descPosition(token) + Token.descLength(token); - // Block closing brace. if (needsBraces) { expect(RBRACE); } - newBlock.setFinish(possibleEnd); - - return newBlock; + return new Block(blockToken, finish, newBlock.getFlags(), newBlock.getStatements()); } + /** * Get all the statements generated by a single statement. * @return Statements. @@ -557,13 +552,13 @@ loop: return getBlock(true); } // Set up new block. Captures first token. - Block newBlock = newBlock(); + final ParserContextBlockNode newBlock = newBlock(); try { statement(); } finally { - newBlock = restoreBlock(newBlock); + restoreBlock(newBlock); } - return newBlock; + return new Block(newBlock.getToken(), finish, newBlock.getFlags(), newBlock.getStatements()); } /** @@ -584,7 +579,7 @@ loop: */ private void detectSpecialProperty(final IdentNode ident) { if (isArguments(ident)) { - lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_ARGUMENTS); + lc.getCurrentFunction().setFlag(FunctionNode.USES_ARGUMENTS); } } @@ -698,18 +693,19 @@ loop: // Make a pseudo-token for the script holding its start and length. final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength()); final int functionLine = line; - // Set up the script to append elements. - - FunctionNode script = newFunctionNode( - functionToken, - new IdentNode(functionToken, Token.descPosition(functionToken), scriptName), - new ArrayList(), - FunctionNode.Kind.SCRIPT, - functionLine); + final IdentNode ident = new IdentNode(functionToken, Token.descPosition(functionToken), scriptName); + final ParserContextFunctionNode script = createParserContextFunctionNode( + ident, + functionToken, + FunctionNode.Kind.SCRIPT, + functionLine, + Collections.emptyList()); + lc.push(script); + final ParserContextBlockNode body = newBlock(); // If ES6 block scope is enabled add a per-script block for top-level LET and CONST declarations. final int startLine = start; - Block outer = useBlockScope() ? newBlock() : null; + final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null; functionDeclarations = new ArrayList<>(); try { @@ -717,20 +713,25 @@ loop: addFunctionDeclarations(script); } finally { if (outer != null) { - outer = restoreBlock(outer); - appendStatement(new BlockStatement(startLine, outer)); + restoreBlock(outer); + appendStatement(new BlockStatement( + startLine, + new Block( + functionToken, + startLine, outer.getFlags(), + outer.getStatements()))); } } functionDeclarations = null; + restoreBlock(body); + body.setFlag(Block.NEEDS_SCOPE); + final Block programBody = new Block(functionToken, functionLine, body.getFlags(), body.getStatements()); + lc.pop(script); + script.setLastToken(token); expect(EOF); - script.setFinish(source.getLength() - 1); - - script = restoreFunctionNode(script, token); //commit code - script = script.setBody(lc, script.getBody().setNeedsScope(lc)); - - return script; + return createFunctionNode(script, functionToken, ident, Collections.emptyList(), FunctionNode.Kind.SCRIPT, functionLine, programBody); } /** @@ -789,7 +790,7 @@ loop: // check for directive prologues if (checkDirective) { // skip any debug statement like line number to get actual first line - final Node lastStatement = lc.getLastStatement(); + final Statement lastStatement = lc.getLastStatement(); // get directive prologue, if any final String directive = getDirective(lastStatement); @@ -809,8 +810,8 @@ loop: // handle use strict directive if ("use strict".equals(directive)) { isStrictMode = true; - final FunctionNode function = lc.getCurrentFunction(); - lc.setFlag(lc.getCurrentFunction(), FunctionNode.IS_STRICT); + final ParserContextFunctionNode function = lc.getCurrentFunction(); + function.setFlag(FunctionNode.IS_STRICT); // We don't need to check these, if lexical environment is already strict if (!oldStrictMode && directiveStmts != null) { @@ -831,8 +832,8 @@ loop: } else if (Context.DEBUG) { final int flag = FunctionNode.getDirectiveFlag(directive); if (flag != 0) { - final FunctionNode function = lc.getCurrentFunction(); - lc.setFlag(function, flag); + final ParserContextFunctionNode function = lc.getCurrentFunction(); + function.setFlag(flag); } } } @@ -1114,11 +1115,7 @@ loop: // If is a statement then handle end of line. if (isStatement) { - final boolean semicolon = type == SEMICOLON; endOfLine(); - if (semicolon) { - lc.getCurrentBlock().setFinish(finish); - } } return vars; @@ -1166,11 +1163,6 @@ loop: } endOfLine(); - - if (expressionStatement != null) { - expressionStatement.setFinish(finish); - lc.getCurrentBlock().setFinish(finish); - } } /** @@ -1216,13 +1208,23 @@ loop: * Parse a FOR statement. */ private void forStatement() { + final long forToken = token; + final int forLine = line; // When ES6 for-let is enabled we create a container block to capture the LET. final int startLine = start; - Block outer = useBlockScope() ? newBlock() : null; + final ParserContextBlockNode outer = useBlockScope() ? newBlock() : null; + // Create FOR node, capturing FOR token. - ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR); + final ParserContextLoopNode forNode = new ParserContextLoopNode(); lc.push(forNode); + Block body = null; + List vars = null; + Expression init = null; + JoinPredecessorExpression test = null; + JoinPredecessorExpression modify = null; + + int flags = 0; try { // FOR tested in caller. @@ -1231,13 +1233,12 @@ loop: // Nashorn extension: for each expression. // iterate property values rather than property names. if (!env._no_syntax_extensions && type == IDENT && "each".equals(getValue())) { - forNode = forNode.setIsForEach(lc); + flags |= ForNode.IS_FOR_EACH; next(); } expect(LPAREN); - List vars = null; switch (type) { case VAR: @@ -1258,8 +1259,7 @@ loop: break; } - final Expression expression = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true); - forNode = forNode.setInit(lc, expression); + init = expression(unaryExpression(), COMMARIGHT.getPrecedence(), true); break; } @@ -1268,26 +1268,27 @@ loop: // for (init; test; modify) // for each (init; test; modify) is invalid - if (forNode.isForEach()) { + if ((flags & ForNode.IS_FOR_EACH) != 0) { throw error(AbstractParser.message("for.each.without.in"), token); } expect(SEMICOLON); if (type != SEMICOLON) { - forNode = forNode.setTest(lc, joinPredecessorExpression()); + test = joinPredecessorExpression(); } expect(SEMICOLON); if (type != RPAREN) { - forNode = forNode.setModify(lc, joinPredecessorExpression()); + modify = joinPredecessorExpression(); } break; case IN: - forNode = forNode.setIsForIn(lc).setTest(lc, new JoinPredecessorExpression()); + flags |= ForNode.IS_FOR_IN; + test = new JoinPredecessorExpression(); if (vars != null) { // for (var i in obj) if (vars.size() == 1) { - forNode = forNode.setInit(lc, new IdentNode(vars.get(0).getName())); + init = new IdentNode(vars.get(0).getName()); } else { // for (var i, j in obj) is invalid throw error(AbstractParser.message("many.vars.in.for.in.loop"), vars.get(1).getToken()); @@ -1295,7 +1296,6 @@ loop: } else { // for (expr in obj) - final Node init = forNode.getInit(); assert init != null : "for..in init expression can not be null here"; // check if initial expression is a valid L-value @@ -1316,7 +1316,7 @@ loop: next(); // Get the collection expression. - forNode = forNode.setModify(lc, joinPredecessorExpression()); + modify = joinPredecessorExpression(); break; default: @@ -1327,37 +1327,27 @@ loop: expect(RPAREN); // Set the for body. - final Block body = getStatement(); - forNode = forNode.setBody(lc, body); - forNode.setFinish(body.getFinish()); - - appendStatement(forNode); + body = getStatement(); } finally { lc.pop(forNode); + if (vars != null) { + for (final VarNode var : vars) { + appendStatement(var); + } + } + if (body != null) { + appendStatement(new ForNode(forLine, forToken, body.getFinish(), body, (forNode.getFlags() | flags), init, test, modify)); + } if (outer != null) { - outer.setFinish(forNode.getFinish()); - outer = restoreBlock(outer); - appendStatement(new BlockStatement(startLine, outer)); + restoreBlock(outer); + appendStatement(new BlockStatement(startLine, new Block( + outer.getToken(), + body.getFinish(), + outer.getStatements()))); } } } - /** - * ... IterationStatement : - * ... - * Expression[NoIn]?; Expression? ; Expression? - * var VariableDeclarationList[NoIn]; Expression? ; Expression? - * LeftHandSideExpression in Expression - * var VariableDeclaration[NoIn] in Expression - * - * See 12.6 - * - * Parse the control section of a FOR statement. Also used for - * comprehensions. - * @param forNode Owning FOR. - */ - - /** * ...IterationStatement : * ... @@ -1371,25 +1361,26 @@ loop: private void whileStatement() { // Capture WHILE token. final long whileToken = token; + final int whileLine = line; // WHILE tested in caller. next(); - // Construct WHILE node. - WhileNode whileNode = new WhileNode(line, whileToken, Token.descPosition(whileToken), false); + final ParserContextLoopNode whileNode = new ParserContextLoopNode(); lc.push(whileNode); + JoinPredecessorExpression test = null; + Block body = null; + try { expect(LPAREN); - final int whileLine = line; - final JoinPredecessorExpression test = joinPredecessorExpression(); + test = joinPredecessorExpression(); expect(RPAREN); - final Block body = getStatement(); - appendStatement(whileNode = - new WhileNode(whileLine, whileToken, finish, false). - setTest(lc, test). - setBody(lc, body)); + body = getStatement(); } finally { lc.pop(whileNode); + if (body != null){ + appendStatement(new WhileNode(whileLine, whileToken, body.getFinish(), false, test, body)); + } } } @@ -1406,34 +1397,32 @@ loop: private void doStatement() { // Capture DO token. final long doToken = token; + int doLine = 0; // DO tested in the caller. next(); - WhileNode doWhileNode = new WhileNode(-1, doToken, Token.descPosition(doToken), true); + final ParserContextLoopNode doWhileNode = new ParserContextLoopNode(); lc.push(doWhileNode); + Block body = null; + JoinPredecessorExpression test = null; + try { // Get DO body. - final Block body = getStatement(); + body = getStatement(); expect(WHILE); expect(LPAREN); - final int doLine = line; - final JoinPredecessorExpression test = joinPredecessorExpression(); + doLine = line; + test = joinPredecessorExpression(); expect(RPAREN); if (type == SEMICOLON) { endOfLine(); } - doWhileNode.setFinish(finish); - - //line number is last - appendStatement(doWhileNode = - new WhileNode(doLine, doToken, finish, true). - setBody(lc, body). - setTest(lc, test)); } finally { lc.pop(doWhileNode); + appendStatement(new WhileNode(doLine, doToken, finish, true, test, body)); } } @@ -1452,7 +1441,7 @@ loop: // CONTINUE tested in caller. nextOrEOL(); - LabelNode labelNode = null; + ParserContextLabelNode labelNode = null; // SEMICOLON or label. switch (type) { @@ -1474,7 +1463,7 @@ loop: } final String labelName = labelNode == null ? null : labelNode.getLabelName(); - final LoopNode targetNode = lc.getContinueTo(labelName); + final ParserContextLoopNode targetNode = lc.getContinueTo(labelName); if (targetNode == null) { throw error(AbstractParser.message("illegal.continue.stmt"), continueToken); @@ -1500,7 +1489,7 @@ loop: // BREAK tested in caller. nextOrEOL(); - LabelNode labelNode = null; + ParserContextLabelNode labelNode = null; // SEMICOLON or label. switch (type) { @@ -1524,7 +1513,7 @@ loop: //either an explicit label - then get its node or just a "break" - get first breakable //targetNode is what we are breaking out from. final String labelName = labelNode == null ? null : labelNode.getLabelName(); - final BreakableNode targetNode = lc.getBreakable(labelName); + final ParserContextBreakableNode targetNode = lc.getBreakable(labelName); if (targetNode == null) { throw error(AbstractParser.message("illegal.break.stmt"), breakToken); } @@ -1632,20 +1621,17 @@ loop: throw error(AbstractParser.message("strict.no.with"), withToken); } - // Get WITH expression. - WithNode withNode = new WithNode(withLine, withToken, finish); - + Expression expression = null; + Block body = null; try { - lc.push(withNode); expect(LPAREN); - withNode = withNode.setExpression(lc, expression()); + expression = expression(); expect(RPAREN); - withNode = withNode.setBody(lc, getStatement()); + body = getStatement(); } finally { - lc.pop(withNode); + appendStatement(new WithNode(withLine, withToken, finish, expression, body)); } - appendStatement(withNode); } /** @@ -1677,19 +1663,22 @@ loop: next(); // Create and add switch statement. - SwitchNode switchNode = new SwitchNode(switchLine, switchToken, Token.descPosition(switchToken), null, new ArrayList(), null); + final ParserContextSwitchNode switchNode= new ParserContextSwitchNode(); lc.push(switchNode); + CaseNode defaultCase = null; + // Prepare to accumulate cases. + final List cases = new ArrayList<>(); + + Expression expression = null; + try { expect(LPAREN); - switchNode = switchNode.setExpression(lc, expression()); + expression = expression(); expect(RPAREN); expect(LBRACE); - // Prepare to accumulate cases. - final List cases = new ArrayList<>(); - CaseNode defaultCase = null; while (type != RBRACE) { // Prepare for next case. @@ -1720,7 +1709,6 @@ loop: // Get CASE body. final Block statements = getBlock(false); final CaseNode caseNode = new CaseNode(caseToken, finish, caseExpression, statements); - statements.setFinish(finish); if (caseExpression == null) { defaultCase = caseNode; @@ -1729,13 +1717,10 @@ loop: cases.add(caseNode); } - switchNode = switchNode.setCases(lc, cases, defaultCase); next(); - switchNode.setFinish(finish); - - appendStatement(switchNode); } finally { lc.pop(switchNode); + appendStatement(new SwitchNode(switchLine, switchToken, finish, expression, cases, defaultCase)); } } @@ -1759,15 +1744,17 @@ loop: throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken); } - LabelNode labelNode = new LabelNode(line, labelToken, finish, ident.getName(), null); + final ParserContextLabelNode labelNode = new ParserContextLabelNode(ident.getName()); + Block body = null; try { lc.push(labelNode); - labelNode = labelNode.setBody(lc, getStatement()); - labelNode.setFinish(finish); - appendStatement(labelNode); + body = getStatement(); } finally { - assert lc.peek() instanceof LabelNode; + assert lc.peek() instanceof ParserContextLabelNode; lc.pop(labelNode); + if (ident != null){ + appendStatement(new LabelNode(line, labelToken, finish, ident.getName(), body)); + } } } @@ -1835,8 +1822,7 @@ loop: // Container block needed to act as target for labeled break statements final int startLine = line; - Block outer = newBlock(); - + final ParserContextBlockNode outer = newBlock(); // Create try. try { @@ -1867,15 +1853,15 @@ loop: expect(RPAREN); - Block catchBlock = newBlock(); + final ParserContextBlockNode catchBlock = newBlock(); try { // Get CATCH body. final Block catchBody = getBlock(true); final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false); appendStatement(catchNode); } finally { - catchBlock = restoreBlock(catchBlock); - catchBlocks.add(catchBlock); + restoreBlock(catchBlock); + catchBlocks.add(new Block(catchBlock.getToken(), finish, catchBlock.getFlags(), catchBlock.getStatements())); } // If unconditional catch then should to be the end. @@ -1897,19 +1883,15 @@ loop: throw error(AbstractParser.message("missing.catch.or.finally"), tryToken); } - final TryNode tryNode = new TryNode(tryLine, tryToken, Token.descPosition(tryToken), tryBody, catchBlocks, finallyStatements); + final TryNode tryNode = new TryNode(tryLine, tryToken, finish, tryBody, catchBlocks, finallyStatements); // Add try. assert lc.peek() == outer; appendStatement(tryNode); - - tryNode.setFinish(finish); - outer.setFinish(finish); - } finally { - outer = restoreBlock(outer); + restoreBlock(outer); } - appendStatement(new BlockStatement(startLine, outer)); + appendStatement(new BlockStatement(startLine, new Block(tryToken, finish, outer.getFlags(), outer.getStatements()))); } /** @@ -1927,7 +1909,7 @@ loop: // DEBUGGER tested in caller. next(); endOfLine(); - appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, new ArrayList()))); + appendStatement(new ExpressionStatement(debuggerLine, debuggerToken, finish, new RuntimeNode(debuggerToken, finish, RuntimeNode.Request.DEBUGGER, Collections.emptyList()))); } /** @@ -1954,7 +1936,7 @@ loop: case THIS: final String name = type.getName(); next(); - lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_THIS); + lc.getCurrentFunction().setFlag(FunctionNode.USES_THIS); return new IdentNode(primaryToken, finish, name); case IDENT: final IdentNode ident = getIdent(); @@ -2314,9 +2296,24 @@ loop: final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName)); expect(LPAREN); expect(RPAREN); - final FunctionNode functionNode = functionBody(getSetToken, getNameNode, new ArrayList(), FunctionNode.Kind.GETTER, functionLine); - return new PropertyFunction(getIdent, functionNode); + final ParserContextFunctionNode functionNode = createParserContextFunctionNode(getNameNode, getSetToken, FunctionNode.Kind.GETTER, functionLine, Collections.emptyList()); + lc.push(functionNode); + + final Block functionBody = functionBody(functionNode); + + lc.pop(functionNode); + + final FunctionNode function = createFunctionNode( + functionNode, + getSetToken, + getNameNode, + Collections.emptyList(), + FunctionNode.Kind.GETTER, + functionLine, + functionBody); + + return new PropertyFunction(getIdent, function); } private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) { @@ -2338,9 +2335,25 @@ loop: if (argIdent != null) { parameters.add(argIdent); } - final FunctionNode functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER, functionLine); - return new PropertyFunction(setIdent, functionNode); + + final ParserContextFunctionNode functionNode = createParserContextFunctionNode(setNameNode, getSetToken, FunctionNode.Kind.SETTER, functionLine, parameters); + lc.push(functionNode); + + final Block functionBody = functionBody(functionNode); + + lc.pop(functionNode); + + final FunctionNode function = createFunctionNode( + functionNode, + getSetToken, + setNameNode, + parameters, + FunctionNode.Kind.SETTER, + functionLine, + functionBody); + + return new PropertyFunction(setIdent, function); } private static class PropertyFunction { @@ -2655,11 +2668,18 @@ loop: final List parameters = formalParameterList(); expect(RPAREN); - FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine); + final ParserContextFunctionNode functionNode = createParserContextFunctionNode(name, functionToken, FunctionNode.Kind.NORMAL, functionLine, parameters); + lc.push(functionNode); + Block functionBody = null; + try{ + functionBody = functionBody(functionNode); + } finally { + lc.pop(functionNode); + } if (isStatement) { if (topLevel || useBlockScope()) { - functionNode = functionNode.setFlag(lc, FunctionNode.IS_DECLARED); + functionNode.setFlag(FunctionNode.IS_DECLARED); } else if (isStrictMode) { throw error(JSErrorType.SYNTAX_ERROR, AbstractParser.message("strict.no.func.decl.here"), functionToken); } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.ERROR) { @@ -2668,12 +2688,12 @@ loop: warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken); } if (isArguments(name)) { - lc.setFlag(lc.getCurrentFunction(), FunctionNode.DEFINES_ARGUMENTS); + lc.getCurrentFunction().setFlag(FunctionNode.DEFINES_ARGUMENTS); } } if (isAnonymous) { - functionNode = functionNode.setFlag(lc, FunctionNode.IS_ANONYMOUS); + functionNode.setFlag(FunctionNode.IS_ANONYMOUS); } final int arity = parameters.size(); @@ -2687,7 +2707,7 @@ loop: String parameterName = parameter.getName(); if (isArguments(parameterName)) { - functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS); + functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS); } if (parametersSet.contains(parameterName)) { @@ -2705,17 +2725,26 @@ loop: } } else if (arity == 1) { if (isArguments(parameters.get(0))) { - functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS); + functionNode.setFlag(FunctionNode.DEFINES_ARGUMENTS); } } + final FunctionNode function = createFunctionNode( + functionNode, + functionToken, + name, + parameters, + FunctionNode.Kind.NORMAL, + functionLine, + functionBody); + if (isStatement) { int varFlags = VarNode.IS_STATEMENT; if (!topLevel && useBlockScope()) { // mark ES6 block functions as lexically scoped varFlags |= VarNode.IS_LET; } - final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, functionNode, varFlags); + final VarNode varNode = new VarNode(functionLine, functionToken, finish, name, function, varFlags); if (topLevel) { functionDeclarations.add(varNode); } else if (useBlockScope()) { @@ -2725,7 +2754,7 @@ loop: } } - return functionNode; + return function; } private String getDefaultValidFunctionName(final int functionLine) { @@ -2832,15 +2861,19 @@ loop: * Parse function body. * @return function node (body.) */ - private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List parameters, final FunctionNode.Kind kind, final int functionLine) { - FunctionNode functionNode = null; + private Block functionBody(final ParserContextFunctionNode functionNode) { long lastToken = 0L; + ParserContextBlockNode body = null; + final long bodyToken = token; + Block functionBody; + int bodyFinish = 0; + final boolean parseBody; Object endParserState = null; try { // Create a new function block. - functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine); + body = newBlock(); assert functionNode != null; final int functionId = functionNode.getId(); parseBody = reparsedFunction == null || functionId <= reparsedFunction.getFunctionNodeId(); @@ -2856,6 +2889,7 @@ loop: // just expression as function body final Expression expr = assignmentExpression(true); lastToken = previousToken; + functionNode.setLastToken(previousToken); assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode); // EOL uses length field to store the line number final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken)); @@ -2868,7 +2902,6 @@ loop: final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr); appendStatement(returnNode); } - functionNode.setFinish(lastFinish); } else { expectDontAdvance(LBRACE); if (parseBody || !skipFunctionBody(functionNode)) { @@ -2902,25 +2935,25 @@ loop: // we'll rather just restart parsing from this well-known, friendly token instead. } } + bodyFinish = finish; + functionNode.setLastToken(token); expect(RBRACE); - functionNode.setFinish(finish); } } finally { - functionNode = restoreFunctionNode(functionNode, lastToken); + restoreBlock(body); } // NOTE: we can only do alterations to the function node after restoreFunctionNode. if (parseBody) { - functionNode = functionNode.setEndParserState(lc, endParserState); - } else if (functionNode.getBody().getStatementCount() > 0){ + functionNode.setEndParserState(endParserState); + } else if (!body.getStatements().isEmpty()){ // This is to ensure the body is empty when !parseBody but we couldn't skip parsing it (see // skipFunctionBody() for possible reasons). While it is not strictly necessary for correctness to // enforce empty bodies in nested functions that were supposed to be skipped, we do assert it as // an invariant in few places in the compiler pipeline, so for consistency's sake we'll throw away // nested bodies early if we were supposed to skip 'em. - functionNode = functionNode.setBody(null, functionNode.getBody().setStatements(null, - Collections.emptyList())); + body.setStatements(Collections.emptyList()); } if (reparsedFunction != null) { @@ -2932,20 +2965,20 @@ loop: if (data != null) { // Data can be null if when we originally parsed the file, we removed the function declaration // as it was dead code. - functionNode = functionNode.setFlags(lc, data.getFunctionFlags()); + functionNode.setFlag(data.getFunctionFlags()); // This compensates for missing markEval() in case the function contains an inner function // that contains eval(), that now we didn't discover since we skipped the inner function. if (functionNode.hasNestedEval()) { assert functionNode.hasScopeBlock(); - functionNode = functionNode.setBody(lc, functionNode.getBody().setNeedsScope(null)); + body.setFlag(Block.NEEDS_SCOPE); } } } - printAST(functionNode); - return functionNode; + functionBody = new Block(bodyToken, bodyFinish, body.getFlags(), body.getStatements()); + return functionBody; } - private boolean skipFunctionBody(final FunctionNode functionNode) { + private boolean skipFunctionBody(final ParserContextFunctionNode functionNode) { if (reparsedFunction == null) { // Not reparsing, so don't skip any function body. return false; @@ -3008,13 +3041,13 @@ loop: } } - private void addFunctionDeclarations(final FunctionNode functionNode) { + private void addFunctionDeclarations(final ParserContextFunctionNode functionNode) { VarNode lastDecl = null; for (int i = functionDeclarations.size() - 1; i >= 0; i--) { Statement decl = functionDeclarations.get(i); if (lastDecl == null && decl instanceof VarNode) { decl = lastDecl = ((VarNode)decl).setFlag(VarNode.IS_LAST_FUNCTION_DECLARATION); - lc.setFlag(functionNode, FunctionNode.HAS_FUNCTION_DECLARATIONS); + functionNode.setFlag(FunctionNode.HAS_FUNCTION_DECLARATIONS); } prependStatement(decl); } @@ -3359,29 +3392,31 @@ loop: return "'JavaScript Parsing'"; } - private static void markEval(final LexicalContext lc) { - final Iterator iter = lc.getFunctions(); + private static void markEval(final ParserContext lc) { + final Iterator iter = lc.getFunctions(); boolean flaggedCurrentFn = false; while (iter.hasNext()) { - final FunctionNode fn = iter.next(); + final ParserContextFunctionNode fn = iter.next(); if (!flaggedCurrentFn) { - lc.setFlag(fn, FunctionNode.HAS_EVAL); + fn.setFlag(FunctionNode.HAS_EVAL); flaggedCurrentFn = true; } else { - lc.setFlag(fn, FunctionNode.HAS_NESTED_EVAL); + fn.setFlag(FunctionNode.HAS_NESTED_EVAL); } + final ParserContextBlockNode body = lc.getFunctionBody(fn); // NOTE: it is crucial to mark the body of the outer function as needing scope even when we skip // parsing a nested function. functionBody() contains code to compensate for the lack of invoking // this method when the parser skips a nested function. - lc.setBlockNeedsScope(lc.getFunctionBody(fn)); + body.setFlag(Block.NEEDS_SCOPE); + fn.setFlag(FunctionNode.HAS_SCOPE_BLOCK); } } private void prependStatement(final Statement statement) { - lc.prependStatement(statement); + lc.prependStatementToCurrentNode(statement); } private void appendStatement(final Statement statement) { - lc.appendStatement(statement); + lc.appendStatementToCurrentNode(statement); } } diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java new file mode 100644 index 00000000000..7a90adfb0dc --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContext.java @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +import java.util.Iterator; +import java.util.NoSuchElementException; +import jdk.nashorn.internal.ir.Statement; + +/** + * A class that tracks the current lexical context of node visitation as a stack of {@code ParserContextNode} nodes. Has special + * methods to retrieve useful subsets of the context. + * + * This is implemented with a primitive array and a stack pointer, because it really makes a difference + * performance wise. None of the collection classes were optimal + */ + +class ParserContext { + + private ParserContextNode[] stack; + private int sp; + + private static final int INITIAL_DEPTH = 16; + + /** + * Constructs a ParserContext, + * initializes the stack + */ + public ParserContext(){ + this.sp = 0; + this.stack = new ParserContextNode[INITIAL_DEPTH]; + } + + /** + * Pushes a new block on top of the context, making it the innermost open block. + * @param node the new node + * @return The node that was pushed + */ + public T push(final T node) { + assert !contains(node); + if (sp == stack.length) { + final ParserContextNode[] newStack = new ParserContextNode[sp * 2]; + System.arraycopy(stack, 0, newStack, 0, sp); + stack = newStack; + } + stack[sp] = node; + sp++; + + return node; + } + + /** + * The topmost node on the stack + * @return The topmost node on the stack + */ + public ParserContextNode peek() { + return stack[sp - 1]; + } + + /** + * Removes and returns the topmost Node from the stack. + * @param node The node expected to be popped, used for sanity check + * @return The removed node + */ + public T pop(final T node) { + --sp; + @SuppressWarnings("unchecked") + final T popped = (T)stack[sp]; + stack[sp] = null; + assert node == popped; + + return popped; + } + + /** + * Tests if a node is on the stack. + * @param node The node to test + * @return true if stack contains node, false otherwise + */ + public boolean contains(final ParserContextNode node) { + for (int i = 0; i < sp; i++) { + if (stack[i] == node) { + return true; + } + } + return false; + } + + /** + * Returns the topmost {@link ParserContextBreakableNode} on the stack, null if none on stack + * @return Returns the topmost {@link ParserContextBreakableNode} on the stack, null if none on stack + */ + private ParserContextBreakableNode getBreakable() { + for (final NodeIterator iter = new NodeIterator<>(ParserContextBreakableNode.class, getCurrentFunction()); iter.hasNext(); ) { + final ParserContextBreakableNode next = iter.next(); + if (next.isBreakableWithoutLabel()) { + return next; + } + } + return null; + } + + + + /** + * Find the breakable node corresponding to this label. + * @param labelName name of the label to search for. If null, the closest breakable node will be returned + * unconditionally, e.g. a while loop with no label + * @return closest breakable node + */ + public ParserContextBreakableNode getBreakable(final String labelName) { + if (labelName != null) { + final ParserContextLabelNode foundLabel = findLabel(labelName); + if (foundLabel != null) { + // iterate to the nearest breakable to the foundLabel + ParserContextBreakableNode breakable = null; + for (final NodeIterator iter = new NodeIterator<>(ParserContextBreakableNode.class, foundLabel); iter.hasNext(); ) { + breakable = iter.next(); + } + return breakable; + } + return null; + } else { + return getBreakable(); + } + } + + /** + * Returns the loop node of the current loop, or null if not inside a loop + * @return loop noder + */ + public ParserContextLoopNode getCurrentLoop() { + final Iterator iter = new NodeIterator<>(ParserContextLoopNode.class, getCurrentFunction()); + return iter.hasNext() ? iter.next() : null; + } + + private ParserContextLoopNode getContinueTo() { + return getCurrentLoop(); + } + + /** + * Find the continue target node corresponding to this label. + * @param labelName label name to search for. If null the closest loop node will be returned unconditionally, e.g. a + * while loop with no label + * @return closest continue target node + */ + public ParserContextLoopNode getContinueTo(final String labelName) { + if (labelName != null) { + final ParserContextLabelNode foundLabel = findLabel(labelName); + if (foundLabel != null) { + // iterate to the nearest loop to the foundLabel + ParserContextLoopNode loop = null; + for (final NodeIterator iter = new NodeIterator<>(ParserContextLoopNode.class, foundLabel); iter.hasNext(); ) { + loop = iter.next(); + } + return loop; + } + return null; + } + return getContinueTo(); + } + + /** + * Get the function body of a function node on the stack. + * This will trigger an assertion if node isn't present + * @param functionNode function node + * @return body of function node + */ + public ParserContextBlockNode getFunctionBody(final ParserContextFunctionNode functionNode) { + for (int i = sp - 1; i >= 0 ; i--) { + if (stack[i] == functionNode) { + return (ParserContextBlockNode)stack[i + 1]; + } + } + throw new AssertionError(functionNode.getName() + " not on context stack"); + } + + /** + * Check the stack for a given label node by name + * @param name name of the label + * @return LabelNode if found, null otherwise + */ + public ParserContextLabelNode findLabel(final String name) { + for (final Iterator iter = new NodeIterator<>(ParserContextLabelNode.class, getCurrentFunction()); iter.hasNext(); ) { + final ParserContextLabelNode next = iter.next(); + if (next.getLabelName().equals(name)) { + return next; + } + } + return null; + } + + /** + * Prepends a statement to the current node. + * @param statement The statement to prepend + */ + public void prependStatementToCurrentNode(final Statement statement) { + assert statement != null; + stack[sp - 1].prependStatement(statement); + } + + /** + * Appends a statement to the current Node. + * @param statement The statement to append + */ + public void appendStatementToCurrentNode(final Statement statement) { + assert statement != null; + stack[sp - 1].appendStatement(statement); + } + + /** + * Returns the innermost function in the context. + * @return the innermost function in the context. + */ + public ParserContextFunctionNode getCurrentFunction() { + for (int i = sp - 1; i >= 0; i--) { + if (stack[i] instanceof ParserContextFunctionNode) { + return (ParserContextFunctionNode) stack[i]; + } + } + return null; + } + + /** + * Returns an iterator over all blocks in the context, with the top block (innermost lexical context) first. + * @return an iterator over all blocks in the context. + */ + public Iterator getBlocks() { + return new NodeIterator<>(ParserContextBlockNode.class); + } + + /** + * Returns the innermost block in the context. + * @return the innermost block in the context. + */ + public ParserContextBlockNode getCurrentBlock() { + return getBlocks().next(); + } + + /** + * The last statement added to the context + * @return The last statement added to the context + */ + public Statement getLastStatement() { + if (sp == 0) { + return null; + } + final ParserContextNode top = stack[sp - 1]; + final int s = top.getStatements().size(); + return s == 0 ? null : top.getStatements().get(s - 1); + } + + /** + * Returns an iterator over all functions in the context, with the top (innermost open) function first. + * @return an iterator over all functions in the context. + */ + public Iterator getFunctions() { + return new NodeIterator<>(ParserContextFunctionNode.class); + } + + private class NodeIterator implements Iterator { + private int index; + private T next; + private final Class clazz; + private ParserContextNode until; + + NodeIterator(final Class clazz) { + this(clazz, null); + } + + NodeIterator(final Class clazz, final ParserContextNode until) { + this.index = sp - 1; + this.clazz = clazz; + this.until = until; + this.next = findNext(); + } + + @Override + public boolean hasNext() { + return next != null; + } + + @Override + public T next() { + if (next == null) { + throw new NoSuchElementException(); + } + final T lnext = next; + next = findNext(); + return lnext; + } + + @SuppressWarnings("unchecked") + private T findNext() { + for (int i = index; i >= 0; i--) { + final Object node = stack[i]; + if (node == until) { + return null; + } + if (clazz.isAssignableFrom(node.getClass())) { + index = i - 1; + return (T)node; + } + } + return null; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBaseNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBaseNode.java new file mode 100644 index 00000000000..262bc541d2e --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBaseNode.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +import java.util.ArrayList; +import java.util.List; +import jdk.nashorn.internal.ir.Statement; + +/** + * Base class for parser context nodes + */ +abstract class ParserContextBaseNode implements ParserContextNode { + /** + * Flags for this node + */ + protected int flags; + + private List statements; + + /** + * Constructor + */ + public ParserContextBaseNode() { + this.statements = new ArrayList<>(); + } + + /** + * @return The flags for this node + */ + @Override + public int getFlags() { + return flags; + } + + /** + * Returns a single flag + * @param flag + * @return A single flag + */ + protected int getFlag(final int flag) { + return (flags & flag); + } + + /** + * @param flag + * @return the new flags + */ + @Override + public int setFlag(final int flag) { + flags |= flag; + return flags; + } + + /** + * @return The list of statements that belongs to this node + */ + @Override + public List getStatements() { + return statements; + } + + /** + * @param statements + */ + @Override + public void setStatements(final List statements) { + this.statements = statements; + } + + /** + * Adds a Statement at the end of the Statementlist + * @param statement The statement to add + */ + @Override + public void appendStatement(final Statement statement) { + this.statements.add(statement); + } + + /** + * Adds a statement at the begining of the statementlist + * @param statement The statement to add + */ + @Override + public void prependStatement(final Statement statement) { + this.statements.add(0, statement); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBlockNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBlockNode.java new file mode 100644 index 00000000000..e87bd1293a9 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBlockNode.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +/** + * A ParserContextNode that represents a block that is currently being parsed + */ +class ParserContextBlockNode extends ParserContextBaseNode implements ParserContextBreakableNode { + + private final long token; + + /** + * Constructs a ParserContextBlockNode + * + * @param token The first token of the block + */ + public ParserContextBlockNode(final long token) { + this.token = token; + } + + @Override + public boolean isBreakableWithoutLabel() { + return false; + } + + /** + * Get token + * @return The first token of the block + */ + public long getToken() { + return token; + } + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBreakableNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBreakableNode.java new file mode 100644 index 00000000000..cb0b46d9c14 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextBreakableNode.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +import jdk.nashorn.internal.ir.BreakNode; + +/** + * An interface that is implemented by ParserContextNodes that can + * contain a {@link BreakNode} + */ +interface ParserContextBreakableNode extends ParserContextNode { + + /** + * Returns true if not i breakable without label, false otherwise + * @return Returns true if not i breakable without label, false otherwise + */ + boolean isBreakableWithoutLabel(); +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java new file mode 100644 index 00000000000..5418caff915 --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +import java.util.List; +import jdk.nashorn.internal.codegen.Namespace; +import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.IdentNode; + +/** + * ParserContextNode that represents a function that is currently being parsed + */ +class ParserContextFunctionNode extends ParserContextBaseNode { + + /** Function name */ + private final String name; + + /** Function identifier node */ + private final IdentNode ident; + + /** Name space for function */ + private final Namespace namespace; + + /** Line number for function declaration */ + private final int line; + + /** Function node kind, see {@link FunctionNode#Kind} */ + private final FunctionNode.Kind kind; + + /** List of parameter identifiers for function */ + private final List parameters; + + /** Token for function start */ + private final long token; + + /** Last function token */ + private long lastToken; + + /** Opaque node for parser end state, see {@link Parser} */ + private Object endParserState; + + /** + * @param token The token for the function + * @param ident External function name + * @param name Internal name of the function + * @param namespace Function's namespace + * @param line The source line of the function + * @param kind Function kind + * @param parameters The parameters of the function + */ + public ParserContextFunctionNode(final long token, final IdentNode ident, final String name, final Namespace namespace, final int line, final FunctionNode.Kind kind, final List parameters) { + this.ident = ident; + this.namespace = namespace; + this.line = line; + this.kind = kind; + this.name = name; + this.parameters = parameters; + this.token = token; + } + + /** + * @return Internal name of the function + */ + public String getName() { + return name; + } + + /** + * @return The external identifier for the function + */ + public IdentNode getIdent() { + return ident; + } + + /** + * + * @return true if function is the program function + */ + public boolean isProgram() { + return getFlag(FunctionNode.IS_PROGRAM) != 0; + } + + /** + * @return if function in strict mode + */ + public boolean isStrict() { + return getFlag(FunctionNode.IS_STRICT) != 0; + } + + /** + * @return true if the function has nested evals + */ + public boolean hasNestedEval() { + return getFlag(FunctionNode.HAS_NESTED_EVAL) != 0; + } + + /** + * Returns true if any of the blocks in this function create their own scope. + * @return true if any of the blocks in this function create their own scope. + */ + public boolean hasScopeBlock() { + return getFlag(FunctionNode.HAS_SCOPE_BLOCK) != 0; + } + + /** + * Create a unique name in the namespace of this FunctionNode + * @param base prefix for name + * @return base if no collision exists, otherwise a name prefix with base + */ + public String uniqueName(final String base) { + return namespace.uniqueName(base); + } + + /** + * @return line number of the function + */ + public int getLineNumber() { + return line; + } + + /** + * @return The kind if function + */ + public FunctionNode.Kind getKind() { + return kind; + } + + /** + * Get parameters + * @return The parameters of the function + */ + public List getParameters() { + return parameters; + } + + /** + * Set last token + * @param token New last token + */ + public void setLastToken(final long token) { + this.lastToken = token; + + } + + /** + * @return lastToken Function's last token + */ + public long getLastToken() { + return lastToken; + } + + /** + * Returns the ParserState of when the parsing of this function was ended + * @return endParserState The end parser state + */ + public Object getEndParserState() { + return endParserState; + } + + /** + * Sets the ParserState of when the parsing of this function was ended + * @param endParserState The end parser state + */ + public void setEndParserState(final Object endParserState) { + this.endParserState = endParserState; + } + + /** + * Returns the if of this function + * @return The function id + */ + public int getId() { + return isProgram() ? -1 : Token.descPosition(token); + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLabelNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLabelNode.java new file mode 100644 index 00000000000..a5179107b3c --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLabelNode.java @@ -0,0 +1,52 @@ +/** +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +/** + * ParserContextNode that represents a LabelNode + */ +class ParserContextLabelNode extends ParserContextBaseNode { + + /** Name for label */ + private final String name; + + /** + * Constructor + * + * @param name The name of the label + */ + public ParserContextLabelNode(final String name) { + this.name = name; + } + + /** + * Returns the name of the label + * @return name of label + */ + public String getLabelName() { + return name; + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLoopNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLoopNode.java new file mode 100644 index 00000000000..31e4b3ad5ea --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextLoopNode.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +/** + * A ParserContextNode that represents a loop that is being parsed + */ +class ParserContextLoopNode extends ParserContextBaseNode implements ParserContextBreakableNode { + + @Override + public boolean isBreakableWithoutLabel() { + return true; + } + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextNode.java new file mode 100644 index 00000000000..d44a106b8dd --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextNode.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +import java.util.List; +import jdk.nashorn.internal.ir.Statement; + +/** + * Used for keeping state when needed in the parser. + */ +interface ParserContextNode { + /** + * @return The flags for this node + */ + public int getFlags(); + + /** + * @param flag The flag to set + * @return All current flags after update + */ + public int setFlag(final int flag); + + /** + * @return The list of statements that belongs to this node + */ + public List getStatements(); + + /** + * @param statements The statement list + */ + public void setStatements(final List statements); + + /** + * Adds a Statement at the end of the Statementlist + * @param statement The statement to add + */ + public void appendStatement(final Statement statement); + + /** + * Adds a statement at the begining of the statementlist + * @param statement The statement to add + */ + public void prependStatement(final Statement statement); + +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java new file mode 100644 index 00000000000..8c9c96a6a2d --- /dev/null +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextSwitchNode.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.nashorn.internal.parser; + +/** + * A ParserContextNode that represents a SwithcNode that is currently being parsed + */ +class ParserContextSwitchNode extends ParserContextBaseNode implements ParserContextBreakableNode { + + @Override + public boolean isBreakableWithoutLabel() { + return true; + } +} diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java index e77c204afbb..ff543a36290 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/Context.java @@ -483,7 +483,7 @@ public final class Context { final int cacheSize = env._class_cache_size; if (cacheSize > 0) { - classCache = new ClassCache(cacheSize); + classCache = new ClassCache(this, cacheSize); } if (env._persistent_cache) { @@ -1261,17 +1261,23 @@ public final class Context { * Cache for compiled script classes. */ @SuppressWarnings("serial") - private static class ClassCache extends LinkedHashMap { + @Logger(name="classcache") + private static class ClassCache extends LinkedHashMap implements Loggable { private final int size; private final ReferenceQueue> queue; + private final DebugLogger log; - ClassCache(final int size) { + ClassCache(final Context context, final int size) { super(size, 0.75f, true); this.size = size; this.queue = new ReferenceQueue<>(); + this.log = initLogger(context); } void cache(final Source source, final Class clazz) { + if (log.isEnabled()) { + log.info("Caching ", source, " in class cache"); + } put(source, new ClassReference(clazz, queue, source)); } @@ -1283,9 +1289,28 @@ public final class Context { @Override public ClassReference get(final Object key) { for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) { - remove(ref.source); + final Source source = ref.source; + if (log.isEnabled()) { + log.info("Evicting ", source, " from class cache."); + } + remove(source); } - return super.get(key); + + final ClassReference ref = super.get(key); + if (ref != null && log.isEnabled()) { + log.info("Retrieved class reference for ", ref.source, " from class cache"); + } + return ref; + } + + @Override + public DebugLogger initLogger(final Context context) { + return context.getLogger(getClass()); + } + + @Override + public DebugLogger getLogger() { + return log; } } From bd3defa4bb79eedcc1ba2dd91bed46f8da7a669a Mon Sep 17 00:00:00 2001 From: Andreas Gabrielsson Date: Tue, 14 Oct 2014 16:11:07 +0200 Subject: [PATCH 72/91] 8060471: DynamicLinker.getLinkedCallSiteLocation() is called even when logger is disabled, and it creates a stacktrace. This contributes unnecessarily to compile time Reviewed-by: lagergren, attila --- .../jdk/nashorn/internal/runtime/GlobalConstants.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java index 6099a70bce8..c6f9b9644d7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/GlobalConstants.java @@ -31,7 +31,6 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint; import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.SwitchPoint; @@ -328,7 +327,9 @@ public final class GlobalConstants implements Loggable { } if (!acc.mayRetry()) { - log.info("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + if (log.isEnabled()) { + log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + } return null; } @@ -404,7 +405,9 @@ public final class GlobalConstants implements Loggable { } if (acc.hasBeenInvalidated() || acc.guardFailed()) { - log.fine("*** GET: Giving up on " + quote(name) + " - retry count has exceeded"); + if (log.isEnabled()) { + log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation()); + } return null; } From 7f6646995189d3f3e50a2b1a4f5031416666f9d4 Mon Sep 17 00:00:00 2001 From: Olivier Lagneau Date: Tue, 14 Oct 2014 11:39:07 -0700 Subject: [PATCH 73/91] 8039915: Wrong NumberFormat.format() HALF_UP rounding when last digit exactly at rounding position greater than 5 Fixes erroneous rounding in DigitList for corner cases uncovered previously. Adds dedicated unit tests to TieRoundingTest Reviewed-by: bpb, darcy --- .../share/classes/java/text/DigitList.java | 92 +++++++++---------- .../Format/DecimalFormat/TieRoundingTest.java | 44 +++++++-- 2 files changed, 79 insertions(+), 57 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/text/DigitList.java b/jdk/src/java.base/share/classes/java/text/DigitList.java index 363306406eb..0b73543a9d4 100644 --- a/jdk/src/java.base/share/classes/java/text/DigitList.java +++ b/jdk/src/java.base/share/classes/java/text/DigitList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -290,25 +290,26 @@ final class DigitList implements Cloneable { FloatingDecimal.BinaryToASCIIConverter fdConverter = FloatingDecimal.getBinaryToASCIIConverter(source); boolean hasBeenRoundedUp = fdConverter.digitsRoundedUp(); - boolean allDecimalDigits = fdConverter.decimalDigitsExact(); + boolean valueExactAsDecimal = fdConverter.decimalDigitsExact(); assert !fdConverter.isExceptional(); String digitsString = fdConverter.toJavaFormatString(); set(isNegative, digitsString, - hasBeenRoundedUp, allDecimalDigits, + hasBeenRoundedUp, valueExactAsDecimal, maximumDigits, fixedPoint); } /** * Generate a representation of the form DDDDD, DDDDD.DDDDD, or * DDDDDE+/-DDDDD. - * @param roundedUp Boolean value indicating if the s digits were rounded-up. - * @param allDecimalDigits Boolean value indicating if the digits in s are - * an exact decimal representation of the double that was passed. + * @param roundedUp whether or not rounding up has already happened. + * @param valueExactAsDecimal whether or not collected digits provide + * an exact decimal representation of the value. */ private void set(boolean isNegative, String s, - boolean roundedUp, boolean allDecimalDigits, + boolean roundedUp, boolean valueExactAsDecimal, int maximumDigits, boolean fixedPoint) { + this.isNegative = isNegative; int len = s.length(); char[] source = getDataChars(len); @@ -361,7 +362,7 @@ final class DigitList implements Cloneable { } else if (-decimalAt == maximumDigits) { // If we round 0.0009 to 3 fractional digits, then we have to // create a new one digit in the least significant location. - if (shouldRoundUp(0, roundedUp, allDecimalDigits)) { + if (shouldRoundUp(0, roundedUp, valueExactAsDecimal)) { count = 1; ++decimalAt; digits[0] = '1'; @@ -381,25 +382,26 @@ final class DigitList implements Cloneable { // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. round(fixedPoint ? (maximumDigits + decimalAt) : maximumDigits, - roundedUp, allDecimalDigits); - } + roundedUp, valueExactAsDecimal); + + } /** * Round the representation to the given number of digits. * @param maximumDigits The maximum number of digits to be shown. - * @param alreadyRounded Boolean indicating if rounding up already happened. - * @param allDecimalDigits Boolean indicating if the digits provide an exact - * representation of the value. + * @param alreadyRounded whether or not rounding up has already happened. + * @param valueExactAsDecimal whether or not collected digits provide + * an exact decimal representation of the value. * * Upon return, count will be less than or equal to maximumDigits. */ private final void round(int maximumDigits, boolean alreadyRounded, - boolean allDecimalDigits) { + boolean valueExactAsDecimal) { // Eliminate digits beyond maximum digits to be displayed. // Round up if appropriate. if (maximumDigits >= 0 && maximumDigits < count) { - if (shouldRoundUp(maximumDigits, alreadyRounded, allDecimalDigits)) { + if (shouldRoundUp(maximumDigits, alreadyRounded, valueExactAsDecimal)) { // Rounding up involved incrementing digits from LSD to MSD. // In most cases this is simple, but in a worst case situation // (9999..99) we have to adjust the decimalAt value. @@ -440,6 +442,9 @@ final class DigitList implements Cloneable { * count-1. If 0, then all digits are rounded away, and * this method returns true if a one should be generated (e.g., formatting * 0.09 with "#.#"). + * @param alreadyRounded whether or not rounding up has already happened. + * @param valueExactAsDecimal whether or not collected digits provide + * an exact decimal representation of the value. * @exception ArithmeticException if rounding is needed with rounding * mode being set to RoundingMode.UNNECESSARY * @return true if digit maximumDigits-1 should be @@ -447,7 +452,7 @@ final class DigitList implements Cloneable { */ private boolean shouldRoundUp(int maximumDigits, boolean alreadyRounded, - boolean allDecimalDigits) { + boolean valueExactAsDecimal) { if (maximumDigits < count) { /* * To avoid erroneous double-rounding or truncation when converting @@ -460,7 +465,7 @@ final class DigitList implements Cloneable { * account what FloatingDecimal has done in the binary to decimal * conversion. * - * Considering the tie cases, FloatingDecimal may round-up the + * Considering the tie cases, FloatingDecimal may round up the * value (returning decimal digits equal to tie when it is below), * or "truncate" the value to the tie while value is above it, * or provide the exact decimal digits when the binary value can be @@ -490,7 +495,7 @@ final class DigitList implements Cloneable { * * - For other numbers that are always converted to exact digits * (like BigInteger, Long, ...), the passed alreadyRounded boolean - * have to be set to false, and allDecimalDigits has to be set to + * have to be set to false, and valueExactAsDecimal has to be set to * true in the upper DigitList call stack, providing the right state * for those situations.. */ @@ -520,42 +525,31 @@ final class DigitList implements Cloneable { } break; case HALF_UP: - if (digits[maximumDigits] >= '5') { - // We should not round up if the rounding digits position is - // exactly the last index and if digits were already rounded. - if ((maximumDigits == (count - 1)) && - (alreadyRounded)) - return false; - - // Value was exactly at or was above tie. We must round up. - return true; - } - break; case HALF_DOWN: if (digits[maximumDigits] > '5') { + // Value is above tie ==> must round up return true; - } else if (digits[maximumDigits] == '5' ) { - if (maximumDigits == (count - 1)) { - // The rounding position is exactly the last index. - if (allDecimalDigits || alreadyRounded) - /* FloatingDecimal rounded up (value was below tie), - * or provided the exact list of digits (value was - * an exact tie). We should not round up, following - * the HALF_DOWN rounding rule. - */ - return false; - else - // Value was above the tie, we must round up. - return true; - } - - // We must round up if it gives a non null digit after '5'. - for (int i=maximumDigits+1; i must round up + return true; + } else { + // Digit at rounding position is the last one ! + if (valueExactAsDecimal) { + // Exact binary representation. On the tie. + // Apply rounding given by roundingMode. + return roundingMode == RoundingMode.HALF_UP; + } else { + // Not an exact binary representation. + // Digit sequence either rounded up or truncated. + // Round up only if it was truncated. + return !alreadyRounded; } } } + // Digit at rounding position is < '5' ==> no round up. + // Just let do the default, which is no round up (thus break). break; case HALF_EVEN: // Implement IEEE half-even rounding @@ -569,7 +563,7 @@ final class DigitList implements Cloneable { // then we should not round up again. return false; - if (!allDecimalDigits) + if (!valueExactAsDecimal) // Otherwise if the digits don't represent exact value, // value was above tie and FloatingDecimal truncated // digits to tie. We must round up. diff --git a/jdk/test/java/text/Format/DecimalFormat/TieRoundingTest.java b/jdk/test/java/text/Format/DecimalFormat/TieRoundingTest.java index 16f481726a2..989f54295b6 100644 --- a/jdk/test/java/text/Format/DecimalFormat/TieRoundingTest.java +++ b/jdk/test/java/text/Format/DecimalFormat/TieRoundingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * - * @bug 7131459 + * @bug 7131459 8039915 * @summary test various situations of NumberFormat rounding when close to tie * @author Olivier Lagneau * @run main TieRoundingTest @@ -56,7 +56,7 @@ public class TieRoundingTest { if (!result.equals(expectedOutput)) { System.out.println(); System.out.println("========================================"); - System.out.println("***Error formatting double value from string : " + + System.out.println("***Failure : error formatting value from string : " + inputDigits); System.out.println("NumberFormat pattern is : " + ((DecimalFormat ) nf).toPattern()); @@ -103,7 +103,7 @@ public class TieRoundingTest { if (!result.equals(expectedOutput)) { System.out.println(); System.out.println("========================================"); - System.out.println("***Error formatting double value from string : " + + System.out.println("***Failure : error formatting value from string : " + inputDigits); System.out.println("NumberFormat pattern is : " + ((DecimalFormat ) nf).toPattern()); @@ -144,7 +144,7 @@ public class TieRoundingTest { if (!result.equals(expectedOutput)) { System.out.println(); System.out.println("========================================"); - System.out.println("***Error formatting number value from string : " + + System.out.println("***Failure : error formatting value from string : " + inputDigits); System.out.println("NumberFormat pattern is : " + ((DecimalFormat ) nf).toPattern()); @@ -174,7 +174,7 @@ public class TieRoundingTest { public static void main(String[] args) { - // Only the 3 rounding modes below may be impacted by bug 7131459. + // The 3 HALF_* rounding modes are impacted by bugs 7131459, 8039915. // So we do not test the other rounding modes. RoundingMode[] roundingModes = { RoundingMode.HALF_DOWN, @@ -183,10 +183,14 @@ public class TieRoundingTest { }; // Precise the relative position of input value against its closest tie. + // The double values tested below for 3 and 5 fractional digits must follow + // this scheme (position toward tie). String[] tieRelativePositions = { "below", "exact", "above", "below", "exact", "above", "below", "exact", "above", + "below", "above", "above", + "below", "below", "above", "below", "exact", "above" }; @@ -196,9 +200,13 @@ public class TieRoundingTest { double[] values3FractDigits = { // unimpacting values close to tie, with less than 3 input fract digits 1.115d, 1.125d, 1.135d, - // impacting close to tie values covering all 6 cases + // HALF_* impacting close to tie values covering all 6 tie cases 0.3115d, 0.3125d, 0.3135d, 0.6865d, 0.6875d, 0.6885d, + // specific HALF_UP close to tie values + 0.3124d, 0.3126d, 0.3128d, + // specific HALF_DOWN close to tie values + 0.6864d, 0.6865d, 0.6868d, // unimpacting values close to tie, with more than 3 input fract digits 1.46885d, 2.46875d, 1.46865d }; @@ -207,6 +215,8 @@ public class TieRoundingTest { "1.115d", "1.125d", "1.135d", "0.3115d", "0.3125d", "0.3135d", "0.6865d", "0.6875d", "0.6885d", + "0.3124d", "0.3126d", "0.3128d", + "0.6864d", "0.6865d", "0.6868d", "1.46885d", "2.46875d", "1.46865d" }; @@ -214,16 +224,22 @@ public class TieRoundingTest { {"1.115", "1.125", "1.135", "0.311", "0.312", "0.314", "0.686", "0.687", "0.689", + "0.312", "0.313", "0.313", + "0.686", "0.686", "0.687", "1.469", "2.469", "1.469" }, {"1.115", "1.125", "1.135", "0.311", "0.312", "0.314", "0.686", "0.688", "0.689", + "0.312", "0.313", "0.313", + "0.686", "0.686", "0.687", "1.469", "2.469", "1.469" }, {"1.115", "1.125", "1.135", "0.311", "0.313", "0.314", "0.686", "0.688", "0.689", + "0.312", "0.313", "0.313", + "0.686", "0.686", "0.687", "1.469", "2.469", "1.469" }, }; @@ -250,9 +266,13 @@ public class TieRoundingTest { double[] values5FractDigits = { // unimpacting values close to tie, with less than 5 input fract digits 1.3135d, 1.3125d, 1.3115d, - // impacting values close to tie, covering all 6 cases + // HALF_* impacting values close to tie, covering all 6 cases 1.328115d, 1.328125d, 1.328135d, 1.796865d, 1.796875d, 1.796885d, + // specific HALF_UP close to tie values + 1.328124d, 1.798876d, 1.796889d, + // specific HALF_DOWN close to tie values + 1.328114d, 1.796865d, 1.328138d, // unimpacting values close to tie, with more than 5 input fract digits 1.3281149999999d, 1.75390625d, 1.7968750000001d }; @@ -261,6 +281,8 @@ public class TieRoundingTest { "1.3135d", "1.3125d", "1.3115d", "1.328115d", "1.328125d", "1.328135d", "1.796865d", "1.796875d", "1.796885d", + "1.328124d", "1.798876d", "1.796889d", + "1.328114d", "1.796865d", "1.328138d", "1.3281149999999d", "1.75390625d", "1.7968750000001d" }; @@ -268,16 +290,22 @@ public class TieRoundingTest { {"1.3135", "1.3125", "1.3115", "1.32811", "1.32812", "1.32814", "1.79686", "1.79687", "1.79689", + "1.32812", "1.79888", "1.79689", + "1.32811", "1.79686", "1.32814", "1.32811", "1.75391", "1.79688" }, {"1.3135", "1.3125", "1.3115", "1.32811", "1.32812", "1.32814", "1.79686", "1.79688", "1.79689", + "1.32812", "1.79888", "1.79689", + "1.32811", "1.79686", "1.32814", "1.32811", "1.75391", "1.79688" }, {"1.3135", "1.3125", "1.3115", "1.32811", "1.32813", "1.32814", "1.79686", "1.79688", "1.79689", + "1.32812", "1.79888", "1.79689", + "1.32811", "1.79686", "1.32814", "1.32811", "1.75391", "1.79688" } }; From 9db8ce689b6ec6fb4a38377ef837f654cbba1912 Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 14 Oct 2014 20:26:15 -0700 Subject: [PATCH 74/91] 8059083: Remove jdk.compact3 from modules.xml Reviewed-by: alanb --- jdk/make/src/classes/build/tools/module/GenModulesList.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/jdk/make/src/classes/build/tools/module/GenModulesList.java b/jdk/make/src/classes/build/tools/module/GenModulesList.java index ac9df5fa683..66a9f8c76ed 100644 --- a/jdk/make/src/classes/build/tools/module/GenModulesList.java +++ b/jdk/make/src/classes/build/tools/module/GenModulesList.java @@ -112,8 +112,7 @@ public final class GenModulesList { } static final List AGGREGATORS = Arrays.asList(new String[] { - "java.se", "java.compact1", "java.compact2", - "java.compact3", "jdk.compact3"}); + "java.se", "java.compact1", "java.compact2", "java.compact3"}); class TopoSorter { final Deque result = new LinkedList<>(); From c25af2a63829eff420ee18e1951824495fba2f46 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 14 Oct 2014 19:35:03 +0200 Subject: [PATCH 75/91] 8060485: (str) contentEquals checks the String contents twice on mismatch Reviewed-by: martin, chegar, alanb --- jdk/src/java.base/share/classes/java/lang/String.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index 27c0ead5b10..92d381b3259 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -1045,8 +1045,9 @@ public final class String } } // Argument is a String - if (cs.equals(this)) - return true; + if (cs instanceof String) { + return equals(cs); + } // Argument is a generic CharSequence char v1[] = value; int n = v1.length; From ad65e81ce7b0ac2e9bc1654cbf6d18292962b0a9 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Tue, 14 Oct 2014 18:47:46 -0700 Subject: [PATCH 76/91] 8044269: Analysis of archive files Add checksum verification. Reviewed-by: iklam, dholmes, mschoene --- .../src/share/vm/classfile/classLoader.cpp | 11 ++++- .../src/share/vm/classfile/classLoader.hpp | 1 + hotspot/src/share/vm/memory/filemap.cpp | 41 ++++++++++++++++++- hotspot/src/share/vm/memory/filemap.hpp | 10 ++++- .../src/share/vm/memory/metaspaceShared.cpp | 5 +++ hotspot/src/share/vm/runtime/arguments.cpp | 5 +++ hotspot/src/share/vm/runtime/globals.hpp | 4 ++ 7 files changed, 72 insertions(+), 5 deletions(-) diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index ada7857a434..780fea1c2a3 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -75,6 +75,7 @@ typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *siz typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf); typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf); typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n); +typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len); static ZipOpen_t ZipOpen = NULL; static ZipClose_t ZipClose = NULL; @@ -83,6 +84,7 @@ static ReadEntry_t ReadEntry = NULL; static ReadMappedEntry_t ReadMappedEntry = NULL; static GetNextEntry_t GetNextEntry = NULL; static canonicalize_fn_t CanonicalizeEntry = NULL; +static Crc32_t Crc32 = NULL; // Globals @@ -799,9 +801,11 @@ void ClassLoader::load_zip_library() { ReadEntry = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry")); ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry")); GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry")); + Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32")); // ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL - if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || GetNextEntry == NULL) { + if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL || + GetNextEntry == NULL || Crc32 == NULL) { vm_exit_during_initialization("Corrupted ZIP library", path); } @@ -811,6 +815,11 @@ void ClassLoader::load_zip_library() { // This lookup only works on 1.3. Do not check for non-null here } +int ClassLoader::crc32(int crc, const char* buf, int len) { + assert(Crc32 != NULL, "ZIP_CRC32 is not found"); + return (*Crc32)(crc, (const jbyte*)buf, len); +} + // PackageInfo data exists in order to support the java.lang.Package // class. A Package object provides information about a java package // (version, vendor, etc.) which originates in the manifest of the jar diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 8f0bf77ac37..f69de2ec2cd 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -226,6 +226,7 @@ class ClassLoader: AllStatic { // to avoid confusing the zip library static bool get_canonical_path(const char* orig, char* out, int len); public: + static int crc32(int crc, const char* buf, int len); static bool update_class_path_entry_list(const char *path, bool check_for_duplicates, bool throw_exception=true); diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 2eb6870fd19..07027b52c42 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -331,6 +331,14 @@ bool FileMapInfo::init_from_file(int fd) { return false; } + size_t len = lseek(fd, 0, SEEK_END); + struct FileMapInfo::FileMapHeader::space_info* si = + &_header->_space[MetaspaceShared::mc]; + if (si->_file_offset >= len || len - si->_file_offset < si->_used) { + fail_continue("The shared archive file has been truncated."); + return false; + } + _file_offset += (long)n; return true; } @@ -431,6 +439,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size, si->_capacity = capacity; si->_read_only = read_only; si->_allow_exec = allow_exec; + si->_crc = ClassLoader::crc32(0, base, (jint)size); write_bytes_aligned(base, (int)size); } @@ -455,14 +464,15 @@ void FileMapInfo::write_bytes(const void* buffer, int nbytes) { // Align file position to an allocation unit boundary. void FileMapInfo::align_file_position() { - long new_file_offset = align_size_up(_file_offset, os::vm_allocation_granularity()); + size_t new_file_offset = align_size_up(_file_offset, + os::vm_allocation_granularity()); if (new_file_offset != _file_offset) { _file_offset = new_file_offset; if (_file_open) { // Seek one byte back from the target and write a byte to insure // that the written file is the correct length. _file_offset -= 1; - if (lseek(_fd, _file_offset, SEEK_SET) < 0) { + if (lseek(_fd, (long)_file_offset, SEEK_SET) < 0) { fail_stop("Unable to seek."); } char zero = 0; @@ -569,6 +579,19 @@ char* FileMapInfo::map_region(int i) { return base; } +bool FileMapInfo::verify_region_checksum(int i) { + if (!VerifySharedSpaces) { + return true; + } + const char* buf = _header->_space[i]._base; + size_t sz = _header->_space[i]._used; + int crc = ClassLoader::crc32(0, buf, (jint)sz); + if (crc != _header->_space[i]._crc) { + fail_continue("Checksum verification failed."); + return false; + } + return true; +} // Unmap a memory region in the address space. @@ -629,7 +652,21 @@ bool FileMapInfo::initialize() { return true; } +int FileMapInfo::FileMapHeader::compute_crc() { + char* header = data(); + // start computing from the field after _crc + char* buf = (char*)&_crc + sizeof(int); + size_t sz = data_size() - (buf - header); + int crc = ClassLoader::crc32(0, buf, (jint)sz); + return crc; +} + bool FileMapInfo::FileMapHeader::validate() { + if (VerifySharedSpaces && compute_crc() != _crc) { + fail_continue("Header checksum verification failed."); + return false; + } + if (_version != current_version()) { FileMapInfo::fail_continue("The shared archive file is the wrong version."); return false; diff --git a/hotspot/src/share/vm/memory/filemap.hpp b/hotspot/src/share/vm/memory/filemap.hpp index 821bf66bf6b..a84aa17457f 100644 --- a/hotspot/src/share/vm/memory/filemap.hpp +++ b/hotspot/src/share/vm/memory/filemap.hpp @@ -61,7 +61,7 @@ private: bool _file_open; int _fd; - long _file_offset; + size_t _file_offset; private: static SharedClassPathEntry* _classpath_entry_table; @@ -87,12 +87,14 @@ public: } int _magic; // identify file type. + int _crc; // header crc checksum. int _version; // (from enum, above.) size_t _alignment; // how shared archive should be aligned int _obj_alignment; // value of ObjectAlignmentInBytes struct space_info { - int _file_offset; // sizeof(this) rounded to vm page size + int _crc; // crc checksum of the current space + size_t _file_offset; // sizeof(this) rounded to vm page size char* _base; // copy-on-write base address size_t _capacity; // for validity checking size_t _used; // for setting space top on read @@ -135,6 +137,7 @@ public: virtual bool validate(); virtual void populate(FileMapInfo* info, size_t alignment); + int compute_crc(); }; FileMapHeader * _header; @@ -153,6 +156,8 @@ public: ~FileMapInfo(); static int current_version() { return _current_version; } + int compute_header_crc() { return _header->compute_crc(); } + void set_header_crc(int crc) { _header->_crc = crc; } void populate_header(size_t alignment); bool validate_header(); void invalidate(); @@ -181,6 +186,7 @@ public: void write_bytes_aligned(const void* buffer, int count); char* map_region(int i); void unmap_region(int i); + bool verify_region_checksum(int i); void close(); bool is_open() { return _file_open; } ReservedSpace reserve_shared_memory(); diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 67c1618e3b5..ab0d5de72b0 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -608,6 +608,7 @@ void VM_PopulateDumpSharedSpace::doit() { // Pass 2 - write data. mapinfo->open_for_write(); + mapinfo->set_header_crc(mapinfo->compute_header_crc()); mapinfo->write_header(); mapinfo->write_space(MetaspaceShared::ro, _loader_data->ro_metaspace(), true); mapinfo->write_space(MetaspaceShared::rw, _loader_data->rw_metaspace(), false); @@ -937,9 +938,13 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) { // Map each shared region if ((_ro_base = mapinfo->map_region(ro)) != NULL && + mapinfo->verify_region_checksum(ro) && (_rw_base = mapinfo->map_region(rw)) != NULL && + mapinfo->verify_region_checksum(rw) && (_md_base = mapinfo->map_region(md)) != NULL && + mapinfo->verify_region_checksum(md) && (_mc_base = mapinfo->map_region(mc)) != NULL && + mapinfo->verify_region_checksum(mc) && (image_alignment == (size_t)max_alignment()) && mapinfo->validate_classpath_entry_table()) { // Success (no need to do anything) diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 7f0399bd6cc..80b56221107 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -3836,6 +3836,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) { return JNI_ENOMEM; } + // Set up VerifySharedSpaces + if (FLAG_IS_DEFAULT(VerifySharedSpaces) && SharedArchiveFile != NULL) { + VerifySharedSpaces = true; + } + // Delay warning until here so that we've had a chance to process // the -XX:-PrintWarnings flag if (needs_hotspotrc_warning) { diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index d2952060e8d..128afc2ae3a 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3790,6 +3790,10 @@ class CommandLineFlags { product(bool, UseSharedSpaces, true, \ "Use shared spaces for metadata") \ \ + product(bool, VerifySharedSpaces, false, \ + "Verify shared spaces (false for default archive, true for " \ + "archive specified by -XX:SharedArchiveFile)") \ + \ product(bool, RequireSharedSpaces, false, \ "Require shared spaces for metadata") \ \ From ffbd381c8cd81a5358d663a611106cb8cf9f556b Mon Sep 17 00:00:00 2001 From: Mandy Chung Date: Tue, 14 Oct 2014 20:26:09 -0700 Subject: [PATCH 77/91] 8059083: Remove jdk.compact3 from modules.xml Reviewed-by: alanb --- modules.xml | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/modules.xml b/modules.xml index 0b94edee620..0a4ba04eb2f 100644 --- a/modules.xml +++ b/modules.xml @@ -1490,16 +1490,6 @@ java.desktop - - jdk.compact3 - java.compact3 - java.smartcardio - jdk.httpserver - jdk.naming.dns - jdk.naming.rmi - jdk.sctp - jdk.security.auth - jdk.compiler java.base @@ -1735,7 +1725,6 @@ java.base java.desktop java.se - jdk.compact3 jdk.scripting.nashorn From 5d93e4cb2561a1ae6941ca11c6a66023f97504c7 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Wed, 15 Oct 2014 15:57:46 +0200 Subject: [PATCH 78/91] 8060242: Compile-time expression evaluator was not seeing into ArrayBufferViews Reviewed-by: hannesw, lagergren, sundar --- .../nashorn/internal/codegen/TypeEvaluator.java | 17 ++++++++--------- .../internal/objects/ArrayBufferView.java | 3 +-- .../internal/objects/NativeFloat32Array.java | 6 ++++++ .../internal/objects/NativeFloat64Array.java | 6 ++++++ .../internal/objects/NativeInt16Array.java | 16 ++++++++++++++++ .../internal/objects/NativeInt32Array.java | 16 ++++++++++++++++ .../internal/objects/NativeInt8Array.java | 16 ++++++++++++++++ .../internal/objects/NativeUint16Array.java | 16 ++++++++++++++++ .../internal/objects/NativeUint32Array.java | 13 ++++++++++++- .../internal/objects/NativeUint8Array.java | 16 ++++++++++++++++ .../objects/NativeUint8ClampedArray.java | 16 ++++++++++++++++ .../runtime/arrays/ContinuousArrayData.java | 7 +++++++ .../internal/runtime/arrays/IntArrayData.java | 7 +------ .../internal/runtime/arrays/LongArrayData.java | 7 +------ .../runtime/arrays/NumberArrayData.java | 7 +------ .../runtime/arrays/ObjectArrayData.java | 7 +------ 16 files changed, 140 insertions(+), 36 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java index 11a23ecd3a1..319866b5478 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java @@ -35,6 +35,7 @@ import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IndexNode; import jdk.nashorn.internal.ir.Optimistic; +import jdk.nashorn.internal.objects.ArrayBufferView; import jdk.nashorn.internal.objects.NativeArray; import jdk.nashorn.internal.runtime.FindProperty; import jdk.nashorn.internal.runtime.JSType; @@ -204,16 +205,14 @@ final class TypeEvaluator { if (expr instanceof IndexNode) { final IndexNode indexNode = (IndexNode)expr; final Object base = evaluateSafely(indexNode.getBase()); - if(!(base instanceof NativeArray)) { - // We only know how to deal with NativeArray. TODO: maybe manage buffers too - return null; + if(base instanceof NativeArray || base instanceof ArrayBufferView) { + // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their underlying + // array storage, not based on values of individual elements. Thus, a LongArrayData will throw UOE for every + // optimistic int linkage attempt, even if the long value being returned in the first invocation would be + // representable as int. That way, we can presume that the array's optimistic type is the most optimistic + // type for which an element getter has a chance of executing successfully. + return ((ScriptObject)base).getArray().getOptimisticType(); } - // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their underlying - // array storage, not based on values of individual elements. Thus, a LongArrayData will throw UOE for every - // optimistic int linkage attempt, even if the long value being returned in the first invocation would be - // representable as int. That way, we can presume that the array's optimistic type is the most optimistic - // type for which an element getter has a chance of executing successfully. - return ((NativeArray)base).getArray().getOptimisticType(); } return null; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java index efcc3ddcf60..e33fac3bb11 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/ArrayBufferView.java @@ -31,7 +31,6 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_ import java.nio.ByteBuffer; import java.nio.ByteOrder; - import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; @@ -46,7 +45,7 @@ import jdk.nashorn.internal.runtime.arrays.ArrayData; import jdk.nashorn.internal.runtime.arrays.TypedArrayData; @ScriptClass("ArrayBufferView") -abstract class ArrayBufferView extends ScriptObject { +public abstract class ArrayBufferView extends ScriptObject { private final NativeArrayBuffer buffer; private final int byteOffset; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java index 049d8fa8142..e5ef0b5a5fd 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat32Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -140,6 +141,11 @@ public final class NativeFloat32Array extends ArrayBufferView { return getElem(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getDouble(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java index 79268cc51a9..1ad61b277c2 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeFloat64Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -140,6 +141,11 @@ public final class NativeFloat64Array extends ArrayBufferView { return getElem(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getDouble(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java index 72e24a20418..061488487f7 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt16Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -123,16 +124,31 @@ public final class NativeInt16Array extends ArrayBufferView { return getElem(index); } + @Override + public int getIntOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public long getLong(final int index) { return getInt(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getInt(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getInt(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java index 56b3106fb44..5074dc68539 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt32Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -121,16 +122,31 @@ public final class NativeInt32Array extends ArrayBufferView { return getElem(index); } + @Override + public int getIntOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public long getLong(final int index) { return getInt(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getInt(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getInt(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java index 68e6b0bc1ca..319168c0522 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeInt8Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -121,16 +122,31 @@ public final class NativeInt8Array extends ArrayBufferView { return getElem(index); } + @Override + public int getIntOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public long getLong(final int index) { return getInt(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getInt(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getInt(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java index d049c9331f3..7f8a192399a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint16Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -127,16 +128,31 @@ public final class NativeUint16Array extends ArrayBufferView { return getElem(index); } + @Override + public int getIntOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public long getLong(final int index) { return getInt(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getInt(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getInt(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java index 2ae2be056ae..4772b977dd8 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint32Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -128,7 +129,7 @@ public final class NativeUint32Array extends ArrayBufferView { @Override public Class getElementType() { - return int.class; + return long.class; } @Override @@ -141,11 +142,21 @@ public final class NativeUint32Array extends ArrayBufferView { return getElem(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getLong(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getLong(index); + } + @Override public Object getObject(final int index) { return getLong(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java index 1067baa58d4..be7eb368b49 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8Array.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -127,16 +128,31 @@ public final class NativeUint8Array extends ArrayBufferView { return getElem(index); } + @Override + public int getIntOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public long getLong(final int index) { return getInt(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getInt(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getInt(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java index ffd0f14cfec..125ac0a2128 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java @@ -28,6 +28,7 @@ package jdk.nashorn.internal.objects; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; import static jdk.nashorn.internal.lookup.Lookup.MH; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.nio.ByteBuffer; @@ -157,16 +158,31 @@ public final class NativeUint8ClampedArray extends ArrayBufferView { return getElem(index); } + @Override + public int getIntOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public long getLong(final int index) { return getInt(index); } + @Override + public long getLongOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public double getDouble(final int index) { return getInt(index); } + @Override + public double getDoubleOptimistic(final int index, final int programPoint) { + return getElem(index); + } + @Override public Object getObject(final int index) { return getInt(index); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java index dfa6133db1d..8724d64ac2a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java @@ -30,6 +30,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT; import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -37,6 +38,7 @@ import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; +import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.lookup.Lookup; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; @@ -120,6 +122,11 @@ public abstract class ContinuousArrayData extends ArrayData { */ public abstract Class getElementType(); + @Override + public Type getOptimisticType() { + return Type.typeFor(getElementType()); + } + /** * Look up a continuous array element getter * @param get getter, sometimes combined with a has check that throws CCE on failure for relink diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java index fece3a6ef64..0792b6b6fa0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/IntArrayData.java @@ -26,10 +26,10 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; -import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -256,11 +256,6 @@ final class IntArrayData extends ContinuousArrayData implements IntElements { return convert(Double.class).set(index, value, strict); } - @Override - public Type getOptimisticType() { - return Type.INT; - } - @Override public int getInt(final int index) { return array[index]; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java index 31a4484e2ae..f41ee15a818 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/LongArrayData.java @@ -27,10 +27,10 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.lookup.Lookup.MH; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; -import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -186,11 +186,6 @@ final class LongArrayData extends ContinuousArrayData implements IntOrLongElemen return convert(Double.class).set(index, value, strict); } - @Override - public Type getOptimisticType() { - return Type.LONG; - } - private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle(); private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java index 4d27f51df3c..2c57208f496 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java @@ -28,10 +28,10 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; import static jdk.nashorn.internal.lookup.Lookup.MH; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; -import jdk.nashorn.internal.codegen.types.Type; /** * Implementation of {@link ArrayData} as soon as a double has been @@ -166,11 +166,6 @@ final class NumberArrayData extends ContinuousArrayData implements NumericElemen return this; } - @Override - public Type getOptimisticType() { - return Type.NUMBER; - } - private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "getElem", double.class, int.class).methodHandle(); private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "setElem", void.class, int.class, double.class).methodHandle(); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java index 001ea61c7c8..379ba6e438b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java @@ -26,10 +26,10 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall; + import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.Arrays; -import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -160,11 +160,6 @@ final class ObjectArrayData extends ContinuousArrayData { return this; } - @Override - public Type getOptimisticType() { - return Type.OBJECT; - } - private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "getElem", Object.class, int.class).methodHandle(); private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "setElem", void.class, int.class, Object.class).methodHandle(); From f571816c7988beda630259fa020b2bdfbcacde35 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Wed, 15 Oct 2014 16:00:21 +0200 Subject: [PATCH 79/91] 8060241: Immediately invoked function expressions cause lot of deoptimization Reviewed-by: hannesw, lagergren --- .../internal/codegen/TypeEvaluator.java | 45 ++++++++++++++----- .../RecompilableScriptFunctionData.java | 16 +++++++ 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java index 319866b5478..b3c0dd8a915 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java @@ -29,9 +29,12 @@ import static jdk.nashorn.internal.runtime.Property.NOT_CONFIGURABLE; import static jdk.nashorn.internal.runtime.Property.NOT_ENUMERABLE; import static jdk.nashorn.internal.runtime.Property.NOT_WRITABLE; +import java.lang.invoke.MethodType; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.ir.AccessNode; +import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.Expression; +import jdk.nashorn.internal.ir.FunctionNode; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IndexNode; import jdk.nashorn.internal.ir.Optimistic; @@ -40,6 +43,8 @@ import jdk.nashorn.internal.objects.NativeArray; import jdk.nashorn.internal.runtime.FindProperty; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.Property; +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; +import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -48,6 +53,13 @@ import jdk.nashorn.internal.runtime.ScriptRuntime; * Used during recompilation. */ final class TypeEvaluator { + /** + * Type signature for invocation of functions without parameters: we must pass (callee, this) of type + * (ScriptFunction, Object) respectively. We also use Object as the return type (we must pass something, + * but it'll be ignored; it can't be void, though). + */ + private static final MethodType EMPTY_INVOCATION_TYPE = MethodType.methodType(Object.class, ScriptFunction.class, Object.class); + private final Compiler compiler; private final ScriptObject runtimeScope; @@ -191,28 +203,39 @@ final class TypeEvaluator { return null; } return getPropertyType(runtimeScope, ((IdentNode)expr).getName()); - } - - if (expr instanceof AccessNode) { + } else if (expr instanceof AccessNode) { final AccessNode accessNode = (AccessNode)expr; final Object base = evaluateSafely(accessNode.getBase()); if (!(base instanceof ScriptObject)) { return null; } return getPropertyType((ScriptObject)base, accessNode.getProperty()); - } - - if (expr instanceof IndexNode) { + } else if (expr instanceof IndexNode) { final IndexNode indexNode = (IndexNode)expr; final Object base = evaluateSafely(indexNode.getBase()); if(base instanceof NativeArray || base instanceof ArrayBufferView) { - // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their underlying - // array storage, not based on values of individual elements. Thus, a LongArrayData will throw UOE for every - // optimistic int linkage attempt, even if the long value being returned in the first invocation would be - // representable as int. That way, we can presume that the array's optimistic type is the most optimistic - // type for which an element getter has a chance of executing successfully. + // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their + // underlying array storage, not based on values of individual elements. Thus, a LongArrayData will + // throw UOE for every optimistic int linkage attempt, even if the long value being returned in the + // first invocation would be representable as int. That way, we can presume that the array's optimistic + // type is the most optimistic type for which an element getter has a chance of executing successfully. return ((ScriptObject)base).getArray().getOptimisticType(); } + } else if (expr instanceof CallNode) { + // Currently, we'll only try to guess the return type of immediately invoked function expressions with no + // parameters, that is (function() { ... })(). We could do better, but these are all heuristics and we can + // gradually introduce them as needed. An easy one would be to do the same for .call(this) idiom. + final CallNode callExpr = (CallNode)expr; + final Expression fnExpr = callExpr.getFunction(); + if (fnExpr instanceof FunctionNode) { + final FunctionNode fn = (FunctionNode)fnExpr; + if (callExpr.getArgs().isEmpty()) { + final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId()); + if (data != null) { + return Type.typeFor(data.getReturnType(EMPTY_INVOCATION_TYPE, runtimeScope)); + } + } + } } return null; diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java index f3ad23393de..2e0b33bf69f 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java @@ -676,6 +676,22 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp return addCode(lookup(fnInit).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags()); } + /** + * Returns the return type of a function specialization for particular parameter types.
+ * Be aware that the way this is implemented, it forces full materialization (compilation and installation) of + * code for that specialization. + * @param callSiteType the parameter types at the call site. It must include the mandatory {@code callee} and + * {@code this} parameters, so it needs to start with at least {@code ScriptFunction.class} and + * {@code Object.class} class. Since the return type of the function is calculated from the code itself, it is + * irrelevant and should be set to {@code Object.class}. + * @param runtimeScope a current runtime scope. Can be null but when it's present it will be used as a source of + * current runtime values that can improve the compiler's type speculations (and thus reduce the need for later + * recompilations) if the specialization is not already present and thus needs to be freshly compiled. + * @return the return type of the function specialization. + */ + public Class getReturnType(final MethodType callSiteType, final ScriptObject runtimeScope) { + return getBest(callSiteType, runtimeScope, CompiledFunction.NO_FUNCTIONS).type().returnType(); + } @Override synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope, final Collection forbidden) { From 6427d424c8bd9876a940dc2d009b299271d33f85 Mon Sep 17 00:00:00 2001 From: Athijegannathan Sundararajan Date: Wed, 15 Oct 2014 19:50:03 +0530 Subject: [PATCH 80/91] 8060688: Nashorn: Generated script class name fails --verify-code for names with special chars Reviewed-by: jlaskey, hannesw --- .../nashorn/internal/codegen/Compiler.java | 21 ++++++- nashorn/test/script/nosecurity/JDK-8060688.js | 56 +++++++++++++++++++ .../internal/codegen/CompilerTest.java | 1 + .../runtime/TrustedScriptEngineTest.java | 25 +++++++++ 4 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 nashorn/test/script/nosecurity/JDK-8060688.js diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java index 3a0cc6bfb4b..80846e139dd 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Compiler.java @@ -410,10 +410,29 @@ public final class Compiler implements Loggable { baseName = baseName + installer.getUniqueScriptId(); } - final String mangled = NameCodec.encode(baseName); + // ASM's bytecode verifier does not allow JVM allowed safe escapes using '\' as escape char. + // While ASM accepts such escapes for method names, field names, it enforces Java identifier + // for class names. Workaround that ASM bug here by replacing JVM 'dangerous' chars with '_' + // rather than safe encoding using '\'. + final String mangled = env._verify_code? replaceDangerChars(baseName) : NameCodec.encode(baseName); return mangled != null ? mangled : baseName; } + private static final String DANGEROUS_CHARS = "\\/.;:$[]<>"; + private static String replaceDangerChars(final String name) { + final int len = name.length(); + final StringBuilder buf = new StringBuilder(); + for (int i = 0; i < len; i++) { + final char ch = name.charAt(i); + if (DANGEROUS_CHARS.indexOf(ch) != -1) { + buf.append('_'); + } else { + buf.append(ch); + } + } + return buf.toString(); + } + private String firstCompileUnitName() { final StringBuilder sb = new StringBuilder(SCRIPTS_PACKAGE). append('/'). diff --git a/nashorn/test/script/nosecurity/JDK-8060688.js b/nashorn/test/script/nosecurity/JDK-8060688.js new file mode 100644 index 00000000000..8fe578146bb --- /dev/null +++ b/nashorn/test/script/nosecurity/JDK-8060688.js @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8060688: Nashorn: Generated script class name fails --verify-code for names with special chars + * + * @test + * @run + */ + +var NashornEngineFactory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory"); +var ScriptEngine = Java.type("javax.script.ScriptEngine"); +var ScriptContext = Java.type("javax.script.ScriptContext"); + +var factory = new NashornEngineFactory(); + +var e = factory.getScriptEngine("--verify-code"); + +function evalAndCheck(code) { + try { + e.eval(code); + } catch (exp) { + exp.printStackTrace(); + } +} + +// check default name +evalAndCheck("var a = 3"); +// check few names with special chars +var scontext = e.context; +scontext.setAttribute(ScriptEngine.FILENAME, "", ScriptContext.ENGINE_SCOPE); +evalAndCheck("var h = 'hello'"); +scontext.setAttribute(ScriptEngine.FILENAME, "[myscript]", ScriptContext.ENGINE_SCOPE); +evalAndCheck("var foo = 'world'"); +scontext.setAttribute(ScriptEngine.FILENAME, ";/\\$.", ScriptContext.ENGINE_SCOPE); +evalAndCheck("var foo = 'helloworld'"); diff --git a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java index 9eb801fdd33..dadeb15f64e 100644 --- a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java +++ b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java @@ -72,6 +72,7 @@ public class CompilerTest { options.set("print.parse", true); options.set("scripting", true); options.set("const.as.var", true); + options.set("verify.code", true); final ErrorManager errors = new ErrorManager() { @Override diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java index 8225cc083b4..f7a18dcd6b2 100644 --- a/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java @@ -325,4 +325,29 @@ public class TrustedScriptEngineTest { ); assertEquals(ret, 10, "Parsed and executed OK"); } + + @Test + public void evalDefaultFileNameTest() throws ScriptException { + final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + final ScriptEngine engine = fac.getScriptEngine(new String[] { "--verify-code=true" }); + // default FILENAME being "" make sure generated code bytecode verifies. + engine.eval("var a = 3;"); + } + + @Test + public void evalFileNameWithSpecialCharsTest() throws ScriptException { + final NashornScriptEngineFactory fac = new NashornScriptEngineFactory(); + final ScriptEngine engine = fac.getScriptEngine(new String[] { "--verify-code=true" }); + final ScriptContext ctxt = new SimpleScriptContext(); + // use file name with "dangerous" chars. + ctxt.setAttribute(ScriptEngine.FILENAME, "", ScriptContext.ENGINE_SCOPE); + engine.eval("var a = 3;"); + ctxt.setAttribute(ScriptEngine.FILENAME, "[myscript]", ScriptContext.ENGINE_SCOPE); + engine.eval("var h = 'hello';"); + ctxt.setAttribute(ScriptEngine.FILENAME, ";/\\$.", ScriptContext.ENGINE_SCOPE); + engine.eval("var foo = 'world';"); + // name used by jjs shell tool for the interactive mode + ctxt.setAttribute(ScriptEngine.FILENAME, "", ScriptContext.ENGINE_SCOPE); + engine.eval("var foo = 'world';"); + } } From 972cb662d895c0401ae7cfe155f93aab39596876 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 16 Oct 2014 10:37:57 +0200 Subject: [PATCH 81/91] 8055191: Split GensrcProperties.gmk into separate modules Reviewed-by: tbell --- jdk/make/gensrc/Gensrc-java.base.gmk | 32 +++- jdk/make/gensrc/Gensrc-java.desktop.gmk | 42 +++++ jdk/make/gensrc/Gensrc-java.logging.gmk | 43 +++++ jdk/make/gensrc/Gensrc-java.management.gmk | 43 +++++ jdk/make/gensrc/Gensrc-jdk.dev.gmk | 43 +++++ jdk/make/gensrc/Gensrc-jdk.jdi.gmk | 11 ++ jdk/make/gensrc/Gensrc-jdk.localedata.gmk | 14 ++ jdk/make/gensrc/GensrcProperties.gmk | 189 ++++++++------------- 8 files changed, 293 insertions(+), 124 deletions(-) create mode 100644 jdk/make/gensrc/Gensrc-java.logging.gmk create mode 100644 jdk/make/gensrc/Gensrc-java.management.gmk create mode 100644 jdk/make/gensrc/Gensrc-jdk.dev.gmk diff --git a/jdk/make/gensrc/Gensrc-java.base.gmk b/jdk/make/gensrc/Gensrc-java.base.gmk index b43e822402c..58287ef18bb 100644 --- a/jdk/make/gensrc/Gensrc-java.base.gmk +++ b/jdk/make/gensrc/Gensrc-java.base.gmk @@ -25,10 +25,6 @@ include GensrcCommon.gmk -# TODO: maybe split into separate modules? -include GensrcProperties.gmk -GENSRC_JAVA_BASE += $(GENSRC_PROPERTIES) - include GensrcLocaleData.gmk include GensrcCharacterData.gmk include GensrcMisc.gmk @@ -37,6 +33,34 @@ include GensrcCharsetCoder.gmk include GensrcBuffer.gmk include GensrcExceptions.gmk +################################################################################ + +include GensrcProperties.gmk + +$(eval $(call SetupCompileProperties,LIST_RESOURCE_BUNDLE, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources)), \ + ListResourceBundle)) + +$(eval $(call SetupCompileProperties,SUN_UTIL, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources)), \ + sun.util.resources.LocaleNamesBundle)) + +GENSRC_JAVA_BASE += $(LIST_RESOURCE_BUNDLE) $(SUN_UTIL) + +# Some resources bundles are already present as java files but still need to be +# copied to zh_HK locale. +$(eval $(call SetupCopy-zh_HK,COPY_ZH_HK, \ + $(addprefix $(JDK_TOPDIR)/src/java.base/share/classes/, \ + sun/misc/resources/Messages_zh_TW.java \ + sun/security/util/AuthResources_zh_TW.java \ + sun/security/util/Resources_zh_TW.java))) + +GENSRC_JAVA_BASE += $(COPY_ZH_HK) + +################################################################################ + java.base: $(GENSRC_JAVA_BASE) all: java.base diff --git a/jdk/make/gensrc/Gensrc-java.desktop.gmk b/jdk/make/gensrc/Gensrc-java.desktop.gmk index ec26dfe4679..76484189cda 100644 --- a/jdk/make/gensrc/Gensrc-java.desktop.gmk +++ b/jdk/make/gensrc/Gensrc-java.desktop.gmk @@ -38,6 +38,48 @@ endif include GensrcSwing.gmk +################################################################################ + +include GensrcProperties.gmk + +PROP_SRC_DIRS := \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/awt/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/accessibility/internal/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/swing/internal/plaf/synth/resources \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/print/resources \ + # + +ifeq ($(OPENJDK_TARGET_OS), macosx) + PROP_SRC_DIRS += \ + $(JDK_TOPDIR)/src/java.desktop/macosx/classes/com/apple/laf/resources \ + $(JDK_TOPDIR)/src/java.desktop/macosx/classes/sun/awt/resources \ + # +endif + +ifeq ($(OPENJDK_TARGET_OS), windows) + PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/windows/classes/sun/awt/windows +else + PROP_SRC_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources +endif + +$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ + $(filter %.properties, $(call CacheFind, $(PROP_SRC_DIRS))), ListResourceBundle)) + +GENSRC_JAVA_DESKTOP += $(COMPILE_PROPERTIES) + +# Some resources bundles are already present as java files but still need to be +# copied to zh_HK locale. +$(eval $(call SetupCopy-zh_HK,COPY_ZH_HK, \ + $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer_zh_TW.java)) + +GENSRC_JAVA_DESKTOP += $(COPY_ZH_HK) + +################################################################################ + java.desktop: $(GENSRC_JAVA_DESKTOP) all: java.desktop diff --git a/jdk/make/gensrc/Gensrc-java.logging.gmk b/jdk/make/gensrc/Gensrc-java.logging.gmk new file mode 100644 index 00000000000..18ad984f859 --- /dev/null +++ b/jdk/make/gensrc/Gensrc-java.logging.gmk @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 GensrcCommon.gmk + +################################################################################ + +include GensrcProperties.gmk + +$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)), \ + ListResourceBundle)) + +TARGETS += $(COMPILE_PROPERTIES) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all diff --git a/jdk/make/gensrc/Gensrc-java.management.gmk b/jdk/make/gensrc/Gensrc-java.management.gmk new file mode 100644 index 00000000000..408fe46f35e --- /dev/null +++ b/jdk/make/gensrc/Gensrc-java.management.gmk @@ -0,0 +1,43 @@ +# +# Copyright (c) 2011, 2013, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 GensrcCommon.gmk + +################################################################################ + +include GensrcProperties.gmk + +$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources)), \ + ListResourceBundle)) + +TARGETS += $(COMPILE_PROPERTIES) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all diff --git a/jdk/make/gensrc/Gensrc-jdk.dev.gmk b/jdk/make/gensrc/Gensrc-jdk.dev.gmk new file mode 100644 index 00000000000..60c6a527217 --- /dev/null +++ b/jdk/make/gensrc/Gensrc-jdk.dev.gmk @@ -0,0 +1,43 @@ +# +# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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 GensrcCommon.gmk + +################################################################################ + +include GensrcProperties.gmk + +$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/jdk.dev/share/classes/sun/tools/jar/resources)), \ + ListResourceBundle)) + +TARGETS += $(COMPILE_PROPERTIES) + +################################################################################ + +all: $(TARGETS) + +.PHONY: all diff --git a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk index 0f82955eb5e..e5bad8240d8 100644 --- a/jdk/make/gensrc/Gensrc-jdk.jdi.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.jdi.gmk @@ -69,6 +69,17 @@ GENSRC_JDK_JDI += $(JDK_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi. ################################################################################ +include GensrcProperties.gmk + +$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources)), \ + ListResourceBundle)) + +GENSRC_JDK_JDI += $(COMPILE_PROPERTIES) + +################################################################################ + jdk.jdi: $(GENSRC_JDK_JDI) all: jdk.jdi diff --git a/jdk/make/gensrc/Gensrc-jdk.localedata.gmk b/jdk/make/gensrc/Gensrc-jdk.localedata.gmk index bdc26421172..5759cb6093d 100644 --- a/jdk/make/gensrc/Gensrc-jdk.localedata.gmk +++ b/jdk/make/gensrc/Gensrc-jdk.localedata.gmk @@ -31,6 +31,20 @@ $(eval $(call IncludeCustomExtension, jdk, gensrc/Gensrc-jdk.localedata.gmk)) include GensrcLocaleData.gmk include GensrcCLDR.gmk +################################################################################ + +include GensrcProperties.gmk + +$(eval $(call SetupCompileProperties,COMPILE_PROPERTIES, \ + $(filter %.properties, \ + $(call CacheFind, $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources)), \ + sun.util.resources.LocaleNamesBundle)) + +# Skip generating zh_HK from zh_TW for this module. +GENSRC_JDK_LOCALEDATA += $(filter-out %_zh_HK.java, $(COMPILE_PROPERTIES)) + +################################################################################ + jdk.localedata: $(GENSRC_JDK_LOCALEDATA) all: jdk.localedata diff --git a/jdk/make/gensrc/GensrcProperties.gmk b/jdk/make/gensrc/GensrcProperties.gmk index a33015b150c..0b0520c6fd9 100644 --- a/jdk/make/gensrc/GensrcProperties.gmk +++ b/jdk/make/gensrc/GensrcProperties.gmk @@ -23,132 +23,81 @@ # questions. # -# All .properties files to be compiled are appended to this variable. -ALL_COMPILED_PROPSOURCES := -# All generated .java files from compilation are appended to this variable. -ALL_COMPILED_PROPJAVAS := -# The (very long) command line for compilation, stored in a file, prior to use. -COMPILE_PROPCMDLINE := +# This file defines macros that sets up rules for generating java classes +# from resource bundle properties files. -define add_properties_to_compile - # $1 is the name of the properties group - # $2 is the files belonging to this group - # $3 is the super class for the generated java file. +################################################################################ +# Helper macro for SetupCopy-zh_HK. +define SetupOneCopy-zh_HK + $1_$2_TARGET := $$(patsubst $(JDK_TOPDIR)/src/$(MODULE)/share/classes/%, \ + $(JDK_OUTPUTDIR)/gensrc/$(MODULE)/%, \ + $$(subst _zh_TW,_zh_HK, $2)) - # Convert /jdk/src//share/classes/sun/util/resources/CurrencyNames_sv.properties - # to /jdk/gensrc/ $$@ - # Accumulate all found properties files. - ALL_COMPILED_PROPSOURCES += $2 + $1 += $$($1_$2_TARGET) +endef - # Generate the list of to be created java files. - ALL_COMPILED_PROPJAVAS += $$($1_PROPJAVAS) +################################################################################ +# Creates rules for copying zh_TW resources to zh_HK. +# Param 1 - Variable to add targets to +# Param 2 - Files to copy from +define SetupCopy-zh_HK + $$(foreach f, $2, $$(eval $$(call SetupOneCopy-zh_HK,$1,$$f))) +endef - # Now generate a sequence of - # "-compile ...CurrencyNames_sv.properties ...CurrencyNames_sv.java ListResourceBundle" +################################################################################ +# Creates a rule that runs CompileProperties on a set of properties files. +# Param 1 - Variable to add targets to, must not contain space +# Param 2 - Properties files to process +# Param 3 - The super class for the generated classes +define SetupCompileProperties + $1_SRCS := $2 + $1_CLASS := $3 + + # Convert .../src//share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties + # to .../langtools/gensrc//com/sun/tools/javac/resources/javac_zh_CN.java + # Strip away prefix and suffix, leaving for example only: + # "/share/classes/com/sun/tools/javac/resources/javac_zh_CN" + $1_JAVAS := $$(patsubst $(JDK_TOPDIR)/src/%, \ + $(JDK_OUTPUTDIR)/gensrc/%, \ + $$(patsubst %.properties, %.java, \ + $$(subst /share/classes,, $$($1_SRCS)))) + + # Generate the package dirs for the to be generated java files. Sort to remove + # duplicates. + $1_DIRS := $$(sort $$(dir $$($1_JAVAS))) + + # Now generate a sequence of: + # "-compile ...javac_zh_CN.properties ...javac_zh_CN.java java.util.ListResourceBundle" # suitable to be fed into the CompileProperties command. - COMPILE_PROPCMDLINE += $$(subst _SPACE_,$(SPACE),$$(join $$(addprefix -compile_SPACE_, $2), \ - $$(addsuffix _SPACE_$(strip $3), \ - $$(addprefix _SPACE_, $$($1_PROPJAVAS))))) + $1_CMDLINE := $$(subst _SPACE_, $(SPACE), \ + $$(join $$(addprefix -compile_SPACE_, $$($1_SRCS)), \ + $$(addsuffix _SPACE_$$($1_CLASS), \ + $$(addprefix _SPACE_, $$($1_JAVAS))))) + + $1_TARGET := $(JDK_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.done + $1_CMDLINE_FILE := $(JDK_OUTPUTDIR)/gensrc/$(MODULE)/_the.$1.cmdline + + # Now setup the rule for the generation of the resource bundles. + $$($1_TARGET): $$($1_SRCS) $$($1_JAVAS) $(BUILD_TOOLS_JDK) + $(MKDIR) -p $$(@D) $$($1_DIRS) + $(ECHO) Compiling $$(words $$($1_SRCS)) properties into resource bundles for $(MODULE) + $(RM) $$($1_CMDLINE_FILE) + $$(call ListPathsSafely,$1_CMDLINE,\n, >> $$($1_CMDLINE_FILE)) + $(TOOL_COMPILEPROPERTIES) -quiet @$$($1_CMDLINE_FILE) + $(TOUCH) $$@ + + $$($1_JAVAS): $$($1_SRCS) + + # Create zh_HK versions of all zh_TW files created above + $$(eval $$(call SetupCopy-zh_HK,$1_HK,$$(filter %_zh_TW.java, $$($1_JAVAS)))) + # The zh_HK copy must wait for the compile properties tool to run + $$($1_HK): $$($1_TARGET) + + $1 += $$($1_JAVAS) $$($1_TARGET) $$($1_HK) endef ################################################################################ -# Some packages have properties that need to be converted to java source files. -COMPILE_PROP_SRC_FILES := \ - $(filter %.properties, $(call CacheFind, \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/accessibility/internal/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/windows/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/swing/internal/plaf/metal/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/swing/internal/plaf/synth/resources \ - $(JDK_TOPDIR)/src/jdk.jdi/share/classes/com/sun/tools/jdi/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/awt/resources \ - $(JDK_TOPDIR)/src/java.base/share/classes/sun/launcher/resources \ - $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/print/resources \ - $(JDK_TOPDIR)/src/jdk.dev/share/classes/sun/tools/jar/resources \ - $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)) \ - # - -ifeq ($(OPENJDK_TARGET_OS), macosx) - COMPILE_PROP_SRC_FILES += \ - $(filter %.properties, $(call CacheFind, \ - $(JDK_TOPDIR)/src/java.desktop/macosx/classes/com/apple/laf/resources \ - $(JDK_TOPDIR)/src/java.desktop/macosx/classes/sun/awt/resources)) \ - # -endif - -ifeq ($(OPENJDK_TARGET_OS), windows) - COMPILE_PROP_SRC_FILES += \ - $(filter %.properties, $(call CacheFind, \ - $(JDK_TOPDIR)/src/java.desktop/windows/classes/sun/awt/windows)) \ - # -else # ! windows - COMPILE_PROP_SRC_FILES += \ - $(filter %.properties, $(call CacheFind, \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/resources)) \ - # -endif - -$(eval $(call add_properties_to_compile,LIST_RESOURCE_BUNDLE, \ - $(COMPILE_PROP_SRC_FILES), ListResourceBundle)) - -# sun/util/resources -$(eval $(call add_properties_to_compile,SUN_UTIL, \ - $(filter %.properties, \ - $(call CacheFind, $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/resources) \ - $(call CacheFind, $(JDK_TOPDIR)/src/jdk.localedata/share/classes/sun/util/resources)), \ - sun.util.resources.LocaleNamesBundle)) - -################################################################################ -# Now setup the rule for the generation of the resource bundles. -$(JDK_OUTPUTDIR)/gensrc/_the.compiled_properties: $(ALL_COMPILED_PROPSOURCES) $(BUILD_TOOLS_JDK) - # Generate all output directories in advance since the build tool does not do that... - $(MKDIR) -p $(sort $(dir $(ALL_COMPILED_PROPJAVAS))) - $(ECHO) Compiling $(words $(ALL_COMPILED_PROPSOURCES)) properties into resource bundles - $(call ListPathsSafely,COMPILE_PROPCMDLINE,\n, >> $(JDK_OUTPUTDIR)/gensrc/_the.cmdline) - $(TOOL_COMPILEPROPERTIES) -quiet @$(JDK_OUTPUTDIR)/gensrc/_the.cmdline - $(TOUCH) $@ - -$(ALL_COMPILED_PROPJAVAS): $(JDK_OUTPUTDIR)/gensrc/_the.compiled_properties - -################################################################################ -# Some zh_HK resources are just copies of zh_TW - -define convert_tw_to_hk - $(MKDIR) -p $(@D) - $(CAT) $< | $(SED) -e '/class/s/_zh_TW/_zh_HK/' > $@ -endef - -# Some are copies of existing sources -$(JDK_OUTPUTDIR)/gensrc/java.desktop/%_zh_HK.java: \ - $(JDK_TOPDIR)/src/java.desktop/share/classes/%_zh_TW.java - $(call convert_tw_to_hk) - -$(JDK_OUTPUTDIR)/gensrc/java.base/%_zh_HK.java: \ - $(JDK_TOPDIR)/src/java.base/share/classes/%_zh_TW.java - $(call convert_tw_to_hk) - -# Others are copies of sources generated by this makefile -$(JDK_OUTPUTDIR)/gensrc/%_zh_HK.java: $(JDK_OUTPUTDIR)/gensrc/%_zh_TW.java - $(call convert_tw_to_hk) - -# The existing sources -ZH_HK_JAVA := java.desktop/sun/applet/resources/MsgAppletViewer_zh_HK.java \ - java.base/sun/misc/resources/Messages_zh_HK.java \ - java.base/sun/security/util/AuthResources_zh_HK.java \ - java.base/sun/security/util/Resources_zh_HK.java - -ZH_HK_JAVA_FILES := $(addprefix $(JDK_OUTPUTDIR)/gensrc/, $(ZH_HK_JAVA)) \ - $(filter-out $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/zh/%, \ - $(subst _zh_TW,_zh_HK,$(filter %_zh_TW.java, $(ALL_COMPILED_PROPJAVAS)))) - -################################################################################ - -GENSRC_PROPERTIES := $(ALL_COMPILED_PROPJAVAS) $(ZH_HK_JAVA_FILES) From 3f4fc41640459325196d3c83815b5ef816b185a9 Mon Sep 17 00:00:00 2001 From: Amanda Jiang Date: Thu, 16 Oct 2014 10:50:17 +0100 Subject: [PATCH 82/91] 8047031: Add SocketPermission tests for legacy socket types Reviewed-by: chegar --- .../SocketPermissionTest.java | 236 ++++++++++++++++++ jdk/test/java/net/SocketPermission/policy | 3 + 2 files changed, 239 insertions(+) create mode 100644 jdk/test/java/net/SocketPermission/SocketPermissionTest.java create mode 100644 jdk/test/java/net/SocketPermission/policy diff --git a/jdk/test/java/net/SocketPermission/SocketPermissionTest.java b/jdk/test/java/net/SocketPermission/SocketPermissionTest.java new file mode 100644 index 00000000000..3188f8695a8 --- /dev/null +++ b/jdk/test/java/net/SocketPermission/SocketPermissionTest.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8047031 + * @summary SocketPermission tests for legacy socket types + * @library ../../../lib/testlibrary + * @run testng/othervm/policy=policy SocketPermissionTest + */ +import java.io.IOException; +import java.net.DatagramPacket; +import java.net.DatagramSocket; +import java.net.InetAddress; +import java.net.MulticastSocket; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketPermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.Permission; +import java.security.Permissions; +import java.security.PrivilegedAction; +import java.security.ProtectionDomain; +import java.util.Arrays; +import java.util.function.Function; +import java.util.function.IntConsumer; +import static jdk.testlibrary.Utils.getFreePort; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class SocketPermissionTest { + private int freePort = -1; + + //positive tests + @Test(dataProvider = "positiveProvider") + public void testPositive(Function genAcc, IntConsumer func) { + String addr = "localhost:" + freePort; + AccessControlContext acc = genAcc.apply(addr); + AccessController.doPrivileged((PrivilegedAction) () -> { + func.accept(freePort); + return null; + }, acc); + } + + //negative tests + @Test(dataProvider = "negativeProvider", expectedExceptions = SecurityException.class) + public void testNegative(AccessControlContext acc, IntConsumer func) { + AccessController.doPrivileged((PrivilegedAction) () -> { + func.accept(freePort); + return null; + }, acc); + } + + @BeforeMethod + public void setFreePort() throws Exception { + freePort = getFreePort(); + } + + @DataProvider + public Object[][] positiveProvider() { + //test for SocketPermission "host:port","connect,resolve"; + Function generateAcc1 = (addr) -> getAccessControlContext( + new SocketPermission(addr, "listen, connect,resolve")); + IntConsumer func1 = (i) -> connectSocketTest(i); + IntConsumer func2 = (i) -> connectDatagramSocketTest(i); + + //test for SocketPermission "localhost:1024-","accept"; + Function generateAcc2 = (addr) -> getAccessControlContext( + new SocketPermission(addr, "listen,connect,resolve"), + new SocketPermission("localhost:1024-", "accept")); + IntConsumer func3 = (i) -> acceptServerSocketTest(i); + + //test for SocketPermission "229.227.226.221", "connect,accept" + Function generateAcc3 = (addr) -> getAccessControlContext( + new SocketPermission(addr, "listen,resolve"), + new SocketPermission("229.227.226.221", "connect,accept")); + IntConsumer func4 = (i) -> sendDatagramPacketTest(i); + IntConsumer func5 = (i) -> joinGroupMulticastTest(i); + + //test for SocketPermission "host:port", "listen" + Function generateAcc4 = (addr) -> getAccessControlContext( + new SocketPermission(addr, "listen")); + IntConsumer func6 = (i) -> listenDatagramSocketTest(i); + IntConsumer func7 = (i) -> listenMulticastSocketTest(i); + IntConsumer func8 = (i) -> listenServerSocketTest(i); + + return new Object[][]{ + {generateAcc1, func1}, + {generateAcc1, func2}, + {generateAcc2, func3}, + {generateAcc3, func4}, + {generateAcc3, func5}, + {generateAcc4, func6}, + {generateAcc4, func7}, + {generateAcc4, func8} + }; + } + + @DataProvider + public Object[][] negativeProvider() { + IntConsumer[] funcs = {i -> connectSocketTest(i), + i -> connectDatagramSocketTest(i), i -> acceptServerSocketTest(i), + i -> sendDatagramPacketTest(i), i -> joinGroupMulticastTest(i), + i -> listenDatagramSocketTest(i), i -> listenMulticastSocketTest(i), + i -> listenServerSocketTest(i)}; + return Arrays.stream(funcs).map(f -> { + //Construct an AccessControlContext without SocketPermission + AccessControlContext acc = getAccessControlContext( + new java.io.FilePermission("<>", "read,write,execute,delete"), + new java.net.NetPermission("*"), + new java.util.PropertyPermission("*", "read,write"), + new java.lang.reflect.ReflectPermission("*"), + new java.lang.RuntimePermission("*"), + new java.security.SecurityPermission("*"), + new java.io.SerializablePermission("*")); + return new Object[]{acc, f}; + }).toArray(Object[][]::new); + } + + public void connectSocketTest(int port) { + try (ServerSocket server = new ServerSocket(port); + Socket client = new Socket(InetAddress.getLocalHost(), port);) { + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void connectDatagramSocketTest(int port) { + String msg = "Hello"; + try { + InetAddress me = InetAddress.getLocalHost(); + try (DatagramSocket ds = new DatagramSocket(port, me)) { + DatagramPacket dp = new DatagramPacket(msg.getBytes(), + msg.length(), me, port); + ds.send(dp); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void acceptServerSocketTest(int port) { + try { + InetAddress me = InetAddress.getLocalHost(); + try (ServerSocket server = new ServerSocket(port)) { + Socket client = new Socket(me, port); + server.accept(); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public static void sendDatagramPacketTest(int port) { + String msg = "Hello"; + try { + InetAddress group = InetAddress.getByName("229.227.226.221"); + try (DatagramSocket s = new DatagramSocket(port)) { + DatagramPacket hi = new DatagramPacket(msg.getBytes(), + msg.length(), group, port); + s.send(hi); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void joinGroupMulticastTest(int port) { + try { + InetAddress group = InetAddress.getByName("229.227.226.221"); + try (MulticastSocket s = new MulticastSocket(port)) { + s.joinGroup(group); + s.leaveGroup(group); + } + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void listenDatagramSocketTest(int port) { + try (DatagramSocket ds = new DatagramSocket(port)) { + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void listenMulticastSocketTest(int port) { + try (MulticastSocket ms = new MulticastSocket(port)) { + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + public void listenServerSocketTest(int port) { + try (ServerSocket ms = new ServerSocket(port)) { + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private static AccessControlContext getAccessControlContext(Permission... ps) { + Permissions perms = new Permissions(); + for (Permission p : ps) { + perms.add(p); + } + /* + *Create an AccessControlContext that consist a single protection domain + * with only the permissions calculated above + */ + ProtectionDomain pd = new ProtectionDomain(null, perms); + return new AccessControlContext(new ProtectionDomain[]{pd}); + } + +} diff --git a/jdk/test/java/net/SocketPermission/policy b/jdk/test/java/net/SocketPermission/policy new file mode 100644 index 00000000000..eb780373774 --- /dev/null +++ b/jdk/test/java/net/SocketPermission/policy @@ -0,0 +1,3 @@ +grant { + permission java.security.AllPermission; +}; \ No newline at end of file From 4bf024dde1db3424f2e6756658b54dc89a0c6ca6 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Thu, 16 Oct 2014 12:34:07 +0100 Subject: [PATCH 83/91] 8044627: Update JNDI to work with modules Reviewed-by: alanb, chegar --- .../javax/naming/spi/NamingManager.java | 72 +++- .../spi/providers/InitialContextTest.java | 372 ++++++++++++++++++ .../spi/providers/broken_factory.template | 178 +++++++++ .../naming/spi/providers/factory.template | 173 ++++++++ .../javax/naming/spi/providers/test.template | 40 ++ 5 files changed, 816 insertions(+), 19 deletions(-) create mode 100644 jdk/test/javax/naming/spi/providers/InitialContextTest.java create mode 100644 jdk/test/javax/naming/spi/providers/broken_factory.template create mode 100644 jdk/test/javax/naming/spi/providers/factory.template create mode 100644 jdk/test/javax/naming/spi/providers/test.template diff --git a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java index 6bb98ddc0ee..b7c0010dae2 100644 --- a/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java +++ b/jdk/src/java.naming/share/classes/javax/naming/spi/NamingManager.java @@ -25,9 +25,7 @@ package javax.naming.spi; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.StringTokenizer; +import java.util.*; import java.net.MalformedURLException; import javax.naming.*; @@ -625,15 +623,28 @@ public class NamingManager { /** * Creates an initial context using the specified environment * properties. - *

- * If an InitialContextFactoryBuilder has been installed, - * it is used to create the factory for creating the initial context. - * Otherwise, the class specified in the - * Context.INITIAL_CONTEXT_FACTORY environment property is used. - * Note that an initial context factory (an object that implements the - * InitialContextFactory interface) must be public and must have a - * public constructor that accepts no arguments. - * + *

+ * This is done as follows: + *

    + *
  • If an InitialContextFactoryBuilder has been installed, + * it is used to create the factory for creating the initial + * context
  • + *
  • Otherwise, the class specified in the + * Context.INITIAL_CONTEXT_FACTORY environment property + * is used + *
      + *
    • First, the {@linkplain java.util.ServiceLoader ServiceLoader} + * mechanism tries to locate an {@code InitialContextFactory} + * provider using the current thread's context class loader
    • + *
    • Failing that, this implementation tries to locate a suitable + * {@code InitialContextFactory} using a built-in mechanism + *
      + * (Note that an initial context factory (an object that implements + * the InitialContextFactory interface) must be public and must have + * a public constructor that accepts no arguments)
    • + *
    + *
  • + *
* @param env The possibly null environment properties used when * creating the context. * @return A non-null initial context. @@ -649,11 +660,11 @@ public class NamingManager { */ public static Context getInitialContext(Hashtable env) throws NamingException { - InitialContextFactory factory; + InitialContextFactory factory = null; InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder(); if (builder == null) { - // No factory installed, use property + // No builder installed, use property // Get initial context factory class name String className = env != null ? @@ -666,16 +677,39 @@ public class NamingManager { throw ne; } + ServiceLoader loader = + ServiceLoader.load(InitialContextFactory.class); + + Iterator iterator = loader.iterator(); try { - factory = (InitialContextFactory) - helper.loadClass(className).newInstance(); - } catch(Exception e) { + while (iterator.hasNext()) { + InitialContextFactory f = iterator.next(); + if (f.getClass().getName().equals(className)) { + factory = f; + break; + } + } + } catch (ServiceConfigurationError e) { NoInitialContextException ne = - new NoInitialContextException( - "Cannot instantiate class: " + className); + new NoInitialContextException( + "Cannot load initial context factory " + + "'" + className + "'"); ne.setRootCause(e); throw ne; } + + if (factory == null) { + try { + factory = (InitialContextFactory) + helper.loadClass(className).newInstance(); + } catch (Exception e) { + NoInitialContextException ne = + new NoInitialContextException( + "Cannot instantiate class: " + className); + ne.setRootCause(e); + throw ne; + } + } } else { factory = builder.createInitialContextFactory(env); } diff --git a/jdk/test/javax/naming/spi/providers/InitialContextTest.java b/jdk/test/javax/naming/spi/providers/InitialContextTest.java new file mode 100644 index 00000000000..079f636331e --- /dev/null +++ b/jdk/test/javax/naming/spi/providers/InitialContextTest.java @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.naming.Context; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.lang.String.format; +import static java.util.Arrays.asList; +import static java.util.Collections.singleton; +import static java.util.Collections.singletonMap; + +/* + * @test + * @bug 8044627 + * @summary Examines different ways JNDI providers can hook up themselves and + * become available. Each case mimics the most straightforward way of + * executing scenarios. + */ +public class InitialContextTest { + + public static void main(String[] args) throws Throwable { + unknownInitialContextFactory(); + initialContextFactoryInAJar(); + initialContextFactoryAsService(); + } + + private static void unknownInitialContextFactory() throws Throwable { + + // This is a parameter of this test case, it should work for any value + // of it, provided a class with this FQN is not available in a runtime. + // So pick any name you like. + String factoryClassFqn = + "net.java.openjdk.test.UnknownInitialContextFactory"; + + Path tmp = Files.createDirectory(Paths.get("InitialContextTest-1")); + + Path src = templatesHome().resolve("test.template"); + Path dst = tmp.resolve("Test.java"); + Files.copy(src, dst); + + javac(tmp, dst); + + Path build = Files.createDirectory(tmp.resolve("build")); + Files.copy(tmp.resolve("Test.class"), build.resolve("Test.class")); + + Map props + = singletonMap(Context.INITIAL_CONTEXT_FACTORY, factoryClassFqn); + + Result r = java(props, singleton(build), "Test"); + + if (r.exitValue == 0 || !r.output.startsWith( + stackTraceStringForClassNotFound(factoryClassFqn))) { + throw new RuntimeException( + "Expected a different kind of failure: " + r.output); + } + } + + private static String stackTraceStringForClassNotFound(String fqn) { + return String.format( + "Exception in thread \"main\" javax.naming.NoInitialContextException: " + + "Cannot instantiate class: %s " + + "[Root exception is java.lang.ClassNotFoundException: %s]", + fqn, fqn); + } + + private static void initialContextFactoryInAJar() throws Throwable { + + String factoryClassFqn = + "net.java.openjdk.test.DummyInitialContextFactory"; + + Path tmp = Files.createDirectory(Paths.get("InitialContextTest-2")); + + Path src = templatesHome().resolve("test.template"); + Path dst = tmp.resolve("Test.java"); + Files.copy(src, dst); + + Path dst1 = createFactoryFrom(templatesHome().resolve("factory.template"), + factoryClassFqn, tmp); + + javac(tmp, dst); + Path explodedJar = Files.createDirectory(tmp.resolve("exploded-jar")); + javac(explodedJar, dst1); + jar(tmp.resolve("test.jar"), explodedJar); + + Path build = Files.createDirectory(tmp.resolve("build")); + Files.copy(tmp.resolve("Test.class"), build.resolve("Test.class")); + Files.copy(tmp.resolve("test.jar"), build.resolve("test.jar")); + + Map props + = singletonMap(Context.INITIAL_CONTEXT_FACTORY, factoryClassFqn); + + Result r = java(props, asList(build.resolve("test.jar"), build), "Test"); + + if (r.exitValue != 0 || !r.output.isEmpty()) + throw new RuntimeException(r.output); + } + + + private static Path createFactoryFrom(Path srcTemplate, + String factoryFqn, + Path dstFolder) throws IOException { + + String factorySimpleName, packageName; + int i = factoryFqn.lastIndexOf('.'); + if (i < 0) { + packageName = ""; + factorySimpleName = factoryFqn; + } else { + packageName = factoryFqn.substring(0, i); + factorySimpleName = factoryFqn.substring(i + 1); + } + + Path result = dstFolder.resolve(factorySimpleName + ".java"); + File dst = result.toFile(); + File src = srcTemplate.toFile(); + try (BufferedReader r = new BufferedReader(new FileReader(src)); + BufferedWriter w = new BufferedWriter(new FileWriter(dst))) { + + List lines = processTemplate(packageName, factorySimpleName, + r.lines()).collect(Collectors.toList()); + + Iterator it = lines.iterator(); + if (it.hasNext()) + w.write(it.next()); + while (it.hasNext()) { + w.newLine(); + w.write(it.next()); + } + } + return result; + } + + private static Stream processTemplate(String packageName, + String factorySimpleName, + Stream lines) { + Function pckg; + + if (packageName.isEmpty()) { + pckg = s -> s.contains("$package") ? "" : s; + } else { + pckg = s -> s.replaceAll("\\$package", packageName); + } + + Function factory + = s -> s.replaceAll("\\$factoryName", factorySimpleName); + + return lines.map(pckg).map(factory); + } + + private static void initialContextFactoryAsService() throws Throwable { + + String factoryClassFqn = + "net.java.openjdk.test.BrokenInitialContextFactory"; + + Path tmp = Files.createDirectory(Paths.get("InitialContextTest-3")); + + Path src = templatesHome().resolve("test.template"); + Path dst = tmp.resolve("Test.java"); + Files.copy(src, dst); + + Path dst1 = createFactoryFrom(templatesHome().resolve("broken_factory.template"), + factoryClassFqn, tmp); + + javac(tmp, dst); + + Path explodedJar = Files.createDirectory(tmp.resolve("exploded-jar")); + Path services = Files.createDirectories(explodedJar.resolve("META-INF") + .resolve("services")); + + Path s = services.resolve("javax.naming.spi.InitialContextFactory"); + FileWriter fw = new FileWriter(s.toFile()); + try { + fw.write(factoryClassFqn); + } finally { + fw.close(); + } + + javac(explodedJar, dst1); + jar(tmp.resolve("test.jar"), explodedJar); + + Path build = Files.createDirectory(tmp.resolve("build")); + Files.copy(tmp.resolve("Test.class"), build.resolve("Test.class")); + Files.copy(tmp.resolve("test.jar"), build.resolve("test.jar")); + + Map props = new HashMap<>(); + props.put("java.ext.dirs", build.toString()); + props.put(Context.INITIAL_CONTEXT_FACTORY, factoryClassFqn); + + Result r = java(props, singleton(build), "Test"); + + if (r.exitValue == 0 || !verifyOutput(r.output, factoryClassFqn)) + throw new RuntimeException(r.output); + } + + // IMO, that's the easiest way that gives you a fair amount of confidence in + // that j.u.ServiceLoader is loading a factory rather than Class.forName + private static boolean verifyOutput(String output, String fqn) { + String s1 = String.format( + "Exception in thread \"main\" javax.naming.NoInitialContextException: " + + "Cannot load initial context factory '%s' " + + "[Root exception is java.util.ServiceConfigurationError: " + + "javax.naming.spi.InitialContextFactory: " + + "Provider %s could not be instantiated]", fqn, fqn); + + String s2 = String.format("Caused by: java.util.ServiceConfigurationError: " + + "javax.naming.spi.InitialContextFactory: " + + "Provider %s could not be instantiated", fqn); + + String s3 = "Caused by: java.lang.RuntimeException: " + + "This is a broken factory. It is supposed to throw this exception."; + + return output.startsWith(s1) && output.contains(s2) + && output.contains(s1); + } + + private static void jar(Path jarName, Path jarRoot) { + String jar = getJDKTool("jar"); + ProcessBuilder p = new ProcessBuilder(jar, "cf", jarName.toString(), + "-C", jarRoot.toString(), "."); + quickFail(run(p)); + } + + private static void javac(Path compilationOutput, Path... sourceFiles) { + String javac = getJDKTool("javac"); + List commands = new ArrayList<>(); + commands.addAll(asList(javac, "-d", compilationOutput.toString())); + List paths = asList(sourceFiles); + commands.addAll(paths.stream() + .map(Path::toString) + .collect(Collectors.toList())); + quickFail(run(new ProcessBuilder(commands))); + } + + private static void quickFail(Result r) { + if (r.exitValue != 0) + throw new RuntimeException(r.output); + } + + private static Result java(Map properties, + Collection classpath, + String classname) { + + String java = getJDKTool("java"); + + List commands = new ArrayList<>(); + commands.add(java); + commands.addAll(properties.entrySet() + .stream() + .map(e -> "-D" + e.getKey() + "=" + e.getValue()) + .collect(Collectors.toList())); + + String cp = classpath.stream() + .map(Path::toString) + .collect(Collectors.joining(File.pathSeparator)); + commands.add("-cp"); + commands.add(cp); + commands.add(classname); + + return run(new ProcessBuilder(commands)); + } + + private static Result run(ProcessBuilder b) { + Process p = null; + try { + p = b.start(); + } catch (IOException e) { + throw new RuntimeException( + format("Couldn't start process '%s'", b.command()), e); + } + + String output; + try { + output = toString(p.getInputStream(), p.getErrorStream()); + } catch (IOException e) { + throw new RuntimeException( + format("Couldn't read process output '%s'", b.command()), e); + } + + try { + p.waitFor(); + } catch (InterruptedException e) { + throw new RuntimeException( + format("Process hasn't finished '%s'", b.command()), e); + } + + return new Result(p.exitValue(), output); + } + + private static String getJDKTool(String name) { + String testJdk = System.getProperty("test.jdk"); + if (testJdk == null) + throw new RuntimeException("Please provide test.jdk property at a startup"); + return testJdk + File.separator + "bin" + File.separator + name; + } + + private static Path templatesHome() { + String testSrc = System.getProperty("test.src"); + if (testSrc == null) + throw new RuntimeException("Please provide test.src property at a startup"); + return Paths.get(testSrc); + } + + private static String toString(InputStream... src) throws IOException { + StringWriter dst = new StringWriter(); + Reader concatenated = + new InputStreamReader( + new SequenceInputStream( + Collections.enumeration(asList(src)))); + copy(concatenated, dst); + return dst.toString(); + } + + private static void copy(Reader src, Writer dst) throws IOException { + int len; + char[] buf = new char[1024]; + try { + while ((len = src.read(buf)) != -1) + dst.write(buf, 0, len); + } finally { + try { + src.close(); + } catch (IOException ignored1) { + } finally { + try { + dst.close(); + } catch (IOException ignored2) { + } + } + } + } + + private static class Result { + + final int exitValue; + final String output; + + private Result(int exitValue, String output) { + this.exitValue = exitValue; + this.output = output; + } + } +} diff --git a/jdk/test/javax/naming/spi/providers/broken_factory.template b/jdk/test/javax/naming/spi/providers/broken_factory.template new file mode 100644 index 00000000000..1f45837c591 --- /dev/null +++ b/jdk/test/javax/naming/spi/providers/broken_factory.template @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package $package; + +import javax.naming.*; +import javax.naming.spi.InitialContextFactory; +import java.util.Hashtable; + +public class $factoryName implements InitialContextFactory { + + public $factoryName() { + throw new RuntimeException( + "This is a broken factory. It is supposed to throw this exception."); + } + + @Override + public Context getInitialContext(Hashtable env) throws NamingException { + return new DummyInitialContext(); + } + + private class DummyInitialContext implements Context { + + @Override + public Object lookup(Name name) { + return null; + } + + @Override + public Object lookup(String name) { + return null; + } + + @Override + public void bind(Name name, Object obj) { + } + + @Override + public void bind(String name, Object obj) { + } + + @Override + public void rebind(Name name, Object obj) { + } + + @Override + public void rebind(String name, Object obj) { + } + + @Override + public void unbind(Name name) { + } + + @Override + public void unbind(String name) { + } + + @Override + public void rename(Name oldName, Name newName) { + } + + @Override + public void rename(String oldName, String newName) { + } + + @Override + public NamingEnumeration list(Name name) { + return null; + } + + @Override + public NamingEnumeration list(String name) { + return null; + } + + @Override + public NamingEnumeration listBindings(Name name) { + return null; + } + + @Override + public NamingEnumeration listBindings(String name) { + return null; + } + + @Override + public void destroySubcontext(Name name) { + } + + @Override + public void destroySubcontext(String name) { + } + + @Override + public Context createSubcontext(Name name) { + return null; + } + + @Override + public Context createSubcontext(String name) { + return null; + } + + @Override + public Object lookupLink(Name name) { + return null; + } + + @Override + public Object lookupLink(String name) { + return null; + } + + @Override + public NameParser getNameParser(Name name) { + return null; + } + + @Override + public NameParser getNameParser(String name) { + return null; + } + + @Override + public Name composeName(Name name, Name prefix) { + return null; + } + + @Override + public String composeName(String name, String prefix) { + return null; + } + + @Override + public Object addToEnvironment(String propName, Object propVal) { + return null; + } + + @Override + public Object removeFromEnvironment(String propName) { + return null; + } + + @Override + public Hashtable getEnvironment() { + return null; + } + + @Override + public void close() { + } + + @Override + public String getNameInNamespace() { + return null; + } + } +} diff --git a/jdk/test/javax/naming/spi/providers/factory.template b/jdk/test/javax/naming/spi/providers/factory.template new file mode 100644 index 00000000000..51eb6d09438 --- /dev/null +++ b/jdk/test/javax/naming/spi/providers/factory.template @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package $package; + +import javax.naming.*; +import javax.naming.spi.InitialContextFactory; +import java.util.Hashtable; + +public class $factoryName implements InitialContextFactory { + + @Override + public Context getInitialContext(Hashtable env) throws NamingException { + return new DummyInitialContext(); + } + + private class DummyInitialContext implements Context { + + @Override + public Object lookup(Name name) { + return null; + } + + @Override + public Object lookup(String name) { + return null; + } + + @Override + public void bind(Name name, Object obj) { + } + + @Override + public void bind(String name, Object obj) { + } + + @Override + public void rebind(Name name, Object obj) { + } + + @Override + public void rebind(String name, Object obj) { + } + + @Override + public void unbind(Name name) { + } + + @Override + public void unbind(String name) { + } + + @Override + public void rename(Name oldName, Name newName) { + } + + @Override + public void rename(String oldName, String newName) { + } + + @Override + public NamingEnumeration list(Name name) { + return null; + } + + @Override + public NamingEnumeration list(String name) { + return null; + } + + @Override + public NamingEnumeration listBindings(Name name) { + return null; + } + + @Override + public NamingEnumeration listBindings(String name) { + return null; + } + + @Override + public void destroySubcontext(Name name) { + } + + @Override + public void destroySubcontext(String name) { + } + + @Override + public Context createSubcontext(Name name) { + return null; + } + + @Override + public Context createSubcontext(String name) { + return null; + } + + @Override + public Object lookupLink(Name name) { + return null; + } + + @Override + public Object lookupLink(String name) { + return null; + } + + @Override + public NameParser getNameParser(Name name) { + return null; + } + + @Override + public NameParser getNameParser(String name) { + return null; + } + + @Override + public Name composeName(Name name, Name prefix) { + return null; + } + + @Override + public String composeName(String name, String prefix) { + return null; + } + + @Override + public Object addToEnvironment(String propName, Object propVal) { + return null; + } + + @Override + public Object removeFromEnvironment(String propName) { + return null; + } + + @Override + public Hashtable getEnvironment() { + return null; + } + + @Override + public void close() { + } + + @Override + public String getNameInNamespace() { + return null; + } + } +} diff --git a/jdk/test/javax/naming/spi/providers/test.template b/jdk/test/javax/naming/spi/providers/test.template new file mode 100644 index 00000000000..860cce27555 --- /dev/null +++ b/jdk/test/javax/naming/spi/providers/test.template @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import java.util.Properties; + +public class Test { + + public static void main(String[] args) throws NamingException { + Properties env = System.getProperties(); + Context ctx = new InitialContext(env); + try { + ctx.lookup(""); + } finally { + ctx.close(); + } + } +} From 823f5f273e9a02b41317fed4fc356ff3c6e0b5ed Mon Sep 17 00:00:00 2001 From: Jamil Nimeh Date: Wed, 15 Oct 2014 11:43:27 -0700 Subject: [PATCH 84/91] 8032573: CertificateFactory.getInstance("X.509").generateCertificates(InputStream) does not throw CertificateException for invalid input Reviewed-by: weijun --- .../sun/security/provider/X509Factory.java | 80 ++- .../DetectInvalidEncoding.java | 545 +++++++++++++++++- .../invalidEncodedCerts/invalidcert.pem | 14 - 3 files changed, 602 insertions(+), 37 deletions(-) delete mode 100644 jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/invalidcert.pem diff --git a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java index 51b618d93b8..46b1a3c8d7d 100644 --- a/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java +++ b/jdk/src/java.base/share/classes/sun/security/provider/X509Factory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,7 @@ public class X509Factory extends CertificateFactorySpi { * * @exception CertificateException on parsing errors. */ + @Override public Certificate engineGenerateCertificate(InputStream is) throws CertificateException { @@ -103,8 +104,8 @@ public class X509Factory extends CertificateFactorySpi { throw new IOException("Empty input"); } } catch (IOException ioe) { - throw (CertificateException)new CertificateException - ("Could not parse certificate: " + ioe.toString()).initCause(ioe); + throw new CertificateException("Could not parse certificate: " + + ioe.toString(), ioe); } } @@ -140,6 +141,12 @@ public class X509Factory extends CertificateFactorySpi { * It is useful for certificates that cannot be created via * generateCertificate() and for converting other X509Certificate * implementations to an X509CertImpl. + * + * @param c The source X509Certificate + * @return An X509CertImpl object that is either a cached certificate or a + * newly built X509CertImpl from the provided X509Certificate + * @throws CertificateException if failures occur while obtaining the DER + * encoding for certificate data. */ public static synchronized X509CertImpl intern(X509Certificate c) throws CertificateException { @@ -170,6 +177,12 @@ public class X509Factory extends CertificateFactorySpi { /** * Return an interned X509CRLImpl for the given certificate. * For more information, see intern(X509Certificate). + * + * @param c The source X509CRL + * @return An X509CRLImpl object that is either a cached CRL or a + * newly built X509CRLImpl from the provided X509CRL + * @throws CRLException if failures occur while obtaining the DER + * encoding for CRL data. */ public static synchronized X509CRLImpl intern(X509CRL c) throws CRLException { @@ -229,6 +242,7 @@ public class X509Factory extends CertificateFactorySpi { * @exception CertificateException if an exception occurs while decoding * @since 1.4 */ + @Override public CertPath engineGenerateCertPath(InputStream inStream) throws CertificateException { @@ -260,6 +274,7 @@ public class X509Factory extends CertificateFactorySpi { * the encoding requested is not supported * @since 1.4 */ + @Override public CertPath engineGenerateCertPath(InputStream inStream, String encoding) throws CertificateException { @@ -292,6 +307,7 @@ public class X509Factory extends CertificateFactorySpi { * @exception CertificateException if an exception occurs * @since 1.4 */ + @Override public CertPath engineGenerateCertPath(List certificates) throws CertificateException @@ -311,6 +327,7 @@ public class X509Factory extends CertificateFactorySpi { * CertPath encodings (as Strings) * @since 1.4 */ + @Override public Iterator engineGetCertPathEncodings() { return(X509CertPath.getEncodingsStatic()); } @@ -326,6 +343,7 @@ public class X509Factory extends CertificateFactorySpi { * * @exception CertificateException on parsing errors. */ + @Override public Collection engineGenerateCertificates(InputStream is) throws CertificateException { @@ -351,6 +369,7 @@ public class X509Factory extends CertificateFactorySpi { * * @exception CRLException on parsing errors. */ + @Override public CRL engineGenerateCRL(InputStream is) throws CRLException { @@ -388,6 +407,7 @@ public class X509Factory extends CertificateFactorySpi { * * @exception CRLException on parsing errors. */ + @Override public Collection engineGenerateCRLs( InputStream is) throws CRLException { @@ -410,11 +430,30 @@ public class X509Factory extends CertificateFactorySpi { parseX509orPKCS7Cert(InputStream is) throws CertificateException, IOException { + int peekByte; + byte[] data; + PushbackInputStream pbis = new PushbackInputStream(is); Collection coll = new ArrayList<>(); - byte[] data = readOneBlock(is); - if (data == null) { + + // Test the InputStream for end-of-stream. If the stream's + // initial state is already at end-of-stream then return + // an empty collection. Otherwise, push the byte back into the + // stream and let readOneBlock look for the first certificate. + peekByte = pbis.read(); + if (peekByte == -1) { return new ArrayList<>(0); + } else { + pbis.unread(peekByte); + data = readOneBlock(pbis); } + + // If we end up with a null value after reading the first block + // then we know the end-of-stream has been reached and no certificate + // data has been found. + if (data == null) { + throw new CertificateException("No certificate data found"); + } + try { PKCS7 pkcs7 = new PKCS7(data); X509Certificate[] certs = pkcs7.getCertificates(); @@ -422,13 +461,13 @@ public class X509Factory extends CertificateFactorySpi { if (certs != null) { return Arrays.asList(certs); } else { - // no crls provided + // no certificates provided return new ArrayList<>(0); } } catch (ParsingException e) { while (data != null) { coll.add(new X509CertImpl(data)); - data = readOneBlock(is); + data = readOneBlock(pbis); } } return coll; @@ -443,11 +482,30 @@ public class X509Factory extends CertificateFactorySpi { parseX509orPKCS7CRL(InputStream is) throws CRLException, IOException { + int peekByte; + byte[] data; + PushbackInputStream pbis = new PushbackInputStream(is); Collection coll = new ArrayList<>(); - byte[] data = readOneBlock(is); - if (data == null) { + + // Test the InputStream for end-of-stream. If the stream's + // initial state is already at end-of-stream then return + // an empty collection. Otherwise, push the byte back into the + // stream and let readOneBlock look for the first CRL. + peekByte = pbis.read(); + if (peekByte == -1) { return new ArrayList<>(0); + } else { + pbis.unread(peekByte); + data = readOneBlock(pbis); } + + // If we end up with a null value after reading the first block + // then we know the end-of-stream has been reached and no CRL + // data has been found. + if (data == null) { + throw new CRLException("No CRL data found"); + } + try { PKCS7 pkcs7 = new PKCS7(data); X509CRL[] crls = pkcs7.getCRLs(); @@ -461,7 +519,7 @@ public class X509Factory extends CertificateFactorySpi { } catch (ParsingException e) { while (data != null) { coll.add(new X509CRLImpl(data)); - data = readOneBlock(is); + data = readOneBlock(pbis); } } return coll; @@ -623,7 +681,7 @@ public class X509Factory extends CertificateFactorySpi { int n = is.read(); if (n == -1) { - throw new IOException("BER/DER length info ansent"); + throw new IOException("BER/DER length info absent"); } bout.write(n); diff --git a/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/DetectInvalidEncoding.java b/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/DetectInvalidEncoding.java index 26db324f235..dab36fcb290 100644 --- a/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/DetectInvalidEncoding.java +++ b/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/DetectInvalidEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,27 +23,548 @@ /** * @test - * @bug 4776466 + * @bug 4776466 8032573 * @summary check that CertificateFactory rejects invalid encoded X.509 certs */ import java.io.*; +import java.util.Collection; +import java.util.List; +import java.util.LinkedList; +import javax.security.auth.x500.X500Principal; +import java.security.GeneralSecurityException; import java.security.cert.*; public class DetectInvalidEncoding { + // Originally found in the test file: + // java/security/cert/CertificateFactory/invalidEncodedCerts/invalidcert.pem + // The first character of the PEM encoding has been changed from "M" to + // "X" to force a failure during decoding. + private static final String INVALID_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "XIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx\n" + + "EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFTAT\n" + + "BgNVBAoTDEJFQSBXZWJMb2dpYzERMA8GA1UECxMIU2VjdXJpdHkxIzAhBgNVBAMT\n" + + "GkRlbW8gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9zdXBw\n" + + "b3J0QGJlYS5jb20wHhcNMDAwNTMwMjEzODAxWhcNMDQwNTEzMjEzODAxWjCBjDEL\n" + + "MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\n" + + "cmFuY2lzY28xFTATBgNVBAoTDEJFQSBXZWJMb2dpYzEZMBcGA1UEAxMQd2VibG9n\n" + + "aWMuYmVhLmNvbTEeMBwGCSqGSIb3DQEJARYPc3VwcG9ydEBiZWEuY29tMFwwDQYJ\n" + + "KoZIhvcNAQEBBQADSwAwSAJBALdsXEHqKHgs6zj0hU5sXMAUHzoT8kgWXmNkKHXH\n" + + "79qbPh6EfdlriW9G/AbRF/pKrCQu7hhllAxREbqTuSlf2EMCAwEAATANBgkqhkiG\n" + + "9w0BAQQFAANBACgmqflL5m5LNeJGpWx9aIoABCiuDcpw1fFyegsqGX7CBhffcruS\n" + + "1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU=\n" + + "-----END CERTIFICATE-----"; + + // Created with keytool: + // keytool -genkeypair -keyalg rsa -keysize 2048 -keystore + // -alias root -sigalg SHA256withRSA -dname "CN=Root, O=SomeCompany" + // -validity 730 -ext bc:critical=ca:true + // -ext ku:critical=keyCertSign,cRLSign + private static final String SINGLE_ROOT_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDCjCCAfKgAwIBAgIEDUiw+DANBgkqhkiG9w0BAQsFADAlMRQwEgYDVQQKEwtT\n" + + "b21lQ29tcGFueTENMAsGA1UEAxMEUm9vdDAeFw0xNDA4MjgyMTI5MjZaFw0xNjA4\n" + + "MjcyMTI5MjZaMCUxFDASBgNVBAoTC1NvbWVDb21wYW55MQ0wCwYDVQQDEwRSb290\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0VFecSNdH6CJhPOSG127\n" + + "tuvld4y7GGJ0kQf3Q0b8qgprsXAmn0/bQR+YX7PfS408cFW+q2SWXeY2kC/3chvi\n" + + "2syMsGdUJrDzuMbYsbvKPKyuJ2GJskX3mSbLMJj5Tzhg4qmwbzDTFIJ51yGa1Wmh\n" + + "i2+4PhltqT0TohvSVJlBrOWNhmvwv5UWsF4e2i04rebDZQoWkmD3MpImZXF/HYre\n" + + "9P8NP97vN0xZmh5PySHy2ILXN3ZhTn3tq0YxNSQTaMUfhgoyzWFvZKAnm/tZIh/1\n" + + "oswwEQPIZJ25AUTm9r3YPQXl1hsNdLU0asEVYRsgzGSTX5gCuUY+KzhStzisOcUY\n" + + "uQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV\n" + + "HQ4EFgQUz1FBNixG/KCgcn6FOWzxP1hujG0wDQYJKoZIhvcNAQELBQADggEBAL60\n" + + "ZaNc6eIMbKntGVE/pdxxyKwPdDyAAeEevX23KRWoLbQjHXo5jrfDPhI5k45ztlyU\n" + + "+tIQbc81LlCl88I4dIx0fvEbxjNaAYhFNXwwSQBs2CuEAdRK8hodXbRcEeI+G10F\n" + + "ARIVs2C7JNm/RhxskCWgj6tFIOGaTZ9gHyvlQUEM18sr5fXZlXTqspZCmz3t5XPi\n" + + "5/wYLv6vk7k3G8WzMHbBE0bYI+61cCc8rbMHldtymbwSwiqfKC9y7oPEfRCbzVUe\n" + + "fgrKcOyVWDuw0y0hhsQL/oONjPp4uK/bl9B7T84t4+ihxdocWKx6eyhFvOvZH9t2\n" + + "kUylb9yBUYStwGExMHg=\n" + + "-----END CERTIFICATE-----"; + + // Created with keytool: + // keytool -genkeypair -keyalg rsa -keysize 2048 -keystore + // -alias root -sigalg SHA256withRSA + // -dname "CN=Intermed, O=SomeCompany" -validity 730 + // -ext bc:critical=ca:true -ext ku:critical=keyCertSign,cRLSign + // keytool -certreq -keystore -sigalg SHA256withRSA + // -alias intermed -dname "CN=Intermed, O=SomeCompany" + // keytool -gencert -keystore -alias intermed + // -sigalg SHA256withRSA -validity 730 + // -ext bc:critical=ca:true -ext ku:critical=keyCertSign,cRLSign + private static final String INTERMED_CA_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIDLzCCAhegAwIBAgIEIIgOyDANBgkqhkiG9w0BAQsFADAlMRQwEgYDVQQKEwtT\n" + + "b21lQ29tcGFueTENMAsGA1UEAxMEUm9vdDAeFw0xNDA4MjgyMjUyNDJaFw0xNjA4\n" + + "MDcyMjUyNDJaMCkxFDASBgNVBAoTC1NvbWVDb21wYW55MREwDwYDVQQDEwhJbnRl\n" + + "cm1lZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJEecvTWla8kdWx+\n" + + "HHu5ryfBpJ95I7V4MEajnmzJVZcwvKhDjlDgABDMuVwFEUUSyeOdbWJF3DLKnyMD\n" + + "KTx6/58kuVak3NX2TJ8cmmIlKf1upFbdrEtjYViSnNrApprfO8B3ORdBbO6QDYza\n" + + "IkAWdI5GllFnVkb4yhMUBg3zfhglF+bl3D3lVRlp9bCrUZoNRs+mZjhVbcMn22ej\n" + + "TfG5Y3VpNM4SN8dFIxPQLLk/aao+cmWEQdbQ0R6ydemRukqrw170olSVLeoGGala\n" + + "3D4oJckde8EgNPcghcsdQ6tpGhkpFhmoyzEsuToR7Gq9UT5V2kkqJneiKXqQg4wz\n" + + "vMAlUGECAwEAAaNjMGEwHwYDVR0jBBgwFoAUOw+92bevFoJz96pR1DrAkPPUKb0w\n" + + "DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLbnErBs\n" + + "q/Mhci5XElfjjLZp3GRyMA0GCSqGSIb3DQEBCwUAA4IBAQAq8y2DpkSV31IXZ1vr\n" + + "/Ye+Nj/2NvBydFeHVRGMAN1LJv6/Q42TCSXbr6cDQ4NWQUtPm90yZBYJSznkbShx\n" + + "HOJEE6R8PRJvoUtMm7fJrNtkybTt6jX4j50Lw8gdYB/rgZb4z8ZQZVEo/0zpW4HV\n" + + "Gs+q4z8TkdmLR18hl39sUEsxt99AOBk8NtKKVNfBWq9b0QDhRkXfmqhyeXdDsHOV\n" + + "8ksulsa7hseheHhdjziEOpQugh8qzSea2kFPrLB53VjWfa4qDzEPaNhahho9piCu\n" + + "82XDnOrcEk9KyHWM7sa7vtK7++W+0MXD/p9nkZ6NHrJXweLriU0DXO6ZY3mzNKJK\n" + + "435M\n" + + "-----END CERTIFICATE-----"; + + // Subordinate cert created using keytool, both certs exported to + // files individually, then use openssl to place in a PKCS#7: + // openssl crl2pkcs7 -nocrl -certfile + // -certfile -out + private static final String PKCS7_INTERMED_ROOT_CERTS = + "-----BEGIN PKCS7-----\n" + + "MIIGbgYJKoZIhvcNAQcCoIIGXzCCBlsCAQExADALBgkqhkiG9w0BBwGgggZBMIID\n" + + "LzCCAhegAwIBAgIEIIgOyDANBgkqhkiG9w0BAQsFADAlMRQwEgYDVQQKEwtTb21l\n" + + "Q29tcGFueTENMAsGA1UEAxMEUm9vdDAeFw0xNDA4MjgyMjUyNDJaFw0xNjA4MDcy\n" + + "MjUyNDJaMCkxFDASBgNVBAoTC1NvbWVDb21wYW55MREwDwYDVQQDEwhJbnRlcm1l\n" + + "ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJEecvTWla8kdWx+HHu5\n" + + "ryfBpJ95I7V4MEajnmzJVZcwvKhDjlDgABDMuVwFEUUSyeOdbWJF3DLKnyMDKTx6\n" + + "/58kuVak3NX2TJ8cmmIlKf1upFbdrEtjYViSnNrApprfO8B3ORdBbO6QDYzaIkAW\n" + + "dI5GllFnVkb4yhMUBg3zfhglF+bl3D3lVRlp9bCrUZoNRs+mZjhVbcMn22ejTfG5\n" + + "Y3VpNM4SN8dFIxPQLLk/aao+cmWEQdbQ0R6ydemRukqrw170olSVLeoGGala3D4o\n" + + "Jckde8EgNPcghcsdQ6tpGhkpFhmoyzEsuToR7Gq9UT5V2kkqJneiKXqQg4wzvMAl\n" + + "UGECAwEAAaNjMGEwHwYDVR0jBBgwFoAUOw+92bevFoJz96pR1DrAkPPUKb0wDwYD\n" + + "VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLbnErBsq/Mh\n" + + "ci5XElfjjLZp3GRyMA0GCSqGSIb3DQEBCwUAA4IBAQAq8y2DpkSV31IXZ1vr/Ye+\n" + + "Nj/2NvBydFeHVRGMAN1LJv6/Q42TCSXbr6cDQ4NWQUtPm90yZBYJSznkbShxHOJE\n" + + "E6R8PRJvoUtMm7fJrNtkybTt6jX4j50Lw8gdYB/rgZb4z8ZQZVEo/0zpW4HVGs+q\n" + + "4z8TkdmLR18hl39sUEsxt99AOBk8NtKKVNfBWq9b0QDhRkXfmqhyeXdDsHOV8ksu\n" + + "lsa7hseheHhdjziEOpQugh8qzSea2kFPrLB53VjWfa4qDzEPaNhahho9piCu82XD\n" + + "nOrcEk9KyHWM7sa7vtK7++W+0MXD/p9nkZ6NHrJXweLriU0DXO6ZY3mzNKJK435M\n" + + "MIIDCjCCAfKgAwIBAgIEdffjKTANBgkqhkiG9w0BAQsFADAlMRQwEgYDVQQKEwtT\n" + + "b21lQ29tcGFueTENMAsGA1UEAxMEUm9vdDAeFw0xNDA4MjgyMjQ2MzZaFw0xNjA4\n" + + "MjcyMjQ2MzZaMCUxFDASBgNVBAoTC1NvbWVDb21wYW55MQ0wCwYDVQQDEwRSb290\n" + + "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhnXc8Avv54Gk2xjVa2yA\n" + + "lBL/Cug1nyvKl5wqmN+foT6cMOX6bneCkJOJ4lSbch3gvl4ctlX/9hm3pB/+HhSr\n" + + "em2NcLQrLEq8l9Ar4RnqfoXQR4Uy+4P6wj9OcVV7e/v/+ZPnStOoEAtb5nAwsR2b\n" + + "hOC/tIFNwflrsmsmtMSoOiNftpYLFF4eOAdpDrXYMrqNu6ZxZsOQ7WZl4SsVOx1N\n" + + "/IINXwBLyoHJDzLZ0iJEV0O6mh846s0n6QXeK1P5d0uLcoZaZ1k8Q4sRcdoLA6rS\n" + + "e1WffipBFMvIuoDIigkHZIKVYRLG828rO+PFnRah0ybybkVsN6s3oLxfhswZDvut\n" + + "OwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV\n" + + "HQ4EFgQUOw+92bevFoJz96pR1DrAkPPUKb0wDQYJKoZIhvcNAQELBQADggEBACBN\n" + + "wEaV70FKKBINHtNwesd7TB6fgSaVgDZOO08aseHbXnm7AUhtDV3P5rQR2AsKtbg4\n" + + "COhlKw2/Ki18D4DfdCccFKFTRZBjqj2PxNmn6C68l1/bT4PuUXuM7rW++53RcOA7\n" + + "TbgLuzA25kSz7XinRvR8L4VwHtppu5tSYEthMIMgLZLGGV9r7kBfpY8lXdxQM8vb\n" + + "xZUIysasvVtVUFPOTV6g2dfn8QCoqLOmxyzTLdXe4M6acP6f7lmhgr3LMqDtB6K9\n" + + "pN+OImr77zNdZ+jTB+5e9a8gAvc5ZfG7Nk5RfwUatYTAFZ6Uggy2cKmIRpXCia18\n" + + "If78mc7goS1+lHkGCs2hADEA\n" + + "-----END PKCS7-----"; + + // Empty PKCS#7 in DER form can be created with openssl: + // openssl crl2pkcs7 -nocrl -outform DER + private static final byte[] PKCS7_BER_EMPTY = { + 48, 39, 6, 9, 42, -122, 72, -122, + -9, 13, 1, 7, 2, -96, 26, 48, + 24, 2, 1, 1, 49, 0, 48, 11, + 6, 9, 42, -122, 72, -122, -9, 13, + 1, 7, 1, -96, 0, -95, 0, 49, + 0 + }; + + private static final String JTEST_ROOT_CRL = + "-----BEGIN X509 CRL-----\n" + + "MIICoTCBigIBATANBgkqhkiG9w0BAQsFADA1MQ4wDAYDVQQKEwVKVGVzdDELMAkG\n" + + "A1UECxMCSVQxFjAUBgNVBAMTDUpUZXN0IFJvb3QgQ0EXDTE0MDkwNDE4NDIyMVqg\n" + + "MDAuMB8GA1UdIwQYMBaAFO6bllCV6kctH77MfqAtefNeRdsmMAsGA1UdFAQEAgIA\n" + + "jjANBgkqhkiG9w0BAQsFAAOCAgEAmp8ihtiRthknDC+VzehmlQw5u8MftMZYQYk5\n" + + "EI04SwyzY9JTL8QHb4u7fXjnZAyN89aYPypI5OSyDsyyGP/JDNsBt2Um/fl0aaCl\n" + + "Z4Np6x+dB9+oIU1XY7y2+uyQUC5MHivQ5ddbGPoAvK/msbugTGAjHvZpM+l0okiV\n" + + "3SofDrii5BSosFEkXfkf2oG9ZLO3YamsFMEZaOj/eWDyGhTyJMGsq2/8NeTF21Tp\n" + + "YkeDcTHqR5KHoYXjOIaS7NjmErm+uDpKH9Lq+JUcYrbUhmjnq5z04EsPF2F2L7Vb\n" + + "THI+awQAUQit16lXGuz7fFRZi2vPyiaRP5n2QT5D+ac1dAs+oWLDJw6Tf2v9KVTe\n" + + "OmW62yd6zQqCwBg+n57UcNu3sv/Sq3t7iRuN0AmWlIhu659POPQv7Np6bEo6dIpp\n" + + "u7Ze6D2KPtM177ETHYlCx2a3g9VEZYKrVhQ2749St0Cp5szVq691jFZAWYOzcfEO\n" + + "XfK1y25pmlBjvhNIIVRlU+T5rjNb8GaleYKVYnKOcv700K32QxFzcPf7nbNKwW99\n" + + "tcaNHFNP+LW/XP8I3CJ8toXLLcOITKVwMA+0GlO5eL7eX5POc+vE9+7IzGuybmU4\n" + + "uslxoLdJ0NSZWpYmf6a6qrJ67cj5i3706H+eBsWQcShfSYreh+TyWQaGk+fkEiUV\n" + + "iy4QdJ0=\n" + + "-----END X509 CRL-----"; + + private static final String JTEST_INTERMED_CRL = + "-----BEGIN X509 CRL-----\n" + + "MIICzzCBuAIBATANBgkqhkiG9w0BAQsFADA/MQ4wDAYDVQQKEwVKVGVzdDELMAkG\n" + + "A1UECxMCSVQxIDAeBgNVBAMTF0pUZXN0IEludGVybWVkaWF0ZSBDQSAxFw0xNDA5\n" + + "MDQyMjE2NTRaMCIwIAIBBhcNMTQwOTA0MjIxNjU0WjAMMAoGA1UdFQQDCgEFoDAw\n" + + "LjAfBgNVHSMEGDAWgBSvRdjbkSMJ3A7s5H6EWghQ+lkw/zALBgNVHRQEBAICAJsw\n" + + "DQYJKoZIhvcNAQELBQADggIBALJmikMwil8oywhenoO8o9xxCOIU0xrt3KdfiSXw\n" + + "8MtQXZHT9d1C6tlLAsYkWAfmfTvM2OU6wquFCLLsFmDZszbbCqmn4JhYBSKQMqlm\n" + + "IHnsiOFPvITW2FU08fWNLM+FtQzPnTFmx/CJo+wfGpq5tZMIbsccsCJ5uvZVAWGh\n" + + "0KbPmYcJG/O384+kzr/2H2IaoZoMMABec5c5FEF/tpp8jawzY+0VFyaVrumKWdan\n" + + "+3OvRQxT1wLxfNi2vdxB2rmNPo423qanXZAoVv260um3LYlmXBNK1jwQ9lp78jkT\n" + + "B7zMVa4hOUWVxdWc/LE6fUYgPsNqZd+hWy/PolIRp5TS21B5hkc5K87LT59GkexK\n" + + "vNVKQennOLGtH+Q7htK4UeY4Gm/W7UydOQ0k7hZzyfMDkCfLfNfK0l63qKwUku36\n" + + "UdeI1LXqulPEvb/d7rRAAM9p5Sm+RsECj2bcrZBMdIGXcSo26A5tzZpTEC79i4S1\n" + + "yxYIooeBnouUkDJ9+VBsJTSKY5fpU8JSkQPRyHKt+trGAkBt2Ka5MqrHtITzQ1vP\n" + + "5q4tNr45JGEXllH83NlBpWURfsdtkDHa3lxTD/pkrywOCyzz7wQ22D8Kul7EN8nT\n" + + "7LDbN+O3G9GHICxvWlJHp6HMsqGTuH1MIUR+5uZFOJa1S0IzorUIEieLncDUPgzO\n" + + "M4JA\n" + + "-----END X509 CRL-----"; + + // PKCS#7 CRL Set containing JTEST root and intermediate CRLs + private static final String PKCS7_CRL_SET = + "-----BEGIN PKCS7-----\n" + + "MIIFpQYJKoZIhvcNAQcCoIIFljCCBZICAQExADALBgkqhkiG9w0BBwGgAKGCBXgw\n" + + "ggKhMIGKAgEBMA0GCSqGSIb3DQEBCwUAMDUxDjAMBgNVBAoTBUpUZXN0MQswCQYD\n" + + "VQQLEwJJVDEWMBQGA1UEAxMNSlRlc3QgUm9vdCBDQRcNMTQwOTA0MTg0MjIxWqAw\n" + + "MC4wHwYDVR0jBBgwFoAU7puWUJXqRy0fvsx+oC15815F2yYwCwYDVR0UBAQCAgCO\n" + + "MA0GCSqGSIb3DQEBCwUAA4ICAQCanyKG2JG2GScML5XN6GaVDDm7wx+0xlhBiTkQ\n" + + "jThLDLNj0lMvxAdvi7t9eOdkDI3z1pg/Kkjk5LIOzLIY/8kM2wG3ZSb9+XRpoKVn\n" + + "g2nrH50H36ghTVdjvLb67JBQLkweK9Dl11sY+gC8r+axu6BMYCMe9mkz6XSiSJXd\n" + + "Kh8OuKLkFKiwUSRd+R/agb1ks7dhqawUwRlo6P95YPIaFPIkwayrb/w15MXbVOli\n" + + "R4NxMepHkoehheM4hpLs2OYSub64Okof0ur4lRxittSGaOernPTgSw8XYXYvtVtM\n" + + "cj5rBABRCK3XqVca7Pt8VFmLa8/KJpE/mfZBPkP5pzV0Cz6hYsMnDpN/a/0pVN46\n" + + "ZbrbJ3rNCoLAGD6fntRw27ey/9Kre3uJG43QCZaUiG7rn0849C/s2npsSjp0imm7\n" + + "tl7oPYo+0zXvsRMdiULHZreD1URlgqtWFDbvj1K3QKnmzNWrr3WMVkBZg7Nx8Q5d\n" + + "8rXLbmmaUGO+E0ghVGVT5PmuM1vwZqV5gpVico5y/vTQrfZDEXNw9/uds0rBb321\n" + + "xo0cU0/4tb9c/wjcIny2hcstw4hMpXAwD7QaU7l4vt5fk85z68T37sjMa7JuZTi6\n" + + "yXGgt0nQ1JlaliZ/prqqsnrtyPmLfvTof54GxZBxKF9Jit6H5PJZBoaT5+QSJRWL\n" + + "LhB0nTCCAs8wgbgCAQEwDQYJKoZIhvcNAQELBQAwPzEOMAwGA1UEChMFSlRlc3Qx\n" + + "CzAJBgNVBAsTAklUMSAwHgYDVQQDExdKVGVzdCBJbnRlcm1lZGlhdGUgQ0EgMRcN\n" + + "MTQwOTA0MjIxNjU0WjAiMCACAQYXDTE0MDkwNDIyMTY1NFowDDAKBgNVHRUEAwoB\n" + + "BaAwMC4wHwYDVR0jBBgwFoAUr0XY25EjCdwO7OR+hFoIUPpZMP8wCwYDVR0UBAQC\n" + + "AgCbMA0GCSqGSIb3DQEBCwUAA4ICAQCyZopDMIpfKMsIXp6DvKPccQjiFNMa7dyn\n" + + "X4kl8PDLUF2R0/XdQurZSwLGJFgH5n07zNjlOsKrhQiy7BZg2bM22wqpp+CYWAUi\n" + + "kDKpZiB57IjhT7yE1thVNPH1jSzPhbUMz50xZsfwiaPsHxqaubWTCG7HHLAiebr2\n" + + "VQFhodCmz5mHCRvzt/OPpM6/9h9iGqGaDDAAXnOXORRBf7aafI2sM2PtFRcmla7p\n" + + "ilnWp/tzr0UMU9cC8XzYtr3cQdq5jT6ONt6mp12QKFb9utLpty2JZlwTStY8EPZa\n" + + "e/I5Ewe8zFWuITlFlcXVnPyxOn1GID7DamXfoVsvz6JSEaeU0ttQeYZHOSvOy0+f\n" + + "RpHsSrzVSkHp5zixrR/kO4bSuFHmOBpv1u1MnTkNJO4Wc8nzA5Any3zXytJet6is\n" + + "FJLt+lHXiNS16rpTxL2/3e60QADPaeUpvkbBAo9m3K2QTHSBl3EqNugObc2aUxAu\n" + + "/YuEtcsWCKKHgZ6LlJAyfflQbCU0imOX6VPCUpED0chyrfraxgJAbdimuTKqx7SE\n" + + "80Nbz+auLTa+OSRhF5ZR/NzZQaVlEX7HbZAx2t5cUw/6ZK8sDgss8+8ENtg/Crpe\n" + + "xDfJ0+yw2zfjtxvRhyAsb1pSR6ehzLKhk7h9TCFEfubmRTiWtUtCM6K1CBIni53A\n" + + "1D4MzjOCQDEA\n" + + "-----END PKCS7-----"; + public static void main(String[] args) throws Exception { CertificateFactory cf = CertificateFactory.getInstance("X.509"); - File f = new File - (System.getProperty("test.src", "."), "invalidcert.pem"); - InputStream inStream = new FileInputStream(f); - try { - X509Certificate cert = - (X509Certificate) cf.generateCertificate(inStream); - } catch (CertificateParsingException ce) { - return; + List validTests = new LinkedList<>(); + List invalidTests = new LinkedList<>(); + + // Load up positive test cases (for sanity checks) + StringBuilder sb = new StringBuilder(); + + validTests.add(new GenMultiCertTest("Single, valid certificate", + SINGLE_ROOT_CERT.getBytes(), null, + new X500Principal("CN=Root, O=SomeCompany"))); + validTests.add(new GenMultiCertTest("PEM-encoded PKCS#7 chain", + PKCS7_INTERMED_ROOT_CERTS.getBytes(), null, + new X500Principal("CN=Intermed, O=SomeCompany"), + new X500Principal("CN=Root, O=SomeCompany"))); + validTests.add(new GenMultiCertTest("Two PEM-encoded X509 certs", + (INTERMED_CA_CERT + "\n" + SINGLE_ROOT_CERT).getBytes(), + null, + new X500Principal("CN=Intermed, O=SomeCompany"), + new X500Principal("CN=Root, O=SomeCompany"))); + validTests.add(new GenMultiCertTest("Empty data", new byte[0], null)); + + sb.append("Certificate 1: CN=Root, O=SomeCompany\n"); + sb.append(SINGLE_ROOT_CERT).append("\n"); + sb.append("Certificate 2: CN=Intermed, O=SomeCompany\n"); + sb.append(INTERMED_CA_CERT).append("\n"); + sb.append("Extra trailing data\n"); + validTests.add(new GenMultiCertTest( + "Two PEM-encoded certs with leading/trailing " + + "text data around each.", sb.toString().getBytes(), null, + new X500Principal("CN=Root, O=SomeCompany"), + new X500Principal("CN=Intermed, O=SomeCompany"))); + validTests.add(new GenMultiCertTest( + "BER-encoded PKCS#7 with empty certificates segment", + PKCS7_BER_EMPTY, null)); + validTests.add(new GenMultiCRLTest( + "CRL with leading and trailing text data", + ("This is a CRL\n" + JTEST_ROOT_CRL + + "\nSee? Told you so\n\n").getBytes(), null, + new X500Principal("CN=JTest Root CA,OU=IT,O=JTest"))); + validTests.add(new GenMultiCRLTest( + "Two CRLs, one after the other with leading/trailing text", + ("This is a CRL\n" + JTEST_ROOT_CRL + + "\nAnd this is another CRL\n" + JTEST_INTERMED_CRL + + "\nAnd this is trailing text\n").getBytes(), null, + new X500Principal("CN=JTest Root CA,OU=IT,O=JTest"), + new X500Principal( + "CN=JTest Intermediate CA 1,OU=IT,O=JTest"))); + validTests.add(new GenMultiCRLTest("Two CRLs in a PKCS#7 CRL set", + PKCS7_CRL_SET.getBytes(), null, + new X500Principal("CN=JTest Root CA,OU=IT,O=JTest"), + new X500Principal("CN=JTest Intermediate CA 1,OU=IT,O=JTest"))); + + // Load up all test cases where we expect failures + invalidTests.add(new GenSingleCertTest("Invalid PEM encoding", + INVALID_CERT.getBytes(), + new CertificateParsingException())); + invalidTests.add(new GenMultiCertTest("Invalid PEM encoding", + INVALID_CERT.getBytes(), + new CertificateParsingException())); + invalidTests.add(new GenMultiCertTest( + "Two cert sequence, one valid and one invalid", + (INTERMED_CA_CERT + "\n" + INVALID_CERT).getBytes(), + new CertificateParsingException())); + invalidTests.add(new GenMultiCertTest("Non-certificate text", + "This is not a certificate".getBytes(), + new CertificateException())); + invalidTests.add(new GenMultiCertTest( + "Non-certificate text with partial PEM header (4 hyphens)", + "----This is not a valid x509 certificate".getBytes(), + new CertificateException())); + invalidTests.add(new GenMultiCertTest( + "Leading non-certificate text plus valid PEM header, " + + "but not on new line", + "This is not valid -----BEGIN CERTIFICATE-----".getBytes(), + new CertificateException())); + byte[] emptyCString = {0}; + invalidTests.add(new GenMultiCertTest("Empty C-style string", + emptyCString, new CertificateException())); + invalidTests.add(new GenMultiCRLTest("Non-CRL text", + "This is not a CRL".getBytes(), new CRLException())); + invalidTests.add(new GenMultiCRLTest("Valid headers, but not a CRL", + INTERMED_CA_CERT.getBytes(), new CRLException())); + + System.out.println("===== Valid Tests ====="); + for (DecodeTest dt : validTests) { + dt.passTest(); + } + System.out.print("\n"); + + System.out.println("===== Invalid Tests ====="); + for (DecodeTest dt : invalidTests) { + dt.failTest(); + } + } + + public static abstract class DecodeTest { + protected String testName; + protected byte[] testData; + protected Throwable expectedException; + protected X500Principal[] principals; + protected CertificateFactory cf; + + /** + * Construct a DecodeTest + * + * @param name The test name + * @param input A byte array consisting of the input for this test + * @param failType An exception whose class should match the expected + * exception that will be thrown when this test is run + * @param princs Zero of more X500Principals which will be used + * to compare the output in a success case. + */ + DecodeTest(String name, byte[] input, Throwable failType, + X500Principal... princs) throws CertificateException { + testName = name; + testData = input.clone(); + expectedException = failType; + principals = princs; + cf = CertificateFactory.getInstance("X.509"); + } + + public abstract void passTest() throws GeneralSecurityException; + + public abstract void failTest() throws GeneralSecurityException; + } + + public static class GenMultiCertTest extends DecodeTest { + public GenMultiCertTest(String name, byte[] input, Throwable failType, + X500Principal... princs) throws CertificateException { + super(name, input, failType, princs); + } + + @Override + public void passTest() throws GeneralSecurityException { + Collection certs; + + System.out.println("generateCertificates(): " + testName); + certs = cf.generateCertificates(new ByteArrayInputStream(testData)); + + // Walk the certs Collection and do a comparison of subject names + int i = 0; + if (certs.size() == principals.length) { + for (Certificate crt : certs) { + X509Certificate xc = (X509Certificate)crt; + if (!xc.getSubjectX500Principal().equals( + principals[i])) { + throw new RuntimeException("Name mismatch: " + + "cert: " + xc.getSubjectX500Principal() + + ", expected: " + principals[i]); + } + i++; + } + } else { + throw new RuntimeException("Size mismatch: certs = " + + certs.size() + ", expected = " + + principals.length); + } + } + + @Override + public void failTest() throws GeneralSecurityException { + Throwable caughtException = null; + Collection certs = null; + + System.out.println("generateCertificates(): " + testName); + if (expectedException == null) { + throw new RuntimeException("failTest requires non-null " + + "expectedException"); + } + + try { + certs = + cf.generateCertificates(new ByteArrayInputStream(testData)); + } catch (CertificateException ce) { + caughtException = ce; + } + + if (caughtException != null) { + // It has to be the right kind of exception though... + if (!caughtException.getClass().equals( + expectedException.getClass())) { + System.err.println("Unexpected exception thrown. " + + "Received: " + caughtException + ", Expected: " + + expectedException.getClass()); + throw new RuntimeException(caughtException); + } + } else { + // For a failure test, we'd expect some kind of exception + // to be thrown. + throw new RuntimeException("Failed to catch expected " + + "exception " + expectedException.getClass()); + } + } + } + + public static class GenSingleCertTest extends DecodeTest { + public GenSingleCertTest(String name, byte[] input, Throwable failType, + X500Principal... princs) throws CertificateException { + super(name, input, failType, princs); + } + + @Override + public void passTest() throws GeneralSecurityException { + X509Certificate cert; + + System.out.println("generateCertificate(): " + testName); + cert = (X509Certificate)cf.generateCertificate( + new ByteArrayInputStream(testData)); + + // Compare the cert's subject name against the expected value + // provided in the test. If multiple X500Principals were provided + // just use the first one as the expected value. + if (!cert.getSubjectX500Principal().equals(principals[0])) { + throw new RuntimeException("Name mismatch: " + + "cert: " + cert.getSubjectX500Principal() + + ", expected: " + principals[0]); + } + } + + @Override + public void failTest() throws GeneralSecurityException { + Throwable caughtException = null; + X509Certificate cert = null; + System.out.println("generateCertificate(): " + testName); + + if (expectedException == null) { + throw new RuntimeException("failTest requires non-null " + + "expectedException"); + } + + try { + cert = (X509Certificate)cf.generateCertificate( + new ByteArrayInputStream(testData)); + } catch (CertificateException e) { + caughtException = e; + } + + if (caughtException != null) { + // It has to be the right kind of exception though... + if (!caughtException.getClass().equals( + expectedException.getClass())) { + System.err.println("Unexpected exception thrown. " + + "Received: " + caughtException + ", Expected: " + + expectedException.getClass()); + throw new RuntimeException(caughtException); + } + } else { + // For a failure test, we'd expect some kind of exception + // to be thrown. + throw new RuntimeException("Failed to catch expected " + + "exception " + expectedException.getClass()); + } + } + } + + public static class GenMultiCRLTest extends DecodeTest { + public GenMultiCRLTest(String name, byte[] input, Throwable failType, + X500Principal... princs) throws CertificateException { + super(name, input, failType, princs); + } + + @Override + public void passTest() throws GeneralSecurityException { + Collection crls; + + System.out.println("generateCRLs(): " + testName); + crls = cf.generateCRLs(new ByteArrayInputStream(testData)); + + // Walk the crls Collection and do a comparison of issuer names + int i = 0; + if (crls.size() == principals.length) { + for (CRL revlist : crls) { + X509CRL xc = (X509CRL)revlist; + if (!xc.getIssuerX500Principal().equals(principals[i])) { + throw new RuntimeException("Name mismatch: " + + "CRL: " + xc.getIssuerX500Principal() + + ", expected: " + principals[i]); + } + i++; + } + } else { + throw new RuntimeException("Size mismatch: crls = " + + crls.size() + ", expected = " + + principals.length); + } + } + + @Override + public void failTest() throws GeneralSecurityException { + Throwable caughtException = null; + Collection crls = null; + + System.out.println("generateCRLs(): " + testName); + if (expectedException == null) { + throw new RuntimeException("failTest requires non-null " + + "expectedException"); + } + + try { + crls = + cf.generateCRLs(new ByteArrayInputStream(testData)); + } catch (CRLException e) { + caughtException = e; + } + + if (caughtException != null) { + // It has to be the right kind of exception though... + if (!caughtException.getClass().equals( + expectedException.getClass())) { + System.err.println("Unexpected exception thrown. " + + "Received: " + caughtException + ", Expected: " + + expectedException.getClass()); + throw new RuntimeException(caughtException); + } + } else { + // For a failure test, we'd expect some kind of exception + // to be thrown. + throw new RuntimeException("Failed to catch expected " + + "exception " + expectedException.getClass()); + } } - throw new Exception("CertificateFactory.generateCertificate() did not " - + "throw CertificateParsingException on invalid X.509 cert data"); } } diff --git a/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/invalidcert.pem b/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/invalidcert.pem deleted file mode 100644 index 214b0c7a9ae..00000000000 --- a/jdk/test/java/security/cert/CertificateFactory/invalidEncodedCerts/invalidcert.pem +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN CERTIFICATE----- -XIICJjCCAdCgAwIBAgIBITANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCVVMx -EzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28xFTAT -BgNVBAoTDEJFQSBXZWJMb2dpYzERMA8GA1UECxMIU2VjdXJpdHkxIzAhBgNVBAMT -GkRlbW8gQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9zdXBw -b3J0QGJlYS5jb20wHhcNMDAwNTMwMjEzODAxWhcNMDQwNTEzMjEzODAxWjCBjDEL -MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG -cmFuY2lzY28xFTATBgNVBAoTDEJFQSBXZWJMb2dpYzEZMBcGA1UEAxMQd2VibG9n -aWMuYmVhLmNvbTEeMBwGCSqGSIb3DQEJARYPc3VwcG9ydEBiZWEuY29tMFwwDQYJ -KoZIhvcNAQEBBQADSwAwSAJBALdsXEHqKHgs6zj0hU5sXMAUHzoT8kgWXmNkKHXH -79qbPh6EfdlriW9G/AbRF/pKrCQu7hhllAxREbqTuSlf2EMCAwEAATANBgkqhkiG -9w0BAQQFAANBACgmqflL5m5LNeJGpWx9aIoABCiuDcpw1fFyegsqGX7CBhffcruS -1p8h5vkHVbMu1frD1UgGnPlOO/K7Ig/KrsU= ------END CERTIFICATE----- From 318f1da1b6fc9af44065d9c9909878134ccc5839 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Thu, 16 Oct 2014 10:37:03 +0200 Subject: [PATCH 85/91] 8055191: Split GensrcProperties.gmk into separate modules Reviewed-by: tbell --- make/MakeHelpers.gmk | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/make/MakeHelpers.gmk b/make/MakeHelpers.gmk index b8581e3f6eb..62b9add30cd 100644 --- a/make/MakeHelpers.gmk +++ b/make/MakeHelpers.gmk @@ -324,9 +324,10 @@ define DeclareRecipeForModuleMakefile +($(CD) $$(dir $$(firstword $$(wildcard $$(addsuffix /$$(strip $3)/$$(strip $4)-$$(strip $1).gmk, \ $(MAKE_DIR_LIST))))) \ && $(MAKE) $(MAKE_ARGS) \ - -f $$(strip $4)-$$(strip $1).gmk \ - $$(addprefix -I, $$(wildcard $(MAKE_DIR_LIST) \ - $$(addsuffix /$$(strip $3), $(MAKE_DIR_LIST))))) + -f $$(strip $4)-$$(strip $1).gmk \ + $$(addprefix -I, $$(wildcard $(MAKE_DIR_LIST) \ + $$(addsuffix /$$(strip $3), $(MAKE_DIR_LIST)))) \ + MODULE=$$(strip $1)) endef ################################################################################ From 6da7daa4c2783c04a6f9d881f2f1a97a60bc0190 Mon Sep 17 00:00:00 2001 From: Attila Szegedi Date: Thu, 16 Oct 2014 11:34:31 +0200 Subject: [PATCH 86/91] 8061113: Boolean used as optimistic call return type Reviewed-by: hannesw, sundar --- .../internal/codegen/TypeEvaluator.java | 9 ++++- nashorn/test/script/basic/JDK-8061113.js | 35 +++++++++++++++++++ .../test/script/basic/JDK-8061113.js.EXPECTED | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 nashorn/test/script/basic/JDK-8061113.js create mode 100644 nashorn/test/script/basic/JDK-8061113.js.EXPECTED diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java index b3c0dd8a915..4f3bc07f1db 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/TypeEvaluator.java @@ -232,7 +232,14 @@ final class TypeEvaluator { if (callExpr.getArgs().isEmpty()) { final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fn.getId()); if (data != null) { - return Type.typeFor(data.getReturnType(EMPTY_INVOCATION_TYPE, runtimeScope)); + final Type returnType = Type.typeFor(data.getReturnType(EMPTY_INVOCATION_TYPE, runtimeScope)); + if (returnType == Type.BOOLEAN) { + // We don't have optimistic booleans. In fact, optimistic call sites getting back boolean + // currently deoptimize all the way to Object. + return Type.OBJECT; + } + assert returnType == Type.INT || returnType == Type.LONG || returnType == Type.NUMBER || returnType == Type.OBJECT; + return returnType; } } } diff --git a/nashorn/test/script/basic/JDK-8061113.js b/nashorn/test/script/basic/JDK-8061113.js new file mode 100644 index 00000000000..1cd8b35bc4a --- /dev/null +++ b/nashorn/test/script/basic/JDK-8061113.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8061113: Boolean used as optimistic call return type + * + * @test + * @run + */ + +function testcase() { + var a = {x:0}; + return (function () {return a.x === 0})(); +} +print(testcase()); diff --git a/nashorn/test/script/basic/JDK-8061113.js.EXPECTED b/nashorn/test/script/basic/JDK-8061113.js.EXPECTED new file mode 100644 index 00000000000..27ba77ddaf6 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8061113.js.EXPECTED @@ -0,0 +1 @@ +true From 5f7c6d15ebcedb238971c14d521c2ddf10b4b59a Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 16 Oct 2014 12:01:55 -0700 Subject: [PATCH 87/91] Added tag jdk9-b35 for changeset 6ca2395495b0 --- .hgtags-top-repo | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 8a9681a9173..367a63ebf4b 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -277,3 +277,4 @@ ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28 7e3512dae8e020d44399c0f1c579ff1fe3090ed6 jdk9-b32 e4ba01b726e263953ae129be37c94de6ed145b1d jdk9-b33 087b23f35631e68e950496a36fce8ccca612966a jdk9-b34 +c173ba994245380fb11ef077d1e59823386840eb jdk9-b35 From aa619e81f8a4c95e704dda5bf08cd4905dcd95e4 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 16 Oct 2014 12:01:56 -0700 Subject: [PATCH 88/91] Added tag jdk9-b35 for changeset ba12299a76d2 --- corba/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/corba/.hgtags b/corba/.hgtags index df4902658de..d1c2f73e5bb 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -277,3 +277,4 @@ c432b80aadd0cb2b2361b02add4d671957d4cec9 jdk9-b31 b5b139354630edb2d06190bf31653acbdcea63a8 jdk9-b32 cfdac5887952c2dd73c73a1d8d9aa880d0539bbf jdk9-b33 24a0bad5910f775bb4002d1dacf8b3af87c63cd8 jdk9-b34 +9bc2dbd3dfb8c9fa88e00056b8b93a81ee6d306e jdk9-b35 From f0c24e1a0fa07bba353f8b935ad18b0af432d3ec Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 16 Oct 2014 12:01:59 -0700 Subject: [PATCH 89/91] Added tag jdk9-b35 for changeset 58090065f895 --- hotspot/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/hotspot/.hgtags b/hotspot/.hgtags index d8bec5bf870..5c2b522d2ea 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -437,3 +437,4 @@ deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29 af46576a8d7cb4003028b8ee8bf408cfe227315b jdk9-b32 9b3f5e4f33725f7c1d9b8e523133fe8383a54d9f jdk9-b33 821164b0131a47ca065697c7d27d8f215e608c8d jdk9-b34 +438cb613151c4bd290bb732697517cba1cafcb04 jdk9-b35 From 3e052996844111bfd32f4d92166e31b485a42f74 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 16 Oct 2014 12:02:05 -0700 Subject: [PATCH 90/91] Added tag jdk9-b35 for changeset 4bee12591374 --- jdk/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/jdk/.hgtags b/jdk/.hgtags index f2a26a52320..82c29df2864 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -277,3 +277,4 @@ f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27 8bdf7083b5bd02aa330ba622895e586dd3378d37 jdk9-b32 60fe681c30bc3821545a2506d4d3c2e04073f67c jdk9-b33 21568031434d7a9dbb0cc6516cc3183d349c2253 jdk9-b34 +e549291a0227031310fa91c574891f892d27f959 jdk9-b35 From 33180b072e390ae1b890c55164fac1a8d3f0b862 Mon Sep 17 00:00:00 2001 From: David Katleman Date: Thu, 16 Oct 2014 12:02:10 -0700 Subject: [PATCH 91/91] Added tag jdk9-b35 for changeset b5cd0f03efc4 --- nashorn/.hgtags | 1 + 1 file changed, 1 insertion(+) diff --git a/nashorn/.hgtags b/nashorn/.hgtags index b29cd38c6fd..430f9dffc2d 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -268,3 +268,4 @@ e541ebaf2ab7038333ad0c13f4decd327c26dd15 jdk9-b29 62ba20541b948fb98a7036d9f01baa54e95fb6fa jdk9-b32 b374d8910e7f8de2b7ecacee9ae4cad88f23feab jdk9-b33 4ece2dad8c37f520f1ccc1cf84870f362c8eb9d6 jdk9-b34 +63b8da4c958c3bbadfff082c547983f5daa50c0f jdk9-b35