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