FunctionNode.java revision 1152:5f6a840fc19d
1139749Simp/*
274429Sorion * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
374429Sorion * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
474429Sorion *
574429Sorion * This code is free software; you can redistribute it and/or modify it
674429Sorion * under the terms of the GNU General Public License version 2 only, as
774429Sorion * published by the Free Software Foundation.  Oracle designates this
874429Sorion * particular file as subject to the "Classpath" exception as provided
974429Sorion * by Oracle in the LICENSE file that accompanied this code.
1074429Sorion *
1174429Sorion * This code is distributed in the hope that it will be useful, but WITHOUT
1274429Sorion * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1374429Sorion * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1474429Sorion * version 2 for more details (a copy is included in the LICENSE file that
1574429Sorion * accompanied this code).
1674429Sorion *
1774429Sorion * You should have received a copy of the GNU General Public License version
1874429Sorion * 2 along with this work; if not, write to the Free Software Foundation,
1974429Sorion * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2074429Sorion *
2174429Sorion * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2274429Sorion * or visit www.oracle.com if you need additional information or have any
2374429Sorion * questions.
2474429Sorion */
25192919Sjoel
26192919Sjoelpackage jdk.nashorn.internal.ir;
27192919Sjoel
2874429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
2974429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
3074429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
3182180Scgimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
3274429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
33193640Sariffimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
34193640Sariff
35193640Sariffimport java.util.Collections;
36193640Sariffimport java.util.EnumSet;
3774429Sorionimport java.util.Iterator;
3874429Sorionimport java.util.List;
3974429Sorionimport jdk.nashorn.internal.AssertsEnabled;
40119287Simpimport jdk.nashorn.internal.codegen.CompileUnit;
41119287Simpimport jdk.nashorn.internal.codegen.Compiler;
4274429Sorionimport jdk.nashorn.internal.codegen.CompilerConstants;
4374429Sorionimport jdk.nashorn.internal.codegen.Namespace;
4474429Sorionimport jdk.nashorn.internal.codegen.types.Type;
4582180Scgimport jdk.nashorn.internal.ir.annotations.Ignore;
4682180Scgimport jdk.nashorn.internal.ir.annotations.Immutable;
4774429Sorionimport jdk.nashorn.internal.ir.visitor.NodeVisitor;
4874429Sorionimport jdk.nashorn.internal.parser.Token;
4974429Sorionimport jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
5074429Sorionimport jdk.nashorn.internal.runtime.ScriptFunction;
5184771Sorionimport jdk.nashorn.internal.runtime.Source;
5284771Sorionimport jdk.nashorn.internal.runtime.UserAccessorProperty;
5374429Sorionimport jdk.nashorn.internal.runtime.linker.LinkerCallSite;
5474429Sorion
5574429Sorion/**
5674429Sorion * IR representation for function (or script.)
5774429Sorion */
5874429Sorion@Immutable
5974429Sorionpublic final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
6074429Sorion    private static final long serialVersionUID = 1L;
6174429Sorion
6274429Sorion    /** Type used for all FunctionNodes */
6374429Sorion    public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
6474429Sorion
6574429Sorion    /** Function kinds */
6674763Scg    public enum Kind {
6774763Scg        /** a normal function - nothing special */
6874571Sorion        NORMAL,
6974429Sorion        /** a script function */
7074429Sorion        SCRIPT,
7174429Sorion        /** a getter, @see {@link UserAccessorProperty} */
7274429Sorion        GETTER,
7374429Sorion        /** a setter, @see {@link UserAccessorProperty} */
7474429Sorion        SETTER
7574429Sorion    }
7674429Sorion
7774429Sorion    /** Compilation states available */
7874429Sorion    public enum CompilationState {
7974429Sorion        /** compiler is ready */
8074429Sorion        INITIALIZED,
8174429Sorion        /** method has been parsed */
8274429Sorion        PARSED,
8374429Sorion        /** method has been parsed */
8474429Sorion        PARSE_ERROR,
8574429Sorion        /** constant folding pass */
8674429Sorion        CONSTANT_FOLDED,
8774429Sorion        /** method has been lowered */
8874429Sorion        LOWERED,
8974429Sorion        /** program points have been assigned to unique locations */
9074429Sorion        PROGRAM_POINTS_ASSIGNED,
9174429Sorion        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
9274429Sorion        BUILTINS_TRANSFORMED,
9374429Sorion        /** method has been split */
9474429Sorion        SPLIT,
9574429Sorion        /** method has had symbols assigned */
9674429Sorion        SYMBOLS_ASSIGNED,
9774429Sorion        /** computed scope depths for symbols */
9884771Sorion        SCOPE_DEPTHS_COMPUTED,
9984771Sorion        /** method has had types calculated*/
10084771Sorion        OPTIMISTIC_TYPES_ASSIGNED,
10174429Sorion        /** method has had types calculated */
10274429Sorion        LOCAL_VARIABLE_TYPES_CALCULATED,
10374429Sorion        /** compile units reused (optional) */
10474429Sorion        COMPILE_UNITS_REUSED,
10574429Sorion        /** method has been emitted to bytecode */
106193640Sariff        BYTECODE_GENERATED,
107193640Sariff        /** method has been installed */
108193640Sariff        BYTECODE_INSTALLED
109193640Sariff    }
11074429Sorion
11174429Sorion    /** Source of entity. */
11274429Sorion    private transient final Source source;
11374763Scg
11474429Sorion    /**
11574429Sorion     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
11674429Sorion     * to skip parsing inner functions.
11774429Sorion     */
11874429Sorion    private final Object endParserState;
11974429Sorion
12074429Sorion    /** External function identifier. */
12174797Scg    @Ignore
12274429Sorion    private final IdentNode ident;
12374429Sorion
12474429Sorion    /** The body of the function node */
12574429Sorion    private final Block body;
12674429Sorion
12774797Scg    /** Internal function name. */
12874429Sorion    private final String name;
12974429Sorion
13074429Sorion    /** Compilation unit. */
13174429Sorion    private final CompileUnit compileUnit;
13274429Sorion
13374429Sorion    /** Function kind. */
13474429Sorion    private final Kind kind;
13574429Sorion
13674429Sorion    /** List of parameters. */
13774429Sorion    private final List<IdentNode> parameters;
13874429Sorion
13974797Scg    /** First token of function. **/
14074429Sorion    private final long firstToken;
14174797Scg
14274429Sorion    /** Last token of function. **/
14374429Sorion    private final long lastToken;
14474429Sorion
14574429Sorion    /** Method's namespace. */
14674429Sorion    private transient final Namespace namespace;
14774429Sorion
14874429Sorion    /** Current compilation state */
14974429Sorion    @Ignore
15074429Sorion    private final EnumSet<CompilationState> compilationState;
15174797Scg
15274429Sorion    /** Number of properties of "this" object assigned in this function */
15374797Scg    @Ignore
15474429Sorion    private final int thisProperties;
15574429Sorion
15674429Sorion    /** Function flags. */
15774429Sorion    private final int flags;
15874429Sorion
15974429Sorion    /** Line number of function start */
16074429Sorion    private final int lineNumber;
16174429Sorion
16274429Sorion    /** Root class for function */
16374429Sorion    private final Class<?> rootClass;
16474429Sorion
16574429Sorion    /** Is anonymous function flag. */
16674429Sorion    public static final int IS_ANONYMOUS                = 1 << 0;
16774429Sorion
16874429Sorion    /** Is the function created in a function declaration (as opposed to a function expression) */
16974797Scg    public static final int IS_DECLARED                 = 1 << 1;
17074797Scg
17174429Sorion    /** is this a strict mode function? */
17274429Sorion    public static final int IS_STRICT                   = 1 << 2;
17374429Sorion
17474429Sorion    /** Does the function use the "arguments" identifier ? */
17574429Sorion    public static final int USES_ARGUMENTS              = 1 << 3;
17674429Sorion
17774429Sorion    /** Has this function been split because it was too large? */
17874429Sorion    public static final int IS_SPLIT                    = 1 << 4;
17974429Sorion
18074429Sorion    /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
18174429Sorion     * introduce new variables into this function's scope too.*/
18274429Sorion    public static final int HAS_EVAL                    = 1 << 5;
18374429Sorion
18474429Sorion    /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
18574429Sorion    public static final int HAS_NESTED_EVAL             = 1 << 6;
18674429Sorion
18774429Sorion    /** Does this function have any blocks that create a scope? This is used to determine if the function needs to
18874429Sorion     * have a local variable slot for the scope symbol. */
18974429Sorion    public static final int HAS_SCOPE_BLOCK             = 1 << 7;
19074429Sorion
19174763Scg    /**
19274429Sorion     * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
19374429Sorion     * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that
19474429Sorion     * defining a local variable named "arguments" still requires construction of the Arguments object (see
19574797Scg     * ECMAScript 5.1 Chapter 10.5).
19674429Sorion     * @see #needsArguments()
19774429Sorion     */
19874429Sorion    public static final int DEFINES_ARGUMENTS           = 1 << 8;
19974429Sorion
20074429Sorion    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
201168847Sariff    public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
20274429Sorion
20374429Sorion    /** Does this function have nested declarations? */
20474429Sorion    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
20574429Sorion
206193640Sariff    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
20774429Sorion    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
20874429Sorion
20974429Sorion    /** Are we vararg, but do we just pass the arguments along to apply or call */
21074429Sorion    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
21174429Sorion
21274429Sorion    /**
21374763Scg     * Is this function the top-level program?
21474429Sorion     */
21574429Sorion    public static final int IS_PROGRAM = 1 << 13;
21674429Sorion
21774429Sorion    /**
21874429Sorion     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
219193640Sariff     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
22074429Sorion     * use the symbol in their parent scope instead when they reference themselves by name.
22174429Sorion     */
22274429Sorion    public static final int USES_SELF_SYMBOL = 1 << 14;
22384771Sorion
22474429Sorion    /** Does this function use the "this" keyword? */
22574429Sorion    public static final int USES_THIS = 1 << 15;
22684771Sorion
22774429Sorion    /** Is this declared in a dynamic context */
22874429Sorion    public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
22982835Sorion
23074429Sorion    /**
23174429Sorion     * The following flags are derived from directive comments within this function.
23274429Sorion     * Note that even IS_STRICT is one such flag but that requires special handling.
23374429Sorion     */
23474429Sorion
23574429Sorion    /** parser, print parse tree */
23674429Sorion    public static final int IS_PRINT_PARSE       = 1 << 17;
23774429Sorion    /** parser, print lower parse tree */
238193640Sariff    public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
23974429Sorion    /** parser, print AST */
24074429Sorion    public static final int IS_PRINT_AST         = 1 << 19;
24174429Sorion    /** parser, print lower AST */
24274429Sorion    public static final int IS_PRINT_LOWER_AST   = 1 << 20;
243193640Sariff    /** parser, print symbols */
24474429Sorion    public static final int IS_PRINT_SYMBOLS     = 1 << 21;
24574429Sorion
24674429Sorion    // callsite tracing, profiling within this function
24774429Sorion    /** profile callsites in this function? */
24874429Sorion    public static final int IS_PROFILE         = 1 << 22;
24974429Sorion
25074429Sorion    /** trace callsite enterexit in this function? */
25174429Sorion    public static final int IS_TRACE_ENTEREXIT = 1 << 23;
25274429Sorion
25374429Sorion    /** trace callsite misses in this function? */
25474429Sorion    public static final int IS_TRACE_MISSES    = 1 << 24;
25574797Scg
25674429Sorion    /** trace callsite values in this function? */
25774429Sorion    public static final int IS_TRACE_VALUES    = 1 << 25;
25874429Sorion
25974429Sorion    /**
26074429Sorion     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
26174429Sorion     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
26274429Sorion     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
26374429Sorion     * will, however, cache the value of this flag.
26474429Sorion     */
26574429Sorion    public static final int NEEDS_CALLEE       = 1 << 26;
26674429Sorion
26774429Sorion    /** extension callsite flags mask */
26874429Sorion    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
26974429Sorion        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
27074429Sorion        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
27174429Sorion        IS_TRACE_MISSES | IS_TRACE_VALUES;
27274429Sorion
27374429Sorion    /** Does this function or any nested functions contain an eval? */
27474429Sorion    private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
27574429Sorion
27674429Sorion    /** Does this function need to store all its variables in scope? */
27774429Sorion    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
27874429Sorion
27974429Sorion    /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
28074797Scg    private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
28174429Sorion
28274429Sorion    /** 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. */
28374429Sorion    public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
28474429Sorion
28574797Scg    /** What is the return type of this function? */
28674429Sorion    private Type returnType = Type.UNKNOWN;
28774429Sorion
28874429Sorion    /**
28974429Sorion     * Constructor
29074429Sorion     *
29174429Sorion     * @param source     the source
29274429Sorion     * @param lineNumber line number
29374429Sorion     * @param token      token
29474429Sorion     * @param finish     finish
29574429Sorion     * @param firstToken first token of the function node (including the function declaration)
29674429Sorion     * @param lastToken  lastToken
29774429Sorion     * @param namespace  the namespace
29874429Sorion     * @param ident      the identifier
29974429Sorion     * @param name       the name of the function
30074429Sorion     * @param parameters parameter list
30174429Sorion     * @param kind       kind of function as in {@link FunctionNode.Kind}
30274429Sorion     * @param flags      initial flags
30374797Scg     * @param body       body of the function
30474429Sorion     * @param state      The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR}
30574429Sorion     * @param endParserState The parser state at the end of the parsing.
30674429Sorion     */
30774429Sorion    public FunctionNode(
30874429Sorion        final Source source,
30974429Sorion        final int lineNumber,
31074429Sorion        final long token,
31174429Sorion        final int finish,
31274797Scg        final long firstToken,
31374429Sorion        final long lastToken,
31474429Sorion        final Namespace namespace,
31574429Sorion        final IdentNode ident,
31674429Sorion        final String name,
31774429Sorion        final List<IdentNode> parameters,
31874429Sorion        final FunctionNode.Kind kind,
31974429Sorion        final int flags,
32074429Sorion        final Block body,
32174429Sorion        final CompilationState state,
32274429Sorion        final Object endParserState) {
32374429Sorion        super(token, finish);
32474429Sorion
32574429Sorion        this.source           = source;
32674429Sorion        this.lineNumber       = lineNumber;
32774429Sorion        this.ident            = ident;
32874429Sorion        this.name             = name;
32974429Sorion        this.kind             = kind;
33074429Sorion        this.parameters       = parameters;
33174429Sorion        this.firstToken       = firstToken;
33274429Sorion        this.lastToken        = lastToken;
333111183Scognet        this.namespace        = namespace;
33474429Sorion        this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state);
33574429Sorion        this.flags            = flags;
33674429Sorion        this.compileUnit      = null;
33774429Sorion        this.body             = body;
33874429Sorion        this.thisProperties   = 0;
33974429Sorion        this.rootClass        = null;
34074429Sorion        this.endParserState    = endParserState;
34174429Sorion    }
34274429Sorion
34374429Sorion    private FunctionNode(
34474429Sorion        final FunctionNode functionNode,
345170521Sariff        final long lastToken,
34674429Sorion        final Object endParserState,
34774429Sorion        final int flags,
34874429Sorion        final String name,
34974429Sorion        final Type returnType,
35074429Sorion        final CompileUnit compileUnit,
35174429Sorion        final EnumSet<CompilationState> compilationState,
35274429Sorion        final Block body,
35374429Sorion        final List<IdentNode> parameters,
35474429Sorion        final int thisProperties,
35574429Sorion        final Class<?> rootClass,
356193640Sariff        final Source source, Namespace namespace) {
35774429Sorion        super(functionNode);
35874429Sorion
35974429Sorion        this.endParserState    = endParserState;
36074429Sorion        this.lineNumber       = functionNode.lineNumber;
36174429Sorion        this.flags            = flags;
36274429Sorion        this.name             = name;
36374429Sorion        this.returnType       = returnType;
36474429Sorion        this.compileUnit      = compileUnit;
36574797Scg        this.lastToken        = lastToken;
36674429Sorion        this.compilationState = compilationState;
36774429Sorion        this.body             = body;
36874429Sorion        this.parameters       = parameters;
36974429Sorion        this.thisProperties   = thisProperties;
37074429Sorion        this.rootClass        = rootClass;
37174429Sorion        this.source           = source;
37274429Sorion        this.namespace        = namespace;
37374429Sorion
37474429Sorion        // the fields below never change - they are final and assigned in constructor
37574429Sorion        this.ident           = functionNode.ident;
37674429Sorion        this.kind            = functionNode.kind;
377193640Sariff        this.firstToken      = functionNode.firstToken;
37874429Sorion    }
37974429Sorion
38074429Sorion    @Override
38174429Sorion    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
38274429Sorion        if (visitor.enterFunctionNode(this)) {
38374429Sorion            return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
38474797Scg        }
38574429Sorion        return this;
38674429Sorion    }
38774429Sorion
38874429Sorion    /**
38974429Sorion     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
39074429Sorion     * @param visitor the visitor to apply to the nodes.
39174429Sorion     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
39274429Sorion     */
39374429Sorion    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
39474429Sorion        return Node.accept(visitor, parameters);
39574429Sorion    }
39674797Scg
39774429Sorion    /**
39874429Sorion     * Get additional callsite flags to be used specific to this function.
39974429Sorion     *
40074429Sorion     * @return callsite flags
40174429Sorion     */
40274429Sorion    public int getCallSiteFlags() {
40374429Sorion        int callsiteFlags = 0;
40474429Sorion        if (getFlag(IS_STRICT)) {
40574429Sorion            callsiteFlags |= CALLSITE_STRICT;
40674429Sorion        }
40774429Sorion
40874429Sorion        // quick check for extension callsite flags turned on by directives.
409111183Scognet        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
41074429Sorion            return callsiteFlags;
41174429Sorion        }
41274429Sorion
41374429Sorion        if (getFlag(IS_PROFILE)) {
41474429Sorion            callsiteFlags |= CALLSITE_PROFILE;
41574429Sorion        }
41674429Sorion
41774429Sorion        if (getFlag(IS_TRACE_MISSES)) {
41874429Sorion            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
41974429Sorion        }
42074429Sorion
42174429Sorion        if (getFlag(IS_TRACE_VALUES)) {
422170521Sariff            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
42374429Sorion        }
42474429Sorion
42574429Sorion        if (getFlag(IS_TRACE_ENTEREXIT)) {
42674429Sorion            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
42774429Sorion        }
42874429Sorion
42974429Sorion        return callsiteFlags;
43074429Sorion    }
43174429Sorion
43274429Sorion    /**
433193640Sariff     * Get the source for this function
43474429Sorion     * @return the source
43574429Sorion     */
43674429Sorion    public Source getSource() {
43774429Sorion        return source;
43874429Sorion    }
43974429Sorion
44074797Scg    /**
44174429Sorion     * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
44274429Sorion     * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
44374429Sorion     * a deserialized function node.
44474429Sorion     * @param source the source for the function.
44574429Sorion     * @param namespace the namespace for the function
44674429Sorion     * @return a new function node with the set source and namespace
44774429Sorion     * @throws IllegalArgumentException if the specified source or namespace is null
44874429Sorion     * @throws IllegalStateException if the function already has either a source or namespace set.
44974429Sorion     */
45074429Sorion    public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
45174429Sorion        if (source == null || namespace == null) {
45274429Sorion            throw new IllegalArgumentException();
45374429Sorion        } else if (this.source == source && this.namespace == namespace) {
454193640Sariff            return this;
45574429Sorion        } else if (this.source != null || this.namespace != null) {
45674429Sorion            throw new IllegalStateException();
45774429Sorion        }
45874429Sorion        return new FunctionNode(
45974429Sorion            this,
46074429Sorion            lastToken,
46174429Sorion            endParserState,
46274429Sorion            flags,
46374429Sorion            name,
46474429Sorion            returnType,
46574429Sorion            compileUnit,
46674429Sorion            compilationState,
46774429Sorion            body,
46874429Sorion            parameters,
46974429Sorion            thisProperties,
47074429Sorion            rootClass, source, namespace);
47174429Sorion    }
47274429Sorion
47374429Sorion    /**
47474429Sorion     * Get the unique ID for this function within the script file.
47574429Sorion     * @return the id
47674429Sorion     */
47774429Sorion    public int getId() {
47874429Sorion        return isProgram() ? -1: Token.descPosition(firstToken);
47974429Sorion    }
48074429Sorion
48174429Sorion    /**
48274429Sorion     * get source name - sourceURL or name derived from Source.
48374429Sorion     *
48474429Sorion     * @return name for the script source
48574797Scg     */
48674429Sorion    public String getSourceName() {
48774429Sorion        return getSourceName(source);
48874429Sorion    }
48974429Sorion
49074429Sorion    /**
49174429Sorion     * Static source name getter
49274429Sorion     *
49374429Sorion     * @param source the source
49474429Sorion     * @return source name
49574429Sorion     */
49674429Sorion    public static String getSourceName(final Source source) {
49774429Sorion        final String explicitURL = source.getExplicitURL();
49874429Sorion        return explicitURL != null ? explicitURL : source.getName();
49974429Sorion    }
50074797Scg
50174429Sorion    /**
50274429Sorion     * Function to parse nashorn per-function extension directive comments.
50374429Sorion     *
50474429Sorion     * @param directive nashorn extension directive string
50574429Sorion     * @return integer flag for the given directive.
50674797Scg     */
50774429Sorion    public static int getDirectiveFlag(final String directive) {
50874429Sorion        switch (directive) {
50974797Scg            case "nashorn callsite trace enterexit":
51074429Sorion                return IS_TRACE_ENTEREXIT;
51174429Sorion            case "nashorn callsite trace misses":
51274797Scg                return IS_TRACE_MISSES;
51374429Sorion            case "nashorn callsite trace objects":
51474429Sorion                return IS_TRACE_VALUES;
51574429Sorion            case "nashorn callsite profile":
51674429Sorion                return IS_PROFILE;
51774429Sorion            case "nashorn print parse":
51874797Scg                return IS_PRINT_PARSE;
51974429Sorion            case "nashorn print lower parse":
52074429Sorion                return IS_PRINT_LOWER_PARSE;
52174763Scg            case "nashorn print ast":
52274429Sorion                return IS_PRINT_AST;
52374429Sorion            case "nashorn print lower ast":
52474429Sorion                return IS_PRINT_LOWER_AST;
52574429Sorion            case "nashorn print symbols":
52674429Sorion                return IS_PRINT_SYMBOLS;
52774429Sorion            default:
52874429Sorion                // unknown/unsupported directive
52974429Sorion                return 0;
53074429Sorion        }
53174429Sorion    }
53274429Sorion
53374429Sorion    /**
53474429Sorion     * Returns the line number.
53574429Sorion     * @return the line number.
53674429Sorion     */
53774429Sorion    public int getLineNumber() {
53874429Sorion        return lineNumber;
53974763Scg    }
54074429Sorion
54174429Sorion    /**
54274429Sorion     * Get the compilation state of this function
54374429Sorion     * @return the compilation state
54474429Sorion     */
545193640Sariff    public EnumSet<CompilationState> getState() {
54674763Scg        return compilationState;
54774429Sorion    }
54874429Sorion
54974429Sorion    /**
55074429Sorion     * Check whether this FunctionNode has reached a give CompilationState.
55174429Sorion     *
55274429Sorion     * @param state the state to check for
55374429Sorion     * @return true of the node is in the given state
55474429Sorion     */
55574429Sorion    public boolean hasState(final EnumSet<CompilationState> state) {
55674429Sorion        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
55774429Sorion    }
558127218Smarcel
55974429Sorion    /**
56074429Sorion     * Add a state to the total CompilationState of this node, e.g. if
56174429Sorion     * FunctionNode has been lowered, the compiler will add
56274429Sorion     * {@code CompilationState#LOWERED} to the state vector
56374429Sorion     *
56474429Sorion     * @param lc lexical context
56574429Sorion     * @param state {@link CompilationState} to add
566193640Sariff     * @return function node or a new one if state was changed
56774429Sorion     */
56874429Sorion    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
56974429Sorion        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
57074429Sorion            return this;
57174429Sorion        }
57274429Sorion        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
57374429Sorion        newState.add(state);
57474429Sorion        return setCompilationState(lc, newState);
57574429Sorion    }
57674429Sorion
57774797Scg    /**
57874429Sorion     * Copy a compilation state from an original function to this function. Used when creating synthetic
57974797Scg     * function nodes by the splitter.
58074429Sorion     *
58174429Sorion     * @param lc lexical context
58274429Sorion     * @param original the original function node to copy compilation state from
58374429Sorion     * @return function node or a new one if state was changed
58474429Sorion     */
58574429Sorion    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
58674429Sorion        final EnumSet<CompilationState> origState = original.compilationState;
58774429Sorion        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
58874797Scg            return this;
58974429Sorion        }
59074429Sorion        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
59174429Sorion        newState.addAll(origState);
59274429Sorion        return setCompilationState(lc, newState);
59374429Sorion    }
59474429Sorion
59574429Sorion    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
59674797Scg        return Node.replaceInLexicalContext(
59774429Sorion                lc,
59874429Sorion                this,
59974429Sorion                new FunctionNode(
60074429Sorion                        this,
60174429Sorion                        lastToken,
60274429Sorion                        endParserState,
60374429Sorion                        flags,
60474429Sorion                        name,
60574429Sorion                        returnType,
60674429Sorion                        compileUnit,
60774429Sorion                        compilationState,
60874429Sorion                        body,
60974429Sorion                        parameters,
61074429Sorion                        thisProperties,
61174429Sorion                        rootClass, source, namespace));
61274429Sorion    }
61374797Scg
61474429Sorion
61574429Sorion    /**
61674429Sorion     * Create a unique name in the namespace of this FunctionNode
61774429Sorion     * @param base prefix for name
61874429Sorion     * @return base if no collision exists, otherwise a name prefix with base
61974429Sorion     */
62074429Sorion    public String uniqueName(final String base) {
62174429Sorion        return namespace.uniqueName(base);
62274429Sorion    }
62374429Sorion
62474429Sorion    @Override
62574429Sorion    public void toString(final StringBuilder sb, final boolean printTypes) {
62674429Sorion        sb.append('[').
62774429Sorion            append(returnType).
62874429Sorion            append(']').
62974429Sorion            append(' ');
63074797Scg
63174429Sorion        sb.append("function");
63274429Sorion
63374429Sorion        if (ident != null) {
63474797Scg            sb.append(' ');
63574429Sorion            ident.toString(sb, printTypes);
63674429Sorion        }
63774429Sorion
63874429Sorion        sb.append('(');
63974429Sorion
64074429Sorion        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
64174429Sorion            final IdentNode parameter = iter.next();
64274429Sorion            if (parameter.getSymbol() != null) {
64374429Sorion                sb.append('[').append(parameter.getType()).append(']').append(' ');
64474429Sorion            }
64574429Sorion            parameter.toString(sb, printTypes);
64674429Sorion            if (iter.hasNext()) {
64774429Sorion                sb.append(", ");
64874429Sorion            }
64974429Sorion        }
65074429Sorion
65174429Sorion        sb.append(')');
65274429Sorion    }
65374429Sorion
65474429Sorion    @Override
65574429Sorion    public int getFlags() {
65674429Sorion        return flags;
65774429Sorion    }
65874429Sorion
65974429Sorion    @Override
66074429Sorion    public boolean getFlag(final int flag) {
66174429Sorion        return (flags & flag) != 0;
66274429Sorion    }
66374429Sorion
66474429Sorion    @Override
66574429Sorion    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
66674429Sorion        if (this.flags == flags) {
66774429Sorion            return this;
66874429Sorion        }
66974429Sorion        return Node.replaceInLexicalContext(
67074429Sorion                lc,
67174429Sorion                this,
67274429Sorion                new FunctionNode(
67374429Sorion                        this,
67474429Sorion                        lastToken,
67574429Sorion                        endParserState,
67674429Sorion                        flags,
67774797Scg                        name,
67874429Sorion                        returnType,
67974429Sorion                        compileUnit,
68074429Sorion                        compilationState,
68174797Scg                        body,
68274429Sorion                        parameters,
68374429Sorion                        thisProperties,
68474429Sorion                        rootClass, source, namespace));
68574429Sorion    }
68674429Sorion
68774429Sorion    @Override
68874429Sorion    public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
68974429Sorion        return setFlags(lc, flags & ~flag);
69074429Sorion    }
69174429Sorion
69274429Sorion    @Override
69374429Sorion    public FunctionNode setFlag(final LexicalContext lc, final int flag) {
69474429Sorion        return setFlags(lc, flags | flag);
69574429Sorion    }
69674429Sorion
69774797Scg    /**
69874429Sorion     * Returns true if the function is the top-level program.
69974429Sorion     * @return True if this function node represents the top-level program.
70074797Scg     */
70174429Sorion    public boolean isProgram() {
70274429Sorion        return getFlag(IS_PROGRAM);
70374797Scg    }
70474429Sorion
70574429Sorion    /**
70674429Sorion     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
70774429Sorion     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
70874429Sorion     */
70974429Sorion    public boolean canBeDeoptimized() {
71074429Sorion        return getFlag(IS_DEOPTIMIZABLE);
71174429Sorion    }
71274429Sorion
71374429Sorion    /**
71474429Sorion     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
715142890Simp     *
71674429Sorion     * @return true if {@code eval} is called.
71774429Sorion     */
71874429Sorion    public boolean hasEval() {
71974429Sorion        return getFlag(HAS_EVAL);
72074429Sorion    }
72174429Sorion
72274429Sorion    /**
72374429Sorion     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
72474429Sorion     *
72574429Sorion     * @return true if a nested function calls {@code eval}.
72682835Sorion     */
72774429Sorion    public boolean hasNestedEval() {
728170873Sariff        return getFlag(HAS_NESTED_EVAL);
72974429Sorion    }
73074429Sorion
731254263Sscottl    /**
73274429Sorion     * Get the first token for this function
73374429Sorion     * @return the first token
73474429Sorion     */
73574429Sorion    public long getFirstToken() {
73674429Sorion        return firstToken;
73774429Sorion    }
73874429Sorion
73974797Scg    /**
74074429Sorion     * Check whether this function has nested function declarations
74174429Sorion     * @return true if nested function declarations exist
74274797Scg     */
74374429Sorion    public boolean hasDeclaredFunctions() {
74474429Sorion        return getFlag(HAS_FUNCTION_DECLARATIONS);
74574429Sorion    }
74674429Sorion
74774429Sorion    /**
74874429Sorion     * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to
74974429Sorion     * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object
75074429Sorion     * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
75174429Sorion     * for split functions to make sure symbols slots are the same in the main and split methods.
75274429Sorion     *
75374429Sorion     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
75474429Sorion     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
75574429Sorion     *
75674429Sorion     * @return true if the function's generated Java method needs a {@code callee} parameter.
75774429Sorion     */
75874429Sorion    public boolean needsCallee() {
75974429Sorion        // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
76074429Sorion        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
76174429Sorion    }
76274429Sorion
76374429Sorion    /**
76474429Sorion     * Return {@code true} if this function makes use of the {@code this} object.
76574797Scg     *
766166917Sariff     * @return true if function uses {@code this} object
76774429Sorion     */
76874429Sorion    public boolean usesThis() {
76974429Sorion        return getFlag(USES_THIS);
77074429Sorion    }
77184771Sorion
772166904Snetchild
773166904Snetchild    /**
77474429Sorion     * Return true if function contains an apply to call transform
77574429Sorion     * @return true if this function has transformed apply to call
77674429Sorion     */
77784771Sorion    public boolean hasOptimisticApplyToCall() {
77874797Scg        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
779117126Sscottl    }
780117126Sscottl
78174429Sorion    /**
78274429Sorion     * Get the identifier for this function, this is its symbol.
78374429Sorion     * @return the identifier as an IdentityNode
78474429Sorion     */
78574429Sorion    public IdentNode getIdent() {
78674429Sorion        return ident;
78774429Sorion    }
78874429Sorion
78974429Sorion    /**
79074429Sorion     * Get the function body
79174429Sorion     * @return the function body
79274429Sorion     */
79374797Scg    public Block getBody() {
79474429Sorion        return body;
79574429Sorion    }
79674429Sorion
79774429Sorion    /**
79874429Sorion     * Reset the function body
79974429Sorion     * @param lc lexical context
80074429Sorion     * @param body new body
80174797Scg     * @return new function node if body changed, same if not
80274429Sorion     */
80374429Sorion    public FunctionNode setBody(final LexicalContext lc, final Block body) {
80474429Sorion        if (this.body == body) {
80574429Sorion            return this;
80682835Sorion        }
80782835Sorion        return Node.replaceInLexicalContext(
80882835Sorion                lc,
80982835Sorion                this,
81082835Sorion                new FunctionNode(
81182835Sorion                        this,
81282835Sorion                        lastToken,
81382835Sorion                        endParserState,
81482835Sorion                        flags |
81582835Sorion                            (body.needsScope() ?
81682835Sorion                                    FunctionNode.HAS_SCOPE_BLOCK :
81782835Sorion                                    0),
81882835Sorion                        name,
81982835Sorion                        returnType,
82082835Sorion                        compileUnit,
82174429Sorion                        compilationState,
82274429Sorion                        body,
82374429Sorion                        parameters,
82482835Sorion                        thisProperties,
82574429Sorion                        rootClass, source, namespace));
82674797Scg    }
82774429Sorion
82874429Sorion    /**
82974429Sorion     * Does this function's method needs to be variable arity (gather all script-declared parameters in a final
83074429Sorion     * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply
83174429Sorion     * declare too many arguments for JVM to handle with fixed arity will need to be variable arity.
83274429Sorion     * @return true if the Java method in the generated code that implements this function needs to be variable arity.
83374429Sorion     * @see #needsArguments()
83474429Sorion     * @see LinkerCallSite#ARGLIMIT
83574797Scg     */
83674429Sorion    public boolean isVarArg() {
83774429Sorion        return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT;
83874429Sorion    }
83974429Sorion
84074429Sorion    /**
84174429Sorion     * Was this function declared in a dynamic context, i.e. in a with or eval style
84274429Sorion     * chain
84374429Sorion     * @return true if in dynamic context
84474429Sorion     */
84574429Sorion    public boolean inDynamicContext() {
84674429Sorion        return getFlag(IN_DYNAMIC_CONTEXT);
84774429Sorion    }
84874429Sorion
84974429Sorion    /**
85074429Sorion     * Check whether a function would need dynamic scope, which is does if it has
85174797Scg     * evals and isn't strict.
85274429Sorion     * @return true if dynamic scope is needed
85374429Sorion     */
85474797Scg    public boolean needsDynamicScope() {
85574429Sorion        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
85674429Sorion        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
85774429Sorion        // isolated scope).
85874429Sorion        return hasEval() && !isStrict();
85974429Sorion    }
86074429Sorion
86174429Sorion    /**
86274429Sorion     * Flag this function as declared in a dynamic context
86374429Sorion     * @param lc lexical context
86474429Sorion     * @return new function node, or same if unmodified
86574429Sorion     */
86674429Sorion    public FunctionNode setInDynamicContext(final LexicalContext lc) {
86774429Sorion        return setFlag(lc, IN_DYNAMIC_CONTEXT);
86874429Sorion    }
86974429Sorion
87074429Sorion    /**
87174429Sorion     * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
87274429Sorion     * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
87374429Sorion     * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
87474429Sorion     * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an
87574429Sorion     * "arguments" object, because it does not have local variables; rather the Global object will have an explicit
87674429Sorion     * "arguments" property that provides command-line arguments for the script.
87774429Sorion     * @return true if this function needs an arguments object.
87874429Sorion     */
87974429Sorion    public boolean needsArguments() {
88074429Sorion        // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since
881126695Smatk        // for top-level script, "arguments" is picked up from Context by Global.init() instead.
882126695Smatk        return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram();
88374429Sorion    }
88474429Sorion
88574429Sorion    /**
88674429Sorion     * Returns true if this function needs access to its parent scope. Functions referencing variables outside their
88774429Sorion     * scope (including global variables), as well as functions that call eval or have a with block, or have nested
88874429Sorion     * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a
88974797Scg     * parent scope since they might be used from within eval, and eval will need an externally passed scope.
89074797Scg     * @return true if the function needs parent scope.
89174429Sorion     */
89274797Scg    public boolean needsParentScope() {
89374429Sorion        return getFlag(NEEDS_PARENT_SCOPE);
89474797Scg    }
89574429Sorion
89674429Sorion    /**
89774429Sorion     * Set the number of properties assigned to the this object in this function.
89874429Sorion     * @param lc the current lexical context.
89974429Sorion     * @param thisProperties number of properties
90074429Sorion     * @return a potentially modified function node
90174429Sorion     */
90274429Sorion    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
90374429Sorion        if (this.thisProperties == thisProperties) {
90474429Sorion            return this;
90574429Sorion        }
90674429Sorion        return Node.replaceInLexicalContext(
90774429Sorion                lc,
90874429Sorion                this,
90974429Sorion                new FunctionNode(
91074429Sorion                        this,
91174429Sorion                        lastToken,
91274429Sorion                        endParserState,
91374429Sorion                        flags,
91474429Sorion                        name,
91574429Sorion                        returnType,
91674429Sorion                        compileUnit,
91774429Sorion                        compilationState,
91874429Sorion                        body,
91974429Sorion                        parameters,
92074429Sorion                        thisProperties,
92174429Sorion                        rootClass, source, namespace));
92274429Sorion    }
92374429Sorion
92474429Sorion    /**
92574429Sorion     * Get the number of properties assigned to the this object in this function.
92674429Sorion     * @return number of properties
92774429Sorion     */
92874429Sorion    public int getThisProperties() {
92974429Sorion        return thisProperties;
93074429Sorion    }
93174429Sorion
93274429Sorion    /**
93374429Sorion     * Returns true if any of the blocks in this function create their own scope.
93474429Sorion     * @return true if any of the blocks in this function create their own scope.
93574429Sorion     */
93674429Sorion    public boolean hasScopeBlock() {
93774429Sorion        return getFlag(HAS_SCOPE_BLOCK);
93874429Sorion    }
93974429Sorion
94074429Sorion    /**
94182180Scg     * Return the kind of this function
94274429Sorion     * @see FunctionNode.Kind
94374429Sorion     * @return the kind
94485443Sjhb     */
945132236Stanimura    public Kind getKind() {
94685443Sjhb        return kind;
947    }
948
949    /**
950     * Return the last token for this function's code
951     * @return last token
952     */
953    public long getLastToken() {
954        return lastToken;
955    }
956
957    /**
958     * Returns the end parser state for this function.
959     * @return the end parser state for this function.
960     */
961    public Object getEndParserState() {
962        return endParserState;
963    }
964
965    /**
966     * Get the name of this function
967     * @return the name
968     */
969    public String getName() {
970        return name;
971    }
972
973    /**
974     * Set the internal name for this function
975     * @param lc    lexical context
976     * @param name new name
977     * @return new function node if changed, otherwise the same
978     */
979    public FunctionNode setName(final LexicalContext lc, final String name) {
980        if (this.name.equals(name)) {
981            return this;
982        }
983        return Node.replaceInLexicalContext(
984                lc,
985                this,
986                new FunctionNode(
987                        this,
988                        lastToken,
989                        endParserState,
990                        flags,
991                        name,
992                        returnType,
993                        compileUnit,
994                        compilationState,
995                        body,
996                        parameters,
997                        thisProperties,
998                        rootClass, source, namespace));
999    }
1000
1001    /**
1002     * Check if this function should have all its variables in its own scope. Split sub-functions, and
1003     * functions having with and/or eval blocks are such.
1004     *
1005     * @return true if all variables should be in scope
1006     */
1007    public boolean allVarsInScope() {
1008        return getFlag(HAS_ALL_VARS_IN_SCOPE);
1009    }
1010
1011    /**
1012     * Checks if this function is split into several smaller fragments.
1013     *
1014     * @return true if this function is split into several smaller fragments.
1015     */
1016    public boolean isSplit() {
1017        return getFlag(IS_SPLIT);
1018    }
1019
1020    /**
1021     * Get the parameters to this function
1022     * @return a list of IdentNodes which represent the function parameters, in order
1023     */
1024    public List<IdentNode> getParameters() {
1025        return Collections.unmodifiableList(parameters);
1026    }
1027
1028    /**
1029     * Returns the identifier for a named parameter at the specified position in this function's parameter list.
1030     * @param index the parameter's position.
1031     * @return the identifier for the requested named parameter.
1032     * @throws IndexOutOfBoundsException if the index is invalid.
1033     */
1034    public IdentNode getParameter(final int index) {
1035        return parameters.get(index);
1036    }
1037
1038    /**
1039     * Reset the compile unit used to compile this function
1040     * @see Compiler
1041     * @param  lc lexical context
1042     * @param  parameters the compile unit
1043     * @return function node or a new one if state was changed
1044     */
1045    public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) {
1046        if (this.parameters == parameters) {
1047            return this;
1048        }
1049        return Node.replaceInLexicalContext(
1050                lc,
1051                this,
1052                new FunctionNode(
1053                        this,
1054                        lastToken,
1055                        endParserState,
1056                        flags,
1057                        name,
1058                        returnType,
1059                        compileUnit,
1060                        compilationState,
1061                        body,
1062                        parameters,
1063                        thisProperties,
1064                        rootClass, source, namespace));
1065    }
1066
1067    /**
1068     * Check if this function is created as a function declaration (as opposed to function expression)
1069     * @return true if function is declared.
1070     */
1071    public boolean isDeclared() {
1072        return getFlag(IS_DECLARED);
1073    }
1074
1075    /**
1076     * Check if this function is anonymous
1077     * @return true if function is anonymous
1078     */
1079    public boolean isAnonymous() {
1080        return getFlag(IS_ANONYMOUS);
1081    }
1082
1083    /**
1084     * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
1085     * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
1086     * scope (since they're bound to the symbol with their name in their enclosing scope).
1087     * @return true if this function node is a named function expression that uses the symbol for itself.
1088     */
1089    public boolean usesSelfSymbol() {
1090        return getFlag(USES_SELF_SYMBOL);
1091    }
1092
1093    /**
1094     * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
1095     * anonymous function expression, and it isn't a program).
1096     * @return true if this is a named function expression
1097     */
1098    public boolean isNamedFunctionExpression() {
1099        return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
1100    }
1101
1102    @Override
1103    public Type getType() {
1104        return FUNCTION_TYPE;
1105    }
1106
1107    @Override
1108    public Type getWidestOperationType() {
1109        return FUNCTION_TYPE;
1110    }
1111
1112    /**
1113     * Get the return type for this function. Return types can be specialized
1114     * if the compiler knows them, but parameters cannot, as they need to go through
1115     * appropriate object conversion
1116     *
1117     * @return the return type
1118     */
1119    public Type getReturnType() {
1120        return returnType;
1121    }
1122
1123    /**
1124     * Set the function return type
1125     * @param lc lexical context
1126     * @param returnType new return type
1127     * @return function node or a new one if state was changed
1128     */
1129    public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
1130        //we never bother with object types narrower than objects, that will lead to byte code verification errors
1131        //as for instance even if we know we are returning a string from a method, the code generator will always
1132        //treat it as an object, at least for now
1133        final Type type = returnType.isObject() ? Type.OBJECT : returnType;
1134        if (this.returnType == type) {
1135            return this;
1136        }
1137        return Node.replaceInLexicalContext(
1138            lc,
1139            this,
1140            new FunctionNode(
1141                this,
1142                lastToken,
1143                endParserState,
1144                flags,
1145                name,
1146                type,
1147                compileUnit,
1148                compilationState,
1149                body,
1150                parameters,
1151                thisProperties,
1152                rootClass, source, namespace
1153                ));
1154   }
1155
1156    /**
1157     * Check if the function is generated in strict mode
1158     * @return true if strict mode enabled for function
1159     */
1160    public boolean isStrict() {
1161        return getFlag(IS_STRICT);
1162    }
1163
1164    /**
1165     * Get the compile unit used to compile this function
1166     * @see Compiler
1167     * @return the compile unit
1168     */
1169    @Override
1170    public CompileUnit getCompileUnit() {
1171        return compileUnit;
1172    }
1173
1174    /**
1175     * Reset the compile unit used to compile this function
1176     * @see Compiler
1177     * @param lc lexical context
1178     * @param compileUnit the compile unit
1179     * @return function node or a new one if state was changed
1180     */
1181    public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1182        if (this.compileUnit == compileUnit) {
1183            return this;
1184        }
1185        return Node.replaceInLexicalContext(
1186                lc,
1187                this,
1188                new FunctionNode(
1189                        this,
1190                        lastToken,
1191                        endParserState,
1192                        flags,
1193                        name,
1194                        returnType,
1195                        compileUnit,
1196                        compilationState,
1197                        body,
1198                        parameters,
1199                        thisProperties,
1200                        rootClass, source, namespace));
1201    }
1202
1203    /**
1204     * Create a temporary variable to the current frame.
1205     *
1206     * @param block that needs the temporary
1207     * @param type  Strong type of symbol.
1208     * @param node  Primary node to use symbol.
1209     *
1210     * @return Symbol used.
1211     */
1212
1213    /**
1214     * Get the symbol for a compiler constant, or null if not available (yet)
1215     * @param cc compiler constant
1216     * @return symbol for compiler constant, or null if not defined yet (for example in Lower)
1217     */
1218    public Symbol compilerConstant(final CompilerConstants cc) {
1219        return body.getExistingSymbol(cc.symbolName());
1220    }
1221
1222    /**
1223     * Get the root class that this function node compiles to
1224     * @return root class
1225     */
1226    public Class<?> getRootClass() {
1227        return rootClass;
1228    }
1229
1230    /**
1231     * Reset the root class that this function is compiled to
1232     * @see Compiler
1233     * @param lc lexical context
1234     * @param rootClass root class
1235     * @return function node or a new one if state was changed
1236     */
1237    public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
1238        if (this.rootClass == rootClass) {
1239            return this;
1240        }
1241        return Node.replaceInLexicalContext(
1242                lc,
1243                this,
1244                new FunctionNode(
1245                        this,
1246                        lastToken,
1247                        endParserState,
1248                        flags,
1249                        name,
1250                        returnType,
1251                        compileUnit,
1252                        compilationState,
1253                        body,
1254                        parameters,
1255                        thisProperties,
1256                        rootClass, source, namespace));
1257    }
1258}
1259