FunctionNode.java revision 1123:c065853b25fe
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 java.util.function.Function;
40import jdk.nashorn.internal.AssertsEnabled;
41import jdk.nashorn.internal.codegen.CompileUnit;
42import jdk.nashorn.internal.codegen.Compiler;
43import jdk.nashorn.internal.codegen.CompilerConstants;
44import jdk.nashorn.internal.codegen.Namespace;
45import jdk.nashorn.internal.codegen.types.Type;
46import jdk.nashorn.internal.ir.annotations.Ignore;
47import jdk.nashorn.internal.ir.annotations.Immutable;
48import jdk.nashorn.internal.ir.visitor.NodeVisitor;
49import jdk.nashorn.internal.parser.Token;
50import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
51import jdk.nashorn.internal.runtime.ScriptFunction;
52import jdk.nashorn.internal.runtime.Source;
53import jdk.nashorn.internal.runtime.UserAccessorProperty;
54import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
55
56/**
57 * IR representation for function (or script.)
58 */
59@Immutable
60public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
61    private static final long serialVersionUID = 1L;
62
63    /** Type used for all FunctionNodes */
64    public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
65
66    /** Function kinds */
67    public enum Kind {
68        /** a normal function - nothing special */
69        NORMAL,
70        /** a script function */
71        SCRIPT,
72        /** a getter, @see {@link UserAccessorProperty} */
73        GETTER,
74        /** a setter, @see {@link UserAccessorProperty} */
75        SETTER
76    }
77
78    /** Compilation states available */
79    public enum CompilationState {
80        /** compiler is ready */
81        INITIALIZED,
82        /** method has been parsed */
83        PARSED,
84        /** method has been parsed */
85        PARSE_ERROR,
86        /** constant folding pass */
87        CONSTANT_FOLDED,
88        /** method has been lowered */
89        LOWERED,
90        /** program points have been assigned to unique locations */
91        PROGRAM_POINTS_ASSIGNED,
92        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
93        BUILTINS_TRANSFORMED,
94        /** method has been split */
95        SPLIT,
96        /** method has had symbols assigned */
97        SYMBOLS_ASSIGNED,
98        /** computed scope depths for symbols */
99        SCOPE_DEPTHS_COMPUTED,
100        /** method has had types calculated*/
101        OPTIMISTIC_TYPES_ASSIGNED,
102        /** method has had types calculated */
103        LOCAL_VARIABLE_TYPES_CALCULATED,
104        /** compile units reused (optional) */
105        COMPILE_UNITS_REUSED,
106        /** method has been emitted to bytecode */
107        BYTECODE_GENERATED,
108        /** method has been installed */
109        BYTECODE_INSTALLED
110    }
111
112    /** Source of entity. */
113    private transient final Source source;
114
115    /**
116     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
117     * to skip parsing inner functions.
118     */
119    private final Object endParserState;
120
121    /** External function identifier. */
122    @Ignore
123    private final IdentNode ident;
124
125    /** The body of the function node */
126    private final Block body;
127
128    /** Internal function name. */
129    private final String name;
130
131    /** Compilation unit. */
132    private final CompileUnit compileUnit;
133
134    /** Function kind. */
135    private final Kind kind;
136
137    /** List of parameters. */
138    private final List<IdentNode> parameters;
139
140    /** First token of function. **/
141    private final long firstToken;
142
143    /** Last token of function. **/
144    private final long lastToken;
145
146    /** Method's namespace. */
147    private transient final Namespace namespace;
148
149    /** Current compilation state */
150    @Ignore
151    private final EnumSet<CompilationState> compilationState;
152
153    /** Number of properties of "this" object assigned in this function */
154    @Ignore
155    private final int thisProperties;
156
157    /** Function flags. */
158    private final int flags;
159
160    /** Line number of function start */
161    private final int lineNumber;
162
163    /** Root class for function */
164    private final Class<?> rootClass;
165
166    /** Is anonymous function flag. */
167    public static final int IS_ANONYMOUS                = 1 << 0;
168
169    /** Is the function created in a function declaration (as opposed to a function expression) */
170    public static final int IS_DECLARED                 = 1 << 1;
171
172    /** is this a strict mode function? */
173    public static final int IS_STRICT                   = 1 << 2;
174
175    /** Does the function use the "arguments" identifier ? */
176    public static final int USES_ARGUMENTS              = 1 << 3;
177
178    /** Has this function been split because it was too large? */
179    public static final int IS_SPLIT                    = 1 << 4;
180
181    /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
182     * introduce new variables into this function's scope too.*/
183    public static final int HAS_EVAL                    = 1 << 5;
184
185    /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
186    public static final int HAS_NESTED_EVAL             = 1 << 6;
187
188    /** Does this function have any blocks that create a scope? This is used to determine if the function needs to
189     * have a local variable slot for the scope symbol. */
190    public static final int HAS_SCOPE_BLOCK             = 1 << 7;
191
192    /**
193     * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
194     * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that
195     * defining a local variable named "arguments" still requires construction of the Arguments object (see
196     * ECMAScript 5.1 Chapter 10.5).
197     * @see #needsArguments()
198     */
199    public static final int DEFINES_ARGUMENTS           = 1 << 8;
200
201    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
202    public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
203
204    /** Does this function have nested declarations? */
205    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
206
207    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
208    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
209
210    /** Are we vararg, but do we just pass the arguments along to apply or call */
211    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
212
213    /**
214     * Is this function the top-level program?
215     */
216    public static final int IS_PROGRAM = 1 << 13;
217
218    /**
219     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
220     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
221     * use the symbol in their parent scope instead when they reference themselves by name.
222     */
223    public static final int USES_SELF_SYMBOL = 1 << 14;
224
225    /** Does this function use the "this" keyword? */
226    public static final int USES_THIS = 1 << 15;
227
228    /** Is this declared in a dynamic context */
229    public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
230
231    /**
232     * The following flags are derived from directive comments within this function.
233     * Note that even IS_STRICT is one such flag but that requires special handling.
234     */
235
236    /** parser, print parse tree */
237    public static final int IS_PRINT_PARSE       = 1 << 17;
238    /** parser, print lower parse tree */
239    public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
240    /** parser, print AST */
241    public static final int IS_PRINT_AST         = 1 << 19;
242    /** parser, print lower AST */
243    public static final int IS_PRINT_LOWER_AST   = 1 << 20;
244    /** parser, print symbols */
245    public static final int IS_PRINT_SYMBOLS     = 1 << 21;
246
247    // callsite tracing, profiling within this function
248    /** profile callsites in this function? */
249    public static final int IS_PROFILE         = 1 << 22;
250
251    /** trace callsite enterexit in this function? */
252    public static final int IS_TRACE_ENTEREXIT = 1 << 23;
253
254    /** trace callsite misses in this function? */
255    public static final int IS_TRACE_MISSES    = 1 << 24;
256
257    /** trace callsite values in this function? */
258    public static final int IS_TRACE_VALUES    = 1 << 25;
259
260    /**
261     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
262     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
263     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
264     * will, however, cache the value of this flag.
265     */
266    public static final int NEEDS_CALLEE       = 1 << 26;
267
268    /** extension callsite flags mask */
269    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
270        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
271        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
272        IS_TRACE_MISSES | IS_TRACE_VALUES;
273
274    /** Does this function or any nested functions contain an eval? */
275    private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
276
277    /** Does this function need to store all its variables in scope? */
278    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
279
280    /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
281    private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
282
283    /** 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. */
284    public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
285
286    /** What is the return type of this function? */
287    private Type returnType = Type.UNKNOWN;
288
289    /**
290     * Constructor
291     *
292     * @param source     the source
293     * @param lineNumber line number
294     * @param token      token
295     * @param finish     finish
296     * @param firstToken first token of the function node (including the function declaration)
297     * @param lastToken  lastToken
298     * @param namespace  the namespace
299     * @param ident      the identifier
300     * @param name       the name of the function
301     * @param parameters parameter list
302     * @param kind       kind of function as in {@link FunctionNode.Kind}
303     * @param flags      initial flags
304     * @param body       body of the function
305     * @param state      The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR}
306     * @param endParserState The parser state at the end of the parsing.
307     */
308    public FunctionNode(
309        final Source source,
310        final int lineNumber,
311        final long token,
312        final int finish,
313        final long firstToken,
314        final long lastToken,
315        final Namespace namespace,
316        final IdentNode ident,
317        final String name,
318        final List<IdentNode> parameters,
319        final FunctionNode.Kind kind,
320        final int flags,
321        final Block body,
322        final CompilationState state,
323        final Object endParserState) {
324        super(token, finish);
325
326        this.source           = source;
327        this.lineNumber       = lineNumber;
328        this.ident            = ident;
329        this.name             = name;
330        this.kind             = kind;
331        this.parameters       = parameters;
332        this.firstToken       = firstToken;
333        this.lastToken        = lastToken;
334        this.namespace        = namespace;
335        this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state);
336        this.flags            = flags;
337        this.compileUnit      = null;
338        this.body             = body;
339        this.thisProperties   = 0;
340        this.rootClass        = null;
341        this.endParserState    = endParserState;
342    }
343
344    private FunctionNode(
345        final FunctionNode functionNode,
346        final long lastToken,
347        final Object endParserState,
348        final int flags,
349        final String name,
350        final Type returnType,
351        final CompileUnit compileUnit,
352        final EnumSet<CompilationState> compilationState,
353        final Block body,
354        final List<IdentNode> parameters,
355        final int thisProperties,
356        final Class<?> rootClass,
357        final Source source, Namespace namespace) {
358        super(functionNode);
359
360        this.endParserState    = endParserState;
361        this.lineNumber       = functionNode.lineNumber;
362        this.flags            = flags;
363        this.name             = name;
364        this.returnType       = returnType;
365        this.compileUnit      = compileUnit;
366        this.lastToken        = lastToken;
367        this.compilationState = compilationState;
368        this.body             = body;
369        this.parameters       = parameters;
370        this.thisProperties   = thisProperties;
371        this.rootClass        = rootClass;
372        this.source           = source;
373        this.namespace        = namespace;
374
375        // the fields below never change - they are final and assigned in constructor
376        this.ident           = functionNode.ident;
377        this.kind            = functionNode.kind;
378        this.firstToken      = functionNode.firstToken;
379    }
380
381    @Override
382    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
383        if (visitor.enterFunctionNode(this)) {
384            return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
385        }
386        return this;
387    }
388
389    /**
390     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
391     * @param visitor the visitor to apply to the nodes.
392     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
393     */
394    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
395        return Node.accept(visitor, parameters);
396    }
397
398    /**
399     * Get additional callsite flags to be used specific to this function.
400     *
401     * @return callsite flags
402     */
403    public int getCallSiteFlags() {
404        int callsiteFlags = 0;
405        if (getFlag(IS_STRICT)) {
406            callsiteFlags |= CALLSITE_STRICT;
407        }
408
409        // quick check for extension callsite flags turned on by directives.
410        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
411            return callsiteFlags;
412        }
413
414        if (getFlag(IS_PROFILE)) {
415            callsiteFlags |= CALLSITE_PROFILE;
416        }
417
418        if (getFlag(IS_TRACE_MISSES)) {
419            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
420        }
421
422        if (getFlag(IS_TRACE_VALUES)) {
423            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
424        }
425
426        if (getFlag(IS_TRACE_ENTEREXIT)) {
427            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
428        }
429
430        return callsiteFlags;
431    }
432
433    /**
434     * Get the source for this function
435     * @return the source
436     */
437    public Source getSource() {
438        return source;
439    }
440
441    /**
442     * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
443     * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
444     * a deserialized function node.
445     * @param source the source for the function.
446     * @param namespace the namespace for the function
447     * @return a new function node with the set source and namespace
448     * @throws IllegalArgumentException if the specified source or namespace is null
449     * @throws IllegalStateException if the function already has either a source or namespace set.
450     */
451    public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
452        if (source == null || namespace == null) {
453            throw new IllegalArgumentException();
454        } else if (this.source == source && this.namespace == namespace) {
455            return this;
456        } else if (this.source != null || this.namespace != null) {
457            throw new IllegalStateException();
458        }
459        return new FunctionNode(
460            this,
461            lastToken,
462            endParserState,
463            flags,
464            name,
465            returnType,
466            compileUnit,
467            compilationState,
468            body,
469            parameters,
470            thisProperties,
471            rootClass, source, namespace);
472    }
473
474    /**
475     * Get the unique ID for this function within the script file.
476     * @return the id
477     */
478    public int getId() {
479        return isProgram() ? -1: Token.descPosition(firstToken);
480    }
481
482    /**
483     * get source name - sourceURL or name derived from Source.
484     *
485     * @return name for the script source
486     */
487    public String getSourceName() {
488        return getSourceName(source);
489    }
490
491    /**
492     * Static source name getter
493     *
494     * @param source the source
495     * @return source name
496     */
497    public static String getSourceName(final Source source) {
498        final String explicitURL = source.getExplicitURL();
499        return explicitURL != null ? explicitURL : source.getName();
500    }
501
502    /**
503     * Function to parse nashorn per-function extension directive comments.
504     *
505     * @param directive nashorn extension directive string
506     * @return integer flag for the given directive.
507     */
508    public static int getDirectiveFlag(final String directive) {
509        switch (directive) {
510            case "nashorn callsite trace enterexit":
511                return IS_TRACE_ENTEREXIT;
512            case "nashorn callsite trace misses":
513                return IS_TRACE_MISSES;
514            case "nashorn callsite trace objects":
515                return IS_TRACE_VALUES;
516            case "nashorn callsite profile":
517                return IS_PROFILE;
518            case "nashorn print parse":
519                return IS_PRINT_PARSE;
520            case "nashorn print lower parse":
521                return IS_PRINT_LOWER_PARSE;
522            case "nashorn print ast":
523                return IS_PRINT_AST;
524            case "nashorn print lower ast":
525                return IS_PRINT_LOWER_AST;
526            case "nashorn print symbols":
527                return IS_PRINT_SYMBOLS;
528            default:
529                // unknown/unsupported directive
530                return 0;
531        }
532    }
533
534    /**
535     * Returns the line number.
536     * @return the line number.
537     */
538    public int getLineNumber() {
539        return lineNumber;
540    }
541
542    /**
543     * Get the compilation state of this function
544     * @return the compilation state
545     */
546    public EnumSet<CompilationState> getState() {
547        return compilationState;
548    }
549
550    /**
551     * Check whether this FunctionNode has reached a give CompilationState.
552     *
553     * @param state the state to check for
554     * @return true of the node is in the given state
555     */
556    public boolean hasState(final EnumSet<CompilationState> state) {
557        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
558    }
559
560    /**
561     * Add a state to the total CompilationState of this node, e.g. if
562     * FunctionNode has been lowered, the compiler will add
563     * {@code CompilationState#LOWERED} to the state vector
564     *
565     * @param lc lexical context
566     * @param state {@link CompilationState} to add
567     * @return function node or a new one if state was changed
568     */
569    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
570        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
571            return this;
572        }
573        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
574        newState.add(state);
575        return setCompilationState(lc, newState);
576    }
577
578    /**
579     * Copy a compilation state from an original function to this function. Used when creating synthetic
580     * function nodes by the splitter.
581     *
582     * @param lc lexical context
583     * @param original the original function node to copy compilation state from
584     * @return function node or a new one if state was changed
585     */
586    public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) {
587        final EnumSet<CompilationState> origState = original.compilationState;
588        if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) {
589            return this;
590        }
591        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
592        newState.addAll(origState);
593        return setCompilationState(lc, newState);
594    }
595
596    private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) {
597        return Node.replaceInLexicalContext(
598                lc,
599                this,
600                new FunctionNode(
601                        this,
602                        lastToken,
603                        endParserState,
604                        flags,
605                        name,
606                        returnType,
607                        compileUnit,
608                        compilationState,
609                        body,
610                        parameters,
611                        thisProperties,
612                        rootClass, source, namespace));
613    }
614
615
616    /**
617     * Create a unique name in the namespace of this FunctionNode
618     * @param base prefix for name
619     * @return base if no collision exists, otherwise a name prefix with base
620     */
621    public String uniqueName(final String base) {
622        return namespace.uniqueName(base);
623    }
624
625    @Override
626    public void toString(final StringBuilder sb, final boolean printTypes) {
627        sb.append('[').
628            append(returnType).
629            append(']').
630            append(' ');
631
632        sb.append("function");
633
634        if (ident != null) {
635            sb.append(' ');
636            ident.toString(sb, printTypes);
637        }
638
639        sb.append('(');
640
641        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
642            final IdentNode parameter = iter.next();
643            if (parameter.getSymbol() != null) {
644                sb.append('[').append(parameter.getType()).append(']').append(' ');
645            }
646            parameter.toString(sb, printTypes);
647            if (iter.hasNext()) {
648                sb.append(", ");
649            }
650        }
651
652        sb.append(')');
653    }
654
655    @Override
656    public int getFlags() {
657        return flags;
658    }
659
660    @Override
661    public boolean getFlag(final int flag) {
662        return (flags & flag) != 0;
663    }
664
665    @Override
666    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
667        if (this.flags == flags) {
668            return this;
669        }
670        return Node.replaceInLexicalContext(
671                lc,
672                this,
673                new FunctionNode(
674                        this,
675                        lastToken,
676                        endParserState,
677                        flags,
678                        name,
679                        returnType,
680                        compileUnit,
681                        compilationState,
682                        body,
683                        parameters,
684                        thisProperties,
685                        rootClass, source, namespace));
686    }
687
688    @Override
689    public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
690        return setFlags(lc, flags & ~flag);
691    }
692
693    @Override
694    public FunctionNode setFlag(final LexicalContext lc, final int flag) {
695        return setFlags(lc, flags | flag);
696    }
697
698    /**
699     * Returns true if the function is the top-level program.
700     * @return True if this function node represents the top-level program.
701     */
702    public boolean isProgram() {
703        return getFlag(IS_PROGRAM);
704    }
705
706    /**
707     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
708     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
709     */
710    public boolean canBeDeoptimized() {
711        return getFlag(IS_DEOPTIMIZABLE);
712    }
713
714    /**
715     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
716     *
717     * @return true if {@code eval} is called.
718     */
719    public boolean hasEval() {
720        return getFlag(HAS_EVAL);
721    }
722
723    /**
724     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
725     *
726     * @return true if a nested function calls {@code eval}.
727     */
728    public boolean hasNestedEval() {
729        return getFlag(HAS_NESTED_EVAL);
730    }
731
732    /**
733     * Get the first token for this function
734     * @return the first token
735     */
736    public long getFirstToken() {
737        return firstToken;
738    }
739
740    /**
741     * Check whether this function has nested function declarations
742     * @return true if nested function declarations exist
743     */
744    public boolean hasDeclaredFunctions() {
745        return getFlag(HAS_FUNCTION_DECLARATIONS);
746    }
747
748    /**
749     * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to
750     * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object
751     * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
752     * for split functions to make sure symbols slots are the same in the main and split methods.
753     *
754     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
755     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
756     *
757     * @return true if the function's generated Java method needs a {@code callee} parameter.
758     */
759    public boolean needsCallee() {
760        // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
761        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
762    }
763
764    /**
765     * Return {@code true} if this function makes use of the {@code this} object.
766     *
767     * @return true if function uses {@code this} object
768     */
769    public boolean usesThis() {
770        return getFlag(USES_THIS);
771    }
772
773
774    /**
775     * Return true if function contains an apply to call transform
776     * @return true if this function has transformed apply to call
777     */
778    public boolean hasOptimisticApplyToCall() {
779        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
780    }
781
782    /**
783     * Get the identifier for this function, this is its symbol.
784     * @return the identifier as an IdentityNode
785     */
786    public IdentNode getIdent() {
787        return ident;
788    }
789
790    /**
791     * Get the function body
792     * @return the function body
793     */
794    public Block getBody() {
795        return body;
796    }
797
798    /**
799     * Reset the function body
800     * @param lc lexical context
801     * @param body new body
802     * @return new function node if body changed, same if not
803     */
804    public FunctionNode setBody(final LexicalContext lc, final Block body) {
805        if (this.body == body) {
806            return this;
807        }
808        return Node.replaceInLexicalContext(
809                lc,
810                this,
811                new FunctionNode(
812                        this,
813                        lastToken,
814                        endParserState,
815                        flags |
816                            (body.needsScope() ?
817                                    FunctionNode.HAS_SCOPE_BLOCK :
818                                    0),
819                        name,
820                        returnType,
821                        compileUnit,
822                        compilationState,
823                        body,
824                        parameters,
825                        thisProperties,
826                        rootClass, source, namespace));
827    }
828
829    /**
830     * Does this function's method needs to be variable arity (gather all script-declared parameters in a final
831     * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply
832     * declare too many arguments for JVM to handle with fixed arity will need to be variable arity.
833     * @return true if the Java method in the generated code that implements this function needs to be variable arity.
834     * @see #needsArguments()
835     * @see LinkerCallSite#ARGLIMIT
836     */
837    public boolean isVarArg() {
838        return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT;
839    }
840
841    /**
842     * Was this function declared in a dynamic context, i.e. in a with or eval style
843     * chain
844     * @return true if in dynamic context
845     */
846    public boolean inDynamicContext() {
847        return getFlag(IN_DYNAMIC_CONTEXT);
848    }
849
850    /**
851     * Check whether a function would need dynamic scope, which is does if it has
852     * evals and isn't strict.
853     * @return true if dynamic scope is needed
854     */
855    public boolean needsDynamicScope() {
856        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
857        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
858        // isolated scope).
859        return hasEval() && !isStrict();
860    }
861
862    /**
863     * Flag this function as declared in a dynamic context
864     * @param lc lexical context
865     * @return new function node, or same if unmodified
866     */
867    public FunctionNode setInDynamicContext(final LexicalContext lc) {
868        return setFlag(lc, IN_DYNAMIC_CONTEXT);
869    }
870
871    /**
872     * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
873     * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
874     * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
875     * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an
876     * "arguments" object, because it does not have local variables; rather the Global object will have an explicit
877     * "arguments" property that provides command-line arguments for the script.
878     * @return true if this function needs an arguments object.
879     */
880    public boolean needsArguments() {
881        // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since
882        // for top-level script, "arguments" is picked up from Context by Global.init() instead.
883        return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram();
884    }
885
886    /**
887     * Returns true if this function needs access to its parent scope. Functions referencing variables outside their
888     * scope (including global variables), as well as functions that call eval or have a with block, or have nested
889     * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a
890     * parent scope since they might be used from within eval, and eval will need an externally passed scope.
891     * @return true if the function needs parent scope.
892     */
893    public boolean needsParentScope() {
894        return getFlag(NEEDS_PARENT_SCOPE);
895    }
896
897    /**
898     * Set the number of properties assigned to the this object in this function.
899     * @param lc the current lexical context.
900     * @param thisProperties number of properties
901     * @return a potentially modified function node
902     */
903    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
904        if (this.thisProperties == thisProperties) {
905            return this;
906        }
907        return Node.replaceInLexicalContext(
908                lc,
909                this,
910                new FunctionNode(
911                        this,
912                        lastToken,
913                        endParserState,
914                        flags,
915                        name,
916                        returnType,
917                        compileUnit,
918                        compilationState,
919                        body,
920                        parameters,
921                        thisProperties,
922                        rootClass, source, namespace));
923    }
924
925    /**
926     * Get the number of properties assigned to the this object in this function.
927     * @return number of properties
928     */
929    public int getThisProperties() {
930        return thisProperties;
931    }
932
933    /**
934     * Returns true if any of the blocks in this function create their own scope.
935     * @return true if any of the blocks in this function create their own scope.
936     */
937    public boolean hasScopeBlock() {
938        return getFlag(HAS_SCOPE_BLOCK);
939    }
940
941    /**
942     * Return the kind of this function
943     * @see FunctionNode.Kind
944     * @return the kind
945     */
946    public Kind getKind() {
947        return kind;
948    }
949
950    /**
951     * Return the last token for this function's code
952     * @return last token
953     */
954    public long getLastToken() {
955        return lastToken;
956    }
957
958    /**
959     * Returns the end parser state for this function.
960     * @return the end parser state for this function.
961     */
962    public Object getEndParserState() {
963        return endParserState;
964    }
965
966    /**
967     * Get the name of this function
968     * @return the name
969     */
970    public String getName() {
971        return name;
972    }
973
974    /**
975     * Set the internal name for this function
976     * @param lc    lexical context
977     * @param name new name
978     * @return new function node if changed, otherwise the same
979     */
980    public FunctionNode setName(final LexicalContext lc, final String name) {
981        if (this.name.equals(name)) {
982            return this;
983        }
984        return Node.replaceInLexicalContext(
985                lc,
986                this,
987                new FunctionNode(
988                        this,
989                        lastToken,
990                        endParserState,
991                        flags,
992                        name,
993                        returnType,
994                        compileUnit,
995                        compilationState,
996                        body,
997                        parameters,
998                        thisProperties,
999                        rootClass, source, namespace));
1000    }
1001
1002    /**
1003     * Check if this function should have all its variables in its own scope. Split sub-functions, and
1004     * functions having with and/or eval blocks are such.
1005     *
1006     * @return true if all variables should be in scope
1007     */
1008    public boolean allVarsInScope() {
1009        return getFlag(HAS_ALL_VARS_IN_SCOPE);
1010    }
1011
1012    /**
1013     * Checks if this function is split into several smaller fragments.
1014     *
1015     * @return true if this function is split into several smaller fragments.
1016     */
1017    public boolean isSplit() {
1018        return getFlag(IS_SPLIT);
1019    }
1020
1021    /**
1022     * Get the parameters to this function
1023     * @return a list of IdentNodes which represent the function parameters, in order
1024     */
1025    public List<IdentNode> getParameters() {
1026        return Collections.unmodifiableList(parameters);
1027    }
1028
1029    /**
1030     * Returns the identifier for a named parameter at the specified position in this function's parameter list.
1031     * @param index the parameter's position.
1032     * @return the identifier for the requested named parameter.
1033     * @throws IndexOutOfBoundsException if the index is invalid.
1034     */
1035    public IdentNode getParameter(final int index) {
1036        return parameters.get(index);
1037    }
1038
1039    /**
1040     * Reset the compile unit used to compile this function
1041     * @see Compiler
1042     * @param  lc lexical context
1043     * @param  parameters the compile unit
1044     * @return function node or a new one if state was changed
1045     */
1046    public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) {
1047        if (this.parameters == parameters) {
1048            return this;
1049        }
1050        return Node.replaceInLexicalContext(
1051                lc,
1052                this,
1053                new FunctionNode(
1054                        this,
1055                        lastToken,
1056                        endParserState,
1057                        flags,
1058                        name,
1059                        returnType,
1060                        compileUnit,
1061                        compilationState,
1062                        body,
1063                        parameters,
1064                        thisProperties,
1065                        rootClass, source, namespace));
1066    }
1067
1068    /**
1069     * Check if this function is created as a function declaration (as opposed to function expression)
1070     * @return true if function is declared.
1071     */
1072    public boolean isDeclared() {
1073        return getFlag(IS_DECLARED);
1074    }
1075
1076    /**
1077     * Check if this function is anonymous
1078     * @return true if function is anonymous
1079     */
1080    public boolean isAnonymous() {
1081        return getFlag(IS_ANONYMOUS);
1082    }
1083
1084    /**
1085     * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
1086     * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
1087     * scope (since they're bound to the symbol with their name in their enclosing scope).
1088     * @return true if this function node is a named function expression that uses the symbol for itself.
1089     */
1090    public boolean usesSelfSymbol() {
1091        return getFlag(USES_SELF_SYMBOL);
1092    }
1093
1094    /**
1095     * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
1096     * anonymous function expression, and it isn't a program).
1097     * @return true if this is a named function expression
1098     */
1099    public boolean isNamedFunctionExpression() {
1100        return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
1101    }
1102
1103    @Override
1104    public Type getType(final Function<Symbol, Type> localVariableTypes) {
1105        return FUNCTION_TYPE;
1106    }
1107
1108    @Override
1109    public Type getWidestOperationType() {
1110        return FUNCTION_TYPE;
1111    }
1112
1113    /**
1114     * Get the return type for this function. Return types can be specialized
1115     * if the compiler knows them, but parameters cannot, as they need to go through
1116     * appropriate object conversion
1117     *
1118     * @return the return type
1119     */
1120    public Type getReturnType() {
1121        return returnType;
1122    }
1123
1124    /**
1125     * Set the function return type
1126     * @param lc lexical context
1127     * @param returnType new return type
1128     * @return function node or a new one if state was changed
1129     */
1130    public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
1131        //we never bother with object types narrower than objects, that will lead to byte code verification errors
1132        //as for instance even if we know we are returning a string from a method, the code generator will always
1133        //treat it as an object, at least for now
1134        final Type type = returnType.isObject() ? Type.OBJECT : returnType;
1135        if (this.returnType == type) {
1136            return this;
1137        }
1138        return Node.replaceInLexicalContext(
1139            lc,
1140            this,
1141            new FunctionNode(
1142                this,
1143                lastToken,
1144                endParserState,
1145                flags,
1146                name,
1147                type,
1148                compileUnit,
1149                compilationState,
1150                body,
1151                parameters,
1152                thisProperties,
1153                rootClass, source, namespace
1154                ));
1155   }
1156
1157    /**
1158     * Check if the function is generated in strict mode
1159     * @return true if strict mode enabled for function
1160     */
1161    public boolean isStrict() {
1162        return getFlag(IS_STRICT);
1163    }
1164
1165    /**
1166     * Get the compile unit used to compile this function
1167     * @see Compiler
1168     * @return the compile unit
1169     */
1170    @Override
1171    public CompileUnit getCompileUnit() {
1172        return compileUnit;
1173    }
1174
1175    /**
1176     * Reset the compile unit used to compile this function
1177     * @see Compiler
1178     * @param lc lexical context
1179     * @param compileUnit the compile unit
1180     * @return function node or a new one if state was changed
1181     */
1182    public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1183        if (this.compileUnit == compileUnit) {
1184            return this;
1185        }
1186        return Node.replaceInLexicalContext(
1187                lc,
1188                this,
1189                new FunctionNode(
1190                        this,
1191                        lastToken,
1192                        endParserState,
1193                        flags,
1194                        name,
1195                        returnType,
1196                        compileUnit,
1197                        compilationState,
1198                        body,
1199                        parameters,
1200                        thisProperties,
1201                        rootClass, source, namespace));
1202    }
1203
1204    /**
1205     * Create a temporary variable to the current frame.
1206     *
1207     * @param block that needs the temporary
1208     * @param type  Strong type of symbol.
1209     * @param node  Primary node to use symbol.
1210     *
1211     * @return Symbol used.
1212     */
1213
1214    /**
1215     * Get the symbol for a compiler constant, or null if not available (yet)
1216     * @param cc compiler constant
1217     * @return symbol for compiler constant, or null if not defined yet (for example in Lower)
1218     */
1219    public Symbol compilerConstant(final CompilerConstants cc) {
1220        return body.getExistingSymbol(cc.symbolName());
1221    }
1222
1223    /**
1224     * Get the root class that this function node compiles to
1225     * @return root class
1226     */
1227    public Class<?> getRootClass() {
1228        return rootClass;
1229    }
1230
1231    /**
1232     * Reset the root class that this function is compiled to
1233     * @see Compiler
1234     * @param lc lexical context
1235     * @param rootClass root class
1236     * @return function node or a new one if state was changed
1237     */
1238    public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
1239        if (this.rootClass == rootClass) {
1240            return this;
1241        }
1242        return Node.replaceInLexicalContext(
1243                lc,
1244                this,
1245                new FunctionNode(
1246                        this,
1247                        lastToken,
1248                        endParserState,
1249                        flags,
1250                        name,
1251                        returnType,
1252                        compileUnit,
1253                        compilationState,
1254                        body,
1255                        parameters,
1256                        thisProperties,
1257                        rootClass, source, namespace));
1258    }
1259}
1260