View Javadoc
1   /*
2    * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package jdk.nashorn.internal.runtime;
27  
28  import java.io.PrintWriter;
29  import java.util.HashSet;
30  import java.util.List;
31  import java.util.Locale;
32  import java.util.Set;
33  import java.util.StringTokenizer;
34  import java.util.TimeZone;
35  
36  import jdk.nashorn.internal.codegen.Namespace;
37  import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
38  import jdk.nashorn.internal.runtime.options.KeyValueOption;
39  import jdk.nashorn.internal.runtime.options.Option;
40  import jdk.nashorn.internal.runtime.options.Options;
41  
42  /**
43   * Script environment consists of command line options, arguments, script files
44   * and output and error writers, top level Namespace etc.
45   */
46  public final class ScriptEnvironment {
47      /** Output writer for this environment */
48      private final PrintWriter out;
49  
50      /** Error writer for this environment */
51      private final PrintWriter err;
52  
53      /** Top level namespace. */
54      private final Namespace namespace;
55  
56      /** Current Options object. */
57      private final Options options;
58  
59      /** Size of the per-global Class cache size */
60      public final int     _class_cache_size;
61  
62      /** Only compile script, do not run it or generate other ScriptObjects */
63      public final boolean _compile_only;
64  
65      /** Accumulated callsite flags that will be used when bootstrapping script callsites */
66      public final int     _callsite_flags;
67  
68      /** Generate line number table in class files */
69      public final boolean _debug_lines;
70  
71      /** Package to which generated class files are added */
72      public final String  _dest_dir;
73  
74      /** Display stack trace upon error, default is false */
75      public final boolean _dump_on_error;
76  
77      /** Invalid lvalue expressions should be reported as early errors */
78      public final boolean _early_lvalue_error;
79  
80      /** Empty statements should be preserved in the AST */
81      public final boolean _empty_statements;
82  
83      /** Show full Nashorn version */
84      public final boolean _fullversion;
85  
86      /** Launch using as fx application */
87      public final boolean _fx;
88  
89      /** Use single Global instance per jsr223 engine instance. */
90      public final boolean _global_per_engine;
91  
92      /**
93       * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
94       * (function declarations are source elements, but not statements).
95       */
96      public enum FunctionStatementBehavior {
97          /**
98           * Accept the function declaration silently and treat it as if it were a function expression assigned to a local
99           * variable.
100          */
101         ACCEPT,
102         /**
103          * Log a parser warning, but accept the function declaration and treat it as if it were a function expression
104          * assigned to a local variable.
105          */
106         WARNING,
107         /**
108          * Raise a {@code SyntaxError}.
109          */
110         ERROR
111     }
112 
113     /**
114      * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
115      * (function declarations are source elements, but not statements).
116      */
117     public final FunctionStatementBehavior _function_statement;
118 
119     /** Should lazy compilation take place */
120     public final boolean _lazy_compilation;
121 
122     /** Create a new class loaded for each compilation */
123     public final boolean _loader_per_compile;
124 
125     /** Do not support Java support extensions. */
126     public final boolean _no_java;
127 
128     /** Do not support non-standard syntax extensions. */
129     public final boolean _no_syntax_extensions;
130 
131     /** Do not support typed arrays. */
132     public final boolean _no_typed_arrays;
133 
134     /** Only parse the source code, do not compile */
135     public final boolean _parse_only;
136 
137     /** Print the AST before lowering */
138     public final boolean _print_ast;
139 
140     /** Print the AST after lowering */
141     public final boolean _print_lower_ast;
142 
143     /** Print resulting bytecode for script */
144     public final boolean _print_code;
145 
146     /** Print memory usage for IR after each phase */
147     public final boolean _print_mem_usage;
148 
149     /** Print function will no print newline characters */
150     public final boolean _print_no_newline;
151 
152     /** Print AST in more human readable form */
153     public final boolean _print_parse;
154 
155     /** Print AST in more human readable form after Lowering */
156     public final boolean _print_lower_parse;
157 
158     /** print symbols and their contents for the script */
159     public final boolean _print_symbols;
160 
161     /** range analysis for known types */
162     public final boolean _range_analysis;
163 
164     /** is this environment in scripting mode? */
165     public final boolean _scripting;
166 
167     /** is the JIT allowed to specializ calls based on callsite types? */
168     public final Set<String> _specialize_calls;
169 
170     /** is this environment in strict mode? */
171     public final boolean _strict;
172 
173     /** print version info of Nashorn */
174     public final boolean _version;
175 
176     /** should code verification be done of generated bytecode */
177     public final boolean _verify_code;
178 
179     /** time zone for this environment */
180     public final TimeZone _timezone;
181 
182     /** Local for error messages */
183     public final Locale _locale;
184 
185     /**
186      * Constructor
187      *
188      * @param options a Options object
189      * @param out output print writer
190      * @param err error print writer
191      */
192     public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
193         this.out = out;
194         this.err = err;
195         this.namespace = new Namespace();
196         this.options = options;
197 
198         _class_cache_size     = options.getInteger("class.cache.size");
199         _compile_only         = options.getBoolean("compile.only");
200         _debug_lines          = options.getBoolean("debug.lines");
201         _dest_dir             = options.getString("d");
202         _dump_on_error        = options.getBoolean("doe");
203         _early_lvalue_error   = options.getBoolean("early.lvalue.error");
204         _empty_statements     = options.getBoolean("empty.statements");
205         _fullversion          = options.getBoolean("fullversion");
206         if(options.getBoolean("function.statement.error")) {
207             _function_statement = FunctionStatementBehavior.ERROR;
208         } else if(options.getBoolean("function.statement.warning")) {
209             _function_statement = FunctionStatementBehavior.WARNING;
210         } else {
211             _function_statement = FunctionStatementBehavior.ACCEPT;
212         }
213         _fx                   = options.getBoolean("fx");
214         _global_per_engine    = options.getBoolean("global.per.engine");
215         _lazy_compilation     = options.getBoolean("lazy.compilation");
216         _loader_per_compile   = options.getBoolean("loader.per.compile");
217         _no_java              = options.getBoolean("no.java");
218         _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
219         _no_typed_arrays      = options.getBoolean("no.typed.arrays");
220         _parse_only           = options.getBoolean("parse.only");
221         _print_ast            = options.getBoolean("print.ast");
222         _print_lower_ast      = options.getBoolean("print.lower.ast");
223         _print_code           = options.getBoolean("print.code");
224         _print_mem_usage      = options.getBoolean("print.mem.usage");
225         _print_no_newline     = options.getBoolean("print.no.newline");
226         _print_parse          = options.getBoolean("print.parse");
227         _print_lower_parse    = options.getBoolean("print.lower.parse");
228         _print_symbols        = options.getBoolean("print.symbols");
229         _range_analysis       = options.getBoolean("range.analysis");
230         _scripting            = options.getBoolean("scripting");
231         _strict               = options.getBoolean("strict");
232         _version              = options.getBoolean("version");
233         _verify_code          = options.getBoolean("verify.code");
234 
235         final String specialize = options.getString("specialize.calls");
236         if (specialize == null) {
237             _specialize_calls = null;
238         } else {
239             _specialize_calls = new HashSet<>();
240             final StringTokenizer st = new StringTokenizer(specialize, ",");
241             while (st.hasMoreElements()) {
242                 _specialize_calls.add(st.nextToken());
243             }
244         }
245 
246         int callSiteFlags = 0;
247         if (options.getBoolean("profile.callsites")) {
248             callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_PROFILE;
249         }
250 
251         if (options.get("trace.callsites") instanceof KeyValueOption) {
252             callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE;
253             final KeyValueOption kv = (KeyValueOption)options.get("trace.callsites");
254             if (kv.hasValue("miss")) {
255                 callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
256             }
257             if (kv.hasValue("enterexit") || (callSiteFlags & NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES) == 0) {
258                 callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
259             }
260             if (kv.hasValue("objects")) {
261                 callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
262             }
263             if (kv.hasValue("scope")) {
264                 callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_SCOPE;
265             }
266         }
267         this._callsite_flags = callSiteFlags;
268 
269         final Option<?> timezoneOption = options.get("timezone");
270         if (timezoneOption != null) {
271             this._timezone = (TimeZone)timezoneOption.getValue();
272         } else {
273             this._timezone  = TimeZone.getDefault();
274         }
275 
276         final Option<?> localeOption = options.get("locale");
277         if (localeOption != null) {
278             this._locale = (Locale)localeOption.getValue();
279         } else {
280             this._locale = Locale.getDefault();
281         }
282     }
283 
284     /**
285      * Can we specialize a particular method name?
286      * @param functionName method name
287      * @return true if we are allowed to generate versions of this method
288      */
289     public boolean canSpecialize(final String functionName) {
290         if (_specialize_calls == null) {
291             return false;
292         }
293         return _specialize_calls.isEmpty() || _specialize_calls.contains(functionName);
294     }
295 
296     /**
297      * Get the output stream for this environment
298      * @return output print writer
299      */
300     public PrintWriter getOut() {
301         return out;
302     }
303 
304     /**
305      * Get the error stream for this environment
306      * @return error print writer
307      */
308     public PrintWriter getErr() {
309         return err;
310     }
311 
312     /**
313      * Get the namespace for this environment
314      * @return namespace
315      */
316     public Namespace getNamespace() {
317         return namespace;
318     }
319 
320     /**
321      * Return the JavaScript files passed to the program
322      *
323      * @return a list of files
324      */
325     public List<String> getFiles() {
326         return options.getFiles();
327     }
328 
329     /**
330      * Return the user arguments to the program, i.e. those trailing "--" after
331      * the filename
332      *
333      * @return a list of user arguments
334      */
335     public List<String> getArguments() {
336         return options.getArguments();
337     }
338 }