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