FunctionNode.java revision 1152:5f6a840fc19d
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.ir;
27
28import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
29import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
30import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
31import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
32import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
33import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
34
35import java.util.Collections;
36import java.util.EnumSet;
37import java.util.Iterator;
38import java.util.List;
39import jdk.nashorn.internal.AssertsEnabled;
40import jdk.nashorn.internal.codegen.CompileUnit;
41import jdk.nashorn.internal.codegen.Compiler;
42import jdk.nashorn.internal.codegen.CompilerConstants;
43import jdk.nashorn.internal.codegen.Namespace;
44import jdk.nashorn.internal.codegen.types.Type;
45import jdk.nashorn.internal.ir.annotations.Ignore;
46import jdk.nashorn.internal.ir.annotations.Immutable;
47import jdk.nashorn.internal.ir.visitor.NodeVisitor;
48import jdk.nashorn.internal.parser.Token;
49import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
50import jdk.nashorn.internal.runtime.ScriptFunction;
51import jdk.nashorn.internal.runtime.Source;
52import jdk.nashorn.internal.runtime.UserAccessorProperty;
53import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
54
55/**
56 * IR representation for function (or script.)
57 */
58@Immutable
59public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
60    private static final long serialVersionUID = 1L;
61
62    /** Type used for all FunctionNodes */
63    public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
64
65    /** Function kinds */
66    public enum Kind {
67        /** a normal function - nothing special */
68        NORMAL,
69        /** a script function */
70        SCRIPT,
71        /** a getter, @see {@link UserAccessorProperty} */
72        GETTER,
73        /** a setter, @see {@link UserAccessorProperty} */
74        SETTER
75    }
76
77    /** Compilation states available */
78    public enum CompilationState {
79        /** compiler is ready */
80        INITIALIZED,
81        /** method has been parsed */
82        PARSED,
83        /** method has been parsed */
84        PARSE_ERROR,
85        /** constant folding pass */
86        CONSTANT_FOLDED,
87        /** method has been lowered */
88        LOWERED,
89        /** program points have been assigned to unique locations */
90        PROGRAM_POINTS_ASSIGNED,
91        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
92        BUILTINS_TRANSFORMED,
93        /** method has been split */
94        SPLIT,
95        /** method has had symbols assigned */
96        SYMBOLS_ASSIGNED,
97        /** computed scope depths for symbols */
98        SCOPE_DEPTHS_COMPUTED,
99        /** method has had types calculated*/
100        OPTIMISTIC_TYPES_ASSIGNED,
101        /** method has had types calculated */
102        LOCAL_VARIABLE_TYPES_CALCULATED,
103        /** compile units reused (optional) */
104        COMPILE_UNITS_REUSED,
105        /** method has been emitted to bytecode */
106        BYTECODE_GENERATED,
107        /** method has been installed */
108        BYTECODE_INSTALLED
109    }
110
111    /** Source of entity. */
112    private transient final Source source;
113
114    /**
115     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
116     * to skip parsing inner functions.
117     */
118    private final Object endParserState;
119
120    /** External function identifier. */
121    @Ignore
122    private final IdentNode ident;
123
124    /** The body of the function node */
125    private final Block body;
126
127    /** Internal function name. */
128    private final String name;
129
130    /** Compilation unit. */
131    private final CompileUnit compileUnit;
132
133    /** Function kind. */
134    private final Kind kind;
135
136    /** List of parameters. */
137    private final List<IdentNode> parameters;
138
139    /** First token of function. **/
140    private final long firstToken;
141
142    /** Last token of function. **/
143    private final long lastToken;
144
145    /** Method's namespace. */
146    private transient final Namespace namespace;
147
148    /** Current compilation state */
149    @Ignore
150    private final EnumSet<CompilationState> compilationState;
151
152    /** Number of properties of "this" object assigned in this function */
153    @Ignore
154    private final int thisProperties;
155
156    /** Function flags. */
157    private final int flags;
158
159    /** Line number of function start */
160    private final int lineNumber;
161
162    /** Root class for function */
163    private final Class<?> rootClass;
164
165    /** Is anonymous function flag. */
166    public static final int IS_ANONYMOUS                = 1 << 0;
167
168    /** Is the function created in a function declaration (as opposed to a function expression) */
169    public static final int IS_DECLARED                 = 1 << 1;
170
171    /** is this a strict mode function? */
172    public static final int IS_STRICT                   = 1 << 2;
173
174    /** Does the function use the "arguments" identifier ? */
175    public static final int USES_ARGUMENTS              = 1 << 3;
176
177    /** Has this function been split because it was too large? */
178    public static final int IS_SPLIT                    = 1 << 4;
179
180    /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
181     * introduce new variables into this function's scope too.*/
182    public static final int HAS_EVAL                    = 1 << 5;
183
184    /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
185    public static final int HAS_NESTED_EVAL             = 1 << 6;
186
187    /** Does this function have any blocks that create a scope? This is used to determine if the function needs to
188     * have a local variable slot for the scope symbol. */
189    public static final int HAS_SCOPE_BLOCK             = 1 << 7;
190
191    /**
192     * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
193     * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that
194     * defining a local variable named "arguments" still requires construction of the Arguments object (see
195     * ECMAScript 5.1 Chapter 10.5).
196     * @see #needsArguments()
197     */
198    public static final int DEFINES_ARGUMENTS           = 1 << 8;
199
200    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
201    public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
202
203    /** Does this function have nested declarations? */
204    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
205
206    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
207    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
208
209    /** Are we vararg, but do we just pass the arguments along to apply or call */
210    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
211
212    /**
213     * Is this function the top-level program?
214     */
215    public static final int IS_PROGRAM = 1 << 13;
216
217    /**
218     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
219     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
220     * use the symbol in their parent scope instead when they reference themselves by name.
221     */
222    public static final int USES_SELF_SYMBOL = 1 << 14;
223
224    /** Does this function use the "this" keyword? */
225    public static final int USES_THIS = 1 << 15;
226
227    /** Is this declared in a dynamic context */
228    public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
229
230    /**
231     * The following flags are derived from directive comments within this function.
232     * Note that even IS_STRICT is one such flag but that requires special handling.
233     */
234
235    /** parser, print parse tree */
236    public static final int IS_PRINT_PARSE       = 1 << 17;
237    /** parser, print lower parse tree */
238    public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
239    /** parser, print AST */
240    public static final int IS_PRINT_AST         = 1 << 19;
241    /** parser, print lower AST */
242    public static final int IS_PRINT_LOWER_AST   = 1 << 20;
243    /** parser, print symbols */
244    public static final int IS_PRINT_SYMBOLS     = 1 << 21;
245
246    // callsite tracing, profiling within this function
247    /** profile callsites in this function? */
248    public static final int IS_PROFILE         = 1 << 22;
249
250    /** trace callsite enterexit in this function? */
251    public static final int IS_TRACE_ENTEREXIT = 1 << 23;
252
253    /** trace callsite misses in this function? */
254    public static final int IS_TRACE_MISSES    = 1 << 24;
255
256    /** trace callsite values in this function? */
257    public static final int IS_TRACE_VALUES    = 1 << 25;
258
259    /**
260     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
261     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
262     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
263     * will, however, cache the value of this flag.
264     */
265    public static final int NEEDS_CALLEE       = 1 << 26;
266
267    /** extension callsite flags mask */
268    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
269        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
270        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
271        IS_TRACE_MISSES | IS_TRACE_VALUES;
272
273    /** Does this function or any nested functions contain an eval? */
274    private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
275
276    /** Does this function need to store all its variables in scope? */
277    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
278
279    /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
280    private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
281
282    /** 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. */
283    public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
284
285    /** What is the return type of this function? */
286    private Type returnType = Type.UNKNOWN;
287
288    /**
289     * Constructor
290     *
291     * @param source     the source
292     * @param lineNumber line number
293     * @param token      token
294     * @param finish     finish
295     * @param firstToken first token of the function node (including the function declaration)
296     * @param lastToken  lastToken
297     * @param namespace  the namespace
298     * @param ident      the identifier
299     * @param name       the name of the function
300     * @param parameters parameter list
301     * @param kind       kind of function as in {@link FunctionNode.Kind}
302     * @param flags      initial flags
303     * @param body       body of the function
304     * @param state      The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR}
305     * @param endParserState The parser state at the end of the parsing.
306     */
307    public FunctionNode(
308        final Source source,
309        final int lineNumber,
310        final long token,
311        final int finish,
312        final long firstToken,
313        final long lastToken,
314        final Namespace namespace,
315        final IdentNode ident,
316        final String name,
317        final List<IdentNode> parameters,
318        final FunctionNode.Kind kind,
319        final int flags,
320        final Block body,
321        final CompilationState state,
322        final Object endParserState) {
323        super(token, finish);
324
325        this.source           = source;
326        this.lineNumber       = lineNumber;
327        this.ident            = ident;
328        this.name             = name;
329        this.kind             = kind;
330        this.parameters       = parameters;
331        this.firstToken       = firstToken;
332        this.lastToken        = lastToken;
333        this.namespace        = namespace;
334        this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state);
335        this.flags            = flags;
336        this.compileUnit      = null;
337        this.body             = body;
338        this.thisProperties   = 0;
339        this.rootClass        = null;
340        this.endParserState    = endParserState;
341    }
342
343    private FunctionNode(
344        final FunctionNode functionNode,
345        final long lastToken,
346        final Object endParserState,
347        final int flags,
348        final String name,
349        final Type returnType,
350        final CompileUnit compileUnit,
351        final EnumSet<CompilationState> compilationState,
352        final Block body,
353        final List<IdentNode> parameters,
354        final int thisProperties,
355        final Class<?> rootClass,
356        final Source source, Namespace namespace) {
357        super(functionNode);
358
359        this.endParserState    = endParserState;
360        this.lineNumber       = functionNode.lineNumber;
361        this.flags            = flags;
362        this.name             = name;
363        this.returnType       = returnType;
364        this.compileUnit      = compileUnit;
365        this.lastToken        = lastToken;
366        this.compilationState = compilationState;
367        this.body             = body;
368        this.parameters       = parameters;
369        this.thisProperties   = thisProperties;
370        this.rootClass        = rootClass;
371        this.source           = source;
372        this.namespace        = namespace;
373
374        // the fields below never change - they are final and assigned in constructor
375        this.ident           = functionNode.ident;
376        this.kind            = functionNode.kind;
377        this.firstToken      = functionNode.firstToken;
378    }
379
380    @Override
381    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
382        if (visitor.enterFunctionNode(this)) {
383            return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
384        }
385        return this;
386    }
387
388    /**
389     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
390     * @param visitor the visitor to apply to the nodes.
391     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
392     */
393    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
394        return Node.accept(visitor, parameters);
395    }
396
397    /**
398     * Get additional callsite flags to be used specific to this function.
399     *
400     * @return callsite flags
401     */
402    public int getCallSiteFlags() {
403        int callsiteFlags = 0;
404        if (getFlag(IS_STRICT)) {
405            callsiteFlags |= CALLSITE_STRICT;
406        }
407
408        // quick check for extension callsite flags turned on by directives.
409        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
410            return callsiteFlags;
411        }
412
413        if (getFlag(IS_PROFILE)) {
414            callsiteFlags |= CALLSITE_PROFILE;
415        }
416
417        if (getFlag(IS_TRACE_MISSES)) {
418            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
419        }
420
421        if (getFlag(IS_TRACE_VALUES)) {
422            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
423        }
424
425        if (getFlag(IS_TRACE_ENTEREXIT)) {
426            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
427        }
428
429        return callsiteFlags;
430    }
431
432    /**
433     * Get the source for this function
434     * @return the source
435     */
436    public Source getSource() {
437        return source;
438    }
439
440    /**
441     * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
442     * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
443     * a deserialized function node.
444     * @param source the source for the function.
445     * @param namespace the namespace for the function
446     * @return a new function node with the set source and namespace
447     * @throws IllegalArgumentException if the specified source or namespace is null
448     * @throws IllegalStateException if the function already has either a source or namespace set.
449     */
450    public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
451        if (source == null || namespace == null) {
452            throw new IllegalArgumentException();
453        } else if (this.source == source && this.namespace == namespace) {
454            return this;
455        } else if (this.source != null || this.namespace != null) {
456            throw new IllegalStateException();
457        }
458        return new FunctionNode(
459            this,
460            lastToken,
461            endParserState,
462            flags,
463            name,
464            returnType,
465            compileUnit,
466            compilationState,
467            body,
468            parameters,
469            thisProperties,
470            rootClass, source, namespace);
471    }
472
473    /**
474     * Get the unique ID for this function within the script file.
475     * @return the id
476     */
477    public int getId() {
478        return isProgram() ? -1: Token.descPosition(firstToken);
479    }
480
481    /**
482     * get source name - sourceURL or name derived from Source.
483     *
484     * @return name for the script source
485     */
486    public String getSourceName() {
487        return getSourceName(source);
488    }
489
490    /**
491     * Static source name getter
492     *
493     * @param source the source
494     * @return source name
495     */
496    public static String getSourceName(final Source source) {
497        final String explicitURL = source.getExplicitURL();
498        return explicitURL != null ? explicitURL : source.getName();
499    }
500
501    /**
502     * Function to parse nashorn per-function extension directive comments.
503     *
504     * @param directive nashorn extension directive string
505     * @return integer flag for the given directive.
506     */
507    public static int getDirectiveFlag(final String directive) {
508        switch (directive) {
509            case "nashorn callsite trace enterexit":
510                return IS_TRACE_ENTEREXIT;
511            case "nashorn callsite trace misses":
512                return IS_TRACE_MISSES;
513            case "nashorn callsite trace objects":
514                return IS_TRACE_VALUES;
515            case "nashorn callsite profile":
516                return IS_PROFILE;
517            case "nashorn print parse":
518                return IS_PRINT_PARSE;
519            case "nashorn print lower parse":
520                return IS_PRINT_LOWER_PARSE;
521            case "nashorn print ast":
522                return IS_PRINT_AST;
523            case "nashorn print lower ast":
524                return IS_PRINT_LOWER_AST;
525            case "nashorn print symbols":
526                return IS_PRINT_SYMBOLS;
527            default:
528                // unknown/unsupported directive
529                return 0;
530        }
531    }
532
533    /**
534     * Returns the line number.
535     * @return the line number.
536     */
537    public int getLineNumber() {
538        return lineNumber;
539    }
540
541    /**
542     * Get the compilation state of this function
543     * @return the compilation state
544     */
545    public EnumSet<CompilationState> getState() {
546        return compilationState;
547    }
548
549    /**
550     * Check whether this FunctionNode has reached a give CompilationState.
551     *
552     * @param state the state to check for
553     * @return true of the node is in the given state
554     */
555    public boolean hasState(final EnumSet<CompilationState> state) {
556        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
557    }
558
559    /**
560     * Add a state to the total CompilationState of this node, e.g. if
561     * FunctionNode has been lowered, the compiler will add
562     * {@code CompilationState#LOWERED} to the state vector
563     *
564     * @param lc lexical context
565     * @param state {@link CompilationState} to add
566     * @return function node or a new one if state was changed
567     */
568    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
569        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
570            return this;
571        }
572        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
573        newState.add(state);
574        return setCompilationState(lc, newState);
575    }
576
577    /**
578     * Copy a compilation state from an original function to this function. Used when creating synthetic
579     * function nodes by the splitter.
580     *
581     * @param lc lexical context
582     * @param original the original function node to copy compilation state from
583     * @return function node or a new one if state was changed
584     */
585    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
586        final EnumSet<CompilationState> origState = original.compilationState;
587        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
588            return this;
589        }
590        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
591        newState.addAll(origState);
592        return setCompilationState(lc, newState);
593    }
594
595    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
596        return Node.replaceInLexicalContext(
597                lc,
598                this,
599                new FunctionNode(
600                        this,
601                        lastToken,
602                        endParserState,
603                        flags,
604                        name,
605                        returnType,
606                        compileUnit,
607                        compilationState,
608                        body,
609                        parameters,
610                        thisProperties,
611                        rootClass, source, namespace));
612    }
613
614
615    /**
616     * Create a unique name in the namespace of this FunctionNode
617     * @param base prefix for name
618     * @return base if no collision exists, otherwise a name prefix with base
619     */
620    public String uniqueName(final String base) {
621        return namespace.uniqueName(base);
622    }
623
624    @Override
625    public void toString(final StringBuilder sb, final boolean printTypes) {
626        sb.append('[').
627            append(returnType).
628            append(']').
629            append(' ');
630
631        sb.append("function");
632
633        if (ident != null) {
634            sb.append(' ');
635            ident.toString(sb, printTypes);
636        }
637
638        sb.append('(');
639
640        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
641            final IdentNode parameter = iter.next();
642            if (parameter.getSymbol() != null) {
643                sb.append('[').append(parameter.getType()).append(']').append(' ');
644            }
645            parameter.toString(sb, printTypes);
646            if (iter.hasNext()) {
647                sb.append(", ");
648            }
649        }
650
651        sb.append(')');
652    }
653
654    @Override
655    public int getFlags() {
656        return flags;
657    }
658
659    @Override
660    public boolean getFlag(final int flag) {
661        return (flags & flag) != 0;
662    }
663
664    @Override
665    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
666        if (this.flags == flags) {
667            return this;
668        }
669        return Node.replaceInLexicalContext(
670                lc,
671                this,
672                new FunctionNode(
673                        this,
674                        lastToken,
675                        endParserState,
676                        flags,
677                        name,
678                        returnType,
679                        compileUnit,
680                        compilationState,
681                        body,
682                        parameters,
683                        thisProperties,
684                        rootClass, source, namespace));
685    }
686
687    @Override
688    public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
689        return setFlags(lc, flags & ~flag);
690    }
691
692    @Override
693    public FunctionNode setFlag(final LexicalContext lc, final int flag) {
694        return setFlags(lc, flags | flag);
695    }
696
697    /**
698     * Returns true if the function is the top-level program.
699     * @return True if this function node represents the top-level program.
700     */
701    public boolean isProgram() {
702        return getFlag(IS_PROGRAM);
703    }
704
705    /**
706     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
707     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
708     */
709    public boolean canBeDeoptimized() {
710        return getFlag(IS_DEOPTIMIZABLE);
711    }
712
713    /**
714     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
715     *
716     * @return true if {@code eval} is called.
717     */
718    public boolean hasEval() {
719        return getFlag(HAS_EVAL);
720    }
721
722    /**
723     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
724     *
725     * @return true if a nested function calls {@code eval}.
726     */
727    public boolean hasNestedEval() {
728        return getFlag(HAS_NESTED_EVAL);
729    }
730
731    /**
732     * Get the first token for this function
733     * @return the first token
734     */
735    public long getFirstToken() {
736        return firstToken;
737    }
738
739    /**
740     * Check whether this function has nested function declarations
741     * @return true if nested function declarations exist
742     */
743    public boolean hasDeclaredFunctions() {
744        return getFlag(HAS_FUNCTION_DECLARATIONS);
745    }
746
747    /**
748     * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to
749     * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object
750     * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
751     * for split functions to make sure symbols slots are the same in the main and split methods.
752     *
753     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
754     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
755     *
756     * @return true if the function's generated Java method needs a {@code callee} parameter.
757     */
758    public boolean needsCallee() {
759        // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
760        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
761    }
762
763    /**
764     * Return {@code true} if this function makes use of the {@code this} object.
765     *
766     * @return true if function uses {@code this} object
767     */
768    public boolean usesThis() {
769        return getFlag(USES_THIS);
770    }
771
772
773    /**
774     * Return true if function contains an apply to call transform
775     * @return true if this function has transformed apply to call
776     */
777    public boolean hasOptimisticApplyToCall() {
778        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
779    }
780
781    /**
782     * Get the identifier for this function, this is its symbol.
783     * @return the identifier as an IdentityNode
784     */
785    public IdentNode getIdent() {
786        return ident;
787    }
788
789    /**
790     * Get the function body
791     * @return the function body
792     */
793    public Block getBody() {
794        return body;
795    }
796
797    /**
798     * Reset the function body
799     * @param lc lexical context
800     * @param body new body
801     * @return new function node if body changed, same if not
802     */
803    public FunctionNode setBody(final LexicalContext lc, final Block body) {
804        if (this.body == body) {
805            return this;
806        }
807        return Node.replaceInLexicalContext(
808                lc,
809                this,
810                new FunctionNode(
811                        this,
812                        lastToken,
813                        endParserState,
814                        flags |
815                            (body.needsScope() ?
816                                    FunctionNode.HAS_SCOPE_BLOCK :
817                                    0),
818                        name,
819                        returnType,
820                        compileUnit,
821                        compilationState,
822                        body,
823                        parameters,
824                        thisProperties,
825                        rootClass, source, namespace));
826    }
827
828    /**
829     * Does this function's method needs to be variable arity (gather all script-declared parameters in a final
830     * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply
831     * declare too many arguments for JVM to handle with fixed arity will need to be variable arity.
832     * @return true if the Java method in the generated code that implements this function needs to be variable arity.
833     * @see #needsArguments()
834     * @see LinkerCallSite#ARGLIMIT
835     */
836    public boolean isVarArg() {
837        return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT;
838    }
839
840    /**
841     * Was this function declared in a dynamic context, i.e. in a with or eval style
842     * chain
843     * @return true if in dynamic context
844     */
845    public boolean inDynamicContext() {
846        return getFlag(IN_DYNAMIC_CONTEXT);
847    }
848
849    /**
850     * Check whether a function would need dynamic scope, which is does if it has
851     * evals and isn't strict.
852     * @return true if dynamic scope is needed
853     */
854    public boolean needsDynamicScope() {
855        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
856        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
857        // isolated scope).
858        return hasEval() && !isStrict();
859    }
860
861    /**
862     * Flag this function as declared in a dynamic context
863     * @param lc lexical context
864     * @return new function node, or same if unmodified
865     */
866    public FunctionNode setInDynamicContext(final LexicalContext lc) {
867        return setFlag(lc, IN_DYNAMIC_CONTEXT);
868    }
869
870    /**
871     * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
872     * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
873     * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
874     * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an
875     * "arguments" object, because it does not have local variables; rather the Global object will have an explicit
876     * "arguments" property that provides command-line arguments for the script.
877     * @return true if this function needs an arguments object.
878     */
879    public boolean needsArguments() {
880        // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since
881        // for top-level script, "arguments" is picked up from Context by Global.init() instead.
882        return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram();
883    }
884
885    /**
886     * Returns true if this function needs access to its parent scope. Functions referencing variables outside their
887     * scope (including global variables), as well as functions that call eval or have a with block, or have nested
888     * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a
889     * parent scope since they might be used from within eval, and eval will need an externally passed scope.
890     * @return true if the function needs parent scope.
891     */
892    public boolean needsParentScope() {
893        return getFlag(NEEDS_PARENT_SCOPE);
894    }
895
896    /**
897     * Set the number of properties assigned to the this object in this function.
898     * @param lc the current lexical context.
899     * @param thisProperties number of properties
900     * @return a potentially modified function node
901     */
902    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
903        if (this.thisProperties == thisProperties) {
904            return this;
905        }
906        return Node.replaceInLexicalContext(
907                lc,
908                this,
909                new FunctionNode(
910                        this,
911                        lastToken,
912                        endParserState,
913                        flags,
914                        name,
915                        returnType,
916                        compileUnit,
917                        compilationState,
918                        body,
919                        parameters,
920                        thisProperties,
921                        rootClass, source, namespace));
922    }
923
924    /**
925     * Get the number of properties assigned to the this object in this function.
926     * @return number of properties
927     */
928    public int getThisProperties() {
929        return thisProperties;
930    }
931
932    /**
933     * Returns true if any of the blocks in this function create their own scope.
934     * @return true if any of the blocks in this function create their own scope.
935     */
936    public boolean hasScopeBlock() {
937        return getFlag(HAS_SCOPE_BLOCK);
938    }
939
940    /**
941     * Return the kind of this function
942     * @see FunctionNode.Kind
943     * @return the kind
944     */
945    public Kind getKind() {
946        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