Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 19 Oct 2012 22:43:10 +0000 (UTC)
From:      Jung-uk Kim <jkim@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r306138 - in head/java: openjdk6 openjdk6-jre openjdk6/files openjdk6/files/icedtea/security
Message-ID:  <201210192243.q9JMhAe2092366@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jkim
Date: Fri Oct 19 22:43:10 2012
New Revision: 306138
URL: http://svn.freebsd.org/changeset/ports/306138

Log:
  - Add 2012/10/16 security patches from IcedTea6 1.11.5. [1]
  
  http://icedtea.classpath.org/hg/release/icedtea6-1.11/rev/d9564350faa6
  http://blog.fuseyism.com/index.php/2012/10/19/security-icedtea-1-10-10-1-11-15-2-1-3-2-2-3-2-3-3-released/
  
  - Completely turn off parallel build by default and remove parallel build
  hack for HotSpot.  There were several reports that it fails to build under
  certain environment, ports/162991 for example.  Users can still do parallel
  build by setting FORCE_MAKE_JOBS (and MAKE_JOBS_NUMBER if desired).
  - Implement os::available_memory().  Now it is consistent with "vm.vmtotal"
  sysctl(3) MIB rather than bogus (physical memory / 4).
  - Prefer sysconf(_SC_NPROCESSORS_CONF) over HW_NCPU sysctl MIB to get the
  number of installed processors.  There is no functional difference except
  for CURRENT, which obtains the information from ELF aux vector.
  - Prefer sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) over HW_USERMEM
  sysctl MIB to get size of physical memory.  Although it looks more logical
  to find currently available memory, it has an inevitable side-effect, i. e.,
  it changes dynamically depending on current wired page count.  Therefore,
  it is unpredictable and not too useful some times.  For example, launcher
  uses the parameter to determine initial heap size and machine class for i386.
  Now it is more consistent with other places (and Linux JDK/JREs, including
  the ones we have in ports tree).
  - Implement os::active_processor_count() using cpuset_getaffinity(2).  For
  example, Runtime.getRuntime().availableProcessors() now returns number of
  available processors for the current process as it should.
  - Sync. launchers (java_md.c) for HotSpot and JDK as much as possible for
  maintainability.  As a good side-effect, launcher for i386 can now determine
  machine class based on the current hardware configuration.  Previously,
  client VM was always chosen by default.
  - Fix CounterGet(), which is only used for debugging launcher.
  - Add swap info for os::print_memory_info().
  
  Obtained from:	IcedTea project [1]
  Feature safe:	yes

Added:
  head/java/openjdk6/files/icedtea/security/
  head/java/openjdk6/files/icedtea/security/6631398.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7093490.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7143535.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7158800.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7158801.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7158804.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7167656.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7169884.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7169888.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7172522.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7176337.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7186286.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7189103.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7189490.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7189567.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7192975.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7195194.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7195917.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7195919.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7198296.patch   (contents, props changed)
  head/java/openjdk6/files/icedtea/security/7198606.patch   (contents, props changed)
Modified:
  head/java/openjdk6-jre/Makefile
  head/java/openjdk6/Makefile
  head/java/openjdk6/files/patch-set

Modified: head/java/openjdk6-jre/Makefile
==============================================================================
--- head/java/openjdk6-jre/Makefile	Fri Oct 19 20:24:21 2012	(r306137)
+++ head/java/openjdk6-jre/Makefile	Fri Oct 19 22:43:10 2012	(r306138)
@@ -1,6 +1,6 @@
 # $FreeBSD$
 
-PORTREVISION=	0
+PORTREVISION=	1
 CATEGORIES=	java devel
 PKGNAMESUFFIX=	-jre
 

Modified: head/java/openjdk6/Makefile
==============================================================================
--- head/java/openjdk6/Makefile	Fri Oct 19 20:24:21 2012	(r306137)
+++ head/java/openjdk6/Makefile	Fri Oct 19 22:43:10 2012	(r306138)
@@ -3,7 +3,7 @@
 
 PORTNAME=	openjdk6
 PORTVERSION=	b26
-PORTREVISION?=	0
+PORTREVISION?=	1
 CATEGORIES=	java devel
 MASTER_SITES=	http://download.java.net/openjdk/jdk6/promoted/${PORTVERSION}/ \
 		http://download.java.net/jaxp/openjdk/jdk6/:jaxp \
@@ -40,8 +40,10 @@ RUN_DEPENDS=	javavm:${PORTSDIR}/java/jav
 
 OPENJDK_BUILDDATE=	21_sep_2012
 
+EXTRA_PATCHES=	${FILESDIR}/icedtea/security/*.patch
+
 OPTIONS_DEFINE=	ICEDTEA IPV6 POLICY SOUND TZUPDATE
-OPTIONS_DEFAULT=ICEDTEA TZUPDATE
+OPTIONS_DEFAULT=ICEDTEA IPV6 TZUPDATE
 ICEDTEA_DESC=	Apply additional patches from IcedTea
 POLICY_DESC=	Install the Unlimited Strength Policy Files
 SOUND_DESC=	Enable sound support
@@ -62,7 +64,6 @@ WRKSRC=		${WRKDIR}
 USE_GMAKE=	yes
 USE_MOTIF=	yes
 USE_XORG=	x11 xext xi xt xtst
-MAKE_JOBS_UNSAFE=	yes
 
 JAXP_BUILD=	144_04
 JAXPFILE=	jaxp${JAXP_BUILD}.zip
@@ -143,6 +144,16 @@ MAKE_ENV+=	CCC="${CXX}" GCC="${CC}"
 # XXX Turn off -Werror from HotSpot.
 MAKE_ENV+=	WARNINGS_ARE_ERRORS="${WARNINGS_ARE_ERRORS}"
 
+# XXX Turn off parallel build by default.
+.if defined(DISABLE_MAKE_JOBS) || !defined(FORCE_MAKE_JOBS)
+BUILD_JOBS_NUMBER=	1
+.elif defined(FORCE_MAKE_JOBS)
+BUILD_JOBS_NUMBER=	${MAKE_JOBS_NUMBER}
+.endif
+_MAKE_JOBS=	#
+MAKE_ENV+=	ALT_PARALLEL_COMPILE_JOBS=${BUILD_JOBS_NUMBER} \
+		HOTSPOT_BUILD_JOBS=${BUILD_JOBS_NUMBER}
+
 .if ${PORT_OPTIONS:MDEBUG}
 ALL_TARGET=	debug_build
 OPENJDK_OSARCH=	bsd-${ARCH:S/i386/i586/}-debug
@@ -183,15 +194,6 @@ BUILD_DEPENDS+=	${LOCALBASE}/lib/X11/fon
 USE_DISPLAY=	yes
 .endif
 
-.if !defined(DISABLE_MAKE_JOBS)
-.if defined(MAKE_JOBS_NUMBER)
-BUILD_JOBS_NUMBER=	${MAKE_JOBS_NUMBER}
-.else
-BUILD_JOBS_NUMBER=	`${SYSCTL} -n kern.smp.cpus`
-.endif
-MAKE_ENV+=	HOTSPOT_BUILD_JOBS=${BUILD_JOBS_NUMBER}
-.endif
-
 COPYDIRS=	\
 	hotspot/src/os/linux/vm \
 	hotspot/src/os_cpu/linux_x86/vm \

Added: head/java/openjdk6/files/icedtea/security/6631398.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/java/openjdk6/files/icedtea/security/6631398.patch	Fri Oct 19 22:43:10 2012	(r306138)
@@ -0,0 +1,20 @@
+# HG changeset patch
+# User weijun
+# Date 1339724916 -28800
+# Node ID 0fdc422fba9b63be684f1229af75f0c1f3ceec87
+# Parent  f09937f0b2e32aa60a2cdd23f03a7e2d45091b60
+6631398: FilePermission improved path checking
+Reviewed-by: mullan, skoivu, jdn
+
+diff --git a/src/share/classes/java/io/FilePermission.java b/src/share/classes/java/io/FilePermission.java
+--- jdk/src/share/classes/java/io/FilePermission.java
++++ jdk/src/share/classes/java/io/FilePermission.java
+@@ -399,7 +399,7 @@
+      */
+ 
+     public int hashCode() {
+-        return this.cpath.hashCode();
++        return 0;
+     }
+ 
+     /**

Added: head/java/openjdk6/files/icedtea/security/7093490.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/java/openjdk6/files/icedtea/security/7093490.patch	Fri Oct 19 22:43:10 2012	(r306138)
@@ -0,0 +1,28 @@
+# HG changeset patch
+# User coffeys
+# Date 1340913225 -3600
+# Node ID e7334bb16ad694bed492da52e5713c8391e79ce8
+# Parent  0fdc422fba9b63be684f1229af75f0c1f3ceec87
+7093490: adjust package access in rmiregistry
+Reviewed-by: smarks
+
+diff --git a/src/share/classes/sun/rmi/registry/RegistryImpl.java b/src/share/classes/sun/rmi/registry/RegistryImpl.java
+--- jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
++++ jdk/src/share/classes/sun/rmi/registry/RegistryImpl.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -405,7 +405,8 @@
+          */
+         perms.add(new SocketPermission("*", "connect,accept"));
+ 
+-        perms.add(new RuntimePermission("accessClassInPackage.sun.*"));
++        perms.add(new RuntimePermission("accessClassInPackage.sun.jvmstat.*"));
++        perms.add(new RuntimePermission("accessClassInPackage.sun.jvm.hotspot.*"));
+ 
+         perms.add(new FilePermission("<<ALL FILES>>", "read"));
+ 

Added: head/java/openjdk6/files/icedtea/security/7143535.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/java/openjdk6/files/icedtea/security/7143535.patch	Fri Oct 19 22:43:10 2012	(r306138)
@@ -0,0 +1,31 @@
+# HG changeset patch
+# User sundar
+# Date 1345469787 -14400
+# Node ID 1e170e3c1b682d0f98a61a47e5049535c5bd4999
+# Parent  e7334bb16ad694bed492da52e5713c8391e79ce8
+7143535: ScriptEngine corrected permissions
+Reviewed-by: mschoene
+
+diff --git a/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java b/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java
+--- jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java
++++ jdk/src/share/classes/com/sun/script/javascript/RhinoScriptEngine.java
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
++ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+  *
+  * This code is free software; you can redistribute it and/or modify it
+@@ -130,7 +130,11 @@
+     public RhinoScriptEngine() {
+ 
+         if (System.getSecurityManager() != null) {
+-            accCtxt = AccessController.getContext();
++            try {
++                AccessController.checkPermission(new AllPermission());
++            } catch (AccessControlException ace) {
++                accCtxt = AccessController.getContext();
++            }
+         }
+ 
+         Context cx = enterContext();

Added: head/java/openjdk6/files/icedtea/security/7158800.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/java/openjdk6/files/icedtea/security/7158800.patch	Fri Oct 19 22:43:10 2012	(r306138)
@@ -0,0 +1,1413 @@
+# HG changeset patch
+# User kevinw
+# Date 1345802362 -3600
+# Node ID 2faa3f7bad65189e69ab2f9a491743786bb8f07f
+# Parent  a080633e3a056dae9e94077c9ac4cf966137ade9
+7158800: Improve storage of symbol tables
+7178670: runtime/7158800/BadUtf8.java fails in SymbolTable::rehash_table
+7181200: JVM new hashing code breaks SA in product mode
+7190262: Debug builds fail to verify String table with +UseCompressedStrings after 7158800
+Reviewed-by: coleenp
+
+diff --git a/src/share/vm/classfile/altHashing.cpp b/src/share/vm/classfile/altHashing.cpp
+new file mode 100644
+--- /dev/null
++++ hotspot/src/share/vm/classfile/altHashing.cpp
+@@ -0,0 +1,304 @@
++/*
++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ *
++ */
++
++#include "precompiled.hpp"
++#include "classfile/altHashing.hpp"
++#include "classfile/symbolTable.hpp"
++#include "classfile/systemDictionary.hpp"
++#include "oops/markOop.hpp"
++#include "runtime/thread.hpp"
++
++// Get the hash code of the classes mirror if it exists, otherwise just
++// return a random number, which is one of the possible hash code used for
++// objects.  We don't want to call the synchronizer hash code to install
++// this value because it may safepoint.
++intptr_t object_hash(klassOop k) {
++  intptr_t hc = Klass::cast(k)->java_mirror()->mark()->hash();
++  return hc != markOopDesc::no_hash ? hc : os::random();
++}
++
++// Seed value used for each alternative hash calculated.
++jint AltHashing::compute_seed() {
++  jlong nanos = os::javaTimeNanos();
++  jlong now = os::javaTimeMillis();
++  jint SEED_MATERIAL[8] = {
++            (jint) object_hash(SystemDictionary::String_klass()),
++            (jint) object_hash(SystemDictionary::System_klass()),
++            (jint) os::random(),  // current thread isn't a java thread
++            (jint) (((julong)nanos) >> 32),
++            (jint) nanos,
++            (jint) (((julong)now) >> 32),
++            (jint) now,
++            (jint) (os::javaTimeNanos() >> 2)
++  };
++
++  return murmur3_32(SEED_MATERIAL, 8);
++}
++
++
++// Murmur3 hashing for Symbol
++jint AltHashing::murmur3_32(jint seed, const jbyte* data, int len) {
++  jint h1 = seed;
++  int count = len;
++  int offset = 0;
++
++  // body
++  while (count >= 4) {
++    jint k1 = (data[offset] & 0x0FF)
++        | (data[offset + 1] & 0x0FF) << 8
++        | (data[offset + 2] & 0x0FF) << 16
++        | data[offset + 3] << 24;
++
++    count -= 4;
++    offset += 4;
++
++    k1 *= 0xcc9e2d51;
++    k1 = Integer_rotateLeft(k1, 15);
++    k1 *= 0x1b873593;
++
++    h1 ^= k1;
++    h1 = Integer_rotateLeft(h1, 13);
++    h1 = h1 * 5 + 0xe6546b64;
++  }
++
++  // tail
++
++  if (count > 0) {
++    jint k1 = 0;
++
++    switch (count) {
++      case 3:
++        k1 ^= (data[offset + 2] & 0xff) << 16;
++      // fall through
++      case 2:
++        k1 ^= (data[offset + 1] & 0xff) << 8;
++      // fall through
++      case 1:
++        k1 ^= (data[offset] & 0xff);
++      // fall through
++      default:
++        k1 *= 0xcc9e2d51;
++        k1 = Integer_rotateLeft(k1, 15);
++        k1 *= 0x1b873593;
++        h1 ^= k1;
++    }
++  }
++
++  // finalization
++  h1 ^= len;
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((unsigned int)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((unsigned int)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((unsigned int)h1) >> 16;
++
++  return h1;
++}
++
++// Murmur3 hashing for Strings
++jint AltHashing::murmur3_32(jint seed, const jchar* data, int len) {
++  jint h1 = seed;
++
++  int off = 0;
++  int count = len;
++
++  // body
++  while (count >= 2) {
++    jchar d1 = data[off++] & 0xFFFF;
++    jchar d2 = data[off++];
++    jint k1 = (d1 | d2 << 16);
++
++    count -= 2;
++
++    k1 *= 0xcc9e2d51;
++    k1 = Integer_rotateLeft(k1, 15);
++    k1 *= 0x1b873593;
++
++    h1 ^= k1;
++    h1 = Integer_rotateLeft(h1, 13);
++    h1 = h1 * 5 + 0xe6546b64;
++  }
++
++  // tail
++
++  if (count > 0) {
++    int k1 = data[off];
++
++    k1 *= 0xcc9e2d51;
++    k1 = Integer_rotateLeft(k1, 15);
++    k1 *= 0x1b873593;
++    h1 ^= k1;
++  }
++
++  // finalization
++  h1 ^= len * 2; // (Character.SIZE / Byte.SIZE);
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((unsigned int)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((unsigned int)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((unsigned int)h1) >> 16;
++
++  return h1;
++}
++
++// Hash used for the seed.
++jint AltHashing::murmur3_32(jint seed, const int* data, int len) {
++  jint h1 = seed;
++
++  int off = 0;
++  int end = len;
++
++  // body
++  while (off < end) {
++    jint k1 = data[off++];
++
++    k1 *= 0xcc9e2d51;
++    k1 = Integer_rotateLeft(k1, 15);
++    k1 *= 0x1b873593;
++
++    h1 ^= k1;
++    h1 = Integer_rotateLeft(h1, 13);
++    h1 = h1 * 5 + 0xe6546b64;
++  }
++
++  // tail (always empty, as body is always 32-bit chunks)
++
++  // finalization
++
++  h1 ^= len * 4; // (Integer.SIZE / Byte.SIZE);
++
++  // finalization mix force all bits of a hash block to avalanche
++  h1 ^= ((juint)h1) >> 16;
++  h1 *= 0x85ebca6b;
++  h1 ^= ((juint)h1) >> 13;
++  h1 *= 0xc2b2ae35;
++  h1 ^= ((juint)h1) >> 16;
++
++  return h1;
++}
++
++jint AltHashing::murmur3_32(const int* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++#ifndef PRODUCT
++// Overloaded versions for internal test.
++jint AltHashing::murmur3_32(const jbyte* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++jint AltHashing::murmur3_32(const jchar* data, int len) {
++  return murmur3_32(0, data, len);
++}
++
++// Internal test for alternate hashing.  Translated from JDK version
++// test/sun/misc/Hashing.java
++static const jbyte ONE_BYTE[] = { (jbyte) 0x80};
++static const jbyte TWO_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81};
++static const jchar ONE_CHAR[] = { (jchar) 0x8180};
++static const jbyte THREE_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82};
++static const jbyte FOUR_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83};
++static const jchar TWO_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382};
++static const jint ONE_INT[] = { 0x83828180};
++static const jbyte SIX_BYTE[] = { (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82, (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85};
++static const jchar THREE_CHAR[] = { (jchar) 0x8180, (jchar) 0x8382, (jchar) 0x8584};
++static const jbyte EIGHT_BYTE[] = {
++  (jbyte) 0x80, (jbyte) 0x81, (jbyte) 0x82,
++  (jbyte) 0x83, (jbyte) 0x84, (jbyte) 0x85,
++  (jbyte) 0x86, (jbyte) 0x87};
++static const jchar FOUR_CHAR[] = {
++  (jchar) 0x8180, (jchar) 0x8382,
++  (jchar) 0x8584, (jchar) 0x8786};
++
++static const jint TWO_INT[] = { 0x83828180, 0x87868584};
++
++static const juint MURMUR3_32_X86_CHECK_VALUE = 0xB0F57EE3;
++
++void AltHashing::testMurmur3_32_ByteArray() {
++  // printf("testMurmur3_32_ByteArray\n");
++
++  jbyte* vector = new jbyte[256];
++  jbyte* hashes = new jbyte[4 * 256];
++
++  for (int i = 0; i < 256; i++) {
++    vector[i] = (jbyte) i;
++  }
++
++  // Hash subranges {}, {0}, {0,1}, {0,1,2}, ..., {0,...,255}
++  for (int i = 0; i < 256; i++) {
++    jint hash = murmur3_32(256 - i, vector, i);
++    hashes[i * 4] = (jbyte) hash;
++    hashes[i * 4 + 1] = (jbyte) (((juint)hash) >> 8);
++    hashes[i * 4 + 2] = (jbyte) (((juint)hash) >> 16);
++    hashes[i * 4 + 3] = (jbyte) (((juint)hash) >> 24);
++  }
++
++  // hash to get const result.
++  juint final_hash = murmur3_32(hashes, 4*256);
++
++  assert (MURMUR3_32_X86_CHECK_VALUE == final_hash,
++    err_msg(
++        "Calculated hash result not as expected. Expected %08X got %08X\n",
++        MURMUR3_32_X86_CHECK_VALUE,
++        final_hash));
++}
++
++void AltHashing::testEquivalentHashes() {
++  jint jbytes, jchars, ints;
++
++  // printf("testEquivalentHashes\n");
++
++  jbytes = murmur3_32(TWO_BYTE, 2);
++  jchars = murmur3_32(ONE_CHAR, 1);
++  assert (jbytes == jchars,
++    err_msg("Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars));
++
++  jbytes = murmur3_32(FOUR_BYTE, 4);
++  jchars = murmur3_32(TWO_CHAR, 2);
++  ints = murmur3_32(ONE_INT, 1);
++  assert ((jbytes == jchars) && (jbytes == ints),
++    err_msg("Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints));
++
++  jbytes = murmur3_32(SIX_BYTE, 6);
++  jchars = murmur3_32(THREE_CHAR, 3);
++  assert (jbytes == jchars,
++    err_msg("Hashes did not match. b:%08x != c:%08x\n", jbytes, jchars));
++
++  jbytes = murmur3_32(EIGHT_BYTE, 8);
++  jchars = murmur3_32(FOUR_CHAR, 4);
++  ints = murmur3_32(TWO_INT, 2);
++  assert ((jbytes == jchars) && (jbytes == ints),
++    err_msg("Hashes did not match. b:%08x != c:%08x != i:%08x\n", jbytes, jchars, ints));
++}
++
++// Returns true if the alternate hashcode is correct
++void AltHashing::test_alt_hash() {
++  testMurmur3_32_ByteArray();
++  testEquivalentHashes();
++}
++#endif // PRODUCT
+diff --git a/src/share/vm/classfile/altHashing.hpp b/src/share/vm/classfile/altHashing.hpp
+new file mode 100644
+--- /dev/null
++++ hotspot/src/share/vm/classfile/altHashing.hpp
+@@ -0,0 +1,62 @@
++/*
++ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * This code is free software; you can redistribute it and/or modify it
++ * under the terms of the GNU General Public License version 2 only, as
++ * published by the Free Software Foundation.
++ *
++ * This code is distributed in the hope that it will be useful, but WITHOUT
++ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
++ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
++ * version 2 for more details (a copy is included in the LICENSE file that
++ * accompanied this code).
++ *
++ * You should have received a copy of the GNU General Public License version
++ * 2 along with this work; if not, write to the Free Software Foundation,
++ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
++ *
++ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
++ * or visit www.oracle.com if you need additional information or have any
++ * questions.
++ *
++ */
++
++#ifndef SHARE_VM_CLASSFILE_ALTHASHING_HPP
++#define SHARE_VM_CLASSFILE_ALTHASHING_HPP
++
++#include "prims/jni.h"
++#include "classfile/symbolTable.hpp"
++
++/**
++ * Hashing utilities.
++ *
++ * Implementation of Murmur3 hashing.
++ * This code was translated from src/share/classes/sun/misc/Hashing.java
++ * code in the JDK.
++ */
++
++class AltHashing : AllStatic {
++
++  // utility function copied from java/lang/Integer
++  static jint Integer_rotateLeft(jint i, int distance) {
++    return (i << distance) | (((juint)i) >> (32-distance));
++  }
++  static jint murmur3_32(const int* data, int len);
++  static jint murmur3_32(jint seed, const int* data, int len);
++
++#ifndef PRODUCT
++  // Hashing functions used for internal testing
++  static jint murmur3_32(const jbyte* data, int len);
++  static jint murmur3_32(const jchar* data, int len);
++  static void testMurmur3_32_ByteArray();
++  static void testEquivalentHashes();
++#endif // PRODUCT
++
++ public:
++  static jint compute_seed();
++  static jint murmur3_32(jint seed, const jbyte* data, int len);
++  static jint murmur3_32(jint seed, const jchar* data, int len);
++  NOT_PRODUCT(static void test_alt_hash();)
++};
++#endif // SHARE_VM_CLASSFILE_ALTHASHING_HPP
+diff --git a/src/share/vm/classfile/javaClasses.cpp b/src/share/vm/classfile/javaClasses.cpp
+--- hotspot/src/share/vm/classfile/javaClasses.cpp
++++ hotspot/src/share/vm/classfile/javaClasses.cpp
+@@ -278,6 +278,28 @@
+   return result;
+ }
+ 
++unsigned int java_lang_String::to_hash(oop java_string) {
++  int          length = java_lang_String::length(java_string);
++  // Zero length string will hash to zero with String.toHash() function.
++  if (length == 0) return 0;
++
++  typeArrayOop value  = java_lang_String::value(java_string);
++  int          offset = java_lang_String::offset(java_string);
++  return java_lang_String::to_hash(value->char_at_addr(offset), length);
++}
++
++unsigned int java_lang_String::hash_string(oop java_string) {
++  int          length = java_lang_String::length(java_string);
++  // Zero length string doesn't hash necessarily hash to zero.
++  if (length == 0) {
++    return StringTable::hash_string(NULL, 0);
++  }
++
++  typeArrayOop value  = java_lang_String::value(java_string);
++  int          offset = java_lang_String::offset(java_string);
++  return StringTable::hash_string(value->char_at_addr(offset), length);
++}
++
+ symbolHandle java_lang_String::as_symbol(Handle java_string, TRAPS) {
+   oop          obj    = java_string();
+   typeArrayOop value  = java_lang_String::value(obj);
+diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp
+--- hotspot/src/share/vm/classfile/javaClasses.hpp
++++ hotspot/src/share/vm/classfile/javaClasses.hpp
+@@ -109,6 +109,30 @@
+   static char*  as_platform_dependent_str(Handle java_string, TRAPS);
+   static jchar* as_unicode_string(oop java_string, int& length);
+ 
++  // Compute the hash value for a java.lang.String object which would
++  // contain the characters passed in.
++  //
++  // As the hash value used by the String object itself, in
++  // String.hashCode().  This value is normally calculated in Java code
++  // in the String.hashCode method(), but is precomputed for String
++  // objects in the shared archive file.
++  // hash P(31) from Kernighan & Ritchie
++  //
++  // For this reason, THIS ALGORITHM MUST MATCH String.toHash().
++  template <typename T> static unsigned int to_hash(T* s, int len) {
++    unsigned int h = 0;
++    while (len-- > 0) {
++      h = 31*h + (unsigned int) *s;
++      s++;
++    }
++    return h;
++  }
++  static unsigned int to_hash(oop java_string);
++
++  // This is the string hash code used by the StringTable, which may be
++  // the same as String.toHash or an alternate hash code.
++  static unsigned int hash_string(oop java_string);
++
+   static bool equals(oop java_string, jchar* chars, int len);
+ 
+   // Conversion between '.' and '/' formats
+diff --git a/src/share/vm/classfile/symbolTable.cpp b/src/share/vm/classfile/symbolTable.cpp
+--- hotspot/src/share/vm/classfile/symbolTable.cpp
++++ hotspot/src/share/vm/classfile/symbolTable.cpp
+@@ -23,6 +23,7 @@
+  */
+ 
+ #include "precompiled.hpp"
++#include "classfile/altHashing.hpp"
+ #include "classfile/javaClasses.hpp"
+ #include "classfile/symbolTable.hpp"
+ #include "classfile/systemDictionary.hpp"
+@@ -34,16 +35,40 @@
+ #include "oops/symbolKlass.hpp"
+ #include "runtime/mutexLocker.hpp"
+ #include "utilities/hashtable.inline.hpp"
++#include "utilities/numberSeq.hpp"
+ 
+ // --------------------------------------------------------------------------
+ 
+ SymbolTable* SymbolTable::_the_table = NULL;
++bool SymbolTable::_needs_rehashing = false;
++
++// Create a new table and using alternate hash code, populate the new table
++// with the existing strings.   Set flag to use the alternate hash code afterwards.
++void SymbolTable::rehash_table() {
++
++  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
++  // This should never happen with -Xshare:dump but it might in testing mode.
++  if (DumpSharedSpaces) return;
++  // Create a new symbol table
++  SymbolTable* new_table = new SymbolTable();
++
++  the_table()->move_to(new_table);
++
++  // Delete the table and buckets (entries are reused in new table).
++  delete _the_table;
++  // Don't check if we need rehashing until the table gets unbalanced again.
++  // Then rehash with a new global seed.
++  _needs_rehashing = false;
++  _the_table = new_table;
++}
+ 
+ // Lookup a symbol in a bucket.
+ 
+ symbolOop SymbolTable::lookup(int index, const char* name,
+                               int len, unsigned int hash) {
++  int count = 0;
+   for (HashtableEntry* e = bucket(index); e != NULL; e = e->next()) {
++    count++;
+     if (e->hash() == hash) {
+       symbolOop sym = symbolOop(e->literal());
+       if (sym->equals(name, len)) {
+@@ -51,9 +76,20 @@
+       }
+     }
+   }
++  // If the bucket size is too deep check if this hash code is insufficient.
++  if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
++    _needs_rehashing = check_rehash_table(count);
++  }
+   return NULL;
+ }
+ 
++// Pick hashing algorithm.
++unsigned int SymbolTable::hash_symbol(const char* s, int len) {
++  return the_table()->use_alternate_hashcode() ?
++           AltHashing::murmur3_32(the_table()->seed(), (const jbyte*)s, len) :
++           java_lang_String::to_hash(s, len);
++}
++
+ 
+ // We take care not to be blocking while holding the
+ // SymbolTable_lock. Otherwise, the system might deadlock, since the
+@@ -71,8 +107,17 @@
+   // Found
+   if (s != NULL) return s;
+ 
++  // We assume that lookup() has been called already, that it failed,
++  // and symbol was not found.  We create the symbol here.
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop s_oop = sk->allocate_symbol((u1*)name, len, CHECK_NULL);
++  symbolHandle sym (THREAD, s_oop);
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
+   // Otherwise, add to symbol to table
+-  return the_table()->basic_add(index, (u1*)name, len, hashValue, CHECK_NULL);
++  return the_table()->basic_add(sym, index, (u1*)name, len, hashValue, CHECK_NULL);
+ }
+ 
+ symbolOop SymbolTable::lookup(symbolHandle sym, int begin, int end, TRAPS) {
+@@ -108,7 +153,16 @@
+   // We can't include the code in No_Safepoint_Verifier because of the
+   // ResourceMark.
+ 
+-  return the_table()->basic_add(index, (u1*)buffer, len, hashValue, CHECK_NULL);
++  // We assume that lookup() has been called already, that it failed,
++  // and symbol was not found.  We create the symbol here.
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop s_oop = sk->allocate_symbol((u1*)buffer, len, CHECK_NULL);
++  symbolHandle newsym (THREAD, s_oop);
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
++  return the_table()->basic_add(newsym, index, (u1*)buffer, len, hashValue, CHECK_NULL);
+ }
+ 
+ symbolOop SymbolTable::lookup_only(const char* name, int len,
+@@ -156,36 +210,68 @@
+ void SymbolTable::add(constantPoolHandle cp, int names_count,
+                       const char** names, int* lengths, int* cp_indices,
+                       unsigned int* hashValues, TRAPS) {
+-  SymbolTable* table = the_table();
+-  bool added = table->basic_add(cp, names_count, names, lengths,
+-                                cp_indices, hashValues, CHECK);
+-  if (!added) {
++
++  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++  symbolOop sym_oops[symbol_alloc_batch_size];
++  bool allocated = sk->allocate_symbols(names_count, names, lengths,
++                                        sym_oops, CHECK);
++  if (!allocated) {
+     // do it the hard way
+     for (int i=0; i<names_count; i++) {
++      assert(!Universe::heap()->is_in_reserved(names[i]) || GC_locker::is_active(),
++         "proposed name of symbol must be stable");
++
++      // We assume that lookup() has been called already, that it failed,
++      // and symbol was not found.  We create the symbol here.
++      symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
++      symbolOop s_oop = sk->allocate_symbol((u1*)names[i], lengths[i], CHECK);
++      symbolHandle sym (THREAD, s_oop);
++
++      // Allocation must be done before grabbing the SymbolTable_lock lock
++      MutexLocker ml(SymbolTable_lock, THREAD);
++
++      SymbolTable* table = the_table();
+       int index = table->hash_to_index(hashValues[i]);
+-      symbolOop sym = table->basic_add(index, (u1*)names[i], lengths[i],
++      symbolOop s = table->basic_add(sym, index, (u1*)names[i], lengths[i],
+                                        hashValues[i], CHECK);
+-      cp->symbol_at_put(cp_indices[i], sym);
++      cp->symbol_at_put(cp_indices[i], s);
+     }
++    return;
+   }
++
++  symbolHandle syms[symbol_alloc_batch_size];
++  for (int i=0; i<names_count; i++) {
++    syms[i] = symbolHandle(THREAD, sym_oops[i]);
++  }
++
++  // Allocation must be done before grabbing the SymbolTable_lock lock
++  MutexLocker ml(SymbolTable_lock, THREAD);
++
++  SymbolTable* table = the_table();
++  bool added = table->basic_add(syms, cp, names_count, names, lengths,
++                                cp_indices, hashValues, CHECK);
++  assert(added, "should always return true");
+ }
+ 
+-symbolOop SymbolTable::basic_add(int index, u1 *name, int len,
+-                                 unsigned int hashValue, TRAPS) {
+-  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
+-         "proposed name of symbol must be stable");
+-
+-  // We assume that lookup() has been called already, that it failed,
+-  // and symbol was not found.  We create the symbol here.
+-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
+-  symbolOop s_oop = sk->allocate_symbol(name, len, CHECK_NULL);
+-  symbolHandle sym (THREAD, s_oop);
+-
+-  // Allocation must be done before grapping the SymbolTable_lock lock
+-  MutexLocker ml(SymbolTable_lock, THREAD);
++symbolOop SymbolTable::basic_add(symbolHandle sym, int index_arg, u1 *name, int len,
++                                 unsigned int hashValue_arg, TRAPS) {
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+   assert(sym->equals((char*)name, len), "symbol must be properly initialized");
+ 
++  // Check if the symbol table has been rehashed, if so, need to recalculate
++  // the hash value and index.
++  unsigned int hashValue;
++  int index;
++  if (use_alternate_hashcode()) {
++    hashValue = hash_symbol((const char*)name, len);
++    index = hash_to_index(hashValue);
++  } else {
++    hashValue = hashValue_arg;
++    index = index_arg;
++  }
++
+   // Since look-up was done lock-free, we need to check if another
+   // thread beat us in the race to insert the symbol.
+ 
+@@ -201,48 +287,42 @@
+   return sym();
+ }
+ 
+-bool SymbolTable::basic_add(constantPoolHandle cp, int names_count,
++bool SymbolTable::basic_add(symbolHandle* syms,
++                            constantPoolHandle cp, int names_count,
+                             const char** names, int* lengths,
+                             int* cp_indices, unsigned int* hashValues,
+                             TRAPS) {
+-  symbolKlass* sk  = (symbolKlass*) Universe::symbolKlassObj()->klass_part();
+-  symbolOop sym_oops[symbol_alloc_batch_size];
+-  bool allocated = sk->allocate_symbols(names_count, names, lengths,
+-                                        sym_oops, CHECK_false);
+-  if (!allocated) {
+-    return false;
+-  }
+-  symbolHandle syms[symbol_alloc_batch_size];
+-  int i;
+-  for (i=0; i<names_count; i++) {
+-    syms[i] = symbolHandle(THREAD, sym_oops[i]);
+-  }
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;
+ 
+-  // Allocation must be done before grabbing the SymbolTable_lock lock
+-  MutexLocker ml(SymbolTable_lock, THREAD);
+-
+-  for (i=0; i<names_count; i++) {
++  for (int i=0; i<names_count; i++) {
+     assert(syms[i]->equals(names[i], lengths[i]), "symbol must be properly initialized");
++    // Check if the symbol table has been rehashed, if so, need to recalculate
++    // the hash value.
++    unsigned int hashValue;
++    if (use_alternate_hashcode()) {
++      hashValue = hash_symbol(names[i], lengths[i]);
++    } else {
++      hashValue = hashValues[i];
++    }
+     // Since look-up was done lock-free, we need to check if another
+     // thread beat us in the race to insert the symbol.
+-    int index = hash_to_index(hashValues[i]);
+-    symbolOop test = lookup(index, names[i], lengths[i], hashValues[i]);
++    int index = hash_to_index(hashValue);
++    symbolOop test = lookup(index, names[i], lengths[i], hashValue);
+     if (test != NULL) {
+       // A race occurred and another thread introduced the symbol, this one
+       // will be dropped and collected. Use test instead.
+       cp->symbol_at_put(cp_indices[i], test);
+     } else {
+       symbolOop sym = syms[i]();
+-      HashtableEntry* entry = new_entry(hashValues[i], sym);
++      HashtableEntry* entry = new_entry(hashValue, sym);
+       add_entry(index, entry);
+       cp->symbol_at_put(cp_indices[i], sym);
+     }
+   }
+-
+-  return true;
++  return true;  // always returns true
+ }
+ 
+-
+ void SymbolTable::verify() {
+   for (int i = 0; i < the_table()->table_size(); ++i) {
+     HashtableEntry* p = the_table()->bucket(i);
+@@ -251,7 +331,7 @@
+       guarantee(s != NULL, "symbol is NULL");
+       s->verify();
+       guarantee(s->is_perm(), "symbol not in permspace");
+-      unsigned int h = hash_symbol((char*)s->bytes(), s->utf8_length());
++      unsigned int h = hash_symbol((const char*)s->bytes(), s->utf8_length());
+       guarantee(p->hash() == h, "broken hash in symbol table entry");
+       guarantee(the_table()->hash_to_index(h) == i,
+                 "wrong index in symbol table");
+@@ -259,6 +339,23 @@
+   }
+ }
+ 
++void SymbolTable::dump(outputStream* st) {
++  NumberSeq summary;
++  for (int i = 0; i < the_table()->table_size(); ++i) {
++    int count = 0;
++    for (HashtableEntry* e = the_table()->bucket(i);
++       e != NULL; e = e->next()) {
++      count++;
++    }
++    summary.add((double)count);
++  }
++  st->print_cr("SymbolTable statistics:");
++  st->print_cr("Number of buckets       : %7d", summary.num());
++  st->print_cr("Average bucket size     : %7.0f", summary.avg());
++  st->print_cr("Variance of bucket size : %7.0f", summary.variance());
++  st->print_cr("Std. dev. of bucket size: %7.0f", summary.sd());
++  st->print_cr("Maximum bucket size     : %7.0f", summary.maximum());
++}
+ 
+ //---------------------------------------------------------------------------
+ // Non-product code
+@@ -321,7 +418,6 @@
+   tty->print_cr(" %s %d: %d\n", "Number chains longer than",
+                     results_length, out_of_range);
+ }
+-
+ #endif // PRODUCT
+ 
+ // --------------------------------------------------------------------------
+@@ -367,66 +463,56 @@
+ // --------------------------------------------------------------------------
+ 
+ 
+-// Compute the hash value for a java.lang.String object which would
+-// contain the characters passed in. This hash value is used for at
+-// least two purposes.
+-//
+-// (a) As the hash value used by the StringTable for bucket selection
+-//     and comparison (stored in the HashtableEntry structures).  This
+-//     is used in the String.intern() method.
+-//
+-// (b) As the hash value used by the String object itself, in
+-//     String.hashCode().  This value is normally calculate in Java code
+-//     in the String.hashCode method(), but is precomputed for String
+-//     objects in the shared archive file.
+-//
+-//     For this reason, THIS ALGORITHM MUST MATCH String.hashCode().
++StringTable* StringTable::_the_table = NULL;
+ 
+-int StringTable::hash_string(jchar* s, int len) {
+-  unsigned h = 0;
+-  while (len-- > 0) {
+-    h = 31*h + (unsigned) *s;
+-    s++;
+-  }
+-  return h;
++bool StringTable::_needs_rehashing = false;
++
++// Pick hashing algorithm
++unsigned int StringTable::hash_string(const jchar* s, int len) {
++  return the_table()->use_alternate_hashcode() ? AltHashing::murmur3_32(the_table()->seed(), s, len) :
++                                    java_lang_String::to_hash(s, len);
+ }
+ 
+-
+-StringTable* StringTable::_the_table = NULL;
+-
+ oop StringTable::lookup(int index, jchar* name,
+                         int len, unsigned int hash) {
++  int count = 0;
+   for (HashtableEntry* l = bucket(index); l != NULL; l = l->next()) {
++    count++;
+     if (l->hash() == hash) {
+       if (java_lang_String::equals(l->literal(), name, len)) {
+         return l->literal();
+       }
+     }
+   }
++  // If the bucket size is too deep check if this hash code is insufficient.
++  if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
++    _needs_rehashing = check_rehash_table(count);
++  }
+   return NULL;
+ }
+ 
+ 
+-oop StringTable::basic_add(int index, Handle string_or_null, jchar* name,
+-                           int len, unsigned int hashValue, TRAPS) {
+-  debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
+-  assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(),
+-         "proposed name of symbol must be stable");
++oop StringTable::basic_add(int index_arg, Handle string, jchar* name,
++                           int len, unsigned int hashValue_arg, TRAPS) {
+ 
+-  Handle string;
+-  // try to reuse the string if possible
+-  if (!string_or_null.is_null() && string_or_null()->is_perm()) {
+-    string = string_or_null;
+-  } else {
+-    string = java_lang_String::create_tenured_from_unicode(name, len, CHECK_NULL);
+-  }
+-
+-  // Allocation must be done before grapping the SymbolTable_lock lock
+-  MutexLocker ml(StringTable_lock, THREAD);
++  // Cannot hit a safepoint in this function because the "this" pointer can move.
++  No_Safepoint_Verifier nsv;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201210192243.q9JMhAe2092366>