FunctionNode.java revision 1399:eea9202e8930
111820Sjulian/* 211820Sjulian * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 311820Sjulian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 411820Sjulian * 511820Sjulian * This code is free software; you can redistribute it and/or modify it 611820Sjulian * under the terms of the GNU General Public License version 2 only, as 711820Sjulian * published by the Free Software Foundation. Oracle designates this 811820Sjulian * particular file as subject to the "Classpath" exception as provided 911820Sjulian * by Oracle in the LICENSE file that accompanied this code. 1011820Sjulian * 1111820Sjulian * This code is distributed in the hope that it will be useful, but WITHOUT 1211820Sjulian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1311820Sjulian * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1411820Sjulian * version 2 for more details (a copy is included in the LICENSE file that 1511820Sjulian * accompanied this code). 1611820Sjulian * 1711820Sjulian * You should have received a copy of the GNU General Public License version 1811820Sjulian * 2 along with this work; if not, write to the Free Software Foundation, 1911820Sjulian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2011820Sjulian * 2111820Sjulian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2211820Sjulian * or visit www.oracle.com if you need additional information or have any 2311820Sjulian * questions. 2411820Sjulian */ 2511820Sjulian 2611820Sjulianpackage jdk.nashorn.internal.ir; 2711820Sjulian 2811820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE; 2911820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; 3011820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE; 3111820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT; 3211820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES; 3311820Sjulianimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES; 3450479Speter 3511820Sjulianimport java.util.Collections; 3611820Sjulianimport java.util.EnumSet; 3711820Sjulianimport java.util.Iterator; 38122760Strhodesimport java.util.List; 3911820Sjulianimport jdk.nashorn.internal.AssertsEnabled; 4011820Sjulianimport jdk.nashorn.internal.codegen.CompileUnit; 4111820Sjulianimport jdk.nashorn.internal.codegen.Compiler; 4211820Sjulianimport jdk.nashorn.internal.codegen.CompilerConstants; 4311820Sjulianimport jdk.nashorn.internal.codegen.Namespace; 4411820Sjulianimport jdk.nashorn.internal.codegen.types.Type; 4511820Sjulianimport jdk.nashorn.internal.ir.annotations.Ignore; 4611820Sjulianimport jdk.nashorn.internal.ir.annotations.Immutable; 4711820Sjulianimport jdk.nashorn.internal.ir.visitor.NodeVisitor; 4811820Sjulianimport jdk.nashorn.internal.parser.Token; 4911820Sjulianimport jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 5011820Sjulianimport jdk.nashorn.internal.runtime.ScriptFunction; 5111820Sjulianimport jdk.nashorn.internal.runtime.Source; 5211820Sjulianimport jdk.nashorn.internal.runtime.UserAccessorProperty; 5311820Sjulianimport jdk.nashorn.internal.runtime.linker.LinkerCallSite; 5411820Sjulian 5511820Sjulian/** 5611820Sjulian * IR representation for function (or script.) 5711820Sjulian */ 5811820Sjulian@Immutable 5911820Sjulianpublic final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder { 6011820Sjulian private static final long serialVersionUID = 1L; 6111820Sjulian 6211820Sjulian /** Type used for all FunctionNodes */ 6311820Sjulian public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class); 6411820Sjulian 6511820Sjulian /** Function kinds */ 6611820Sjulian public enum Kind { 6711820Sjulian /** a normal function - nothing special */ 6811820Sjulian NORMAL, 6911820Sjulian /** a script function */ 7011820Sjulian SCRIPT, 7111820Sjulian /** a getter, @see {@link UserAccessorProperty} */ 7211820Sjulian GETTER, 7311820Sjulian /** a setter, @see {@link UserAccessorProperty} */ 7411820Sjulian SETTER 7511820Sjulian } 7611820Sjulian 7711820Sjulian /** Compilation states available */ 7811820Sjulian public enum CompilationState { 7911820Sjulian /** compiler is ready */ 8011820Sjulian INITIALIZED, 8111820Sjulian /** method has been parsed */ 8211820Sjulian PARSED, 8311820Sjulian /** method has been parsed */ 8411820Sjulian PARSE_ERROR, 8511820Sjulian /** constant folding pass */ 8611820Sjulian CONSTANT_FOLDED, 8711820Sjulian /** method has been lowered */ 8811820Sjulian LOWERED, 8911820Sjulian /** program points have been assigned to unique locations */ 9011820Sjulian PROGRAM_POINTS_ASSIGNED, 9111820Sjulian /** any transformations of builtins have taken place, e.g. apply=>call */ 9227244Sjhay BUILTINS_TRANSFORMED, 9327244Sjhay /** method has been split */ 9427244Sjhay SPLIT, 9527244Sjhay /** method has had symbols assigned */ 9627244Sjhay SYMBOLS_ASSIGNED, 9711820Sjulian /** computed scope depths for symbols */ 9827244Sjhay SCOPE_DEPTHS_COMPUTED, 9927244Sjhay /** method has had types calculated*/ 10027244Sjhay OPTIMISTIC_TYPES_ASSIGNED, 10127244Sjhay /** method has had types calculated */ 10227244Sjhay LOCAL_VARIABLE_TYPES_CALCULATED, 10327244Sjhay /** compile units reused (optional) */ 10427244Sjhay COMPILE_UNITS_REUSED, 10527244Sjhay /** method has been emitted to bytecode */ 10627244Sjhay BYTECODE_GENERATED, 10727244Sjhay /** method has been installed */ 10827244Sjhay BYTECODE_INSTALLED 10927244Sjhay } 11027244Sjhay 11127244Sjhay /** Source of entity. */ 11227244Sjhay private transient final Source source; 11327244Sjhay 11427244Sjhay /** 11511820Sjulian * Opaque object representing parser state at the end of the function. Used when reparsing outer functions 11611820Sjulian * to skip parsing inner functions. 11727244Sjhay */ 11811820Sjulian private final Object endParserState; 11911820Sjulian 12011820Sjulian /** External function identifier. */ 12111820Sjulian @Ignore 12211820Sjulian private final IdentNode ident; 12311820Sjulian 12411820Sjulian /** The body of the function node */ 12511820Sjulian private final Block body; 12611820Sjulian 12711820Sjulian /** Internal function name. */ 12811820Sjulian private final String name; 12911820Sjulian 13011820Sjulian /** Compilation unit. */ 13111820Sjulian private final CompileUnit compileUnit; 13211820Sjulian 13311820Sjulian /** Function kind. */ 13411820Sjulian private final Kind kind; 13511820Sjulian 13611820Sjulian /** List of parameters. */ 13711820Sjulian private final List<IdentNode> parameters; 13811820Sjulian 13911820Sjulian /** First token of function. **/ 14011820Sjulian private final long firstToken; 14111820Sjulian 14211820Sjulian /** Last token of function. **/ 14311820Sjulian private final long lastToken; 14411820Sjulian 14511820Sjulian /** Method's namespace. */ 14611820Sjulian private transient final Namespace namespace; 14711820Sjulian 14811820Sjulian /** Current compilation state */ 14911820Sjulian @Ignore 15011820Sjulian private final EnumSet<CompilationState> compilationState; 15111820Sjulian 15211820Sjulian /** Number of properties of "this" object assigned in this function */ 15311820Sjulian @Ignore 15411820Sjulian private final int thisProperties; 15511820Sjulian 15611820Sjulian /** Function flags. */ 15711820Sjulian private final int flags; 15811820Sjulian 15911820Sjulian /** Line number of function start */ 16011820Sjulian private final int lineNumber; 16111820Sjulian 16211820Sjulian /** Root class for function */ 16311820Sjulian private final Class<?> rootClass; 16411820Sjulian 16511820Sjulian /** Is anonymous function flag. */ 16611820Sjulian public static final int IS_ANONYMOUS = 1 << 0; 16711820Sjulian 16811820Sjulian /** Is the function created in a function declaration (as opposed to a function expression) */ 16911820Sjulian public static final int IS_DECLARED = 1 << 1; 17011820Sjulian 17111820Sjulian /** is this a strict mode function? */ 17211820Sjulian public static final int IS_STRICT = 1 << 2; 17311820Sjulian 17411820Sjulian /** Does the function use the "arguments" identifier ? */ 17511820Sjulian public static final int USES_ARGUMENTS = 1 << 3; 17611820Sjulian 17711820Sjulian /** Has this function been split because it was too large? */ 17811820Sjulian public static final int IS_SPLIT = 1 << 4; 17911820Sjulian 18011820Sjulian /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can 18111820Sjulian * introduce new variables into this function's scope too.*/ 18211820Sjulian public static final int HAS_EVAL = 1 << 5; 18311820Sjulian 18411820Sjulian /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */ 18511820Sjulian public static final int HAS_NESTED_EVAL = 1 << 6; 18611820Sjulian 18711820Sjulian /** Does this function have any blocks that create a scope? This is used to determine if the function needs to 18811820Sjulian * have a local variable slot for the scope symbol. */ 18911820Sjulian public static final int HAS_SCOPE_BLOCK = 1 << 7; 19011820Sjulian 19111820Sjulian /** 19211820Sjulian * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function 19311820Sjulian * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that 19411820Sjulian * defining a local variable named "arguments" still requires construction of the Arguments object (see 19511820Sjulian * ECMAScript 5.1 Chapter 10.5). 19611820Sjulian * @see #needsArguments() 19711820Sjulian */ 19811820Sjulian public static final int DEFINES_ARGUMENTS = 1 << 8; 19911820Sjulian 20011820Sjulian /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */ 20111820Sjulian public static final int USES_ANCESTOR_SCOPE = 1 << 9; 20211820Sjulian 20311820Sjulian /** Does this function have nested declarations? */ 20411820Sjulian public static final int HAS_FUNCTION_DECLARATIONS = 1 << 10; 20511820Sjulian 20611820Sjulian /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */ 20711820Sjulian public static final int IS_DEOPTIMIZABLE = 1 << 11; 20811820Sjulian 20911820Sjulian /** Are we vararg, but do we just pass the arguments along to apply or call */ 21011820Sjulian public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12; 21112620Sjulian 21212620Sjulian /** 21311820Sjulian * Is this function the top-level program? 21411820Sjulian */ 21512620Sjulian public static final int IS_PROGRAM = 1 << 13; 21612620Sjulian 21711820Sjulian /** 21811820Sjulian * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions 21911820Sjulian * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will 22011820Sjulian * use the symbol in their parent scope instead when they reference themselves by name. 22111820Sjulian */ 22211820Sjulian public static final int USES_SELF_SYMBOL = 1 << 14; 22311820Sjulian 22411820Sjulian /** Does this function use the "this" keyword? */ 22511820Sjulian public static final int USES_THIS = 1 << 15; 22611820Sjulian 22711820Sjulian /** Is this declared in a dynamic context */ 22811820Sjulian public static final int IN_DYNAMIC_CONTEXT = 1 << 16; 22911820Sjulian 23011820Sjulian /** 23111820Sjulian * The following flags are derived from directive comments within this function. 23211820Sjulian * Note that even IS_STRICT is one such flag but that requires special handling. 23311820Sjulian */ 23411820Sjulian 23511820Sjulian /** parser, print parse tree */ 23611820Sjulian public static final int IS_PRINT_PARSE = 1 << 17; 23711820Sjulian /** parser, print lower parse tree */ 23811820Sjulian public static final int IS_PRINT_LOWER_PARSE = 1 << 18; 23911820Sjulian /** parser, print AST */ 24011820Sjulian public static final int IS_PRINT_AST = 1 << 19; 24111820Sjulian /** parser, print lower AST */ 24211820Sjulian public static final int IS_PRINT_LOWER_AST = 1 << 20; 24311820Sjulian /** parser, print symbols */ 24411820Sjulian public static final int IS_PRINT_SYMBOLS = 1 << 21; 24511820Sjulian 24611820Sjulian // callsite tracing, profiling within this function 24711820Sjulian /** profile callsites in this function? */ 24811820Sjulian public static final int IS_PROFILE = 1 << 22; 24911820Sjulian 25011820Sjulian /** trace callsite enterexit in this function? */ 25111820Sjulian public static final int IS_TRACE_ENTEREXIT = 1 << 23; 25211820Sjulian 25311820Sjulian /** trace callsite misses in this function? */ 25411820Sjulian public static final int IS_TRACE_MISSES = 1 << 24; 25511820Sjulian 25611820Sjulian /** trace callsite values in this function? */ 25711820Sjulian public static final int IS_TRACE_VALUES = 1 << 25; 25811820Sjulian 25911820Sjulian /** 26011820Sjulian * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a 26111820Sjulian * parameter on invocation. Note that we aren't, in fact using this flag in function nodes. 26211820Sjulian * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData} 26311820Sjulian * will, however, cache the value of this flag. 26411820Sjulian */ 26511820Sjulian public static final int NEEDS_CALLEE = 1 << 26; 26611820Sjulian 26711820Sjulian /** 26811820Sjulian * Is the function node cached? 26911820Sjulian */ 27011820Sjulian public static final int IS_CACHED = 1 << 27; 27111820Sjulian 27211820Sjulian /** extension callsite flags mask */ 27311820Sjulian public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE | 27411820Sjulian IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST | 27511820Sjulian IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT | 27611820Sjulian IS_TRACE_MISSES | IS_TRACE_VALUES; 27711820Sjulian 27811820Sjulian /** Does this function or any nested functions contain an eval? */ 27911820Sjulian private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL; 28011820Sjulian 28111820Sjulian /** Does this function need to store all its variables in scope? */ 28211820Sjulian private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL; 28311820Sjulian 28411820Sjulian /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */ 28511820Sjulian private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL; 28611820Sjulian 28711820Sjulian /** 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. */ 28811820Sjulian public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM; 28911820Sjulian 29011820Sjulian /** What is the return type of this function? */ 29111820Sjulian private Type returnType = Type.UNKNOWN; 29211820Sjulian 29311820Sjulian /** 29411820Sjulian * Constructor 295 * 296 * @param source the source 297 * @param lineNumber line number 298 * @param token token 299 * @param finish finish 300 * @param firstToken first token of the function node (including the function declaration) 301 * @param lastToken lastToken 302 * @param namespace the namespace 303 * @param ident the identifier 304 * @param name the name of the function 305 * @param parameters parameter list 306 * @param kind kind of function as in {@link FunctionNode.Kind} 307 * @param flags initial flags 308 * @param body body of the function 309 * @param state The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR} 310 * @param endParserState The parser state at the end of the parsing. 311 */ 312 public FunctionNode( 313 final Source source, 314 final int lineNumber, 315 final long token, 316 final int finish, 317 final long firstToken, 318 final long lastToken, 319 final Namespace namespace, 320 final IdentNode ident, 321 final String name, 322 final List<IdentNode> parameters, 323 final FunctionNode.Kind kind, 324 final int flags, 325 final Block body, 326 final CompilationState state, 327 final Object endParserState) { 328 super(token, finish); 329 330 this.source = source; 331 this.lineNumber = lineNumber; 332 this.ident = ident; 333 this.name = name; 334 this.kind = kind; 335 this.parameters = parameters; 336 this.firstToken = firstToken; 337 this.lastToken = lastToken; 338 this.namespace = namespace; 339 this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state); 340 this.flags = flags; 341 this.compileUnit = null; 342 this.body = body; 343 this.thisProperties = 0; 344 this.rootClass = null; 345 this.endParserState = endParserState; 346 } 347 348 private FunctionNode( 349 final FunctionNode functionNode, 350 final long lastToken, 351 final Object endParserState, 352 final int flags, 353 final String name, 354 final Type returnType, 355 final CompileUnit compileUnit, 356 final EnumSet<CompilationState> compilationState, 357 final Block body, 358 final List<IdentNode> parameters, 359 final int thisProperties, 360 final Class<?> rootClass, 361 final Source source, final Namespace namespace) { 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 this.source = source; 377 this.namespace = namespace; 378 379 // the fields below never change - they are final and assigned in constructor 380 this.ident = functionNode.ident; 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 * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function 447 * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for 448 * a deserialized function node. 449 * @param source the source for the function. 450 * @param namespace the namespace for the function 451 * @return a new function node with the set source and namespace 452 * @throws IllegalArgumentException if the specified source or namespace is null 453 * @throws IllegalStateException if the function already has either a source or namespace set. 454 */ 455 public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) { 456 if (source == null || namespace == null) { 457 throw new IllegalArgumentException(); 458 } else if (this.source == source && this.namespace == namespace) { 459 return this; 460 } else if (this.source != null || this.namespace != null) { 461 throw new IllegalStateException(); 462 } 463 return new FunctionNode( 464 this, 465 lastToken, 466 endParserState, 467 flags, 468 name, 469 returnType, 470 compileUnit, 471 compilationState, 472 body, 473 parameters, 474 thisProperties, 475 rootClass, source, namespace); 476 } 477 478 /** 479 * Get the unique ID for this function within the script file. 480 * @return the id 481 */ 482 public int getId() { 483 return isProgram() ? -1: Token.descPosition(firstToken); 484 } 485 486 /** 487 * get source name - sourceURL or name derived from Source. 488 * 489 * @return name for the script source 490 */ 491 public String getSourceName() { 492 return getSourceName(source); 493 } 494 495 /** 496 * Static source name getter 497 * 498 * @param source the source 499 * @return source name 500 */ 501 public static String getSourceName(final Source source) { 502 final String explicitURL = source.getExplicitURL(); 503 return explicitURL != null ? explicitURL : source.getName(); 504 } 505 506 /** 507 * Function to parse nashorn per-function extension directive comments. 508 * 509 * @param directive nashorn extension directive string 510 * @return integer flag for the given directive. 511 */ 512 public static int getDirectiveFlag(final String directive) { 513 switch (directive) { 514 case "nashorn callsite trace enterexit": 515 return IS_TRACE_ENTEREXIT; 516 case "nashorn callsite trace misses": 517 return IS_TRACE_MISSES; 518 case "nashorn callsite trace objects": 519 return IS_TRACE_VALUES; 520 case "nashorn callsite profile": 521 return IS_PROFILE; 522 case "nashorn print parse": 523 return IS_PRINT_PARSE; 524 case "nashorn print lower parse": 525 return IS_PRINT_LOWER_PARSE; 526 case "nashorn print ast": 527 return IS_PRINT_AST; 528 case "nashorn print lower ast": 529 return IS_PRINT_LOWER_AST; 530 case "nashorn print symbols": 531 return IS_PRINT_SYMBOLS; 532 default: 533 // unknown/unsupported directive 534 return 0; 535 } 536 } 537 538 /** 539 * Returns the line number. 540 * @return the line number. 541 */ 542 public int getLineNumber() { 543 return lineNumber; 544 } 545 546 /** 547 * Get the compilation state of this function 548 * @return the compilation state 549 */ 550 public EnumSet<CompilationState> getState() { 551 return compilationState; 552 } 553 554 /** 555 * Check whether this FunctionNode has reached a give CompilationState. 556 * 557 * @param state the state to check for 558 * @return true of the node is in the given state 559 */ 560 public boolean hasState(final EnumSet<CompilationState> state) { 561 return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state); 562 } 563 564 /** 565 * Add a state to the total CompilationState of this node, e.g. if 566 * FunctionNode has been lowered, the compiler will add 567 * {@code CompilationState#LOWERED} to the state vector 568 * 569 * @param lc lexical context 570 * @param state {@link CompilationState} to add 571 * @return function node or a new one if state was changed 572 */ 573 public FunctionNode setState(final LexicalContext lc, final CompilationState state) { 574 if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) { 575 return this; 576 } 577 final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); 578 newState.add(state); 579 return setCompilationState(lc, newState); 580 } 581 582 /** 583 * Copy a compilation state from an original function to this function. Used when creating synthetic 584 * function nodes by the splitter. 585 * 586 * @param lc lexical context 587 * @param original the original function node to copy compilation state from 588 * @return function node or a new one if state was changed 589 */ 590 public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) { 591 final EnumSet<CompilationState> origState = original.compilationState; 592 if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) { 593 return this; 594 } 595 final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); 596 newState.addAll(origState); 597 return setCompilationState(lc, newState); 598 } 599 600 private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) { 601 return Node.replaceInLexicalContext( 602 lc, 603 this, 604 new FunctionNode( 605 this, 606 lastToken, 607 endParserState, 608 flags, 609 name, 610 returnType, 611 compileUnit, 612 compilationState, 613 body, 614 parameters, 615 thisProperties, 616 rootClass, source, namespace)); 617 } 618 619 620 /** 621 * Create a unique name in the namespace of this FunctionNode 622 * @param base prefix for name 623 * @return base if no collision exists, otherwise a name prefix with base 624 */ 625 public String uniqueName(final String base) { 626 return namespace.uniqueName(base); 627 } 628 629 @Override 630 public void toString(final StringBuilder sb, final boolean printTypes) { 631 sb.append('['). 632 append(returnType). 633 append(']'). 634 append(' '); 635 636 sb.append("function"); 637 638 if (ident != null) { 639 sb.append(' '); 640 ident.toString(sb, printTypes); 641 } 642 643 sb.append('('); 644 645 for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) { 646 final IdentNode parameter = iter.next(); 647 if (parameter.getSymbol() != null) { 648 sb.append('[').append(parameter.getType()).append(']').append(' '); 649 } 650 parameter.toString(sb, printTypes); 651 if (iter.hasNext()) { 652 sb.append(", "); 653 } 654 } 655 656 sb.append(')'); 657 } 658 659 @Override 660 public int getFlags() { 661 return flags; 662 } 663 664 @Override 665 public boolean getFlag(final int flag) { 666 return (flags & flag) != 0; 667 } 668 669 @Override 670 public FunctionNode setFlags(final LexicalContext lc, final int flags) { 671 if (this.flags == flags) { 672 return this; 673 } 674 return Node.replaceInLexicalContext( 675 lc, 676 this, 677 new FunctionNode( 678 this, 679 lastToken, 680 endParserState, 681 flags, 682 name, 683 returnType, 684 compileUnit, 685 compilationState, 686 body, 687 parameters, 688 thisProperties, 689 rootClass, source, namespace)); 690 } 691 692 @Override 693 public FunctionNode clearFlag(final LexicalContext lc, final int flag) { 694 return setFlags(lc, flags & ~flag); 695 } 696 697 @Override 698 public FunctionNode setFlag(final LexicalContext lc, final int flag) { 699 return setFlags(lc, flags | flag); 700 } 701 702 /** 703 * Returns true if the function is the top-level program. 704 * @return True if this function node represents the top-level program. 705 */ 706 public boolean isProgram() { 707 return getFlag(IS_PROGRAM); 708 } 709 710 /** 711 * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized). 712 * @return true if the function contains at least one optimistic operation (and thus can be deoptimized). 713 */ 714 public boolean canBeDeoptimized() { 715 return getFlag(IS_DEOPTIMIZABLE); 716 } 717 718 /** 719 * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}). 720 * 721 * @return true if {@code eval} is called. 722 */ 723 public boolean hasEval() { 724 return getFlag(HAS_EVAL); 725 } 726 727 /** 728 * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}. 729 * 730 * @return true if a nested function calls {@code eval}. 731 */ 732 public boolean hasNestedEval() { 733 return getFlag(HAS_NESTED_EVAL); 734 } 735 736 /** 737 * Get the first token for this function 738 * @return the first token 739 */ 740 public long getFirstToken() { 741 return firstToken; 742 } 743 744 /** 745 * Check whether this function has nested function declarations 746 * @return true if nested function declarations exist 747 */ 748 public boolean hasDeclaredFunctions() { 749 return getFlag(HAS_FUNCTION_DECLARATIONS); 750 } 751 752 /** 753 * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to 754 * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object 755 * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true 756 * for split functions to make sure symbols slots are the same in the main and split methods. 757 * 758 * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still 759 * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well 760 * 761 * @return true if the function's generated Java method needs a {@code callee} parameter. 762 */ 763 public boolean needsCallee() { 764 // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units. 765 return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization(); 766 } 767 768 /** 769 * Return {@code true} if this function makes use of the {@code this} object. 770 * 771 * @return true if function uses {@code this} object 772 */ 773 public boolean usesThis() { 774 return getFlag(USES_THIS); 775 } 776 777 778 /** 779 * Return true if function contains an apply to call transform 780 * @return true if this function has transformed apply to call 781 */ 782 public boolean hasApplyToCallSpecialization() { 783 return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION); 784 } 785 786 /** 787 * Get the identifier for this function, this is its symbol. 788 * @return the identifier as an IdentityNode 789 */ 790 public IdentNode getIdent() { 791 return ident; 792 } 793 794 /** 795 * Get the function body 796 * @return the function body 797 */ 798 public Block getBody() { 799 return body; 800 } 801 802 /** 803 * Reset the function body 804 * @param lc lexical context 805 * @param body new body 806 * @return new function node if body changed, same if not 807 */ 808 public FunctionNode setBody(final LexicalContext lc, final Block body) { 809 if (this.body == body) { 810 return this; 811 } 812 return Node.replaceInLexicalContext( 813 lc, 814 this, 815 new FunctionNode( 816 this, 817 lastToken, 818 endParserState, 819 flags | 820 (body.needsScope() ? 821 FunctionNode.HAS_SCOPE_BLOCK : 822 0), 823 name, 824 returnType, 825 compileUnit, 826 compilationState, 827 body, 828 parameters, 829 thisProperties, 830 rootClass, source, namespace)); 831 } 832 833 /** 834 * Does this function's method needs to be variable arity (gather all script-declared parameters in a final 835 * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply 836 * declare too many arguments for JVM to handle with fixed arity will need to be variable arity. 837 * @return true if the Java method in the generated code that implements this function needs to be variable arity. 838 * @see #needsArguments() 839 * @see LinkerCallSite#ARGLIMIT 840 */ 841 public boolean isVarArg() { 842 return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT; 843 } 844 845 /** 846 * Was this function declared in a dynamic context, i.e. in a with or eval style 847 * chain 848 * @return true if in dynamic context 849 */ 850 public boolean inDynamicContext() { 851 return getFlag(IN_DYNAMIC_CONTEXT); 852 } 853 854 /** 855 * Check whether a function would need dynamic scope, which is does if it has 856 * evals and isn't strict. 857 * @return true if dynamic scope is needed 858 */ 859 public boolean needsDynamicScope() { 860 // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new 861 // variable into the function's scope), and it isn't strict (as evals in strict functions get an 862 // isolated scope). 863 return hasEval() && !isStrict(); 864 } 865 866 /** 867 * Flag this function as declared in a dynamic context 868 * @param lc lexical context 869 * @return new function node, or same if unmodified 870 */ 871 public FunctionNode setInDynamicContext(final LexicalContext lc) { 872 return setFlag(lc, IN_DYNAMIC_CONTEXT); 873 } 874 875 /** 876 * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments". 877 * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function 878 * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that 879 * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an 880 * "arguments" object, because it does not have local variables; rather the Global object will have an explicit 881 * "arguments" property that provides command-line arguments for the script. 882 * @return true if this function needs an arguments object. 883 */ 884 public boolean needsArguments() { 885 // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since 886 // for top-level script, "arguments" is picked up from Context by Global.init() instead. 887 return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram(); 888 } 889 890 /** 891 * Returns true if this function needs access to its parent scope. Functions referencing variables outside their 892 * scope (including global variables), as well as functions that call eval or have a with block, or have nested 893 * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a 894 * parent scope since they might be used from within eval, and eval will need an externally passed scope. 895 * @return true if the function needs parent scope. 896 */ 897 public boolean needsParentScope() { 898 return getFlag(NEEDS_PARENT_SCOPE); 899 } 900 901 /** 902 * Set the number of properties assigned to the this object in this function. 903 * @param lc the current lexical context. 904 * @param thisProperties number of properties 905 * @return a potentially modified function node 906 */ 907 public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) { 908 if (this.thisProperties == thisProperties) { 909 return this; 910 } 911 return Node.replaceInLexicalContext( 912 lc, 913 this, 914 new FunctionNode( 915 this, 916 lastToken, 917 endParserState, 918 flags, 919 name, 920 returnType, 921 compileUnit, 922 compilationState, 923 body, 924 parameters, 925 thisProperties, 926 rootClass, source, namespace)); 927 } 928 929 /** 930 * Get the number of properties assigned to the this object in this function. 931 * @return number of properties 932 */ 933 public int getThisProperties() { 934 return thisProperties; 935 } 936 937 /** 938 * Returns true if any of the blocks in this function create their own scope. 939 * @return true if any of the blocks in this function create their own scope. 940 */ 941 public boolean hasScopeBlock() { 942 return getFlag(HAS_SCOPE_BLOCK); 943 } 944 945 /** 946 * Return the kind of this function 947 * @see FunctionNode.Kind 948 * @return the kind 949 */ 950 public Kind getKind() { 951 return kind; 952 } 953 954 /** 955 * Return the last token for this function's code 956 * @return last token 957 */ 958 public long getLastToken() { 959 return lastToken; 960 } 961 962 /** 963 * Returns the end parser state for this function. 964 * @return the end parser state for this function. 965 */ 966 public Object getEndParserState() { 967 return endParserState; 968 } 969 970 /** 971 * Get the name of this function 972 * @return the name 973 */ 974 public String getName() { 975 return name; 976 } 977 978 /** 979 * Set the internal name for this function 980 * @param lc lexical context 981 * @param name new name 982 * @return new function node if changed, otherwise the same 983 */ 984 public FunctionNode setName(final LexicalContext lc, final String name) { 985 if (this.name.equals(name)) { 986 return this; 987 } 988 return Node.replaceInLexicalContext( 989 lc, 990 this, 991 new FunctionNode( 992 this, 993 lastToken, 994 endParserState, 995 flags, 996 name, 997 returnType, 998 compileUnit, 999 compilationState, 1000 body, 1001 parameters, 1002 thisProperties, 1003 rootClass, source, namespace)); 1004 } 1005 1006 /** 1007 * Check if this function should have all its variables in its own scope. Split sub-functions, and 1008 * functions having with and/or eval blocks are such. 1009 * 1010 * @return true if all variables should be in scope 1011 */ 1012 public boolean allVarsInScope() { 1013 return getFlag(HAS_ALL_VARS_IN_SCOPE); 1014 } 1015 1016 /** 1017 * Checks if this function is split into several smaller fragments. 1018 * 1019 * @return true if this function is split into several smaller fragments. 1020 */ 1021 public boolean isSplit() { 1022 return getFlag(IS_SPLIT); 1023 } 1024 1025 /** 1026 * Get the parameters to this function 1027 * @return a list of IdentNodes which represent the function parameters, in order 1028 */ 1029 public List<IdentNode> getParameters() { 1030 return Collections.unmodifiableList(parameters); 1031 } 1032 1033 /** 1034 * Return the number of parameters to this function 1035 * @return the number of parameters 1036 */ 1037 public int getNumOfParams() { 1038 return parameters.size(); 1039 } 1040 1041 /** 1042 * Returns the identifier for a named parameter at the specified position in this function's parameter list. 1043 * @param index the parameter's position. 1044 * @return the identifier for the requested named parameter. 1045 * @throws IndexOutOfBoundsException if the index is invalid. 1046 */ 1047 public IdentNode getParameter(final int index) { 1048 return parameters.get(index); 1049 } 1050 1051 /** 1052 * Reset the compile unit used to compile this function 1053 * @see Compiler 1054 * @param lc lexical context 1055 * @param parameters the compile unit 1056 * @return function node or a new one if state was changed 1057 */ 1058 public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) { 1059 if (this.parameters == parameters) { 1060 return this; 1061 } 1062 return Node.replaceInLexicalContext( 1063 lc, 1064 this, 1065 new FunctionNode( 1066 this, 1067 lastToken, 1068 endParserState, 1069 flags, 1070 name, 1071 returnType, 1072 compileUnit, 1073 compilationState, 1074 body, 1075 parameters, 1076 thisProperties, 1077 rootClass, source, namespace)); 1078 } 1079 1080 /** 1081 * Check if this function is created as a function declaration (as opposed to function expression) 1082 * @return true if function is declared. 1083 */ 1084 public boolean isDeclared() { 1085 return getFlag(IS_DECLARED); 1086 } 1087 1088 /** 1089 * Check if this function is anonymous 1090 * @return true if function is anonymous 1091 */ 1092 public boolean isAnonymous() { 1093 return getFlag(IS_ANONYMOUS); 1094 } 1095 1096 /** 1097 * Does this function use its self symbol - this is needed only for self-referencing named function expressions. 1098 * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the 1099 * scope (since they're bound to the symbol with their name in their enclosing scope). 1100 * @return true if this function node is a named function expression that uses the symbol for itself. 1101 */ 1102 public boolean usesSelfSymbol() { 1103 return getFlag(USES_SELF_SYMBOL); 1104 } 1105 1106 /** 1107 * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an 1108 * anonymous function expression, and it isn't a program). 1109 * @return true if this is a named function expression 1110 */ 1111 public boolean isNamedFunctionExpression() { 1112 return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED); 1113 } 1114 1115 @Override 1116 public Type getType() { 1117 return FUNCTION_TYPE; 1118 } 1119 1120 @Override 1121 public Type getWidestOperationType() { 1122 return FUNCTION_TYPE; 1123 } 1124 1125 /** 1126 * Get the return type for this function. Return types can be specialized 1127 * if the compiler knows them, but parameters cannot, as they need to go through 1128 * appropriate object conversion 1129 * 1130 * @return the return type 1131 */ 1132 public Type getReturnType() { 1133 return returnType; 1134 } 1135 1136 /** 1137 * Set the function return type 1138 * @param lc lexical context 1139 * @param returnType new return type 1140 * @return function node or a new one if state was changed 1141 */ 1142 public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) { 1143 //we never bother with object types narrower than objects, that will lead to byte code verification errors 1144 //as for instance even if we know we are returning a string from a method, the code generator will always 1145 //treat it as an object, at least for now 1146 final Type type = returnType.isObject() ? Type.OBJECT : returnType; 1147 if (this.returnType == type) { 1148 return this; 1149 } 1150 return Node.replaceInLexicalContext( 1151 lc, 1152 this, 1153 new FunctionNode( 1154 this, 1155 lastToken, 1156 endParserState, 1157 flags, 1158 name, 1159 type, 1160 compileUnit, 1161 compilationState, 1162 body, 1163 parameters, 1164 thisProperties, 1165 rootClass, source, namespace 1166 )); 1167 } 1168 1169 /** 1170 * Check if the function is generated in strict mode 1171 * @return true if strict mode enabled for function 1172 */ 1173 public boolean isStrict() { 1174 return getFlag(IS_STRICT); 1175 } 1176 1177 /** 1178 * Returns true if this function node has been cached. 1179 * @return true if this function node has been cached. 1180 */ 1181 public boolean isCached() { 1182 return getFlag(IS_CACHED); 1183 } 1184 1185 /** 1186 * Mark this function node as having been cached. 1187 * @param lc the current lexical context 1188 * @return a function node equivalent to this one, with the flag set. 1189 */ 1190 public FunctionNode setCached(final LexicalContext lc) { 1191 return setFlag(lc, IS_CACHED); 1192 } 1193 1194 1195 /** 1196 * Get the compile unit used to compile this function 1197 * @see Compiler 1198 * @return the compile unit 1199 */ 1200 @Override 1201 public CompileUnit getCompileUnit() { 1202 return compileUnit; 1203 } 1204 1205 /** 1206 * Reset the compile unit used to compile this function 1207 * @see Compiler 1208 * @param lc lexical context 1209 * @param compileUnit the compile unit 1210 * @return function node or a new one if state was changed 1211 */ 1212 public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) { 1213 if (this.compileUnit == compileUnit) { 1214 return this; 1215 } 1216 return Node.replaceInLexicalContext( 1217 lc, 1218 this, 1219 new FunctionNode( 1220 this, 1221 lastToken, 1222 endParserState, 1223 flags, 1224 name, 1225 returnType, 1226 compileUnit, 1227 compilationState, 1228 body, 1229 parameters, 1230 thisProperties, 1231 rootClass, source, namespace)); 1232 } 1233 1234 /** 1235 * Create a temporary variable to the current frame. 1236 * 1237 * @param block that needs the temporary 1238 * @param type Strong type of symbol. 1239 * @param node Primary node to use symbol. 1240 * 1241 * @return Symbol used. 1242 */ 1243 1244 /** 1245 * Get the symbol for a compiler constant, or null if not available (yet) 1246 * @param cc compiler constant 1247 * @return symbol for compiler constant, or null if not defined yet (for example in Lower) 1248 */ 1249 public Symbol compilerConstant(final CompilerConstants cc) { 1250 return body.getExistingSymbol(cc.symbolName()); 1251 } 1252 1253 /** 1254 * Get the root class that this function node compiles to 1255 * @return root class 1256 */ 1257 public Class<?> getRootClass() { 1258 return rootClass; 1259 } 1260 1261 /** 1262 * Reset the root class that this function is compiled to 1263 * @see Compiler 1264 * @param lc lexical context 1265 * @param rootClass root class 1266 * @return function node or a new one if state was changed 1267 */ 1268 public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) { 1269 if (this.rootClass == rootClass) { 1270 return this; 1271 } 1272 return Node.replaceInLexicalContext( 1273 lc, 1274 this, 1275 new FunctionNode( 1276 this, 1277 lastToken, 1278 endParserState, 1279 flags, 1280 name, 1281 returnType, 1282 compileUnit, 1283 compilationState, 1284 body, 1285 parameters, 1286 thisProperties, 1287 rootClass, source, namespace)); 1288 } 1289} 1290