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