52
53 /**
54 * IR representation for function (or script.)
55 */
56 @Immutable
57 public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
58 private static final long serialVersionUID = 1L;
59
60 /** Type used for all FunctionNodes */
61 public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
62
63 /** Function kinds */
64 public enum Kind {
65 /** a normal function - nothing special */
66 NORMAL,
67 /** a script function */
68 SCRIPT,
69 /** a getter, @see {@link UserAccessorProperty} */
70 GETTER,
71 /** a setter, @see {@link UserAccessorProperty} */
72 SETTER
73 }
74
75 /** Source of entity. */
76 private transient final Source source;
77
78 /**
79 * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
80 * to skip parsing inner functions.
81 */
82 private final Object endParserState;
83
84 /** External function identifier. */
85 @Ignore
86 private final IdentNode ident;
87
88 /** The body of the function node */
89 private final Block body;
90
91 /** Internal function name. */
92 private final String name;
105
106 /** Last token of function. **/
107 private final long lastToken;
108
109 /** Method's namespace. */
110 private transient final Namespace namespace;
111
112 /** Number of properties of "this" object assigned in this function */
113 @Ignore
114 private final int thisProperties;
115
116 /** Function flags. */
117 private final int flags;
118
119 /** Line number of function start */
120 private final int lineNumber;
121
122 /** Root class for function */
123 private final Class<?> rootClass;
124
125 /** Is anonymous function flag. */
126 public static final int IS_ANONYMOUS = 1 << 0;
127
128 /** Is the function created in a function declaration (as opposed to a function expression) */
129 public static final int IS_DECLARED = 1 << 1;
130
131 /** is this a strict mode function? */
132 public static final int IS_STRICT = 1 << 2;
133
134 /** Does the function use the "arguments" identifier ? */
135 public static final int USES_ARGUMENTS = 1 << 3;
136
137 /** Has this function been split because it was too large? */
138 public static final int IS_SPLIT = 1 << 4;
139
140 /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
141 * introduce new variables into this function's scope too.*/
142 public static final int HAS_EVAL = 1 << 5;
143
144 /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
170 public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
171
172 /**
173 * Is this function the top-level program?
174 */
175 public static final int IS_PROGRAM = 1 << 13;
176
177 /**
178 * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
179 * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
180 * use the symbol in their parent scope instead when they reference themselves by name.
181 */
182 public static final int USES_SELF_SYMBOL = 1 << 14;
183
184 /** Does this function use the "this" keyword? */
185 public static final int USES_THIS = 1 << 15;
186
187 /** Is this declared in a dynamic context */
188 public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
189
190 /**
191 * The following flags are derived from directive comments within this function.
192 * Note that even IS_STRICT is one such flag but that requires special handling.
193 */
194
195 /** parser, print parse tree */
196 public static final int IS_PRINT_PARSE = 1 << 17;
197 /** parser, print lower parse tree */
198 public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
199 /** parser, print AST */
200 public static final int IS_PRINT_AST = 1 << 19;
201 /** parser, print lower AST */
202 public static final int IS_PRINT_LOWER_AST = 1 << 20;
203 /** parser, print symbols */
204 public static final int IS_PRINT_SYMBOLS = 1 << 21;
205
206 // callsite tracing, profiling within this function
207 /** profile callsites in this function? */
208 public static final int IS_PROFILE = 1 << 22;
209
210 /** trace callsite enterexit in this function? */
211 public static final int IS_TRACE_ENTEREXIT = 1 << 23;
212
213 /** trace callsite misses in this function? */
214 public static final int IS_TRACE_MISSES = 1 << 24;
215
216 /** trace callsite values in this function? */
217 public static final int IS_TRACE_VALUES = 1 << 25;
218
219 /**
220 * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
221 * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
222 * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
223 * will, however, cache the value of this flag.
224 */
225 public static final int NEEDS_CALLEE = 1 << 26;
226
227 /**
228 * Is the function node cached?
229 */
230 public static final int IS_CACHED = 1 << 27;
231
232 /** extension callsite flags mask */
233 public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
234 IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
235 IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
236 IS_TRACE_MISSES | IS_TRACE_VALUES;
237
238 /** Does this function or any nested functions contain an eval? */
239 private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
240
241 /** Does this function need to store all its variables in scope? */
242 public static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
243
244 /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
245 private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
246
247 /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
248 public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
249
250 /** What is the return type of this function? */
251 private Type returnType = Type.UNKNOWN;
252
253 /**
254 * Constructor
255 *
256 * @param source the source
257 * @param lineNumber line number
258 * @param token token
259 * @param finish finish
260 * @param firstToken first token of the function node (including the function declaration)
261 * @param lastToken lastToken
262 * @param namespace the namespace
263 * @param ident the identifier
264 * @param name the name of the function
265 * @param parameters parameter list
266 * @param kind kind of function as in {@link FunctionNode.Kind}
267 * @param flags initial flags
268 * @param body body of the function
269 * @param endParserState The parser state at the end of the parsing.
270 */
271 public FunctionNode(
272 final Source source,
273 final int lineNumber,
274 final long token,
275 final int finish,
276 final long firstToken,
277 final long lastToken,
278 final Namespace namespace,
279 final IdentNode ident,
280 final String name,
281 final List<IdentNode> parameters,
282 final FunctionNode.Kind kind,
283 final int flags,
284 final Block body,
285 final Object endParserState) {
286 super(token, finish);
287
288 this.source = source;
289 this.lineNumber = lineNumber;
290 this.ident = ident;
291 this.name = name;
292 this.kind = kind;
293 this.parameters = parameters;
294 this.firstToken = firstToken;
295 this.lastToken = lastToken;
296 this.namespace = namespace;
297 this.flags = flags;
298 this.compileUnit = null;
299 this.body = body;
300 this.thisProperties = 0;
301 this.rootClass = null;
302 this.endParserState = endParserState;
303 }
304
305 private FunctionNode(
306 final FunctionNode functionNode,
307 final long lastToken,
308 final Object endParserState,
309 final int flags,
310 final String name,
311 final Type returnType,
312 final CompileUnit compileUnit,
313 final Block body,
314 final List<IdentNode> parameters,
315 final int thisProperties,
316 final Class<?> rootClass,
317 final Source source, final Namespace namespace) {
318 super(functionNode);
319
320 this.endParserState = endParserState;
321 this.lineNumber = functionNode.lineNumber;
322 this.flags = flags;
323 this.name = name;
324 this.returnType = returnType;
325 this.compileUnit = compileUnit;
326 this.lastToken = lastToken;
327 this.body = body;
328 this.parameters = parameters;
329 this.thisProperties = thisProperties;
330 this.rootClass = rootClass;
331 this.source = source;
332 this.namespace = namespace;
333
334 // the fields below never change - they are final and assigned in constructor
335 this.ident = functionNode.ident;
336 this.kind = functionNode.kind;
337 this.firstToken = functionNode.firstToken;
338 }
339
340 @Override
341 public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
342 if (visitor.enterFunctionNode(this)) {
343 return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
344 }
345 return this;
346 }
347
348 /**
349 * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
350 * @param visitor the visitor to apply to the nodes.
351 * @return a list of parameter nodes, potentially modified from original ones by the visitor.
352 */
353 public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
354 return Node.accept(visitor, parameters);
355 }
356
357 /**
358 * Get additional callsite flags to be used specific to this function.
359 *
360 * @return callsite flags
361 */
362 public int getCallSiteFlags() {
363 int callsiteFlags = 0;
364 if (getFlag(IS_STRICT)) {
365 callsiteFlags |= CALLSITE_STRICT;
366 }
367
368 // quick check for extension callsite flags turned on by directives.
369 if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
370 return callsiteFlags;
371 }
372
373 if (getFlag(IS_PROFILE)) {
374 callsiteFlags |= CALLSITE_PROFILE;
375 }
376
377 if (getFlag(IS_TRACE_MISSES)) {
378 callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
379 }
380
381 if (getFlag(IS_TRACE_VALUES)) {
382 callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
383 }
384
385 if (getFlag(IS_TRACE_ENTEREXIT)) {
386 callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
387 }
388
389 return callsiteFlags;
390 }
391
392 /**
393 * Get the source for this function
394 * @return the source
395 */
396 public Source getSource() {
397 return source;
398 }
399
400 /**
401 * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
402 * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
403 * a deserialized function node.
404 * @param source the source for the function.
405 * @param namespace the namespace for the function
449 /**
450 * Static source name getter
451 *
452 * @param source the source
453 * @return source name
454 */
455 public static String getSourceName(final Source source) {
456 final String explicitURL = source.getExplicitURL();
457 return explicitURL != null ? explicitURL : source.getName();
458 }
459
460 /**
461 * Function to parse nashorn per-function extension directive comments.
462 *
463 * @param directive nashorn extension directive string
464 * @return integer flag for the given directive.
465 */
466 public static int getDirectiveFlag(final String directive) {
467 switch (directive) {
468 case "nashorn callsite trace enterexit":
469 return IS_TRACE_ENTEREXIT;
470 case "nashorn callsite trace misses":
471 return IS_TRACE_MISSES;
472 case "nashorn callsite trace objects":
473 return IS_TRACE_VALUES;
474 case "nashorn callsite profile":
475 return IS_PROFILE;
476 case "nashorn print parse":
477 return IS_PRINT_PARSE;
478 case "nashorn print lower parse":
479 return IS_PRINT_LOWER_PARSE;
480 case "nashorn print ast":
481 return IS_PRINT_AST;
482 case "nashorn print lower ast":
483 return IS_PRINT_LOWER_AST;
484 case "nashorn print symbols":
485 return IS_PRINT_SYMBOLS;
486 default:
487 // unknown/unsupported directive
488 return 0;
489 }
490 }
491
492 /**
493 * Returns the line number.
494 * @return the line number.
495 */
496 public int getLineNumber() {
497 return lineNumber;
498 }
499
500 /**
501 * Create a unique name in the namespace of this FunctionNode
502 * @param base prefix for name
503 * @return base if no collision exists, otherwise a name prefix with base
504 */
505 public String uniqueName(final String base) {
562 name,
563 returnType,
564 compileUnit,
565 body,
566 parameters,
567 thisProperties,
568 rootClass, source, namespace));
569 }
570
571 @Override
572 public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
573 return setFlags(lc, flags & ~flag);
574 }
575
576 @Override
577 public FunctionNode setFlag(final LexicalContext lc, final int flag) {
578 return setFlags(lc, flags | flag);
579 }
580
581 /**
582 * Returns true if the function is the top-level program.
583 * @return True if this function node represents the top-level program.
584 */
585 public boolean isProgram() {
586 return getFlag(IS_PROGRAM);
587 }
588
589 /**
590 * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
591 * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
592 */
593 public boolean canBeDeoptimized() {
594 return getFlag(IS_DEOPTIMIZABLE);
595 }
596
597 /**
598 * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
599 *
600 * @return true if {@code eval} is called.
601 */
1048 return getFlag(IS_STRICT);
1049 }
1050
1051 /**
1052 * Returns true if this function node has been cached.
1053 * @return true if this function node has been cached.
1054 */
1055 public boolean isCached() {
1056 return getFlag(IS_CACHED);
1057 }
1058
1059 /**
1060 * Mark this function node as having been cached.
1061 * @param lc the current lexical context
1062 * @return a function node equivalent to this one, with the flag set.
1063 */
1064 public FunctionNode setCached(final LexicalContext lc) {
1065 return setFlag(lc, IS_CACHED);
1066 }
1067
1068
1069 /**
1070 * Get the compile unit used to compile this function
1071 * @see Compiler
1072 * @return the compile unit
1073 */
1074 @Override
1075 public CompileUnit getCompileUnit() {
1076 return compileUnit;
1077 }
1078
1079 /**
1080 * Reset the compile unit used to compile this function
1081 * @see Compiler
1082 * @param lc lexical context
1083 * @param compileUnit the compile unit
1084 * @return function node or a new one if state was changed
1085 */
1086 public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1087 if (this.compileUnit == compileUnit) {
|
52
53 /**
54 * IR representation for function (or script.)
55 */
56 @Immutable
57 public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
58 private static final long serialVersionUID = 1L;
59
60 /** Type used for all FunctionNodes */
61 public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
62
63 /** Function kinds */
64 public enum Kind {
65 /** a normal function - nothing special */
66 NORMAL,
67 /** a script function */
68 SCRIPT,
69 /** a getter, @see {@link UserAccessorProperty} */
70 GETTER,
71 /** a setter, @see {@link UserAccessorProperty} */
72 SETTER,
73 /** an arrow function */
74 ARROW,
75 /** a generator function */
76 GENERATOR,
77 /** a module function */
78 MODULE
79 }
80
81 /** Source of entity. */
82 private transient final Source source;
83
84 /**
85 * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
86 * to skip parsing inner functions.
87 */
88 private final Object endParserState;
89
90 /** External function identifier. */
91 @Ignore
92 private final IdentNode ident;
93
94 /** The body of the function node */
95 private final Block body;
96
97 /** Internal function name. */
98 private final String name;
111
112 /** Last token of function. **/
113 private final long lastToken;
114
115 /** Method's namespace. */
116 private transient final Namespace namespace;
117
118 /** Number of properties of "this" object assigned in this function */
119 @Ignore
120 private final int thisProperties;
121
122 /** Function flags. */
123 private final int flags;
124
125 /** Line number of function start */
126 private final int lineNumber;
127
128 /** Root class for function */
129 private final Class<?> rootClass;
130
131 /** The ES6 module */
132 private final Module module;
133
134 /** The debug flags */
135 private final int debugFlags;
136
137 /** Is anonymous function flag. */
138 public static final int IS_ANONYMOUS = 1 << 0;
139
140 /** Is the function created in a function declaration (as opposed to a function expression) */
141 public static final int IS_DECLARED = 1 << 1;
142
143 /** is this a strict mode function? */
144 public static final int IS_STRICT = 1 << 2;
145
146 /** Does the function use the "arguments" identifier ? */
147 public static final int USES_ARGUMENTS = 1 << 3;
148
149 /** Has this function been split because it was too large? */
150 public static final int IS_SPLIT = 1 << 4;
151
152 /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
153 * introduce new variables into this function's scope too.*/
154 public static final int HAS_EVAL = 1 << 5;
155
156 /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
182 public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
183
184 /**
185 * Is this function the top-level program?
186 */
187 public static final int IS_PROGRAM = 1 << 13;
188
189 /**
190 * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
191 * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
192 * use the symbol in their parent scope instead when they reference themselves by name.
193 */
194 public static final int USES_SELF_SYMBOL = 1 << 14;
195
196 /** Does this function use the "this" keyword? */
197 public static final int USES_THIS = 1 << 15;
198
199 /** Is this declared in a dynamic context */
200 public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
201
202
203 /**
204 * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
205 * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
206 * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
207 * will, however, cache the value of this flag.
208 */
209 public static final int NEEDS_CALLEE = 1 << 17;
210
211 /**
212 * Is the function node cached?
213 */
214 public static final int IS_CACHED = 1 << 18;
215
216 /**
217 * Does this function contain a super call? (cf. ES6 14.3.5 Static Semantics: HasDirectSuper)
218 */
219 public static final int ES6_HAS_DIRECT_SUPER = 1 << 19;
220
221 /**
222 * Does this function use the super binding?
223 */
224 public static final int ES6_USES_SUPER = 1 << 20;
225
226 /**
227 * Is this function a (class or object) method?
228 */
229 public static final int ES6_IS_METHOD = 1 << 21;
230
231 /**
232 * Is this the constructor method?
233 */
234 public static final int ES6_IS_CLASS_CONSTRUCTOR = 1 << 22;
235
236 /** Is this the constructor of a subclass (i.e., a class with an extends declaration)? */
237 public static final int ES6_IS_SUBCLASS_CONSTRUCTOR = 1 << 23;
238
239 /** is this a strong mode function? */
240 public static final int ES6_IS_STRONG = 1 << 24;
241
242 /** Does this function use new.target? */
243 public static final int ES6_USES_NEW_TARGET = 1 << 25;
244
245 /** Does this function or any nested functions contain an eval? */
246 private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
247
248 /** Does this function need to store all its variables in scope? */
249 public static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
250
251 /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
252 private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
253
254 /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */
255 public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
256
257
258 /**
259 * The following flags are derived from directive comments within this function.
260 * Note that even IS_STRICT is one such flag but that requires special handling.
261 */
262
263 /** parser, print parse tree */
264 public static final int DEBUG_PRINT_PARSE = 1 << 0;
265 /** parser, print lower parse tree */
266 public static final int DEBUG_PRINT_LOWER_PARSE = 1 << 1;
267 /** parser, print AST */
268 public static final int DEBUG_PRINT_AST = 1 << 2;
269 /** parser, print lower AST */
270 public static final int DEBUG_PRINT_LOWER_AST = 1 << 3;
271 /** parser, print symbols */
272 public static final int DEBUG_PRINT_SYMBOLS = 1 << 4;
273
274 // callsite tracing, profiling within this function
275 /** profile callsites in this function? */
276 public static final int DEBUG_PROFILE = 1 << 5;
277
278 /** trace callsite enterexit in this function? */
279 public static final int DEBUG_TRACE_ENTEREXIT = 1 << 6;
280
281 /** trace callsite misses in this function? */
282 public static final int DEBUG_TRACE_MISSES = 1 << 7;
283
284 /** trace callsite values in this function? */
285 public static final int DEBUG_TRACE_VALUES = 1 << 8;
286
287 /** extension callsite flags mask */
288 public static final int DEBUG_CALLSITE_FLAGS = DEBUG_PRINT_PARSE |
289 DEBUG_PRINT_LOWER_PARSE | DEBUG_PRINT_AST | DEBUG_PRINT_LOWER_AST |
290 DEBUG_PRINT_SYMBOLS | DEBUG_PROFILE | DEBUG_TRACE_ENTEREXIT |
291 DEBUG_TRACE_MISSES | DEBUG_TRACE_VALUES;
292
293 /** What is the return type of this function? */
294 public Type returnType = Type.UNKNOWN;
295
296 /**
297 * Constructor
298 *
299 * @param source the source
300 * @param lineNumber line number
301 * @param token token
302 * @param finish finish
303 * @param firstToken first token of the function node (including the function declaration)
304 * @param lastToken lastToken
305 * @param namespace the namespace
306 * @param ident the identifier
307 * @param name the name of the function
308 * @param parameters parameter list
309 * @param kind kind of function as in {@link FunctionNode.Kind}
310 * @param flags initial flags
311 * @param body body of the function
312 * @param endParserState The parser state at the end of the parsing.
313 * @param module the module
314 * @param debugFlags the debug flags
315 */
316 public FunctionNode(
317 final Source source,
318 final int lineNumber,
319 final long token,
320 final int finish,
321 final long firstToken,
322 final long lastToken,
323 final Namespace namespace,
324 final IdentNode ident,
325 final String name,
326 final List<IdentNode> parameters,
327 final FunctionNode.Kind kind,
328 final int flags,
329 final Block body,
330 final Object endParserState,
331 final Module module,
332 final int debugFlags) {
333 super(token, finish);
334
335 this.source = source;
336 this.lineNumber = lineNumber;
337 this.ident = ident;
338 this.name = name;
339 this.kind = kind;
340 this.parameters = parameters;
341 this.firstToken = firstToken;
342 this.lastToken = lastToken;
343 this.namespace = namespace;
344 this.flags = flags;
345 this.compileUnit = null;
346 this.body = body;
347 this.thisProperties = 0;
348 this.rootClass = null;
349 this.endParserState = endParserState;
350 this.module = module;
351 this.debugFlags = debugFlags;
352 }
353
354 private FunctionNode(
355 final FunctionNode functionNode,
356 final long lastToken,
357 final Object endParserState,
358 final int flags,
359 final String name,
360 final Type returnType,
361 final CompileUnit compileUnit,
362 final Block body,
363 final List<IdentNode> parameters,
364 final int thisProperties,
365 final Class<?> rootClass,
366 final Source source, final Namespace namespace) {
367 super(functionNode);
368
369 this.endParserState = endParserState;
370 this.lineNumber = functionNode.lineNumber;
371 this.flags = flags;
372 this.name = name;
373 this.returnType = returnType;
374 this.compileUnit = compileUnit;
375 this.lastToken = lastToken;
376 this.body = body;
377 this.parameters = parameters;
378 this.thisProperties = thisProperties;
379 this.rootClass = rootClass;
380 this.source = source;
381 this.namespace = namespace;
382
383 // the fields below never change - they are final and assigned in constructor
384 this.ident = functionNode.ident;
385 this.kind = functionNode.kind;
386 this.firstToken = functionNode.firstToken;
387 this.module = functionNode.module;
388 this.debugFlags = functionNode.debugFlags;
389 }
390
391 @Override
392 public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
393 if (visitor.enterFunctionNode(this)) {
394 return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
395 }
396 return this;
397 }
398
399 /**
400 * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
401 * @param visitor the visitor to apply to the nodes.
402 * @return a list of parameter nodes, potentially modified from original ones by the visitor.
403 */
404 public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
405 return Node.accept(visitor, parameters);
406 }
407
408 /**
409 * Get additional callsite flags to be used specific to this function.
410 *
411 * @return callsite flags
412 */
413 public int getCallSiteFlags() {
414 int callsiteFlags = 0;
415 if (getFlag(IS_STRICT)) {
416 callsiteFlags |= CALLSITE_STRICT;
417 }
418
419 // quick check for extension callsite flags turned on by directives.
420 if ((debugFlags & DEBUG_CALLSITE_FLAGS) == 0) {
421 return callsiteFlags;
422 }
423
424 if (getDebugFlag(DEBUG_PROFILE)) {
425 callsiteFlags |= CALLSITE_PROFILE;
426 }
427
428 if (getDebugFlag(DEBUG_TRACE_MISSES)) {
429 callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
430 }
431
432 if (getDebugFlag(DEBUG_TRACE_VALUES)) {
433 callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
434 }
435
436 if (getDebugFlag(DEBUG_TRACE_ENTEREXIT)) {
437 callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
438 }
439
440 return callsiteFlags;
441 }
442
443 /**
444 * Get the source for this function
445 * @return the source
446 */
447 public Source getSource() {
448 return source;
449 }
450
451 /**
452 * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
453 * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
454 * a deserialized function node.
455 * @param source the source for the function.
456 * @param namespace the namespace for the function
500 /**
501 * Static source name getter
502 *
503 * @param source the source
504 * @return source name
505 */
506 public static String getSourceName(final Source source) {
507 final String explicitURL = source.getExplicitURL();
508 return explicitURL != null ? explicitURL : source.getName();
509 }
510
511 /**
512 * Function to parse nashorn per-function extension directive comments.
513 *
514 * @param directive nashorn extension directive string
515 * @return integer flag for the given directive.
516 */
517 public static int getDirectiveFlag(final String directive) {
518 switch (directive) {
519 case "nashorn callsite trace enterexit":
520 return DEBUG_TRACE_ENTEREXIT;
521 case "nashorn callsite trace misses":
522 return DEBUG_TRACE_MISSES;
523 case "nashorn callsite trace objects":
524 return DEBUG_TRACE_VALUES;
525 case "nashorn callsite profile":
526 return DEBUG_PROFILE;
527 case "nashorn print parse":
528 return DEBUG_PRINT_PARSE;
529 case "nashorn print lower parse":
530 return DEBUG_PRINT_LOWER_PARSE;
531 case "nashorn print ast":
532 return DEBUG_PRINT_AST;
533 case "nashorn print lower ast":
534 return DEBUG_PRINT_LOWER_AST;
535 case "nashorn print symbols":
536 return DEBUG_PRINT_SYMBOLS;
537 default:
538 // unknown/unsupported directive
539 return 0;
540 }
541 }
542
543 /**
544 * Returns the line number.
545 * @return the line number.
546 */
547 public int getLineNumber() {
548 return lineNumber;
549 }
550
551 /**
552 * Create a unique name in the namespace of this FunctionNode
553 * @param base prefix for name
554 * @return base if no collision exists, otherwise a name prefix with base
555 */
556 public String uniqueName(final String base) {
613 name,
614 returnType,
615 compileUnit,
616 body,
617 parameters,
618 thisProperties,
619 rootClass, source, namespace));
620 }
621
622 @Override
623 public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
624 return setFlags(lc, flags & ~flag);
625 }
626
627 @Override
628 public FunctionNode setFlag(final LexicalContext lc, final int flag) {
629 return setFlags(lc, flags | flag);
630 }
631
632 /**
633 * Returns the debug flags for this function.
634 *
635 * @return the debug flags
636 */
637 public int getDebugFlags() {
638 return debugFlags;
639 }
640
641 /**
642 * Checks whether a debug flag is set for this function.
643 *
644 * @param debugFlag the debug flag
645 * @return true if the flag is set
646 */
647 public boolean getDebugFlag(final int debugFlag) {
648 return (debugFlags & debugFlag) != 0;
649 }
650
651 /**
652 * Returns true if the function is the top-level program.
653 * @return True if this function node represents the top-level program.
654 */
655 public boolean isProgram() {
656 return getFlag(IS_PROGRAM);
657 }
658
659 /**
660 * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
661 * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
662 */
663 public boolean canBeDeoptimized() {
664 return getFlag(IS_DEOPTIMIZABLE);
665 }
666
667 /**
668 * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
669 *
670 * @return true if {@code eval} is called.
671 */
1118 return getFlag(IS_STRICT);
1119 }
1120
1121 /**
1122 * Returns true if this function node has been cached.
1123 * @return true if this function node has been cached.
1124 */
1125 public boolean isCached() {
1126 return getFlag(IS_CACHED);
1127 }
1128
1129 /**
1130 * Mark this function node as having been cached.
1131 * @param lc the current lexical context
1132 * @return a function node equivalent to this one, with the flag set.
1133 */
1134 public FunctionNode setCached(final LexicalContext lc) {
1135 return setFlag(lc, IS_CACHED);
1136 }
1137
1138 /**
1139 * Checks if the function is generated in strong mode.
1140 *
1141 * @return true if strong mode enabled for function
1142 */
1143 public boolean isStrong() {
1144 return getFlag(ES6_IS_STRONG);
1145 }
1146
1147 /**
1148 * Checks if this is an ES6 method.
1149 *
1150 * @return true if the ES6 method flag is set
1151 */
1152 public boolean isMethod() {
1153 return getFlag(ES6_IS_METHOD);
1154 }
1155
1156 /**
1157 * Checks if this function uses the ES6 super binding.
1158 *
1159 * @return true if the ES6 super flag is set
1160 */
1161 public boolean usesSuper() {
1162 return getFlag(ES6_USES_SUPER);
1163 }
1164
1165 /**
1166 * Checks if this function directly uses the super binding.
1167 *
1168 * @return true if the ES6 has-direct-super flag is set
1169 */
1170 public boolean hasDirectSuper() {
1171 return getFlag(ES6_HAS_DIRECT_SUPER);
1172 }
1173
1174 /**
1175 * Checks if this is an ES6 class constructor.
1176 *
1177 * @return true if the ES6 class constructor flag is set
1178 */
1179 public boolean isClassConstructor() {
1180 return getFlag(ES6_IS_CLASS_CONSTRUCTOR);
1181 }
1182
1183 /**
1184 * Checks if this is an ES6 subclass constructor.
1185 *
1186 * @return true if the ES6 subclass constructor flag is set
1187 */
1188 public boolean isSubclassConstructor() {
1189 return getFlag(ES6_IS_SUBCLASS_CONSTRUCTOR);
1190 }
1191
1192 /**
1193 * Checks if this function uses the ES6 new-targert.
1194 *
1195 * @return true if the ES6 new-target flag is set
1196 */
1197 public boolean usesNewTarget() {
1198 return getFlag(ES6_USES_NEW_TARGET);
1199 }
1200
1201 /**
1202 * Checks if this is an ES6 module.
1203 *
1204 * @return true if this is an ES6 module
1205 */
1206 public boolean isModule() {
1207 return kind == Kind.MODULE;
1208 }
1209
1210 /**
1211 * Returns the functions's ES6 module.
1212 *
1213 * @return the module, or null if this function is not part of one
1214 */
1215 public Module getModule() {
1216 return module;
1217 }
1218
1219 /**
1220 * Get the compile unit used to compile this function
1221 * @see Compiler
1222 * @return the compile unit
1223 */
1224 @Override
1225 public CompileUnit getCompileUnit() {
1226 return compileUnit;
1227 }
1228
1229 /**
1230 * Reset the compile unit used to compile this function
1231 * @see Compiler
1232 * @param lc lexical context
1233 * @param compileUnit the compile unit
1234 * @return function node or a new one if state was changed
1235 */
1236 public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1237 if (this.compileUnit == compileUnit) {
|