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








1029      * Returns the identifier for a named parameter at the specified position in this function's parameter list.
1030      * @param index the parameter's position.
1031      * @return the identifier for the requested named parameter.
1032      * @throws IndexOutOfBoundsException if the index is invalid.
1033      */
1034     public IdentNode getParameter(final int index) {
1035         return parameters.get(index);
1036     }
1037 
1038     /**
1039      * Reset the compile unit used to compile this function
1040      * @see Compiler
1041      * @param  lc lexical context
1042      * @param  parameters the compile unit
1043      * @return function node or a new one if state was changed
1044      */
1045     public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) {
1046         if (this.parameters == parameters) {
1047             return this;
1048         }
1049         return Node.replaceInLexicalContext(
1050                 lc,
1051                 this,
1052                 new FunctionNode(
1053                         this,
1054                         lastToken,
1055                         endParserState,
1056                         flags,
1057                         name,
1058                         returnType,
1059                         compileUnit,
1060                         compilationState,
1061                         body,
1062                         parameters,
1063                         thisProperties,
1064                         rootClass, source, namespace));
1065     }
1066 
1067     /**
1068      * Check if this function is created as a function declaration (as opposed to function expression)
1069      * @return true if function is declared.
1070      */
1071     public boolean isDeclared() {
1072         return getFlag(IS_DECLARED);
1073     }
1074 
1075     /**
1076      * Check if this function is anonymous
1077      * @return true if function is anonymous
1078      */
1079     public boolean isAnonymous() {
1080         return getFlag(IS_ANONYMOUS);
1081     }
1082 
1083     /**
1084      * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
1085      * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
1086      * scope (since they're bound to the symbol with their name in their enclosing scope).
1087      * @return true if this function node is a named function expression that uses the symbol for itself.
1088      */
1089     public boolean usesSelfSymbol() {
1090         return getFlag(USES_SELF_SYMBOL);
1091     }
1092 
1093     /**
1094      * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
1095      * anonymous function expression, and it isn't a program).
1096      * @return true if this is a named function expression
1097      */
1098     public boolean isNamedFunctionExpression() {
1099         return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
1100     }
1101 
1102     @Override
1103     public Type getType() {
1104         return FUNCTION_TYPE;
1105     }
1106 
1107     @Override
1108     public Type getWidestOperationType() {
1109         return FUNCTION_TYPE;
1110     }
1111 
1112     /**
1113      * Get the return type for this function. Return types can be specialized
1114      * if the compiler knows them, but parameters cannot, as they need to go through
1115      * appropriate object conversion
1116      *
1117      * @return the return type
1118      */
1119     public Type getReturnType() {
1120         return returnType;
1121     }
1122 
1123     /**
1124      * Set the function return type
1125      * @param lc lexical context
1126      * @param returnType new return type
1127      * @return function node or a new one if state was changed
1128      */
1129     public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
1130         //we never bother with object types narrower than objects, that will lead to byte code verification errors
1131         //as for instance even if we know we are returning a string from a method, the code generator will always
1132         //treat it as an object, at least for now
1133         final Type type = returnType.isObject() ? Type.OBJECT : returnType;
1134         if (this.returnType == type) {
1135             return this;
1136         }
1137         return Node.replaceInLexicalContext(
1138             lc,
1139             this,
1140             new FunctionNode(
1141                 this,
1142                 lastToken,
1143                 endParserState,
1144                 flags,
1145                 name,
1146                 type,
1147                 compileUnit,
1148                 compilationState,
1149                 body,
1150                 parameters,
1151                 thisProperties,
1152                 rootClass, source, namespace
1153                 ));
1154    }
1155 
1156     /**
1157      * Check if the function is generated in strict mode
1158      * @return true if strict mode enabled for function
1159      */
1160     public boolean isStrict() {
1161         return getFlag(IS_STRICT);
1162     }
1163 
1164     /**
1165      * Get the compile unit used to compile this function
1166      * @see Compiler
1167      * @return the compile unit
1168      */
1169     @Override
1170     public CompileUnit getCompileUnit() {
1171         return compileUnit;
1172     }
1173 
1174     /**
1175      * Reset the compile unit used to compile this function
1176      * @see Compiler
1177      * @param lc lexical context
1178      * @param compileUnit the compile unit
1179      * @return function node or a new one if state was changed
1180      */
1181     public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1182         if (this.compileUnit == compileUnit) {
1183             return this;
1184         }
1185         return Node.replaceInLexicalContext(
1186                 lc,
1187                 this,
1188                 new FunctionNode(
1189                         this,
1190                         lastToken,
1191                         endParserState,
1192                         flags,
1193                         name,
1194                         returnType,
1195                         compileUnit,
1196                         compilationState,
1197                         body,
1198                         parameters,
1199                         thisProperties,
1200                         rootClass, source, namespace));
1201     }
1202 
1203     /**
1204      * Create a temporary variable to the current frame.
1205      *
1206      * @param block that needs the temporary
1207      * @param type  Strong type of symbol.
1208      * @param node  Primary node to use symbol.
1209      *
1210      * @return Symbol used.
1211      */
1212 
1213     /**
1214      * Get the symbol for a compiler constant, or null if not available (yet)
1215      * @param cc compiler constant
1216      * @return symbol for compiler constant, or null if not defined yet (for example in Lower)
1217      */
1218     public Symbol compilerConstant(final CompilerConstants cc) {
1219         return body.getExistingSymbol(cc.symbolName());
1220     }
1221 
1222     /**
1223      * Get the root class that this function node compiles to
1224      * @return root class
1225      */
1226     public Class<?> getRootClass() {
1227         return rootClass;
1228     }
1229 
1230     /**
1231      * Reset the root class that this function is compiled to
1232      * @see Compiler
1233      * @param lc lexical context
1234      * @param rootClass root class
1235      * @return function node or a new one if state was changed
1236      */
1237     public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
1238         if (this.rootClass == rootClass) {
1239             return this;
1240         }
1241         return Node.replaceInLexicalContext(
1242                 lc,
1243                 this,
1244                 new FunctionNode(
1245                         this,
1246                         lastToken,
1247                         endParserState,
1248                         flags,
1249                         name,
1250                         returnType,
1251                         compileUnit,
1252                         compilationState,
1253                         body,
1254                         parameters,
1255                         thisProperties,
1256                         rootClass, source, namespace));
1257     }
1258 }
--- EOF ---