# HG changeset patch # User asaha # Date 1446164532 25200 # Node ID bf97e9141fe5bb651469636124534599f2098ed0 # Parent ee2c313d02a3378048528828dd2ec45396043b6c# Parent d0af1c9ef1010cb1fe76c704f9947e0670311a7b Merge diff -r ee2c313d02a3 -r bf97e9141fe5 .hgtags --- a/.hgtags Fri Oct 16 12:19:59 2015 -0700 +++ b/.hgtags Thu Oct 29 17:22:12 2015 -0700 @@ -484,4 +484,14 @@ b8987f466586180cb4dc387f5fa290bb4cf34983 jdk8u71-b01 a8fd49cb76fafc704b746a98bd18647802674d2d jdk8u71-b02 12745568f9fb73a452d85b2388fef29909dafc24 jdk8u71-b03 +92b196168ef13e159e311e864c08d70e2c23dec6 jdk8u71-b04 +c870d760ca23b0f2c21813946eeb36563eeea8d4 jdk8u71-b05 +f76ef9364e15663fe29cda34f7d95cbab224ff36 jdk8u71-b06 +667e020da337e453eac8ecb9285c9b34a47e25fd jdk8u72-b00 +a105e7b0eff93895b82e3d372a63df4311d79821 jdk8u72-b01 +f7c3d65076a0c0bf1bb4ea633b4ea0af9ffb12fe jdk8u72-b02 +c47a6341ae31e394f6748acbeebf68de3ae285ff jdk8u72-b03 +4592976d8655d9ec0ad364901ae07c79813c8cd4 jdk8u72-b04 +0c87ce7cc7d01462476bce07945dc1646b4f08d1 jdk8u72-b05 +a2591c7bcb92f5bb2bd53b46d5a2c97be367f7fe jdk8u72-b06 c7eddafb2ee2cc9d62f20c4d821ccac03bd4617d jdk8u75-b00 diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java Thu Oct 29 17:22:12 2015 -0700 @@ -54,10 +54,9 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_NEWMAP_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROPERTYMAP_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_DESC; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_TYPE; @@ -282,9 +281,9 @@ assert specs != null; if (!specs.isEmpty()) { mi.memberInfoArray(className, specs); - mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC); + mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC); } else { - mi.invokeStatic(SCRIPTFUNCTIONIMPL_TYPE, SCRIPTFUNCTIONIMPL_MAKEFUNCTION, SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC); + mi.invokeStatic(SCRIPTFUNCTION_TYPE, SCRIPTFUNCTION_CREATEBUILTIN, SCRIPTFUNCTION_CREATEBUILTIN_DESC); } if (arityFound) { diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java Thu Oct 29 17:22:12 2015 -0700 @@ -38,9 +38,8 @@ import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_SETCONSTRUCTOR_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.PROTOTYPEOBJECT_TYPE; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC3; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_INIT_DESC4; -import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTIONIMPL_TYPE; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC3; +import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_INIT_DESC4; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETARITY_DESC; import static jdk.nashorn.internal.tools.nasgen.StringConstants.SCRIPTFUNCTION_SETPROTOTYPE; @@ -55,7 +54,7 @@ import jdk.internal.org.objectweb.asm.Handle; /** - * This class generates constructor class for a @ClassInfo annotated class. + * This class generates constructor class for a @ScriptClass annotated class. * */ public class ConstructorGenerator extends ClassGenerator { @@ -75,8 +74,8 @@ } byte[] getClassBytes() { - // new class extensing from ScriptObject - final String superClass = (constructor != null)? SCRIPTFUNCTIONIMPL_TYPE : SCRIPTOBJECT_TYPE; + // new class extending from ScriptObject + final String superClass = (constructor != null)? SCRIPTFUNCTION_TYPE : SCRIPTOBJECT_TYPE; cw.visit(V1_7, ACC_FINAL, className, null, superClass, null); if (memberCount > 0) { // add fields @@ -182,8 +181,8 @@ loadMap(mi); } else { // call Function. - superClass = SCRIPTFUNCTIONIMPL_TYPE; - superDesc = (memberCount > 0) ? SCRIPTFUNCTIONIMPL_INIT_DESC4 : SCRIPTFUNCTIONIMPL_INIT_DESC3; + superClass = SCRIPTFUNCTION_TYPE; + superDesc = (memberCount > 0) ? SCRIPTFUNCTION_INIT_DESC4 : SCRIPTFUNCTION_INIT_DESC3; mi.loadLiteral(constructor.getName()); mi.visitLdcInsn(new Handle(H_INVOKESTATIC, scriptClassInfo.getJavaName(), constructor.getJavaName(), constructor.getJavaDesc())); loadMap(mi); diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java Thu Oct 29 17:22:12 2015 -0700 @@ -161,7 +161,7 @@ } /** - * Tag something as optimitic builtin or not + * Tag something as optimistic builtin or not * @param isOptimistic boolean, true if builtin constructor */ public void setIsOptimistic(final boolean isOptimistic) { @@ -178,7 +178,7 @@ } /** - * Set thre SpecializedFunction link logic class for specializations, i.e. optimistic + * Set the SpecializedFunction link logic class for specializations, i.e. optimistic * builtins * @param linkLogicClass link logic class */ diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java Thu Oct 29 17:22:12 2015 -0700 @@ -42,7 +42,7 @@ import java.io.IOException; /** - * This class generates prototype class for a @ClassInfo annotated class. + * This class generates prototype class for a @ScriptClass annotated class. * */ public class PrototypeGenerator extends ClassGenerator { @@ -57,7 +57,7 @@ } byte[] getClassBytes() { - // new class extensing from ScriptObject + // new class extending from ScriptObject cw.visit(V1_7, ACC_FINAL | ACC_SUPER, className, null, PROTOTYPEOBJECT_TYPE, null); if (memberCount > 0) { // add fields @@ -155,7 +155,7 @@ */ public static void main(final String[] args) throws IOException { if (args.length != 1) { - System.err.println("Usage: " + ConstructorGenerator.class.getName() + " "); + System.err.println("Usage: " + PrototypeGenerator.class.getName() + " "); System.exit(1); } diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfo.java Thu Oct 29 17:22:12 2015 -0700 @@ -48,7 +48,7 @@ * */ public final class ScriptClassInfo { - // descriptots for various annotations + // descriptors for various annotations static final String SCRIPT_CLASS_ANNO_DESC = Type.getDescriptor(ScriptClass.class); static final String CONSTRUCTOR_ANNO_DESC = Type.getDescriptor(Constructor.class); static final String FUNCTION_ANNO_DESC = Type.getDescriptor(Function.class); @@ -140,7 +140,7 @@ } boolean isPrototypeNeeded() { - // Prototype class generation is needed if we have atleast one + // Prototype class generation is needed if we have at least one // prototype property or @Constructor defined in the class. for (final MemberInfo memInfo : members) { if (memInfo.getWhere() == Where.PROTOTYPE || memInfo.isConstructor()) { diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInfoCollector.java Thu Oct 29 17:22:12 2015 -0700 @@ -118,7 +118,7 @@ addScriptMember(memInfo); return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { - // These could be "null" if values are not suppiled, + // These could be "null" if values are not supplied, // in which case we have to use the default values. private String name; private Integer attributes; @@ -194,7 +194,7 @@ final MemberInfo memInfo = new MemberInfo(); - //annokind == e.g. GETTER or SPECIALIZED_FUNCTION + // annoKind == GETTER or SPECIALIZED_FUNCTION memInfo.setKind(annoKind); memInfo.setJavaName(methodName); memInfo.setJavaDesc(methodDesc); @@ -203,7 +203,7 @@ addScriptMember(memInfo); return new AnnotationVisitor(Opcodes.ASM4, delegateAV) { - // These could be "null" if values are not suppiled, + // These could be "null" if values are not supplied, // in which case we have to use the default values. private String name; private Integer attributes; diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ScriptClassInstrumentor.java Thu Oct 29 17:22:12 2015 -0700 @@ -65,7 +65,6 @@ * 2) add "Map" type static field named "$map". * 3) add static initializer block to initialize map. */ - public class ScriptClassInstrumentor extends ClassVisitor { private final ScriptClassInfo scriptClassInfo; private final int memberCount; @@ -267,7 +266,7 @@ */ public static void main(final String[] args) throws IOException { if (args.length != 1) { - System.err.println("Usage: " + ScriptClassInfoCollector.class.getName() + " "); + System.err.println("Usage: " + ScriptClassInstrumentor.class.getName() + " "); System.exit(1); } diff -r ee2c313d02a3 -r bf97e9141fe5 buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java --- a/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Fri Oct 16 12:19:59 2015 -0700 +++ b/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java Thu Oct 29 17:22:12 2015 -0700 @@ -31,10 +31,9 @@ import java.util.Collections; import java.util.List; import jdk.internal.org.objectweb.asm.Type; -import jdk.nashorn.internal.objects.PrototypeObject; -import jdk.nashorn.internal.objects.ScriptFunctionImpl; import jdk.nashorn.internal.runtime.AccessorProperty; import jdk.nashorn.internal.runtime.PropertyMap; +import jdk.nashorn.internal.runtime.PrototypeObject; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.Specialization; @@ -88,7 +87,6 @@ static final Type TYPE_PROPERTYMAP = Type.getType(PropertyMap.class); static final Type TYPE_PROTOTYPEOBJECT = Type.getType(PrototypeObject.class); static final Type TYPE_SCRIPTFUNCTION = Type.getType(ScriptFunction.class); - static final Type TYPE_SCRIPTFUNCTIONIMPL = Type.getType(ScriptFunctionImpl.class); static final Type TYPE_SCRIPTOBJECT = Type.getType(ScriptObject.class); static final String PROTOTYPE_SUFFIX = "$Prototype"; @@ -122,17 +120,14 @@ static final String SCRIPTFUNCTION_SETARITY_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, Type.INT_TYPE); static final String SCRIPTFUNCTION_SETPROTOTYPE = "setPrototype"; static final String SCRIPTFUNCTION_SETPROTOTYPE_DESC = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_OBJECT); - - // ScriptFunctionImpl - static final String SCRIPTFUNCTIONIMPL_TYPE = TYPE_SCRIPTFUNCTIONIMPL.getInternalName(); - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION = "makeFunction"; - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_DESC = + static final String SCRIPTFUNCTION_CREATEBUILTIN = "createBuiltin"; + static final String SCRIPTFUNCTION_CREATEBUILTIN_DESC = Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE); - static final String SCRIPTFUNCTIONIMPL_MAKEFUNCTION_SPECS_DESC = + static final String SCRIPTFUNCTION_CREATEBUILTIN_SPECS_DESC = Type.getMethodDescriptor(TYPE_SCRIPTFUNCTION, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); - static final String SCRIPTFUNCTIONIMPL_INIT_DESC3 = + static final String SCRIPTFUNCTION_INIT_DESC3 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_SPECIALIZATION_ARRAY); - static final String SCRIPTFUNCTIONIMPL_INIT_DESC4 = + static final String SCRIPTFUNCTION_INIT_DESC4 = Type.getMethodDescriptor(Type.VOID_TYPE, TYPE_STRING, TYPE_METHODHANDLE, TYPE_PROPERTYMAP, TYPE_SPECIALIZATION_ARRAY); // ScriptObject diff -r ee2c313d02a3 -r bf97e9141fe5 make/build.xml --- a/make/build.xml Fri Oct 16 12:19:59 2015 -0700 +++ b/make/build.xml Thu Oct 29 17:22:12 2015 -0700 @@ -209,10 +209,11 @@ + + additionalparam="-quiet" failonerror="true" useexternalfile="true"> @@ -226,10 +227,23 @@ + + + + + + + + + + + + windowtitle="${nashorn.product.name}" additionalparam="-quiet" failonerror="true" useexternalfile="true"> @@ -238,7 +252,6 @@ - @@ -267,8 +280,8 @@ @@ -460,7 +473,7 @@ - + diff -r ee2c313d02a3 -r bf97e9141fe5 make/project.properties --- a/make/project.properties Fri Oct 16 12:19:59 2015 -0700 +++ b/make/project.properties Thu Oct 29 17:22:12 2015 -0700 @@ -30,6 +30,8 @@ build.compiler=modern javac.source=1.7 javac.target=1.7 +test.javac.source=1.8 +test.javac.target=1.8 # nashorn version information nashorn.version=0.1 diff -r ee2c313d02a3 -r bf97e9141fe5 samples/EvalWithArbitraryThis.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/EvalWithArbitraryThis.java Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import javax.script.*; +import jdk.nashorn.api.scripting.*; + +// Simple nashorn demo that evals a script with arbitrary script +// object bound as "this" for the evaluated script. + +public class EvalWithArbitraryThis { + public static void main(String[] args) throws Exception { + ScriptEngineManager m = new ScriptEngineManager(); + ScriptEngine e = m.getEngineByName("nashorn"); + Object sobj = e.eval("( { foo: 343, bar: 'hello' } )"); + + // "this" bound to sobj in this eval. + // so it prints sobj.foo and sobj.bar. + ((ScriptObjectMirror)sobj).eval("print(this.foo); print(this.bar)"); + } +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/LambdaAsFunc.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/LambdaAsFunc.java Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import javax.script.*; +import java.util.function.*; + +// example demonstrating that arbitrary Lambda can be called as function from script + +public class LambdaAsFunc { + public static void main(String[] args) throws Exception { + ScriptEngineManager m = new ScriptEngineManager(); + ScriptEngine e = m.getEngineByName("nashorn"); + + // expose a lambda as top-level script function + e.put("upper", (Function) String::toUpperCase); + + // call lambda as though it is a normal script function + System.out.println(e.eval("upper('hello')")); + } +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/Main.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/Main.asm Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple sample to demonstrate openjdk asmtools assembler with +// nashorn dynalink linker in a invokedynamic instruction. +// +// To assemble this file, use the following command: +// +// java -cp org.openjdk.asmtools.Main jasm Main.asm +// +// See also: https://wiki.openjdk.java.net/display/CodeTools/asmtools +// +// NOTE: Uses nashorn internals and so *may* break with later nashorn! + +super public class Main + version 52:0 +{ + + +public Method "":"()V" + stack 1 locals 1 +{ + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; +} + +public static Method main:"([Ljava/lang/String;)V" + stack 2 locals 2 +{ + // List l = new ArrayList(); + new class java/util/ArrayList; + dup; + invokespecial Method java/util/ArrayList."":"()V"; + astore_1; + aload_1; + + // l.add("hello"); + ldc String "hello"; + invokeinterface InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z", 2; + pop; + + // l.add("world"); + aload_1; + ldc String "world"; + invokeinterface InterfaceMethod java/util/List.add:"(Ljava/lang/Object;)Z", 2; + pop; + + // printLength(l); + aload_1; + invokestatic Method printLength:"(Ljava/lang/Object;)V"; + + // printLength(args); // args is argument of main method + aload_0; + invokestatic Method printLength:"(Ljava/lang/Object;)V"; + return; +} + +private static Method printLength:"(Ljava/lang/Object;)V" + stack 2 locals 1 +{ + getstatic Field java/lang/System.out:"Ljava/io/PrintStream;"; + aload_0; + + // Using nashorn embedded dynalink linker with the following invokedynamic + // 'length' property on a bean - arrays, lists supported + + invokedynamic InvokeDynamic REF_invokeStatic:jdk/nashorn/internal/runtime/linker/Bootstrap.bootstrap:"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;I)Ljava/lang/invoke/CallSite;":"dyn:getProp|getElem|getMethod:length":"(Ljava/lang/Object;)Ljava/lang/Object;" int 0; + + // print 'length' value + invokevirtual Method java/io/PrintStream.println:"(Ljava/lang/Object;)V"; + return; +} + +} // end Class Main diff -r ee2c313d02a3 -r bf97e9141fe5 samples/PrintToString.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/PrintToString.java Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import javax.script.*; +import java.io.StringWriter; + +// simple example demonstrating capturing of "print" output +// from script execution as a String via script engine API. + +public class PrintToString { + public static void main(String[] args) throws ScriptException { + ScriptEngineManager m = new ScriptEngineManager(); + ScriptEngine e = m.getEngineByName("nashorn"); + StringWriter sw = new StringWriter(); + e.getContext().setWriter(sw); + e.eval("print('hello world')"); + System.out.println(sw.toString()); + } +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/array_removeif.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/array_removeif.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Sample for Collection.removeIf and Java.to +// See http://docs.oracle.com/javase/8/docs/api/java/util/Collection.html#removeIf-java.util.function.Predicate- + +var langs = [ + "java", "javascript", + "C", "C#", "C++", + "Erlang", "Haskell" +]; + +// convert script array to a Java List +function asList(array) { + return Java.to(array, java.util.List); +} + +// remove elements that satisfy a predicate +// using Collection.removeIf(Predicate) +asList(langs).removeIf( + function(s) s.startsWith("C")); + +// print modified array +print(langs); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/bind_on_java.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/bind_on_java.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// sample to demonstrate calling Function.prototype.bind on Java methods. + +var DoubleStream = java.util.stream.DoubleStream; +var r = new java.util.Random(); + +// bind "this" for nextGaussian method of Random class +var next = Function.bind.call(r.nextGaussian, r); + +// next is used as no argument "function" +DoubleStream + .generate(function() next()) + .limit(100) + .forEach(print); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/call_bind_java.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/call_bind_java.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Sample demonstrating calling Java methods like normal +// functions. Bound instance methods, static methods can be +// called like normal script functions. + +// Java types used +var Files = Java.type("java.nio.file.Files"); +var FileSystems = Java.type("java.nio.file.FileSystems"); +var System = Java.type("java.lang.System"); + +var fs = FileSystems.default; +var bind = Function.prototype.bind; + +// Java methods as "functions" + +// Java method with bound "this" +var Path = bind.call(fs.getPath, fs); +// Java static method +var Property = System.getProperty; + +// call Java static methods and bound instance methods +// like normal script functions. + +var root = Path("/"); +// print URI for root dir +print(root.toUri()); +var home = Path(Property("user.home")); +// list home directory +Files.walk(home).forEach(print); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/check_nashorn.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/check_nashorn.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// check if script is being run using nashorn script engine +function isNashorn() { + try { + // "engine" variable is of type javax.script.ScriptEngine is defined + // by nashorn jsr-223 engine. Check the name of the engine from + // javax.script.ScriptEngineFactory associated + + return engine.factory.engineName.contains("Nashorn"); + } catch (e) { + // if engine or any of the properties are undefined + // then script is not being run using nashorn. + return false; + } +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/datetime.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/datetime.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// converting b/w JavaScript Date and Java LocalDateTime + +// JavaScript Date with current time +var d = new Date(); +print(d); + +// Java 8 java.time classes used +var Instant = java.time.Instant; +var LocalDateTime = java.time.LocalDateTime; +var ZoneId = java.time.ZoneId; + +// Date.prototype.getTime + +// getTime() method returns the numeric value corresponding to the time +// for the specified date according to universal time. The value returned +// by the getTime() method is the number of milliseconds since 1 January 1970 00:00:00 UTC. +// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime + +// Java Instant.ofEpochMilli to convert time in milliseconds to Instant object +// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#ofEpochMilli-long- + +var instant = Instant.ofEpochMilli(d.getTime()); + +// Instant to LocalDateTime using LocalDateTime.ofInstant +// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#ofInstant-java.time.Instant-java.time.ZoneId- + +var ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); +print(ldt); + +// converting a LocalDateTime to JavaScript Date +// convert LocalDateTime to Instant first +// https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#atZone-java.time.ZoneId- + +var instant = ldt.atZone(ZoneId.systemDefault()).toInstant(); + +// instant to to epoch milliseconds +// https://docs.oracle.com/javase/8/docs/api/java/time/Instant.html#toEpochMilli-- +// and then to JavaScript Date from time in milliseconds +// https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date + +var d1 = new Date(instant.toEpochMilli()); +print(d1); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/defaults.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/defaults.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// print default methods of a Java class + +if (arguments.length == 0) { + print("Usage: jjs defaults.js -- "); + exit(1); +} + +var jclass = Java.type(arguments[0]).class; +for each (m in jclass.methods) { + // http://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html#isDefault-- + if (m.default) print(m); +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/exceptionswallow.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/exceptionswallow.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,136 @@ +#// Usage: jjs exceptionswallow.js -- + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This example demonstrates Java subclassing by Java.extend +// and javac Compiler and Tree API. This example looks for +// empty catch blocks ("exception swallow") and reports those. + +if (arguments.length == 0) { + print("Usage: jjs exceptionswallow.js -- "); + exit(1); +} + +// Java types used +var File = Java.type("java.io.File"); +var Files = Java.type("java.nio.file.Files"); +var StringArray = Java.type("java.lang.String[]"); +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var Tree = Java.type("com.sun.source.tree.Tree"); +var EmptyStatementTree = Java.type("com.sun.source.tree.EmptyStatementTree"); +var Trees = Java.type("com.sun.source.util.Trees"); +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); + +// printEmptyCatch + +function printEmptyCatch() { + // get the system compiler tool + var compiler = ToolProvider.systemJavaCompiler; + // get standard file manager + var fileMgr = compiler.getStandardFileManager(null, null, null); + // Using Java.to convert script array (arguments) to a Java String[] + var compUnits = fileMgr.getJavaFileObjects( + Java.to(arguments, StringArray)); + // create a new compilation task + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + + // SourcePositions object to get positions of AST nodes + var sourcePositions = Trees.instance(task).sourcePositions; + + // subclass SimpleTreeVisitor - to print empty catch + var EmptyCatchFinder = Java.extend(TreeScanner); + + function hasOnlyEmptyStats(stats) { + var itr = stats.iterator(); + while (itr.hasNext()) { + if (! (itr.next() instanceof EmptyStatementTree)) { + return false; + } + } + + return true; + } + + var visitor = new EmptyCatchFinder() { + // current CompilationUnitTree + compUnit: null, + // current LineMap (pos -> line, column) + lineMap: null, + // current compilation unit's file name + fileName: null, + + // overrides of TreeScanner methods + + visitCompilationUnit: function(node, p) { + // capture info about current Compilation unit + this.compUnit = node; + this.lineMap = node.lineMap; + this.fileName = node.sourceFile.name; + + // Using Java.super API to call super class method here + return Java.super(visitor).visitCompilationUnit(node, p); + }, + + visitCatch: function (node, p) { + var stats = node.block.statements; + if (stats.empty || hasOnlyEmptyStats(stats)) { + // print information on this empty catch + var pos = sourcePositions.getStartPosition(this.compUnit, node); + var line = this.lineMap.getLineNumber(pos); + var col = this.lineMap.getColumnNumber(pos); + print("Exception swallow" + " @ " + this.fileName + ":" + line + ":" + col); + // print(node); + } + } + } + + for each (var cu in task.parse()) { + cu.accept(visitor, null); + } +} + +// for each ".java" file in directory (recursively) and check it! +function main(dir) { + Files.walk(dir.toPath()). + forEach(function(p) { + var name = p.toFile().absolutePath; + if (name.endsWith(".java")) { + try { + printEmptyCatch(p.toFile().getAbsolutePath()); + } catch (e) { + print(e); + } + } + }); +} + +main(new File(arguments[0])); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/find_max_lines.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/find_max_lines.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Find the file with maximum number of lines + +var Files = Java.type("java.nio.file.Files"); +var Integer = Java.type("java.lang.Integer"); +var Paths = Java.type("java.nio.file.Paths"); + +var file = arguments.length == 0? "." : arguments[0]; +var ext = arguments.length > 1? arguments[1] : ".java"; +var path = Paths.get(file); + +// return number of lines in given Path (that represents a file) +function lines(p) { + var strm = Files.lines(p); + try { + return strm.count(); + } finally { + strm.close(); + } +} + +// walk files, map to file and lines, find the max +var obj = Files.find(path, Integer.MAX_VALUE, + function(p, a) !p.toFile().isDirectory() && p.toString().endsWith(ext)). +map(function(p) ({ path : p, lines: lines(p) })). +max(function(x, y) x.lines - y.lines).get(); + +// print path and lines of the max line file +print(obj.path, obj.lines); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/find_nonfinals2.js --- a/samples/find_nonfinals2.js Fri Oct 16 12:19:59 2015 -0700 +++ b/samples/find_nonfinals2.js Thu Oct 29 17:22:12 2015 -0700 @@ -43,7 +43,6 @@ // Java types used var File = Java.type("java.io.File"); var Files = Java.type("java.nio.file.Files"); -var FileVisitOption = Java.type("java.nio.file.FileVisitOption"); var StringArray = Java.type("java.lang.String[]"); var ToolProvider = Java.type("javax.tools.ToolProvider"); var Tree = Java.type("com.sun.source.tree.Tree"); @@ -106,7 +105,7 @@ // for each ".java" file in directory (recursively). function main(dir) { var totalCount = 0; - Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). + Files.walk(dir.toPath()). forEach(function(p) { var name = p.toFile().absolutePath; if (name.endsWith(".java")) { diff -r ee2c313d02a3 -r bf97e9141fe5 samples/fixed_point.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/fixed_point.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple sample demonstrating "fixed point" computation with Streams + +// See also https://mitpress.mit.edu/sicp/chapter1/node21.html#secprocgeneralmethods +var Stream = Java.type("java.util.stream.Stream"); + +// generic fixed point procedure +function fixed_point(f, init_guess) { + var tolerance = 0.00001; + function close_enough(v1, v2) Math.abs(v1 - v2) < tolerance; + + var prev; + return Stream.iterate(init_guess, f) + .filter(function(x) { + try { + return prev == undefined? false : close_enough(prev, x); + } finally { + prev = x; + } + }) + .findFirst() + .get(); +} + +// solution to x = cos(x) +print(fixed_point(Math.cos, 1.0)) + +// solution to x = sin(x) + cos(x) +print(fixed_point(function(x) Math.sin(x) + Math.cos(x), 1.0)); + +// square root by Newton's method +// http://en.wikipedia.org/wiki/Newton's_method +function sqrt(n) + fixed_point(function(x) (x + n/x) / 2, 2.0); + +print(sqrt(2)) +print(sqrt(3)) + + diff -r ee2c313d02a3 -r bf97e9141fe5 samples/importstatic.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/importstatic.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Java like "import static class_name.*" for nashorn + +function importStatic(clazz) { + // make sure the argument is a Java type + if (! Java.isType(clazz)) { + throw new TypeError(clazz + " is not a Java type"); + } + + // bind properties of clazz to an object + var obj = Object.bindProperties({}, clazz); + + // copy properties to global to "import" those + for (var i in obj) { + this[i] = obj[i]; + } +} + +importStatic(java.time.Instant); +print(now()); +print(ofEpochSecond(1)); +print(parse("2007-12-03T10:15:30.00Z")); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/javabind.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javabind.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// bind on a Java method + +// #javascript "bind" function +var bind = Function.prototype.bind; + +// Java console object +var console = java.lang.System.console(); + +// arguments "this" and prompt string of Console.readLine method are bound +var readName = bind.call(console.readLine, console, "Your name: "); + +// Now call it like a function that takes no arguments! +print("Hello,", readName()); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/javaconstructorbind.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/javaconstructorbind.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// bind on a Java constructor + +// See Function.prototype.bind: +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind +var bind = Function.prototype.bind; + +var URL = Java.type("java.net.URL"); + +// get the constructor that accepts URL, String parameters. +// constructor signatures are properties of type object. +var newURL = URL["(URL, String)"]; + +// bind "context" URL parameter. +var TwitterURL = bind.call(newURL, null, new URL('https://www.twitter.com')); + +// now you can create context relative URLs using the bound constructor +print(new TwitterURL("sundararajan_a")); + +// read the URL content and print (optional part) + +var BufferedReader = Java.type("java.io.BufferedReader"); +var InputStreamReader = Java.type("java.io.InputStreamReader"); + +// function to retrieve text content of the given URL +function readTextFromURL(url) { + var str = ''; + var u = new URL(url); + var reader = new BufferedReader( + new InputStreamReader(u.openStream())); + try { + reader.lines().forEach(function(x) str += x); + return str; + } finally { + reader.close(); + } +} + +print(readTextFromURL(new TwitterURL("sundararajan_a"))); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/javafoovars.js --- a/samples/javafoovars.js Fri Oct 16 12:19:59 2015 -0700 +++ b/samples/javafoovars.js Thu Oct 29 17:22:12 2015 -0700 @@ -42,7 +42,6 @@ // Java types used var File = Java.type("java.io.File"); var Files = Java.type("java.nio.file.Files"); -var FileVisitOption = Java.type("java.nio.file.FileVisitOption"); var StringArray = Java.type("java.lang.String[]"); var ToolProvider = Java.type("javax.tools.ToolProvider"); var Tree = Java.type("com.sun.source.tree.Tree"); @@ -81,7 +80,7 @@ // for each ".java" file in directory (recursively) count "foo". function main(dir) { var totalCount = 0; - Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS). + Files.walk(dir.toPath()). forEach(function(p) { var name = p.toFile().absolutePath; if (name.endsWith(".java")) { diff -r ee2c313d02a3 -r bf97e9141fe5 samples/mapwith.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/mapwith.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Using a Java map with Javascript "with" statement + +var map = new java.util.HashMap(); +map.put("foo", 34); +map.put("bar", "hello"); + +var obj = { + __noSuchProperty__: function(name) { + return map.get(name); + } +}; + +with(obj) { + print(foo); + print(bar); +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/mothers_day.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/mothers_day.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,56 @@ +# compute Mothers day of the given the year + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// print "Mother's day" of the given year using Java Time API + +if (arguments.length == 0) { + print("Usage: jjs mothers_day.js -- year"); + exit(1); +} + +// java classes used +var DayOfWeek = java.time.DayOfWeek; +var LocalDate = java.time.LocalDate; +var TemporalAdjusters = java.time.temporal.TemporalAdjusters; + +var year = parseInt(arguments[0]); + +// See: https://en.wikipedia.org/?title=Mother%27s_Day +// We need second Sunday of May. Make April 30 of the given +// year adjust and adjust to next Sunday from there twice. To adjust a Date +// we use a common TemporalAdjuster provided in JDK8. +// https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html + +print(LocalDate.of(year, 4, 30). + with(TemporalAdjusters.next(DayOfWeek.SUNDAY)). + with(TemporalAdjusters.next(DayOfWeek.SUNDAY))); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/passwordgen.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/passwordgen.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple password generator using SecureRandom + stream API + +// accept optional password length from command line +var len = arguments.length? parseInt(arguments[0]) : 8; + +// Java types used +var Collectors = Java.type("java.util.stream.Collectors"); +var SecureRandom = Java.type("java.security.SecureRandom"); + +// allowed password chars +var chars = + "!@#$%ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + +// generated and print password +print(new SecureRandom(). + ints(len, 0, chars.length). + mapToObj(function(i) chars[i]). + collect(Collectors.joining(""))); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/print_symlinks.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/print_symlinks.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Print all symbolic links in user's home directory + +// JavaImporter and "with" to simulate "import" statements in Java. +// See https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions + +with (new JavaImporter(java.nio.file, java.lang)) { + + var userDir = System.getProperty("user.dir") + var home = FileSystems.default.getPath(userDir); + + // JS functions can be passed where Java lambdas are required. + // Also, using "Expression closure" extension here. + // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Expression_Closures + + Files.walk(home). + filter(function(p) Files.isSymbolicLink(p)). + forEach(function(p) + print(p, '->', Files.readSymbolicLink(p))); +} diff -r ee2c313d02a3 -r bf97e9141fe5 samples/resourcetrysuggester.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/resourcetrysuggester.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,156 @@ +#// Usage: jjs resourcetrysuggester.js -- + +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// This example demonstrates Java subclassing by Java.extend +// and javac Compiler and Tree API. This example looks for +// finally clauses with "close" call and suggests "resource try"! + +if (arguments.length == 0) { + print("Usage: jjs resourcetrysuggester.js -- "); + exit(1); +} + +// Java types used +var ExpressionStatementTree = Java.type("com.sun.source.tree.ExpressionStatementTree"); +var File = Java.type("java.io.File"); +var Files = Java.type("java.nio.file.Files"); +var MemberSelectTree = Java.type("com.sun.source.tree.MemberSelectTree"); +var MethodInvocationTree = Java.type("com.sun.source.tree.MethodInvocationTree"); +var StringArray = Java.type("java.lang.String[]"); +var ToolProvider = Java.type("javax.tools.ToolProvider"); +var Tree = Java.type("com.sun.source.tree.Tree"); +var Trees = Java.type("com.sun.source.util.Trees"); +var TreeScanner = Java.type("com.sun.source.util.TreeScanner"); + +// resourceTrySuggestions + +function resourceTrySuggestions() { + // get the system compiler tool + var compiler = ToolProvider.systemJavaCompiler; + // get standard file manager + var fileMgr = compiler.getStandardFileManager(null, null, null); + // Using Java.to convert script array (arguments) to a Java String[] + var compUnits = fileMgr.getJavaFileObjects( + Java.to(arguments, StringArray)); + // create a new compilation task + var task = compiler.getTask(null, fileMgr, null, null, null, compUnits); + + // SourcePositions object to get positions of AST nodes + var sourcePositions = Trees.instance(task).sourcePositions; + + // subclass SimpleTreeVisitor - to print resource try suggestions + var ResourceTrySuggester = Java.extend(TreeScanner); + + function hasOnlyEmptyStats(stats) { + var itr = stats.iterator(); + while (itr.hasNext()) { + if (! (itr.next() instanceof EmptyStatementTree)) { + return false; + } + } + + return true; + } + + // does the given statement list has an expression statement which + // calls "close" method (don't worry about types - just crude one will do) + function hasCloseCall(stats) { + var itr = stats.iterator(); + while (itr.hasNext()) { + var stat = itr.next(); + if (stat instanceof ExpressionStatementTree) { + var expr = stat.expression; + if (expr instanceof MethodInvocationTree) { + var method = expr.methodSelect; + if (method instanceof MemberSelectTree) { + return method.identifier.toString().equals("close"); + } + } + } + } + return false; + } + + var visitor = new ResourceTrySuggester() { + // current CompilationUnitTree + compUnit: null, + // current LineMap (pos -> line, column) + lineMap: null, + // current compilation unit's file name + fileName: null, + + // overrides of TreeScanner methods + + visitCompilationUnit: function(node, p) { + // capture info about current Compilation unit + this.compUnit = node; + this.lineMap = node.lineMap; + this.fileName = node.sourceFile.name; + + // Using Java.super API to call super class method here + return Java.super(visitor).visitCompilationUnit(node, p); + }, + + visitTry: function (node, p) { + var finallyBlk = node.finallyBlock; + if (finallyBlk != null && hasCloseCall(finallyBlk.statements)) { + var pos = sourcePositions.getStartPosition(this.compUnit, node); + var line = this.lineMap.getLineNumber(pos); + var col = this.lineMap.getColumnNumber(pos); + print("Consider resource try statement " + " @ " + this.fileName + ":" + line + ":" + col); + // print(node); + } + } + } + + for each (var cu in task.parse()) { + cu.accept(visitor, null); + } +} + +// for each ".java" file in directory (recursively) and check it! +function main(dir) { + Files.walk(dir.toPath()). + forEach(function(p) { + var name = p.toFile().absolutePath; + if (name.endsWith(".java")) { + try { + resourceTrySuggestions(p.toFile().getAbsolutePath()); + } catch (e) { + print(e); + } + } + }); +} + +main(new File(arguments[0])); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/sort_by_java8.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/sort_by_java8.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// Simple sorting with Java8 APIs + +// Separation key-extraction from key ordering + +// Simple demo for Comparator.comparing +// http://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html#comparing-java.util.function.Function- + +// data to be sorted +var cards = [ + { name: "hello", email: "foo@hello.com" }, + { name: "world", email: "bar@world.com" }, + { name: "see", email: "see@dontsee.com" }, +]; + +var Collections = java.util.Collections; +var Comparator = java.util.Comparator; + +// sort records name in reverse order of names +Collections.sort(cards, + Comparator.comparing(function(a) a.name).reversed()); + +print(JSON.stringify(cards)) + +// sort records by email +Collections.sort(cards, + Comparator.comparing(function(a) a.email)); + +print(JSON.stringify(cards)) diff -r ee2c313d02a3 -r bf97e9141fe5 samples/this_for_eval.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/samples/this_for_eval.js Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +// how to pass arbitrary "this" object for eval'ed script? + +var obj = { foo: 44 }; + +// the following won't work. eval.apply is indirect eval call +// and so 'this' will be global object always! So, this +// line will print 'undefined' +eval.apply(obj, [ " print(this.foo)" ]); + +obj.myEval = eval; + +// still won't work - still indirect 'eval' call! +// still undefined is printed! +obj.myEval("print(this.foo)"); + +function func(code) { + eval(code); +} + +// eval called inside func and so get's func's "this" as it's "this"! +// So, 44 is printed + +func.apply(obj, [ "print(this.foo)" ]); diff -r ee2c313d02a3 -r bf97e9141fe5 samples/zipfs.js --- a/samples/zipfs.js Fri Oct 16 12:19:59 2015 -0700 +++ b/samples/zipfs.js Thu Oct 29 17:22:12 2015 -0700 @@ -36,13 +36,12 @@ var Files = Java.type("java.nio.file.Files") var FileSystems = Java.type("java.nio.file.FileSystems") -var FileVisitOption = Java.type("java.nio.file.FileVisitOption") var Paths = Java.type("java.nio.file.Paths") var zipfile = Paths.get(arguments[0]) var fs = FileSystems.newFileSystem(zipfile, null) var root = fs.rootDirectories[0] -Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach( +Files.walk(root).forEach( function(p) (print(p), print(Files.readAttributes(p, "zip:*"))) ) fs.close() diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/DynamicLinker.java --- a/src/jdk/internal/dynalink/DynamicLinker.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/DynamicLinker.java Thu Oct 29 17:22:12 2015 -0700 @@ -117,7 +117,7 @@ * return factory.createLinker(); * } * - * public static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) { + * public static CallSite bootstrap(MethodHandles.Lookup lookup, String name, MethodType type) { * return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(lookup, name, type))); * } * } diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java --- a/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java Thu Oct 29 17:22:12 2015 -0700 @@ -107,7 +107,7 @@ private final AccessibleObject target; private final MethodType type; - public CallerSensitiveDynamicMethod(final AccessibleObject target) { + CallerSensitiveDynamicMethod(final AccessibleObject target) { super(getName(target)); this.target = target; this.type = getMethodType(target); @@ -115,8 +115,9 @@ private static String getName(final AccessibleObject target) { final Member m = (Member)target; - return getMethodNameWithSignature(getMethodType(target), getClassAndMethodName(m.getDeclaringClass(), - m.getName())); + final boolean constructor = m instanceof Constructor; + return getMethodNameWithSignature(getMethodType(target), constructor ? m.getName() : + getClassAndMethodName(m.getDeclaringClass(), m.getName()), !constructor); } @Override diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/beans/FacetIntrospector.java --- a/src/jdk/internal/dynalink/beans/FacetIntrospector.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/beans/FacetIntrospector.java Thu Oct 29 17:22:12 2015 -0700 @@ -152,7 +152,7 @@ boolean isAccessible(final Member m) { final Class declaring = m.getDeclaringClass(); // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a - // non-restriced class, so if the declaring class is identical to the class being inspected, then forego + // non-restricted class, so if the declaring class is identical to the class being inspected, then forego // a potentially expensive restricted-package check. return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring); } diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java --- a/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java Thu Oct 29 17:22:12 2015 -0700 @@ -86,7 +86,9 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.text.Collator; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -242,6 +244,35 @@ return methods.getFirst().isConstructor(); } + @Override + public String toString() { + // First gather the names and sort them. This makes it consistent and easier to read. + final List names = new ArrayList<>(methods.size()); + int len = 0; + for (final SingleDynamicMethod m: methods) { + final String name = m.getName(); + len += name.length(); + names.add(name); + } + // Case insensitive sorting, so e.g. "Object" doesn't come before "boolean". + final Collator collator = Collator.getInstance(); + collator.setStrength(Collator.SECONDARY); + Collections.sort(names, collator); + + final String className = getClass().getName(); + // Class name length + length of signatures + 2 chars/per signature for indentation and newline + + // 3 for brackets and initial newline + final int totalLength = className.length() + len + 2 * names.size() + 3; + final StringBuilder b = new StringBuilder(totalLength); + b.append('[').append(className).append('\n'); + for(final String name: names) { + b.append(' ').append(name).append('\n'); + } + b.append(']'); + assert b.length() == totalLength; + return b.toString(); + }; + ClassLoader getClassLoader() { return classLoader; } diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java --- a/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java Thu Oct 29 17:22:12 2015 -0700 @@ -122,13 +122,13 @@ * @param constructor does this represent a constructor? */ SimpleDynamicMethod(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { - super(getName(target, clazz, name)); + super(getName(target, clazz, name, constructor)); this.target = target; this.constructor = constructor; } - private static String getName(final MethodHandle target, final Class clazz, final String name) { - return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name)); + private static String getName(final MethodHandle target, final Class clazz, final String name, final boolean constructor) { + return getMethodNameWithSignature(target.type(), constructor ? name : getClassAndMethodName(clazz, name), !constructor); } @Override diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/beans/SingleDynamicMethod.java --- a/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java Thu Oct 29 17:22:12 2015 -0700 @@ -98,7 +98,6 @@ * target method to a call site type (including mapping variable arity methods to a call site signature with different * arity). * @author Attila Szegedi - * @version $Id: $ */ abstract class SingleDynamicMethod extends DynamicMethod { @@ -143,14 +142,18 @@ return getMethodType().parameterList().equals(method.getMethodType().parameterList()); } - static String getMethodNameWithSignature(final MethodType type, final String methodName) { + static String getMethodNameWithSignature(final MethodType type, final String methodName, final boolean withReturnType) { final String typeStr = type.toString(); final int retTypeIndex = typeStr.lastIndexOf(')') + 1; int secondParamIndex = typeStr.indexOf(',') + 1; if(secondParamIndex == 0) { secondParamIndex = retTypeIndex - 1; } - return typeStr.substring(retTypeIndex) + " " + methodName + "(" + typeStr.substring(secondParamIndex, retTypeIndex); + final StringBuilder b = new StringBuilder(); + if (withReturnType) { + b.append(typeStr, retTypeIndex, typeStr.length()).append(' '); + } + return b.append(methodName).append('(').append(typeStr, secondParamIndex, retTypeIndex).toString(); } /** diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/linker/GuardedInvocation.java --- a/src/jdk/internal/dynalink/linker/GuardedInvocation.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/linker/GuardedInvocation.java Thu Oct 29 17:22:12 2015 -0700 @@ -353,7 +353,7 @@ /** * Applies argument filters to both the invocation and the guard (if there is one). - * @param pos the position of the first argumen being filtered + * @param pos the position of the first argument being filtered * @param filters the argument filters * @return a filtered invocation */ diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/internal/dynalink/linker/GuardedTypeConversion.java --- a/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java Thu Oct 29 17:22:12 2015 -0700 @@ -110,7 +110,7 @@ /** * Check if invocation is cacheable - * @return true if cachable, false otherwise + * @return true if cacheable, false otherwise */ public boolean isCacheable() { return cacheable; diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/api/scripting/AbstractJSObject.java --- a/src/jdk/nashorn/api/scripting/AbstractJSObject.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/AbstractJSObject.java Thu Oct 29 17:22:12 2015 -0700 @@ -182,7 +182,7 @@ /** * Checking whether the given object is an instance of 'this' object. * - * @param instance instace to check + * @param instance instance to check * @return true if the given 'instance' is an instance of this 'function' object */ @Override diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/api/scripting/JSObject.java --- a/src/jdk/nashorn/api/scripting/JSObject.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/JSObject.java Thu Oct 29 17:22:12 2015 -0700 @@ -141,7 +141,7 @@ /** * Checking whether the given object is an instance of 'this' object. * - * @param instance instace to check + * @param instance instance to check * @return true if the given 'instance' is an instance of this 'function' object */ public boolean isInstance(final Object instance); diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/api/scripting/NashornException.java --- a/src/jdk/nashorn/api/scripting/NashornException.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/NashornException.java Thu Oct 29 17:22:12 2015 -0700 @@ -51,6 +51,8 @@ private String fileName; // script line number private int line; + // are the line and fileName unknown? + private boolean lineAndFileNameUnknown; // script column number private int column; // underlying ECMA error object - lazily initialized @@ -92,27 +94,10 @@ */ protected NashornException(final String msg, final Throwable cause) { super(msg, cause == null ? null : cause); - // This is not so pretty - but it gets the job done. Note that the stack - // trace has been already filled by "fillInStackTrace" call from - // Throwable - // constructor and so we don't pay additional cost for it. - // Hard luck - no column number info this.column = -1; - - // Find the first JavaScript frame by walking and set file, line from it - // Usually, we should be able to find it in just few frames depth. - for (final StackTraceElement ste : getStackTrace()) { - if (ECMAErrors.isScriptFrame(ste)) { - // Whatever here is compiled from JavaScript code - this.fileName = ste.getFileName(); - this.line = ste.getLineNumber(); - return; - } - } - - this.fileName = null; - this.line = 0; + // We can retrieve the line number and file name from the stack trace if needed + this.lineAndFileNameUnknown = true; } /** @@ -121,6 +106,7 @@ * @return the file name */ public final String getFileName() { + ensureLineAndFileName(); return fileName; } @@ -131,6 +117,7 @@ */ public final void setFileName(final String fileName) { this.fileName = fileName; + lineAndFileNameUnknown = false; } /** @@ -139,6 +126,7 @@ * @return the line number */ public final int getLineNumber() { + ensureLineAndFileName(); return line; } @@ -148,6 +136,7 @@ * @param line the line number */ public final void setLineNumber(final int line) { + lineAndFileNameUnknown = false; this.line = line; } @@ -274,4 +263,19 @@ public void setEcmaError(final Object ecmaError) { this.ecmaError = ecmaError; } + + private void ensureLineAndFileName() { + if (lineAndFileNameUnknown) { + for (final StackTraceElement ste : getStackTrace()) { + if (ECMAErrors.isScriptFrame(ste)) { + // Whatever here is compiled from JavaScript code + fileName = ste.getFileName(); + line = ste.getLineNumber(); + return; + } + } + + lineAndFileNameUnknown = false; + } + } } diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/api/scripting/NashornScriptEngine.java --- a/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/NashornScriptEngine.java Thu Oct 29 17:22:12 2015 -0700 @@ -140,7 +140,7 @@ this._global_per_engine = nashornContext.getEnv()._global_per_engine; // create new global object - this.global = createNashornGlobal(context); + this.global = createNashornGlobal(); // set the default ENGINE_SCOPE object for the default context context.setBindings(new ScriptObjectMirror(global, global), ScriptContext.ENGINE_SCOPE); } @@ -167,7 +167,7 @@ // We use same 'global' for all Bindings. return new SimpleBindings(); } - return createGlobalMirror(null); + return createGlobalMirror(); } // Compilable methods @@ -317,7 +317,7 @@ // We didn't find associated nashorn global mirror in the Bindings given! // Create new global instance mirror and associate with the Bindings. - final ScriptObjectMirror mirror = createGlobalMirror(ctxt); + final ScriptObjectMirror mirror = createGlobalMirror(); bindings.put(NASHORN_GLOBAL, mirror); return mirror.getHomeGlobal(); } @@ -333,13 +333,13 @@ } // Create a new ScriptObjectMirror wrapping a newly created Nashorn Global object - private ScriptObjectMirror createGlobalMirror(final ScriptContext ctxt) { - final Global newGlobal = createNashornGlobal(ctxt); + private ScriptObjectMirror createGlobalMirror() { + final Global newGlobal = createNashornGlobal(); return new ScriptObjectMirror(newGlobal, newGlobal); } // Create a new Nashorn Global object - private Global createNashornGlobal(final ScriptContext ctxt) { + private Global createNashornGlobal() { final Global newGlobal = AccessController.doPrivileged(new PrivilegedAction() { @Override public Global run() { @@ -354,7 +354,7 @@ } }, CREATE_GLOBAL_ACC_CTXT); - nashornContext.initGlobal(newGlobal, this, ctxt); + nashornContext.initGlobal(newGlobal, this); return newGlobal; } diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/api/scripting/ScriptUtils.java --- a/src/jdk/nashorn/api/scripting/ScriptUtils.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/ScriptUtils.java Thu Oct 29 17:22:12 2015 -0700 @@ -79,7 +79,7 @@ * @return a synchronizing wrapper function */ public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { - return func.makeSynchronizedFunction(unwrap(sync)); + return func.createSynchronized(unwrap(sync)); } /** diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/api/scripting/URLReader.java --- a/src/jdk/nashorn/api/scripting/URLReader.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/api/scripting/URLReader.java Thu Oct 29 17:22:12 2015 -0700 @@ -103,7 +103,7 @@ /** * Charset used by this reader * - * @return the Chartset used to convert bytes to chars + * @return the Charset used to convert bytes to chars */ public Charset getCharset() { return cs; diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/internal/codegen/ApplySpecialization.java --- a/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/ApplySpecialization.java Thu Oct 29 17:22:12 2015 -0700 @@ -40,11 +40,9 @@ import jdk.nashorn.internal.ir.CallNode; import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.IdentNode; -import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.Node; -import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor; import jdk.nashorn.internal.objects.Global; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.logging.DebugLogger; @@ -82,7 +80,7 @@ */ @Logger(name="apply2call") -public final class ApplySpecialization extends NodeVisitor implements Loggable { +public final class ApplySpecialization extends SimpleNodeVisitor implements Loggable { private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true); @@ -106,7 +104,6 @@ * @param compiler compiler */ public ApplySpecialization(final Compiler compiler) { - super(new LexicalContext()); this.compiler = compiler; this.log = initLogger(compiler.getContext()); } @@ -139,7 +136,7 @@ private boolean hasApplies(final FunctionNode functionNode) { try { - functionNode.accept(new NodeVisitor(new LexicalContext()) { + functionNode.accept(new SimpleNodeVisitor() { @Override public boolean enterFunctionNode(final FunctionNode fn) { return fn == functionNode; @@ -173,7 +170,7 @@ final Deque> stack = new ArrayDeque<>(); //ensure that arguments is only passed as arg to apply - functionNode.accept(new NodeVisitor(new LexicalContext()) { + functionNode.accept(new SimpleNodeVisitor() { private boolean isCurrentArg(final Expression expr) { return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call @@ -283,17 +280,13 @@ start++; } - start++; //we always uses this + start++; // we always use this - final List params = functionNode.getParameters(); + assert functionNode.getNumOfParams() == 0 : "apply2call on function with named paramaters!"; final List newParams = new ArrayList<>(); - final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start); + final long to = actualCallSiteType.parameterCount() - start; for (int i = 0; i < to; i++) { - if (i >= params.size()) { - newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i))); - } else { - newParams.add(params.get(i)); - } + newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i))); } callSiteTypes.push(actualCallSiteType); @@ -302,7 +295,28 @@ @Override public boolean enterFunctionNode(final FunctionNode functionNode) { - if (!USE_APPLY2CALL) { + // Cheap tests first + if (!( + // is the transform globally enabled? + USE_APPLY2CALL + + // Are we compiling lazily? We can't known the number and types of the actual parameters at + // the caller when compiling eagerly, so this only works with on-demand compilation. + && compiler.isOnDemandCompilation() + + // Does the function even reference the "arguments" identifier (without redefining it)? If not, + // it trivially can't have an expression of form "f.apply(self, arguments)" that this transform + // is targeting. + && functionNode.needsArguments() + + // Does the function have eval? If so, it can arbitrarily modify arguments so we can't touch it. + && !functionNode.hasEval() + + // Finally, does the function declare any parameters explicitly? We don't support that. It could + // be done, but has some complications. Therefore only a function with no explicit parameters + // is considered. + && functionNode.getNumOfParams() == 0)) + { return false; } @@ -312,14 +326,6 @@ return false; } - if (!compiler.isOnDemandCompilation()) { - return false; - } - - if (functionNode.hasEval()) { - return false; - } - if (!hasApplies(functionNode)) { return false; } @@ -375,7 +381,7 @@ callSiteTypes.pop(); explodedArguments.pop(); - return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED); + return newFunctionNode; } private static boolean isApply(final CallNode callNode) { diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/internal/codegen/AssignSymbols.java --- a/src/jdk/nashorn/internal/codegen/AssignSymbols.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/AssignSymbols.java Thu Oct 29 17:22:12 2015 -0700 @@ -65,17 +65,14 @@ import jdk.nashorn.internal.ir.Expression; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IndexNode; -import jdk.nashorn.internal.ir.LexicalContext; import jdk.nashorn.internal.ir.LexicalContextNode; import jdk.nashorn.internal.ir.LiteralNode; -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; import jdk.nashorn.internal.ir.Node; import jdk.nashorn.internal.ir.RuntimeNode; import jdk.nashorn.internal.ir.RuntimeNode.Request; +import jdk.nashorn.internal.ir.Splittable; import jdk.nashorn.internal.ir.Statement; import jdk.nashorn.internal.ir.SwitchNode; import jdk.nashorn.internal.ir.Symbol; @@ -83,7 +80,7 @@ import jdk.nashorn.internal.ir.UnaryNode; import jdk.nashorn.internal.ir.VarNode; import jdk.nashorn.internal.ir.WithNode; -import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor; import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ECMAErrors; @@ -104,7 +101,7 @@ * visitor. */ @Logger(name="symbols") -final class AssignSymbols extends NodeVisitor implements Loggable { +final class AssignSymbols extends SimpleNodeVisitor implements Loggable { private final DebugLogger log; private final boolean debug; @@ -149,12 +146,13 @@ private final Deque> thisProperties = new ArrayDeque<>(); private final Map globalSymbols = new HashMap<>(); //reuse the same global symbol private final Compiler compiler; + private final boolean isOnDemand; public AssignSymbols(final Compiler compiler) { - super(new LexicalContext()); this.compiler = compiler; this.log = initLogger(compiler.getContext()); this.debug = log.isEnabled(); + this.isOnDemand = compiler.isOnDemandCompilation(); } @Override @@ -187,7 +185,7 @@ */ private void acceptDeclarations(final FunctionNode functionNode, final Block body) { // This visitor will assign symbol to all declared variables. - body.accept(new NodeVisitor(new LexicalContext()) { + body.accept(new SimpleNodeVisitor() { @Override protected boolean enterDefault(final Node node) { // Don't bother visiting expressions; var is a statement, it can't be inside an expression. @@ -242,7 +240,7 @@ /** * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically - * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function + * used to create assignment of {@code :callee} to the function name symbol in self-referential function * expressions as well as for assignment of {@code :arguments} to {@code arguments}. * * @param name the ident node identifying the variable to initialize @@ -390,7 +388,7 @@ // Create and add to appropriate block. symbol = createSymbol(name, flags); - symbolBlock.putSymbol(lc, symbol); + symbolBlock.putSymbol(symbol); if ((flags & IS_SCOPE) == 0) { // Initial assumption; symbol can lose its slot later @@ -440,7 +438,7 @@ start(block); if (lc.isFunctionBody()) { - block.clearSymbols(); + assert !block.hasSymbols(); final FunctionNode fn = lc.getCurrentFunction(); if (isUnparsedFunction(fn)) { // It's a skipped nested function. Just mark the symbols being used by it as being in use. @@ -459,7 +457,7 @@ } private boolean isUnparsedFunction(final FunctionNode fn) { - return compiler.isOnDemandCompilation() && fn != lc.getOutermostFunction(); + return isOnDemand && fn != lc.getOutermostFunction(); } @Override @@ -551,9 +549,7 @@ private void defineVarIdent(final VarNode varNode) { final IdentNode ident = varNode.getName(); final int flags; - if (varNode.isAnonymousFunctionDeclaration()) { - flags = IS_INTERNAL; - } else if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) { + if (!varNode.isBlockScoped() && lc.getCurrentFunction().isProgram()) { flags = IS_SCOPE; } else { flags = 0; @@ -749,28 +745,6 @@ } } - @Override - public Node leaveBlock(final Block block) { - // It's not necessary to guard the marking of symbols as locals with this "if" condition for - // correctness, it's just an optimization -- runtime type calculation is not used when the compilation - // is not an on-demand optimistic compilation, so we can skip locals marking then. - if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) { - // OTOH, we must not declare symbols from nested functions to be locals. As we're doing on-demand - // compilation, and we're skipping parsing the function bodies for nested functions, this - // basically only means their parameters. It'd be enough to mistakenly declare to be a local a - // symbol in the outer function named the same as one of the parameters, though. - if (lc.getFunction(block) == lc.getOutermostFunction()) { - for (final Symbol symbol: block.getSymbols()) { - if (!symbol.isScope()) { - assert symbol.isVar() || symbol.isParam(); - compiler.declareLocalSymbol(symbol.getName()); - } - } - } - } - return block; - } - private Node leaveDELETE(final UnaryNode unaryNode) { final FunctionNode currentFunctionNode = lc.getCurrentFunction(); final boolean strictMode = currentFunctionNode.isStrict(); @@ -785,13 +759,14 @@ // If this is a declared variable or a function parameter, delete always fails (except for globals). final String name = ident.getName(); final Symbol symbol = ident.getSymbol(); + + if (symbol.isThis()) { + // Can't delete "this", ignore and return true + return LiteralNode.newInstance(unaryNode, true); + } + final Expression literalNode = LiteralNode.newInstance(unaryNode, name); final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))); - if (failDelete && symbol.isThis()) { - return LiteralNode.newInstance(unaryNode, true).accept(this); - } - final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this); - if (!failDelete) { args.add(compilerConstantIdentifier(SCOPE)); } @@ -800,13 +775,15 @@ if (failDelete) { request = Request.FAIL_DELETE; + } else if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) { + request = Request.SLOW_DELETE; } } else if (rhs instanceof AccessNode) { final Expression base = ((AccessNode)rhs).getBase(); final String property = ((AccessNode)rhs).getProperty(); args.add(base); - args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this)); + args.add(LiteralNode.newInstance(unaryNode, property)); args.add(strictFlagNode); } else if (rhs instanceof IndexNode) { @@ -819,15 +796,15 @@ args.add(strictFlagNode); } else { - return LiteralNode.newInstance(unaryNode, true).accept(this); + return LiteralNode.newInstance(unaryNode, true); } - return new RuntimeNode(unaryNode, request, args).accept(this); + return new RuntimeNode(unaryNode, request, args); } @Override public Node leaveForNode(final ForNode forNode) { if (forNode.isForIn()) { - forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 + return forNode.setIterator(lc, newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73 } return end(forNode); @@ -847,7 +824,7 @@ lc.applyTopFlags(functionNode)))) .setThisProperties(lc, thisProperties.pop().size())); } - return finalizedFunction.setState(lc, CompilationState.SYMBOLS_ASSIGNED); + return finalizedFunction; } @Override @@ -903,19 +880,18 @@ public Node leaveSwitchNode(final SwitchNode switchNode) { // We only need a symbol for the tag if it's not an integer switch node if(!switchNode.isUniqueInteger()) { - switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX)); + return switchNode.setTag(lc, newObjectInternal(SWITCH_TAG_PREFIX)); } return switchNode; } @Override public Node leaveTryNode(final TryNode tryNode) { - tryNode.setException(exceptionSymbol()); assert tryNode.getFinallyBody() == null; end(tryNode); - return tryNode; + return tryNode.setException(lc, exceptionSymbol()); } private Node leaveTYPEOF(final UnaryNode unaryNode) { @@ -924,13 +900,13 @@ final List args = new ArrayList<>(); if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) { args.add(compilerConstantIdentifier(SCOPE)); - args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null + args.add(LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName())); //null } else { args.add(rhs); - args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' + args.add(LiteralNode.newInstance(unaryNode)); //null, do not reuse token of identifier rhs, it can be e.g. 'this' } - final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this); + final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args); end(unaryNode); @@ -938,7 +914,7 @@ } private FunctionNode markProgramBlock(final FunctionNode functionNode) { - if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) { + if (isOnDemand || !functionNode.isProgram()) { return functionNode; } @@ -1005,7 +981,7 @@ boolean previousWasBlock = false; for (final Iterator it = lc.getAllNodes(); it.hasNext();) { final LexicalContextNode node = it.next(); - if (node instanceof FunctionNode || isSplitArray(node)) { + if (node instanceof FunctionNode || isSplitLiteral(node)) { // We reached the function boundary or a splitting boundary without seeing a definition for the symbol. // It needs to be in scope. return true; @@ -1031,12 +1007,8 @@ throw new AssertionError(); } - private static boolean isSplitArray(final LexicalContextNode expr) { - if(!(expr instanceof ArrayLiteralNode)) { - return false; - } - final List units = ((ArrayLiteralNode)expr).getUnits(); - return !(units == null || units.isEmpty()); + private static boolean isSplitLiteral(final LexicalContextNode expr) { + return expr instanceof Splittable && ((Splittable) expr).getSplitRanges() != null; } private void throwUnprotectedSwitchError(final VarNode varNode) { diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/internal/codegen/AstSerializer.java --- a/src/jdk/nashorn/internal/codegen/AstSerializer.java Fri Oct 16 12:19:59 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * 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. 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.codegen; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.util.Collections; -import java.util.zip.Deflater; -import java.util.zip.DeflaterOutputStream; -import jdk.nashorn.internal.ir.Block; -import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.LexicalContext; -import jdk.nashorn.internal.ir.Node; -import jdk.nashorn.internal.ir.Statement; -import jdk.nashorn.internal.ir.visitor.NodeVisitor; -import jdk.nashorn.internal.runtime.options.Options; - -/** - * This static utility class performs serialization of FunctionNode ASTs to a byte array. - * The format is a standard Java serialization stream, deflated. - */ -final class AstSerializer { - // Experimentally, we concluded that compression level 4 gives a good tradeoff between serialization speed - // and size. - private static final int COMPRESSION_LEVEL = Options.getIntProperty("nashorn.serialize.compression", 4); - static byte[] serialize(final FunctionNode fn) { - final ByteArrayOutputStream out = new ByteArrayOutputStream(); - final Deflater deflater = new Deflater(COMPRESSION_LEVEL); - try (final ObjectOutputStream oout = new ObjectOutputStream(new DeflaterOutputStream(out, deflater))) { - oout.writeObject(removeInnerFunctionBodies(fn)); - } catch (final IOException e) { - throw new AssertionError("Unexpected exception serializing function", e); - } finally { - deflater.end(); - } - return out.toByteArray(); - } - - private static FunctionNode removeInnerFunctionBodies(final FunctionNode fn) { - return (FunctionNode)fn.accept(new NodeVisitor(new LexicalContext()) { - @Override - public Node leaveBlock(final Block block) { - if (lc.isFunctionBody() && lc.getFunction(block) != lc.getOutermostFunction()) { - return block.setStatements(lc, Collections.emptyList()); - } - return super.leaveBlock(block); - } - }); - } -} diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/internal/codegen/CacheAst.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk/nashorn/internal/codegen/CacheAst.java Thu Oct 29 17:22:12 2015 -0700 @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, 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.codegen; + +import java.util.ArrayDeque; +import java.util.Collections; +import java.util.Deque; +import jdk.nashorn.internal.ir.FunctionNode; +import jdk.nashorn.internal.ir.Node; +import jdk.nashorn.internal.ir.Statement; +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor; +import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; + +class CacheAst extends SimpleNodeVisitor { + private final Deque dataStack = new ArrayDeque<>(); + + private final Compiler compiler; + + CacheAst(final Compiler compiler) { + this.compiler = compiler; + assert !compiler.isOnDemandCompilation(); + } + + @Override + public boolean enterFunctionNode(final FunctionNode functionNode) { + final int id = functionNode.getId(); + // It isn't necessary to keep a stack of RecompilableScriptFunctionData, but then we'd need to do a + // potentially transitive lookup with compiler.getScriptFunctionData(id) for deeper functions; this way + // we keep it constant time. + dataStack.push(dataStack.isEmpty() ? compiler.getScriptFunctionData(id) : dataStack.peek().getScriptFunctionData(id)); + return true; + } + + @Override + public Node leaveFunctionNode(final FunctionNode functionNode) { + final RecompilableScriptFunctionData data = dataStack.pop(); + if (functionNode.isSplit()) { + // NOTE: cache only split function ASTs from eager pass. Caching non-split functions would require + // some additional work, namely creating the concept of "uncacheable" function and reworking + // ApplySpecialization to ensure that functions undergoing apply-to-call transformations are not + // cacheable as well as recomputing Symbol.useCount when caching the eagerly parsed AST. + // Recomputing Symbol.useCount would be needed so it will only reflect uses from within the + // function being cached (and not reflect uses from its own nested functions or functions it is + // nested in). This is consistent with the count an on-demand recompilation of the function would + // produce. This is important as the decision to emit shared scope calls is based on this count, + // and if it is not matched between a previous version of the code and its deoptimizing rest-of + // compilation, it can result in rest-of not emitting a shared scope call where a previous version + // of the code (compiled from a cached eager pre-pass seeing higher (global) useCount) would emit + // it, causing a mismatch in stack shapes between previous code and its rest-of. + data.setCachedAst(functionNode); + } + + if (!dataStack.isEmpty() && ((dataStack.peek().getFunctionFlags() & FunctionNode.IS_SPLIT) != 0)) { + // Return a function node with no body so that caching outer functions doesn't hold on to nested + // functions' bodies. Note we're doing this only for functions directly nested inside split + // functions, since we're only caching the split ones. It is not necessary to limit body removal + // to just these functions, but it's a cheap way to prevent unnecessary AST mutations. + return functionNode.setBody(lc, functionNode.getBody().setStatements(null, Collections.emptyList())); + } + return functionNode; + } +} diff -r ee2c313d02a3 -r bf97e9141fe5 src/jdk/nashorn/internal/codegen/CodeGenerator.java --- a/src/jdk/nashorn/internal/codegen/CodeGenerator.java Fri Oct 16 12:19:59 2015 -0700 +++ b/src/jdk/nashorn/internal/codegen/CodeGenerator.java Thu Oct 29 17:22:12 2015 -0700 @@ -93,7 +93,6 @@ import jdk.nashorn.internal.ir.ExpressionStatement; import jdk.nashorn.internal.ir.ForNode; import jdk.nashorn.internal.ir.FunctionNode; -import jdk.nashorn.internal.ir.FunctionNode.CompilationState; import jdk.nashorn.internal.ir.GetSplitState; import jdk.nashorn.internal.ir.IdentNode; import jdk.nashorn.internal.ir.IfNode; @@ -106,7 +105,6 @@ import jdk.nashorn.internal.ir.LexicalContextNode; import jdk.nashorn.internal.ir.LiteralNode; import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode; -import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit; import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode; import jdk.nashorn.internal.ir.LocalVariableConversion; import jdk.nashorn.internal.ir.LoopNode; @@ -119,6 +117,7 @@ import jdk.nashorn.internal.ir.RuntimeNode.Request; import jdk.nashorn.internal.ir.SetSplitState; import jdk.nashorn.internal.ir.SplitReturn; +import jdk.nashorn.internal.ir.Splittable; import jdk.nashorn.internal.ir.Statement; import jdk.nashorn.internal.ir.SwitchNode; import jdk.nashorn.internal.ir.Symbol; @@ -130,9 +129,8 @@ import jdk.nashorn.internal.ir.WhileNode; import jdk.nashorn.internal.ir.WithNode; import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor; -import jdk.nashorn.internal.ir.visitor.NodeVisitor; +import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor; import jdk.nashorn.internal.objects.Global; -import jdk.nashorn.internal.objects.ScriptFunctionImpl; import jdk.nashorn.internal.parser.Lexer.RegexToken; import jdk.nashorn.internal.parser.TokenType; import jdk.nashorn.internal.runtime.Context; @@ -195,9 +193,9 @@ private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class, "ensureNumber", double.class, Object.class, int.class); - private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, + private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class, "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class); - private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class, + private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class, "create", ScriptFunction.class, Object[].class, int.class); private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class, @@ -244,12 +242,12 @@ private final DebugLogger log; /** From what size should we use spill instead of fields for JavaScript objects? */ - private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256); + static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256); private final Set emittedMethods = new HashSet<>(); // Function Id -> ContinuationInfo. Used by compilation of rest-of function only. - private final Map fnIdToContinuationInfo = new HashMap<>(); + private ContinuationInfo continuationInfo; private final Deque