Thanks for the reviews! I uploaded a new webrev that includes most of
your suggestions:
http://cr.openjdk.java.net/~hannesw/8141702/webrev.01/
A few notes:
- I followed Attila's suggestion regarding
NativeSymbol.globalSymbolRegistry, creating a new
jdk.nashorn.internal.WeakValueCache class that is used for both
anonymous classes in Context and interned symbols in NativeSymbol.
- I didn't use ConcurrentHashTable instead of synchronization since I
envision symbol interning to be an infrequent operation. We can revisit
this later on I guess.
- I didn't really find a good place for a comment about symbols and
codegen/serialization. However, I decided to make Symbol serializable
even though it does not have to be yet.
Thanks,
Hannes
Am 2015-11-10 um 18:18 schrieb Attila Szegedi:
Great work!
I have few remarks on the NativeSymbol.globalSymbolRegistry:
I think it’s okay to have a static String->Symbol map in NativeSymbol.globalSymbolRegistry, but it’d
need to be a Map<String, SymbolReference> where SymbolReference is a "class SymbolReference
extends WeakReference<Symbol>" and also carries the string key as its field. A reference
queue would be needed to remove String keys for which references were cleared. This should pretty much
work exactly the same as Context.anonymousHostClasses works. Maybe you could extract that code into a
utility class?
For keyFor, instead of containsValue (linear time lookup) how about checking:
String name = ((Symbol)arg).getName();
return globalSymbolRegistry.get(name) == arg ? name :
Undefined.getUndefined();
instead? Again, if you’d adopt my suggestion for references, then get() returns
a reference instead of a symbol, but the principle is the same.
Finally, globalSymbolRegistry is a HashMap, and you synchronize around it. I’d
consider using a ConcurrentHashMap instead and avoid synchronization. There’s
the minor issue that if you adopt my reference suggestion above then you can’t
atomically deal with the situation where the reference is cleared. You can
still avoid synchronization using a ConcurrentMap and computeIfAbsent if you
want to avoid synchronization, but you’ll need to additionally validate that a
non-absent reference is not cleared, and if it is, then create a new one and do
an additional putIfAbsent. The interaction between FOR and keyFor is not racy
anyway, as in order to not get back undefined, one already has to have a strong
reference to a symbol that’s in the map.
Attila.
On Nov 10, 2015, at 4:35 PM, Sundararajan Athijegannathan
<sundararajan.athijegannat...@oracle.com> wrote:
Hi,
Nice work!
Few comments:
* the symbol "internalizing" table could be per Context. Keeping it as static
field from that class => Symbol instances are leaked permanently. Since we have 1:1
between script engine and nashorn Context instance, it is better if we keep it as
Context-wide global. That way, when the engine dies, it's Symbols can be GC'ed.
* Classes like NativeSymbol, Symbol can be final.
* There could be comment somewhere that codegenerator will take care of String
or Number properties in places where 'serialize' Properties, PropertyMaps
(i.e., arbitrary Object value is taken care of).
That's it!
+1
-Sundar
On 11/10/2015 8:12 PM, Hannes Wallnoefer wrote:
Please review JDK-8141702: Add support for Symbol property keys:
http://cr.openjdk.java.net/~hannesw/8141702/
This adds support for Symbols. Symbols are a new type of guaranteed-unique
property keys that can be used to add properties to objects without risking
conflicts with existing properties. Symbols are used by many other features in
ES6, so it helps a lot to have this in.
The patch looks big but for most files it's just the type of property keys that
changed from String to Object. This change is pretty simple, and it does not
affect the fast property access path.
I had to jump through some hoops in order to deal with some of the strange
characteristics of symbols, such as the fact that implicit conversion to string
or number throws a TypeError. For example, I introduced a dedicated toString
method in tools.Shell to render results so it could display symbols both as top
level values and when contained in an array (which neither JSType.toString nor
ScriptRuntime.safeToString would let us do).
I think I explained all these cases sufficiently, but feel free to ask if
something looks weird.
This change is completely invisible in ES5 mode. I also added a test that
checks the absence of this and other ES6 features in ES5 mode as suggested by
Sundar.
Thanks,
Hannes