Wed, 12 Jun 2013 16:41:38 +0200
8011893: JS Object builtin prototype is not thread safe
Reviewed-by: sundar, jlaskey
1.1 --- a/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java Wed Jun 12 11:22:06 2013 -0300 1.2 +++ b/src/jdk/nashorn/internal/runtime/PropertyListenerManager.java Wed Jun 12 16:41:38 2013 +0200 1.3 @@ -61,7 +61,7 @@ 1.4 * 1.5 * @param listener The property listener that is added. 1.6 */ 1.7 - public final void addPropertyListener(final PropertyListener listener) { 1.8 + public synchronized final void addPropertyListener(final PropertyListener listener) { 1.9 if (listeners == null) { 1.10 listeners = new WeakHashMap<>(); 1.11 } 1.12 @@ -77,7 +77,7 @@ 1.13 * 1.14 * @param listener The property listener that is removed. 1.15 */ 1.16 - public final void removePropertyListener(final PropertyListener listener) { 1.17 + public synchronized final void removePropertyListener(final PropertyListener listener) { 1.18 if (listeners != null) { 1.19 if (Context.DEBUG) { 1.20 listenersRemoved++; 1.21 @@ -92,7 +92,7 @@ 1.22 * @param object The ScriptObject to which property was added. 1.23 * @param prop The property being added. 1.24 */ 1.25 - protected final void notifyPropertyAdded(final ScriptObject object, final Property prop) { 1.26 + protected synchronized final void notifyPropertyAdded(final ScriptObject object, final Property prop) { 1.27 if (listeners != null) { 1.28 for (PropertyListener listener : listeners.keySet()) { 1.29 listener.propertyAdded(object, prop); 1.30 @@ -106,7 +106,7 @@ 1.31 * @param object The ScriptObject from which property was deleted. 1.32 * @param prop The property being deleted. 1.33 */ 1.34 - protected final void notifyPropertyDeleted(final ScriptObject object, final Property prop) { 1.35 + protected synchronized final void notifyPropertyDeleted(final ScriptObject object, final Property prop) { 1.36 if (listeners != null) { 1.37 for (PropertyListener listener : listeners.keySet()) { 1.38 listener.propertyDeleted(object, prop); 1.39 @@ -121,7 +121,7 @@ 1.40 * @param oldProp The old property being replaced. 1.41 * @param newProp The new property that replaces the old property. 1.42 */ 1.43 - protected final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { 1.44 + protected synchronized final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) { 1.45 if (listeners != null) { 1.46 for (PropertyListener listener : listeners.keySet()) { 1.47 listener.propertyModified(object, oldProp, newProp);
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/test/script/basic/JDK-8011893.js Wed Jun 12 16:41:38 2013 +0200 2.3 @@ -0,0 +1,51 @@ 2.4 +/* 2.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 2.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 2.7 + * 2.8 + * This code is free software; you can redistribute it and/or modify it 2.9 + * under the terms of the GNU General Public License version 2 only, as 2.10 + * published by the Free Software Foundation. 2.11 + * 2.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 2.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 2.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 2.15 + * version 2 for more details (a copy is included in the LICENSE file that 2.16 + * accompanied this code). 2.17 + * 2.18 + * You should have received a copy of the GNU General Public License version 2.19 + * 2 along with this work; if not, write to the Free Software Foundation, 2.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2.21 + * 2.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2.23 + * or visit www.oracle.com if you need additional information or have any 2.24 + * questions. 2.25 + */ 2.26 + 2.27 +/** 2.28 + * JDK-8011893: JS Object builtin prototype is not thread safe 2.29 + * 2.30 + * @test 2.31 + * @run 2.32 + */ 2.33 + 2.34 +var a = {}; 2.35 +var thread = new java.lang.Thread(new java.lang.Runnable() { 2.36 + run: function() { 2.37 + print("Thread starts"); 2.38 + for (var i = 0; i < 1000000; i++) { 2.39 + // Unsubscribe to builtin, subscribe to new proto 2.40 + var b = Object.create(a); 2.41 + } 2.42 + print("Thread done"); 2.43 + } 2.44 +}); 2.45 + 2.46 +print("Main starts"); 2.47 +thread.start(); 2.48 +for (var j = 0; j < 1000000; j++) { 2.49 + // Subscribe to builtin prototype. 2.50 + a = {}; 2.51 +} 2.52 + 2.53 +thread.join(); 2.54 +print("Main done");
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/test/script/basic/JDK-8011893.js.EXPECTED Wed Jun 12 16:41:38 2013 +0200 3.3 @@ -0,0 +1,4 @@ 3.4 +Main starts 3.5 +Thread starts 3.6 +Thread done 3.7 +Main done