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