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