FunctionNode.java revision 1399:eea9202e8930
111820Sjulian/*
211820Sjulian * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
311820Sjulian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
411820Sjulian *
511820Sjulian * This code is free software; you can redistribute it and/or modify it
611820Sjulian * under the terms of the GNU General Public License version 2 only, as
711820Sjulian * published by the Free Software Foundation.  Oracle designates this
811820Sjulian * particular file as subject to the "Classpath" exception as provided
911820Sjulian * by Oracle in the LICENSE file that accompanied this code.
1011820Sjulian *
1111820Sjulian * This code is distributed in the hope that it will be useful, but WITHOUT
1211820Sjulian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1311820Sjulian * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1411820Sjulian * version 2 for more details (a copy is included in the LICENSE file that
1511820Sjulian * accompanied this code).
1611820Sjulian *
1711820Sjulian * You should have received a copy of the GNU General Public License version
1811820Sjulian * 2 along with this work; if not, write to the Free Software Foundation,
1911820Sjulian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2011820Sjulian *
2111820Sjulian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2211820Sjulian * or visit www.oracle.com if you need additional information or have any
2311820Sjulian * questions.
2411820Sjulian */
2511820Sjulian
2611820Sjulianpackage jdk.nashorn.internal.ir;
2711820Sjulian
2811820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
2911820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
3011820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
3111820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
3211820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
3311820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
3450479Speter
3511820Sjulianimport java.util.Collections;
3611820Sjulianimport java.util.EnumSet;
3711820Sjulianimport java.util.Iterator;
38122760Strhodesimport java.util.List;
3911820Sjulianimport jdk.nashorn.internal.AssertsEnabled;
4011820Sjulianimport jdk.nashorn.internal.codegen.CompileUnit;
4111820Sjulianimport jdk.nashorn.internal.codegen.Compiler;
4211820Sjulianimport jdk.nashorn.internal.codegen.CompilerConstants;
4311820Sjulianimport jdk.nashorn.internal.codegen.Namespace;
4411820Sjulianimport jdk.nashorn.internal.codegen.types.Type;
4511820Sjulianimport jdk.nashorn.internal.ir.annotations.Ignore;
4611820Sjulianimport jdk.nashorn.internal.ir.annotations.Immutable;
4711820Sjulianimport jdk.nashorn.internal.ir.visitor.NodeVisitor;
4811820Sjulianimport jdk.nashorn.internal.parser.Token;
4911820Sjulianimport jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
5011820Sjulianimport jdk.nashorn.internal.runtime.ScriptFunction;
5111820Sjulianimport jdk.nashorn.internal.runtime.Source;
5211820Sjulianimport jdk.nashorn.internal.runtime.UserAccessorProperty;
5311820Sjulianimport jdk.nashorn.internal.runtime.linker.LinkerCallSite;
5411820Sjulian
5511820Sjulian/**
5611820Sjulian * IR representation for function (or script.)
5711820Sjulian */
5811820Sjulian@Immutable
5911820Sjulianpublic final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
6011820Sjulian    private static final long serialVersionUID = 1L;
6111820Sjulian
6211820Sjulian    /** Type used for all FunctionNodes */
6311820Sjulian    public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
6411820Sjulian
6511820Sjulian    /** Function kinds */
6611820Sjulian    public enum Kind {
6711820Sjulian        /** a normal function - nothing special */
6811820Sjulian        NORMAL,
6911820Sjulian        /** a script function */
7011820Sjulian        SCRIPT,
7111820Sjulian        /** a getter, @see {@link UserAccessorProperty} */
7211820Sjulian        GETTER,
7311820Sjulian        /** a setter, @see {@link UserAccessorProperty} */
7411820Sjulian        SETTER
7511820Sjulian    }
7611820Sjulian
7711820Sjulian    /** Compilation states available */
7811820Sjulian    public enum CompilationState {
7911820Sjulian        /** compiler is ready */
8011820Sjulian        INITIALIZED,
8111820Sjulian        /** method has been parsed */
8211820Sjulian        PARSED,
8311820Sjulian        /** method has been parsed */
8411820Sjulian        PARSE_ERROR,
8511820Sjulian        /** constant folding pass */
8611820Sjulian        CONSTANT_FOLDED,
8711820Sjulian        /** method has been lowered */
8811820Sjulian        LOWERED,
8911820Sjulian        /** program points have been assigned to unique locations */
9011820Sjulian        PROGRAM_POINTS_ASSIGNED,
9111820Sjulian        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
9227244Sjhay        BUILTINS_TRANSFORMED,
9327244Sjhay        /** method has been split */
9427244Sjhay        SPLIT,
9527244Sjhay        /** method has had symbols assigned */
9627244Sjhay        SYMBOLS_ASSIGNED,
9711820Sjulian        /** computed scope depths for symbols */
9827244Sjhay        SCOPE_DEPTHS_COMPUTED,
9927244Sjhay        /** method has had types calculated*/
10027244Sjhay        OPTIMISTIC_TYPES_ASSIGNED,
10127244Sjhay        /** method has had types calculated */
10227244Sjhay        LOCAL_VARIABLE_TYPES_CALCULATED,
10327244Sjhay        /** compile units reused (optional) */
10427244Sjhay        COMPILE_UNITS_REUSED,
10527244Sjhay        /** method has been emitted to bytecode */
10627244Sjhay        BYTECODE_GENERATED,
10727244Sjhay        /** method has been installed */
10827244Sjhay        BYTECODE_INSTALLED
10927244Sjhay    }
11027244Sjhay
11127244Sjhay    /** Source of entity. */
11227244Sjhay    private transient final Source source;
11327244Sjhay
11427244Sjhay    /**
11511820Sjulian     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
11611820Sjulian     * to skip parsing inner functions.
11727244Sjhay     */
11811820Sjulian    private final Object endParserState;
11911820Sjulian
12011820Sjulian    /** External function identifier. */
12111820Sjulian    @Ignore
12211820Sjulian    private final IdentNode ident;
12311820Sjulian
12411820Sjulian    /** The body of the function node */
12511820Sjulian    private final Block body;
12611820Sjulian
12711820Sjulian    /** Internal function name. */
12811820Sjulian    private final String name;
12911820Sjulian
13011820Sjulian    /** Compilation unit. */
13111820Sjulian    private final CompileUnit compileUnit;
13211820Sjulian
13311820Sjulian    /** Function kind. */
13411820Sjulian    private final Kind kind;
13511820Sjulian
13611820Sjulian    /** List of parameters. */
13711820Sjulian    private final List<IdentNode> parameters;
13811820Sjulian
13911820Sjulian    /** First token of function. **/
14011820Sjulian    private final long firstToken;
14111820Sjulian
14211820Sjulian    /** Last token of function. **/
14311820Sjulian    private final long lastToken;
14411820Sjulian
14511820Sjulian    /** Method's namespace. */
14611820Sjulian    private transient final Namespace namespace;
14711820Sjulian
14811820Sjulian    /** Current compilation state */
14911820Sjulian    @Ignore
15011820Sjulian    private final EnumSet<CompilationState> compilationState;
15111820Sjulian
15211820Sjulian    /** Number of properties of "this" object assigned in this function */
15311820Sjulian    @Ignore
15411820Sjulian    private final int thisProperties;
15511820Sjulian
15611820Sjulian    /** Function flags. */
15711820Sjulian    private final int flags;
15811820Sjulian
15911820Sjulian    /** Line number of function start */
16011820Sjulian    private final int lineNumber;
16111820Sjulian
16211820Sjulian    /** Root class for function */
16311820Sjulian    private final Class<?> rootClass;
16411820Sjulian
16511820Sjulian    /** Is anonymous function flag. */
16611820Sjulian    public static final int IS_ANONYMOUS                = 1 << 0;
16711820Sjulian
16811820Sjulian    /** Is the function created in a function declaration (as opposed to a function expression) */
16911820Sjulian    public static final int IS_DECLARED                 = 1 << 1;
17011820Sjulian
17111820Sjulian    /** is this a strict mode function? */
17211820Sjulian    public static final int IS_STRICT                   = 1 << 2;
17311820Sjulian
17411820Sjulian    /** Does the function use the "arguments" identifier ? */
17511820Sjulian    public static final int USES_ARGUMENTS              = 1 << 3;
17611820Sjulian
17711820Sjulian    /** Has this function been split because it was too large? */
17811820Sjulian    public static final int IS_SPLIT                    = 1 << 4;
17911820Sjulian
18011820Sjulian    /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
18111820Sjulian     * introduce new variables into this function's scope too.*/
18211820Sjulian    public static final int HAS_EVAL                    = 1 << 5;
18311820Sjulian
18411820Sjulian    /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
18511820Sjulian    public static final int HAS_NESTED_EVAL             = 1 << 6;
18611820Sjulian
18711820Sjulian    /** Does this function have any blocks that create a scope? This is used to determine if the function needs to
18811820Sjulian     * have a local variable slot for the scope symbol. */
18911820Sjulian    public static final int HAS_SCOPE_BLOCK             = 1 << 7;
19011820Sjulian
19111820Sjulian    /**
19211820Sjulian     * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
19311820Sjulian     * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that
19411820Sjulian     * defining a local variable named "arguments" still requires construction of the Arguments object (see
19511820Sjulian     * ECMAScript 5.1 Chapter 10.5).
19611820Sjulian     * @see #needsArguments()
19711820Sjulian     */
19811820Sjulian    public static final int DEFINES_ARGUMENTS           = 1 << 8;
19911820Sjulian
20011820Sjulian    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
20111820Sjulian    public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
20211820Sjulian
20311820Sjulian    /** Does this function have nested declarations? */
20411820Sjulian    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
20511820Sjulian
20611820Sjulian    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
20711820Sjulian    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
20811820Sjulian
20911820Sjulian    /** Are we vararg, but do we just pass the arguments along to apply or call */
21011820Sjulian    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
21112620Sjulian
21212620Sjulian    /**
21311820Sjulian     * Is this function the top-level program?
21411820Sjulian     */
21512620Sjulian    public static final int IS_PROGRAM = 1 << 13;
21612620Sjulian
21711820Sjulian    /**
21811820Sjulian     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
21911820Sjulian     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
22011820Sjulian     * use the symbol in their parent scope instead when they reference themselves by name.
22111820Sjulian     */
22211820Sjulian    public static final int USES_SELF_SYMBOL = 1 << 14;
22311820Sjulian
22411820Sjulian    /** Does this function use the "this" keyword? */
22511820Sjulian    public static final int USES_THIS = 1 << 15;
22611820Sjulian
22711820Sjulian    /** Is this declared in a dynamic context */
22811820Sjulian    public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
22911820Sjulian
23011820Sjulian    /**
23111820Sjulian     * The following flags are derived from directive comments within this function.
23211820Sjulian     * Note that even IS_STRICT is one such flag but that requires special handling.
23311820Sjulian     */
23411820Sjulian
23511820Sjulian    /** parser, print parse tree */
23611820Sjulian    public static final int IS_PRINT_PARSE       = 1 << 17;
23711820Sjulian    /** parser, print lower parse tree */
23811820Sjulian    public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
23911820Sjulian    /** parser, print AST */
24011820Sjulian    public static final int IS_PRINT_AST         = 1 << 19;
24111820Sjulian    /** parser, print lower AST */
24211820Sjulian    public static final int IS_PRINT_LOWER_AST   = 1 << 20;
24311820Sjulian    /** parser, print symbols */
24411820Sjulian    public static final int IS_PRINT_SYMBOLS     = 1 << 21;
24511820Sjulian
24611820Sjulian    // callsite tracing, profiling within this function
24711820Sjulian    /** profile callsites in this function? */
24811820Sjulian    public static final int IS_PROFILE         = 1 << 22;
24911820Sjulian
25011820Sjulian    /** trace callsite enterexit in this function? */
25111820Sjulian    public static final int IS_TRACE_ENTEREXIT = 1 << 23;
25211820Sjulian
25311820Sjulian    /** trace callsite misses in this function? */
25411820Sjulian    public static final int IS_TRACE_MISSES    = 1 << 24;
25511820Sjulian
25611820Sjulian    /** trace callsite values in this function? */
25711820Sjulian    public static final int IS_TRACE_VALUES    = 1 << 25;
25811820Sjulian
25911820Sjulian    /**
26011820Sjulian     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
26111820Sjulian     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
26211820Sjulian     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
26311820Sjulian     * will, however, cache the value of this flag.
26411820Sjulian     */
26511820Sjulian    public static final int NEEDS_CALLEE       = 1 << 26;
26611820Sjulian
26711820Sjulian    /**
26811820Sjulian     * Is the function node cached?
26911820Sjulian     */
27011820Sjulian    public static final int IS_CACHED = 1 << 27;
27111820Sjulian
27211820Sjulian    /** extension callsite flags mask */
27311820Sjulian    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
27411820Sjulian        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
27511820Sjulian        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
27611820Sjulian        IS_TRACE_MISSES | IS_TRACE_VALUES;
27711820Sjulian
27811820Sjulian    /** Does this function or any nested functions contain an eval? */
27911820Sjulian    private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
28011820Sjulian
28111820Sjulian    /** Does this function need to store all its variables in scope? */
28211820Sjulian    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
28311820Sjulian
28411820Sjulian    /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
28511820Sjulian    private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
28611820Sjulian
28711820Sjulian    /** 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. */
28811820Sjulian    public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
28911820Sjulian
29011820Sjulian    /** What is the return type of this function? */
29111820Sjulian    private Type returnType = Type.UNKNOWN;
29211820Sjulian
29311820Sjulian    /**
29411820Sjulian     * Constructor
295     *
296     * @param source     the source
297     * @param lineNumber line number
298     * @param token      token
299     * @param finish     finish
300     * @param firstToken first token of the function node (including the function declaration)
301     * @param lastToken  lastToken
302     * @param namespace  the namespace
303     * @param ident      the identifier
304     * @param name       the name of the function
305     * @param parameters parameter list
306     * @param kind       kind of function as in {@link FunctionNode.Kind}
307     * @param flags      initial flags
308     * @param body       body of the function
309     * @param state      The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR}
310     * @param endParserState The parser state at the end of the parsing.
311     */
312    public FunctionNode(
313        final Source source,
314        final int lineNumber,
315        final long token,
316        final int finish,
317        final long firstToken,
318        final long lastToken,
319        final Namespace namespace,
320        final IdentNode ident,
321        final String name,
322        final List<IdentNode> parameters,
323        final FunctionNode.Kind kind,
324        final int flags,
325        final Block body,
326        final CompilationState state,
327        final Object endParserState) {
328        super(token, finish);
329
330        this.source           = source;
331        this.lineNumber       = lineNumber;
332        this.ident            = ident;
333        this.name             = name;
334        this.kind             = kind;
335        this.parameters       = parameters;
336        this.firstToken       = firstToken;
337        this.lastToken        = lastToken;
338        this.namespace        = namespace;
339        this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state);
340        this.flags            = flags;
341        this.compileUnit      = null;
342        this.body             = body;
343        this.thisProperties   = 0;
344        this.rootClass        = null;
345        this.endParserState    = endParserState;
346    }
347
348    private FunctionNode(
349        final FunctionNode functionNode,
350        final long lastToken,
351        final Object endParserState,
352        final int flags,
353        final String name,
354        final Type returnType,
355        final CompileUnit compileUnit,
356        final EnumSet<CompilationState> compilationState,
357        final Block body,
358        final List<IdentNode> parameters,
359        final int thisProperties,
360        final Class<?> rootClass,
361        final Source source, final Namespace namespace) {
362        super(functionNode);
363
364        this.endParserState    = endParserState;
365        this.lineNumber       = functionNode.lineNumber;
366        this.flags            = flags;
367        this.name             = name;
368        this.returnType       = returnType;
369        this.compileUnit      = compileUnit;
370        this.lastToken        = lastToken;
371        this.compilationState = compilationState;
372        this.body             = body;
373        this.parameters       = parameters;
374        this.thisProperties   = thisProperties;
375        this.rootClass        = rootClass;
376        this.source           = source;
377        this.namespace        = namespace;
378
379        // the fields below never change - they are final and assigned in constructor
380        this.ident           = functionNode.ident;
381        this.kind            = functionNode.kind;
382        this.firstToken      = functionNode.firstToken;
383    }
384
385    @Override
386    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
387        if (visitor.enterFunctionNode(this)) {
388            return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
389        }
390        return this;
391    }
392
393    /**
394     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
395     * @param visitor the visitor to apply to the nodes.
396     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
397     */
398    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
399        return Node.accept(visitor, parameters);
400    }
401
402    /**
403     * Get additional callsite flags to be used specific to this function.
404     *
405     * @return callsite flags
406     */
407    public int getCallSiteFlags() {
408        int callsiteFlags = 0;
409        if (getFlag(IS_STRICT)) {
410            callsiteFlags |= CALLSITE_STRICT;
411        }
412
413        // quick check for extension callsite flags turned on by directives.
414        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
415            return callsiteFlags;
416        }
417
418        if (getFlag(IS_PROFILE)) {
419            callsiteFlags |= CALLSITE_PROFILE;
420        }
421
422        if (getFlag(IS_TRACE_MISSES)) {
423            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
424        }
425
426        if (getFlag(IS_TRACE_VALUES)) {
427            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
428        }
429
430        if (getFlag(IS_TRACE_ENTEREXIT)) {
431            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
432        }
433
434        return callsiteFlags;
435    }
436
437    /**
438     * Get the source for this function
439     * @return the source
440     */
441    public Source getSource() {
442        return source;
443    }
444
445    /**
446     * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
447     * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
448     * a deserialized function node.
449     * @param source the source for the function.
450     * @param namespace the namespace for the function
451     * @return a new function node with the set source and namespace
452     * @throws IllegalArgumentException if the specified source or namespace is null
453     * @throws IllegalStateException if the function already has either a source or namespace set.
454     */
455    public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
456        if (source == null || namespace == null) {
457            throw new IllegalArgumentException();
458        } else if (this.source == source && this.namespace == namespace) {
459            return this;
460        } else if (this.source != null || this.namespace != null) {
461            throw new IllegalStateException();
462        }
463        return new FunctionNode(
464            this,
465            lastToken,
466            endParserState,
467            flags,
468            name,
469            returnType,
470            compileUnit,
471            compilationState,
472            body,
473            parameters,
474            thisProperties,
475            rootClass, source, namespace);
476    }
477
478    /**
479     * Get the unique ID for this function within the script file.
480     * @return the id
481     */
482    public int getId() {
483        return isProgram() ? -1: Token.descPosition(firstToken);
484    }
485
486    /**
487     * get source name - sourceURL or name derived from Source.
488     *
489     * @return name for the script source
490     */
491    public String getSourceName() {
492        return getSourceName(source);
493    }
494
495    /**
496     * Static source name getter
497     *
498     * @param source the source
499     * @return source name
500     */
501    public static String getSourceName(final Source source) {
502        final String explicitURL = source.getExplicitURL();
503        return explicitURL != null ? explicitURL : source.getName();
504    }
505
506    /**
507     * Function to parse nashorn per-function extension directive comments.
508     *
509     * @param directive nashorn extension directive string
510     * @return integer flag for the given directive.
511     */
512    public static int getDirectiveFlag(final String directive) {
513        switch (directive) {
514            case "nashorn callsite trace enterexit":
515                return IS_TRACE_ENTEREXIT;
516            case "nashorn callsite trace misses":
517                return IS_TRACE_MISSES;
518            case "nashorn callsite trace objects":
519                return IS_TRACE_VALUES;
520            case "nashorn callsite profile":
521                return IS_PROFILE;
522            case "nashorn print parse":
523                return IS_PRINT_PARSE;
524            case "nashorn print lower parse":
525                return IS_PRINT_LOWER_PARSE;
526            case "nashorn print ast":
527                return IS_PRINT_AST;
528            case "nashorn print lower ast":
529                return IS_PRINT_LOWER_AST;
530            case "nashorn print symbols":
531                return IS_PRINT_SYMBOLS;
532            default:
533                // unknown/unsupported directive
534                return 0;
535        }
536    }
537
538    /**
539     * Returns the line number.
540     * @return the line number.
541     */
542    public int getLineNumber() {
543        return lineNumber;
544    }
545
546    /**
547     * Get the compilation state of this function
548     * @return the compilation state
549     */
550    public EnumSet<CompilationState> getState() {
551        return compilationState;
552    }
553
554    /**
555     * Check whether this FunctionNode has reached a give CompilationState.
556     *
557     * @param state the state to check for
558     * @return true of the node is in the given state
559     */
560    public boolean hasState(final EnumSet<CompilationState> state) {
561        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
562    }
563
564    /**
565     * Add a state to the total CompilationState of this node, e.g. if
566     * FunctionNode has been lowered, the compiler will add
567     * {@code CompilationState#LOWERED} to the state vector
568     *
569     * @param lc lexical context
570     * @param state {@link CompilationState} to add
571     * @return function node or a new one if state was changed
572     */
573    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
574        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
575            return this;
576        }
577        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
578        newState.add(state);
579        return setCompilationState(lc, newState);
580    }
581
582    /**
583     * Copy a compilation state from an original function to this function. Used when creating synthetic
584     * function nodes by the splitter.
585     *
586     * @param lc lexical context
587     * @param original the original function node to copy compilation state from
588     * @return function node or a new one if state was changed
589     */
590    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
591        final EnumSet<CompilationState> origState = original.compilationState;
592        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
593            return this;
594        }
595        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
596        newState.addAll(origState);
597        return setCompilationState(lc, newState);
598    }
599
600    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
601        return Node.replaceInLexicalContext(
602                lc,
603                this,
604                new FunctionNode(
605                        this,
606                        lastToken,
607                        endParserState,
608                        flags,
609                        name,
610                        returnType,
611                        compileUnit,
612                        compilationState,
613                        body,
614                        parameters,
615                        thisProperties,
616                        rootClass, source, namespace));
617    }
618
619
620    /**
621     * Create a unique name in the namespace of this FunctionNode
622     * @param base prefix for name
623     * @return base if no collision exists, otherwise a name prefix with base
624     */
625    public String uniqueName(final String base) {
626        return namespace.uniqueName(base);
627    }
628
629    @Override
630    public void toString(final StringBuilder sb, final boolean printTypes) {
631        sb.append('[').
632            append(returnType).
633            append(']').
634            append(' ');
635
636        sb.append("function");
637
638        if (ident != null) {
639            sb.append(' ');
640            ident.toString(sb, printTypes);
641        }
642
643        sb.append('(');
644
645        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
646            final IdentNode parameter = iter.next();
647            if (parameter.getSymbol() != null) {
648                sb.append('[').append(parameter.getType()).append(']').append(' ');
649            }
650            parameter.toString(sb, printTypes);
651            if (iter.hasNext()) {
652                sb.append(", ");
653            }
654        }
655
656        sb.append(')');
657    }
658
659    @Override
660    public int getFlags() {
661        return flags;
662    }
663
664    @Override
665    public boolean getFlag(final int flag) {
666        return (flags & flag) != 0;
667    }
668
669    @Override
670    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
671        if (this.flags == flags) {
672            return this;
673        }
674        return Node.replaceInLexicalContext(
675                lc,
676                this,
677                new FunctionNode(
678                        this,
679                        lastToken,
680                        endParserState,
681                        flags,
682                        name,
683                        returnType,
684                        compileUnit,
685                        compilationState,
686                        body,
687                        parameters,
688                        thisProperties,
689                        rootClass, source, namespace));
690    }
691
692    @Override
693    public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
694        return setFlags(lc, flags & ~flag);
695    }
696
697    @Override
698    public FunctionNode setFlag(final LexicalContext lc, final int flag) {
699        return setFlags(lc, flags | flag);
700    }
701
702    /**
703     * Returns true if the function is the top-level program.
704     * @return True if this function node represents the top-level program.
705     */
706    public boolean isProgram() {
707        return getFlag(IS_PROGRAM);
708    }
709
710    /**
711     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
712     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
713     */
714    public boolean canBeDeoptimized() {
715        return getFlag(IS_DEOPTIMIZABLE);
716    }
717
718    /**
719     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
720     *
721     * @return true if {@code eval} is called.
722     */
723    public boolean hasEval() {
724        return getFlag(HAS_EVAL);
725    }
726
727    /**
728     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
729     *
730     * @return true if a nested function calls {@code eval}.
731     */
732    public boolean hasNestedEval() {
733        return getFlag(HAS_NESTED_EVAL);
734    }
735
736    /**
737     * Get the first token for this function
738     * @return the first token
739     */
740    public long getFirstToken() {
741        return firstToken;
742    }
743
744    /**
745     * Check whether this function has nested function declarations
746     * @return true if nested function declarations exist
747     */
748    public boolean hasDeclaredFunctions() {
749        return getFlag(HAS_FUNCTION_DECLARATIONS);
750    }
751
752    /**
753     * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to
754     * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object
755     * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
756     * for split functions to make sure symbols slots are the same in the main and split methods.
757     *
758     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
759     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
760     *
761     * @return true if the function's generated Java method needs a {@code callee} parameter.
762     */
763    public boolean needsCallee() {
764        // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
765        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization();
766    }
767
768    /**
769     * Return {@code true} if this function makes use of the {@code this} object.
770     *
771     * @return true if function uses {@code this} object
772     */
773    public boolean usesThis() {
774        return getFlag(USES_THIS);
775    }
776
777
778    /**
779     * Return true if function contains an apply to call transform
780     * @return true if this function has transformed apply to call
781     */
782    public boolean hasApplyToCallSpecialization() {
783        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
784    }
785
786    /**
787     * Get the identifier for this function, this is its symbol.
788     * @return the identifier as an IdentityNode
789     */
790    public IdentNode getIdent() {
791        return ident;
792    }
793
794    /**
795     * Get the function body
796     * @return the function body
797     */
798    public Block getBody() {
799        return body;
800    }
801
802    /**
803     * Reset the function body
804     * @param lc lexical context
805     * @param body new body
806     * @return new function node if body changed, same if not
807     */
808    public FunctionNode setBody(final LexicalContext lc, final Block body) {
809        if (this.body == body) {
810            return this;
811        }
812        return Node.replaceInLexicalContext(
813                lc,
814                this,
815                new FunctionNode(
816                        this,
817                        lastToken,
818                        endParserState,
819                        flags |
820                            (body.needsScope() ?
821                                    FunctionNode.HAS_SCOPE_BLOCK :
822                                    0),
823                        name,
824                        returnType,
825                        compileUnit,
826                        compilationState,
827                        body,
828                        parameters,
829                        thisProperties,
830                        rootClass, source, namespace));
831    }
832
833    /**
834     * Does this function's method needs to be variable arity (gather all script-declared parameters in a final
835     * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply
836     * declare too many arguments for JVM to handle with fixed arity will need to be variable arity.
837     * @return true if the Java method in the generated code that implements this function needs to be variable arity.
838     * @see #needsArguments()
839     * @see LinkerCallSite#ARGLIMIT
840     */
841    public boolean isVarArg() {
842        return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT;
843    }
844
845    /**
846     * Was this function declared in a dynamic context, i.e. in a with or eval style
847     * chain
848     * @return true if in dynamic context
849     */
850    public boolean inDynamicContext() {
851        return getFlag(IN_DYNAMIC_CONTEXT);
852    }
853
854    /**
855     * Check whether a function would need dynamic scope, which is does if it has
856     * evals and isn't strict.
857     * @return true if dynamic scope is needed
858     */
859    public boolean needsDynamicScope() {
860        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
861        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
862        // isolated scope).
863        return hasEval() && !isStrict();
864    }
865
866    /**
867     * Flag this function as declared in a dynamic context
868     * @param lc lexical context
869     * @return new function node, or same if unmodified
870     */
871    public FunctionNode setInDynamicContext(final LexicalContext lc) {
872        return setFlag(lc, IN_DYNAMIC_CONTEXT);
873    }
874
875    /**
876     * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
877     * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
878     * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
879     * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an
880     * "arguments" object, because it does not have local variables; rather the Global object will have an explicit
881     * "arguments" property that provides command-line arguments for the script.
882     * @return true if this function needs an arguments object.
883     */
884    public boolean needsArguments() {
885        // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since
886        // for top-level script, "arguments" is picked up from Context by Global.init() instead.
887        return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram();
888    }
889
890    /**
891     * Returns true if this function needs access to its parent scope. Functions referencing variables outside their
892     * scope (including global variables), as well as functions that call eval or have a with block, or have nested
893     * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a
894     * parent scope since they might be used from within eval, and eval will need an externally passed scope.
895     * @return true if the function needs parent scope.
896     */
897    public boolean needsParentScope() {
898        return getFlag(NEEDS_PARENT_SCOPE);
899    }
900
901    /**
902     * Set the number of properties assigned to the this object in this function.
903     * @param lc the current lexical context.
904     * @param thisProperties number of properties
905     * @return a potentially modified function node
906     */
907    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
908        if (this.thisProperties == thisProperties) {
909            return this;
910        }
911        return Node.replaceInLexicalContext(
912                lc,
913                this,
914                new FunctionNode(
915                        this,
916                        lastToken,
917                        endParserState,
918                        flags,
919                        name,
920                        returnType,
921                        compileUnit,
922                        compilationState,
923                        body,
924                        parameters,
925                        thisProperties,
926                        rootClass, source, namespace));
927    }
928
929    /**
930     * Get the number of properties assigned to the this object in this function.
931     * @return number of properties
932     */
933    public int getThisProperties() {
934        return thisProperties;
935    }
936
937    /**
938     * Returns true if any of the blocks in this function create their own scope.
939     * @return true if any of the blocks in this function create their own scope.
940     */
941    public boolean hasScopeBlock() {
942        return getFlag(HAS_SCOPE_BLOCK);
943    }
944
945    /**
946     * Return the kind of this function
947     * @see FunctionNode.Kind
948     * @return the kind
949     */
950    public Kind getKind() {
951        return kind;
952    }
953
954    /**
955     * Return the last token for this function's code
956     * @return last token
957     */
958    public long getLastToken() {
959        return lastToken;
960    }
961
962    /**
963     * Returns the end parser state for this function.
964     * @return the end parser state for this function.
965     */
966    public Object getEndParserState() {
967        return endParserState;
968    }
969
970    /**
971     * Get the name of this function
972     * @return the name
973     */
974    public String getName() {
975        return name;
976    }
977
978    /**
979     * Set the internal name for this function
980     * @param lc    lexical context
981     * @param name new name
982     * @return new function node if changed, otherwise the same
983     */
984    public FunctionNode setName(final LexicalContext lc, final String name) {
985        if (this.name.equals(name)) {
986            return this;
987        }
988        return Node.replaceInLexicalContext(
989                lc,
990                this,
991                new FunctionNode(
992                        this,
993                        lastToken,
994                        endParserState,
995                        flags,
996                        name,
997                        returnType,
998                        compileUnit,
999                        compilationState,
1000                        body,
1001                        parameters,
1002                        thisProperties,
1003                        rootClass, source, namespace));
1004    }
1005
1006    /**
1007     * Check if this function should have all its variables in its own scope. Split sub-functions, and
1008     * functions having with and/or eval blocks are such.
1009     *
1010     * @return true if all variables should be in scope
1011     */
1012    public boolean allVarsInScope() {
1013        return getFlag(HAS_ALL_VARS_IN_SCOPE);
1014    }
1015
1016    /**
1017     * Checks if this function is split into several smaller fragments.
1018     *
1019     * @return true if this function is split into several smaller fragments.
1020     */
1021    public boolean isSplit() {
1022        return getFlag(IS_SPLIT);
1023    }
1024
1025    /**
1026     * Get the parameters to this function
1027     * @return a list of IdentNodes which represent the function parameters, in order
1028     */
1029    public List<IdentNode> getParameters() {
1030        return Collections.unmodifiableList(parameters);
1031    }
1032
1033    /**
1034     * Return the number of parameters to this function
1035     * @return the number of parameters
1036     */
1037    public int getNumOfParams() {
1038        return parameters.size();
1039    }
1040
1041    /**
1042     * Returns the identifier for a named parameter at the specified position in this function's parameter list.
1043     * @param index the parameter's position.
1044     * @return the identifier for the requested named parameter.
1045     * @throws IndexOutOfBoundsException if the index is invalid.
1046     */
1047    public IdentNode getParameter(final int index) {
1048        return parameters.get(index);
1049    }
1050
1051    /**
1052     * Reset the compile unit used to compile this function
1053     * @see Compiler
1054     * @param  lc lexical context
1055     * @param  parameters the compile unit
1056     * @return function node or a new one if state was changed
1057     */
1058    public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) {
1059        if (this.parameters == parameters) {
1060            return this;
1061        }
1062        return Node.replaceInLexicalContext(
1063                lc,
1064                this,
1065                new FunctionNode(
1066                        this,
1067                        lastToken,
1068                        endParserState,
1069                        flags,
1070                        name,
1071                        returnType,
1072                        compileUnit,
1073                        compilationState,
1074                        body,
1075                        parameters,
1076                        thisProperties,
1077                        rootClass, source, namespace));
1078    }
1079
1080    /**
1081     * Check if this function is created as a function declaration (as opposed to function expression)
1082     * @return true if function is declared.
1083     */
1084    public boolean isDeclared() {
1085        return getFlag(IS_DECLARED);
1086    }
1087
1088    /**
1089     * Check if this function is anonymous
1090     * @return true if function is anonymous
1091     */
1092    public boolean isAnonymous() {
1093        return getFlag(IS_ANONYMOUS);
1094    }
1095
1096    /**
1097     * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
1098     * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
1099     * scope (since they're bound to the symbol with their name in their enclosing scope).
1100     * @return true if this function node is a named function expression that uses the symbol for itself.
1101     */
1102    public boolean usesSelfSymbol() {
1103        return getFlag(USES_SELF_SYMBOL);
1104    }
1105
1106    /**
1107     * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
1108     * anonymous function expression, and it isn't a program).
1109     * @return true if this is a named function expression
1110     */
1111    public boolean isNamedFunctionExpression() {
1112        return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
1113    }
1114
1115    @Override
1116    public Type getType() {
1117        return FUNCTION_TYPE;
1118    }
1119
1120    @Override
1121    public Type getWidestOperationType() {
1122        return FUNCTION_TYPE;
1123    }
1124
1125    /**
1126     * Get the return type for this function. Return types can be specialized
1127     * if the compiler knows them, but parameters cannot, as they need to go through
1128     * appropriate object conversion
1129     *
1130     * @return the return type
1131     */
1132    public Type getReturnType() {
1133        return returnType;
1134    }
1135
1136    /**
1137     * Set the function return type
1138     * @param lc lexical context
1139     * @param returnType new return type
1140     * @return function node or a new one if state was changed
1141     */
1142    public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
1143        //we never bother with object types narrower than objects, that will lead to byte code verification errors
1144        //as for instance even if we know we are returning a string from a method, the code generator will always
1145        //treat it as an object, at least for now
1146        final Type type = returnType.isObject() ? Type.OBJECT : returnType;
1147        if (this.returnType == type) {
1148            return this;
1149        }
1150        return Node.replaceInLexicalContext(
1151            lc,
1152            this,
1153            new FunctionNode(
1154                this,
1155                lastToken,
1156                endParserState,
1157                flags,
1158                name,
1159                type,
1160                compileUnit,
1161                compilationState,
1162                body,
1163                parameters,
1164                thisProperties,
1165                rootClass, source, namespace
1166                ));
1167   }
1168
1169    /**
1170     * Check if the function is generated in strict mode
1171     * @return true if strict mode enabled for function
1172     */
1173    public boolean isStrict() {
1174        return getFlag(IS_STRICT);
1175    }
1176
1177    /**
1178     * Returns true if this function node has been cached.
1179     * @return true if this function node has been cached.
1180     */
1181    public boolean isCached() {
1182        return getFlag(IS_CACHED);
1183    }
1184
1185    /**
1186     * Mark this function node as having been cached.
1187     * @param lc the current lexical context
1188     * @return a function node equivalent to this one, with the flag set.
1189     */
1190    public FunctionNode setCached(final LexicalContext lc) {
1191        return setFlag(lc, IS_CACHED);
1192    }
1193
1194
1195    /**
1196     * Get the compile unit used to compile this function
1197     * @see Compiler
1198     * @return the compile unit
1199     */
1200    @Override
1201    public CompileUnit getCompileUnit() {
1202        return compileUnit;
1203    }
1204
1205    /**
1206     * Reset the compile unit used to compile this function
1207     * @see Compiler
1208     * @param lc lexical context
1209     * @param compileUnit the compile unit
1210     * @return function node or a new one if state was changed
1211     */
1212    public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1213        if (this.compileUnit == compileUnit) {
1214            return this;
1215        }
1216        return Node.replaceInLexicalContext(
1217                lc,
1218                this,
1219                new FunctionNode(
1220                        this,
1221                        lastToken,
1222                        endParserState,
1223                        flags,
1224                        name,
1225                        returnType,
1226                        compileUnit,
1227                        compilationState,
1228                        body,
1229                        parameters,
1230                        thisProperties,
1231                        rootClass, source, namespace));
1232    }
1233
1234    /**
1235     * Create a temporary variable to the current frame.
1236     *
1237     * @param block that needs the temporary
1238     * @param type  Strong type of symbol.
1239     * @param node  Primary node to use symbol.
1240     *
1241     * @return Symbol used.
1242     */
1243
1244    /**
1245     * Get the symbol for a compiler constant, or null if not available (yet)
1246     * @param cc compiler constant
1247     * @return symbol for compiler constant, or null if not defined yet (for example in Lower)
1248     */
1249    public Symbol compilerConstant(final CompilerConstants cc) {
1250        return body.getExistingSymbol(cc.symbolName());
1251    }
1252
1253    /**
1254     * Get the root class that this function node compiles to
1255     * @return root class
1256     */
1257    public Class<?> getRootClass() {
1258        return rootClass;
1259    }
1260
1261    /**
1262     * Reset the root class that this function is compiled to
1263     * @see Compiler
1264     * @param lc lexical context
1265     * @param rootClass root class
1266     * @return function node or a new one if state was changed
1267     */
1268    public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
1269        if (this.rootClass == rootClass) {
1270            return this;
1271        }
1272        return Node.replaceInLexicalContext(
1273                lc,
1274                this,
1275                new FunctionNode(
1276                        this,
1277                        lastToken,
1278                        endParserState,
1279                        flags,
1280                        name,
1281                        returnType,
1282                        compileUnit,
1283                        compilationState,
1284                        body,
1285                        parameters,
1286                        thisProperties,
1287                        rootClass, source, namespace));
1288    }
1289}
1290