src/jdk/nashorn/internal/runtime/ScriptingFunctions.java

Thu, 14 Feb 2013 13:01:52 +0100

author
lagergren
date
Thu, 14 Feb 2013 13:01:52 +0100
changeset 89
43e32b36153c
parent 82
abea4ba28901
child 108
a971adb68f38
permissions
-rw-r--r--

8008199: Lazy compilation and trampoline implementation
Summary: The code pipeline now supports lazy compilation, which can be used to only compile certain FunctionNodes and leave others be, saving startup time. When these uncompiled nodes are hit, a trampoline will force them to be recompiled. This can also be used to specialize compilation fixing parameter types and return types to a callsite specific compilation. This will give performance.
Reviewed-by: attila, sundar

jlaskey@3 1 /*
jlaskey@7 2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
jlaskey@3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
jlaskey@3 4 *
jlaskey@3 5 * This code is free software; you can redistribute it and/or modify it
jlaskey@3 6 * under the terms of the GNU General Public License version 2 only, as
jlaskey@3 7 * published by the Free Software Foundation. Oracle designates this
jlaskey@3 8 * particular file as subject to the "Classpath" exception as provided
jlaskey@3 9 * by Oracle in the LICENSE file that accompanied this code.
jlaskey@3 10 *
jlaskey@3 11 * This code is distributed in the hope that it will be useful, but WITHOUT
jlaskey@3 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
jlaskey@3 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
jlaskey@3 14 * version 2 for more details (a copy is included in the LICENSE file that
jlaskey@3 15 * accompanied this code).
jlaskey@3 16 *
jlaskey@3 17 * You should have received a copy of the GNU General Public License version
jlaskey@3 18 * 2 along with this work; if not, write to the Free Software Foundation,
jlaskey@3 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
jlaskey@3 20 *
jlaskey@3 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
jlaskey@3 22 * or visit www.oracle.com if you need additional information or have any
jlaskey@3 23 * questions.
jlaskey@3 24 */
jlaskey@3 25
jlaskey@3 26 package jdk.nashorn.internal.runtime;
jlaskey@3 27
jlaskey@3 28 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
jlaskey@3 29 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
jlaskey@3 30 import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
jlaskey@3 31
jlaskey@3 32 import java.io.BufferedReader;
jlaskey@3 33 import java.io.File;
jlaskey@3 34 import java.io.IOException;
jlaskey@67 35 import java.io.InputStream;
jlaskey@3 36 import java.io.InputStreamReader;
jlaskey@67 37 import java.io.OutputStream;
jlaskey@3 38 import java.lang.invoke.MethodHandle;
jlaskey@3 39 import java.lang.invoke.MethodHandles;
jlaskey@67 40 import java.util.Map;
jlaskey@67 41 import java.util.StringTokenizer;
jlaskey@3 42
jlaskey@3 43 /**
jlaskey@3 44 * Global functions supported only in scripting mode.
jlaskey@3 45 */
sundar@82 46 public final class ScriptingFunctions {
jlaskey@3 47
lagergren@57 48 /** Handle to implementation of {@link ScriptingFunctions#readLine} - Nashorn extension */
jlaskey@3 49 public static final MethodHandle READLINE = findOwnMH("readLine", Object.class, Object.class);
jlaskey@3 50
sundar@52 51 /** Handle to implementation of {@link ScriptingFunctions#readFully} - Nashorn extension */
sundar@52 52 public static final MethodHandle READFULLY = findOwnMH("readFully", Object.class, Object.class, Object.class);
jlaskey@3 53
jlaskey@75 54 /** Handle to implementation of {@link ScriptingFunctions#exec} - Nashorn extension */
jlaskey@67 55 public static final MethodHandle EXEC = findOwnMH("exec", Object.class, Object.class, Object.class, Object.class);
jlaskey@67 56
lagergren@89 57 /** EXEC name - special property used by $EXEC API. */
lagergren@89 58 public static final String EXEC_NAME = "$EXEC";
lagergren@89 59
lagergren@89 60 /** OUT name - special property used by $EXEC API. */
lagergren@89 61 public static final String OUT_NAME = "$OUT";
lagergren@89 62
lagergren@89 63 /** ERR name - special property used by $EXEC API. */
lagergren@89 64 public static final String ERR_NAME = "$ERR";
lagergren@89 65
lagergren@89 66 /** EXIT name - special property used by $EXEC API. */
lagergren@89 67 public static final String EXIT_NAME = "$EXIT";
jlaskey@67 68
jlaskey@67 69 /** Names of special properties used by $ENV API. */
jlaskey@67 70 public static final String ENV_NAME = "$ENV";
lagergren@89 71
jlaskey@67 72 private static final String PWD_NAME = "PWD";
jlaskey@67 73
jlaskey@3 74 private ScriptingFunctions() {
jlaskey@3 75 }
jlaskey@3 76
jlaskey@3 77 /**
jlaskey@3 78 * Nashorn extension: global.readLine (scripting-mode-only)
jlaskey@3 79 * Read one line of input from the standard input.
jlaskey@3 80 *
jlaskey@3 81 * @param self self reference
jlaskey@3 82 *
jlaskey@3 83 * @return line that was read
jlaskey@3 84 *
jlaskey@3 85 * @throws IOException if an exception occurs
jlaskey@3 86 */
jlaskey@3 87 public static Object readLine(final Object self) throws IOException {
jlaskey@3 88 final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
jlaskey@3 89 return reader.readLine();
jlaskey@3 90 }
jlaskey@3 91
jlaskey@3 92 /**
jlaskey@3 93 * Nashorn extension: Read the entire contents of a text file and return as String.
jlaskey@3 94 *
jlaskey@3 95 * @param self self reference
jlaskey@3 96 * @param file The input file whose content is read.
jlaskey@3 97 *
jlaskey@3 98 * @return String content of the input file.
jlaskey@3 99 *
jlaskey@3 100 * @throws IOException if an exception occurs
jlaskey@3 101 */
sundar@52 102 public static Object readFully(final Object self, final Object file) throws IOException {
jlaskey@3 103 File f = null;
jlaskey@3 104
jlaskey@3 105 if (file instanceof File) {
jlaskey@3 106 f = (File)file;
jlaskey@3 107 } else if (file instanceof String) {
jlaskey@3 108 f = new java.io.File((String)file);
jlaskey@3 109 }
jlaskey@3 110
jlaskey@3 111 if (f == null || !f.isFile()) {
sundar@44 112 typeError("not.a.file", ScriptRuntime.safeToString(file));
jlaskey@3 113 return UNDEFINED;
jlaskey@3 114 }
jlaskey@3 115
jlaskey@3 116 return new String(Source.readFully(f));
jlaskey@3 117 }
jlaskey@3 118
jlaskey@3 119 /**
jlaskey@67 120 * Nashorn extension: exec a string in a separate process.
jlaskey@67 121 *
jlaskey@67 122 * @param self self reference
jlaskey@67 123 * @param string string to execute
lagergren@89 124 * @param input
jlaskey@67 125 *
jlaskey@67 126 * @return output string from the request
lagergren@89 127 * @throws IOException
lagergren@89 128 * @throws InterruptedException
jlaskey@67 129 */
jlaskey@67 130 public static Object exec(final Object self, final Object string, final Object input) throws IOException, InterruptedException {
jlaskey@67 131 // Current global is need to fetch additional inputs and for additional results.
jlaskey@67 132 final ScriptObject global = Context.getGlobal();
jlaskey@67 133
jlaskey@67 134 // Break exec string into tokens.
jlaskey@67 135 final StringTokenizer tokenizer = new StringTokenizer(JSType.toString(string));
jlaskey@67 136 final String[] cmdArray = new String[tokenizer.countTokens()];
jlaskey@67 137 for (int i = 0; tokenizer.hasMoreTokens(); i++) {
jlaskey@67 138 cmdArray[i] = tokenizer.nextToken();
jlaskey@67 139 }
jlaskey@67 140
jlaskey@67 141 // Set up initial process.
jlaskey@67 142 final ProcessBuilder processBuilder = new ProcessBuilder(cmdArray);
jlaskey@67 143
sundar@69 144 // Current ENV property state.
sundar@69 145 final Object env = global.get(ENV_NAME);
sundar@69 146 if (env instanceof ScriptObject) {
sundar@69 147 final ScriptObject envProperties = (ScriptObject)env;
jlaskey@67 148
sundar@69 149 // If a working directory is present, use it.
sundar@69 150 final Object pwd = envProperties.get(PWD_NAME);
sundar@69 151 if (pwd != UNDEFINED) {
sundar@69 152 processBuilder.directory(new File(JSType.toString(pwd)));
sundar@69 153 }
jlaskey@67 154
sundar@69 155 // Set up ENV variables.
sundar@69 156 final Map<String, String> environment = processBuilder.environment();
sundar@69 157 environment.clear();
sundar@69 158 for (Map.Entry<Object, Object> entry : envProperties.entrySet()) {
sundar@69 159 environment.put(JSType.toString(entry.getKey()), JSType.toString(entry.getValue()));
sundar@69 160 }
jlaskey@67 161 }
jlaskey@67 162
jlaskey@67 163 // Start the process.
jlaskey@67 164 final Process process = processBuilder.start();
jlaskey@67 165
jlaskey@67 166 // If input is present, pass on to process.
jlaskey@67 167 try (OutputStream outputStream = process.getOutputStream()) {
jlaskey@67 168 if (input != UNDEFINED) {
jlaskey@67 169 outputStream.write(JSType.toString(input).getBytes());
jlaskey@67 170 }
jlaskey@67 171 }
jlaskey@67 172
jlaskey@67 173 // Wait for the process to complete.
jlaskey@67 174 final int exit = process.waitFor();
jlaskey@67 175
jlaskey@67 176 // Collect output.
jlaskey@67 177 String out;
jlaskey@67 178 try (InputStream inputStream = process.getInputStream()) {
jlaskey@67 179 final StringBuilder outBuffer = new StringBuilder();
jlaskey@67 180 for (int ch; (ch = inputStream.read()) != -1; ) {
jlaskey@67 181 outBuffer.append((char)ch);
jlaskey@67 182 }
jlaskey@67 183 out = outBuffer.toString();
jlaskey@67 184 }
jlaskey@67 185
jlaskey@67 186 // Collect errors.
jlaskey@67 187 String err;
jlaskey@67 188 try (InputStream errorStream = process.getErrorStream()) {
jlaskey@67 189 final StringBuilder errBuffer = new StringBuilder();
jlaskey@67 190 for (int ch; (ch = errorStream.read()) != -1; ) {
jlaskey@67 191 errBuffer.append((char)ch);
jlaskey@67 192 }
jlaskey@67 193 err = errBuffer.toString();
jlaskey@67 194 }
jlaskey@67 195
jlaskey@67 196 // Set globals for secondary results.
jlaskey@67 197 final boolean isStrict = global.isStrictContext();
jlaskey@67 198 global.set(OUT_NAME, out, isStrict);
jlaskey@67 199 global.set(ERR_NAME, err, isStrict);
jlaskey@67 200 global.set(EXIT_NAME, exit, isStrict);
jlaskey@67 201
jlaskey@67 202 // Return the result from stdout.
jlaskey@67 203 return out;
jlaskey@67 204 }
jlaskey@67 205
jlaskey@3 206 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
jlaskey@3 207 return MH.findStatic(MethodHandles.lookup(), ScriptingFunctions.class, name, MH.type(rtype, types));
jlaskey@3 208 }
jlaskey@3 209 }

mercurial