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