nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
author attila
Wed, 28 Jan 2015 17:58:08 +0100
changeset 28690 78317797ab62
parent 28320 bbf9cfde97f6
child 29281 8cc2618a07aa
permissions -rw-r--r--
8067139: Finally blocks inlined incorrectly Reviewed-by: hannesw, lagergren
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     1
/*
16151
97c1e756ae1e 8005663: Update copyright year to 2013
jlaskey
parents: 16147
diff changeset
     2
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     4
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    10
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    15
 * accompanied this code).
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    16
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    20
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    23
 * questions.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    24
 */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    25
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    26
package jdk.nashorn.internal.codegen;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    27
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    28
import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.PRIVATE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    29
import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    30
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    31
import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    32
import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    33
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    34
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    35
import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    36
import static jdk.nashorn.internal.codegen.CompilerConstants.REGEX_PREFIX;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    37
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    38
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    39
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    40
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    41
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    42
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    43
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    44
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
    45
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    46
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
    47
import static jdk.nashorn.internal.ir.Symbol.HAS_SLOT;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    48
import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    49
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    50
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
    51
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL;
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
    52
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    53
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    54
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    55
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    56
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    57
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    58
import java.io.PrintWriter;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    59
import java.util.ArrayDeque;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    60
import java.util.ArrayList;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    61
import java.util.Arrays;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
    62
import java.util.BitSet;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    63
import java.util.Collection;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    64
import java.util.Collections;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    65
import java.util.Deque;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    66
import java.util.EnumSet;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    67
import java.util.HashMap;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
    68
import java.util.HashSet;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    69
import java.util.Iterator;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    70
import java.util.LinkedList;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    71
import java.util.List;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    72
import java.util.Map;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
    73
import java.util.Set;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    74
import java.util.TreeMap;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
    75
import java.util.function.Supplier;
26250
84bbd0e8b2b2 8056025: CompilationPhase.setStates() is hot in class installation phase
attila
parents: 26241
diff changeset
    76
import jdk.nashorn.internal.AssertsEnabled;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
    77
import jdk.nashorn.internal.IntDeque;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    78
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    79
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    80
import jdk.nashorn.internal.codegen.types.ArrayType;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    81
import jdk.nashorn.internal.codegen.types.Type;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    82
import jdk.nashorn.internal.ir.AccessNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    83
import jdk.nashorn.internal.ir.BaseNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    84
import jdk.nashorn.internal.ir.BinaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    85
import jdk.nashorn.internal.ir.Block;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
    86
import jdk.nashorn.internal.ir.BlockStatement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    87
import jdk.nashorn.internal.ir.BreakNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    88
import jdk.nashorn.internal.ir.CallNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    89
import jdk.nashorn.internal.ir.CaseNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    90
import jdk.nashorn.internal.ir.CatchNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    91
import jdk.nashorn.internal.ir.ContinueNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    92
import jdk.nashorn.internal.ir.EmptyNode;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
    93
import jdk.nashorn.internal.ir.Expression;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
    94
import jdk.nashorn.internal.ir.ExpressionStatement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    95
import jdk.nashorn.internal.ir.ForNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    96
import jdk.nashorn.internal.ir.FunctionNode;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
    97
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
    98
import jdk.nashorn.internal.ir.GetSplitState;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    99
import jdk.nashorn.internal.ir.IdentNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   100
import jdk.nashorn.internal.ir.IfNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   101
import jdk.nashorn.internal.ir.IndexNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   102
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
   103
import jdk.nashorn.internal.ir.JumpStatement;
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
   104
import jdk.nashorn.internal.ir.JumpToInlinedFinally;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   105
import jdk.nashorn.internal.ir.LabelNode;
17968
108ba976aa02 8015684: FieldObjectCreator.putField ignores getValueType
attila
parents: 17778
diff changeset
   106
import jdk.nashorn.internal.ir.LexicalContext;
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   107
import jdk.nashorn.internal.ir.LexicalContextNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   108
import jdk.nashorn.internal.ir.LiteralNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   109
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   110
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   111
import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   112
import jdk.nashorn.internal.ir.LocalVariableConversion;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   113
import jdk.nashorn.internal.ir.LoopNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   114
import jdk.nashorn.internal.ir.Node;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   115
import jdk.nashorn.internal.ir.ObjectNode;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   116
import jdk.nashorn.internal.ir.Optimistic;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   117
import jdk.nashorn.internal.ir.PropertyNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   118
import jdk.nashorn.internal.ir.ReturnNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   119
import jdk.nashorn.internal.ir.RuntimeNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   120
import jdk.nashorn.internal.ir.RuntimeNode.Request;
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   121
import jdk.nashorn.internal.ir.SetSplitState;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   122
import jdk.nashorn.internal.ir.SplitReturn;
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
   123
import jdk.nashorn.internal.ir.Statement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   124
import jdk.nashorn.internal.ir.SwitchNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   125
import jdk.nashorn.internal.ir.Symbol;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   126
import jdk.nashorn.internal.ir.TernaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   127
import jdk.nashorn.internal.ir.ThrowNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   128
import jdk.nashorn.internal.ir.TryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   129
import jdk.nashorn.internal.ir.UnaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   130
import jdk.nashorn.internal.ir.VarNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   131
import jdk.nashorn.internal.ir.WhileNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   132
import jdk.nashorn.internal.ir.WithNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   133
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   134
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   135
import jdk.nashorn.internal.objects.Global;
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   136
import jdk.nashorn.internal.objects.ScriptFunctionImpl;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   137
import jdk.nashorn.internal.parser.Lexer.RegexToken;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   138
import jdk.nashorn.internal.parser.TokenType;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   139
import jdk.nashorn.internal.runtime.Context;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   140
import jdk.nashorn.internal.runtime.Debug;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   141
import jdk.nashorn.internal.runtime.ECMAException;
17241
c337fefb8c84 8012334: ToUint32, ToInt32, and ToUint16 don't conform to spec
hannesw
parents: 17239
diff changeset
   142
import jdk.nashorn.internal.runtime.JSType;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   143
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   144
import jdk.nashorn.internal.runtime.PropertyMap;
16523
af8b30edebce 8009718: Lazy execution architecture continued - ScriptFunctionData is either final or recompilable. Moved ScriptFunctionData creation logic away from runtime to compile time. Prepared for method generation/specialization. Got rid of ScriptFunctionImplTrampoline whose semantics could be done as part of the relinking anyway. Merge with the lookup package change.
lagergren
parents: 16268
diff changeset
   145
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   146
import jdk.nashorn.internal.runtime.RewriteException;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   147
import jdk.nashorn.internal.runtime.Scope;
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
   148
import jdk.nashorn.internal.runtime.ScriptEnvironment;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   149
import jdk.nashorn.internal.runtime.ScriptFunction;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   150
import jdk.nashorn.internal.runtime.ScriptObject;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   151
import jdk.nashorn.internal.runtime.ScriptRuntime;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   152
import jdk.nashorn.internal.runtime.Source;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   153
import jdk.nashorn.internal.runtime.Undefined;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   154
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
   155
import jdk.nashorn.internal.runtime.arrays.ArrayData;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   156
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   157
import jdk.nashorn.internal.runtime.logging.DebugLogger;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   158
import jdk.nashorn.internal.runtime.logging.Loggable;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   159
import jdk.nashorn.internal.runtime.logging.Logger;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   160
import jdk.nashorn.internal.runtime.options.Options;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   161
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   162
/**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   163
 * This is the lowest tier of the code generator. It takes lowered ASTs emitted
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   164
 * from Lower and emits Java byte code. The byte code emission logic is broken
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   165
 * out into MethodEmitter. MethodEmitter works internally with a type stack, and
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   166
 * keeps track of the contents of the byte code stack. This way we avoid a large
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   167
 * number of special cases on the form
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   168
 * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   169
 * if (type == INT) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   170
 *     visitInsn(ILOAD, slot);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   171
 * } else if (type == DOUBLE) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   172
 *     visitInsn(DOUBLE, slot);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   173
 * }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   174
 * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   175
 * This quickly became apparent when the code generator was generalized to work
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   176
 * with all types, and not just numbers or objects.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   177
 * <p>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   178
 * The CodeGenerator visits nodes only once, tags them as resolved and emits
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   179
 * bytecode for them.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   180
 */
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   181
@Logger(name="codegen")
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   182
final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   183
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   184
    private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   185
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   186
    private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class);
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   187
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   188
    private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   189
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   190
    private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class,
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   191
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   192
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   193
    private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   194
            "ensureInt", int.class, Object.class, int.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   195
    private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   196
            "ensureLong", long.class, Object.class, int.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   197
    private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   198
            "ensureNumber", double.class, Object.class, int.class);
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   199
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   200
    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   201
            "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   202
    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   203
            "create", ScriptFunction.class, Object[].class, int.class);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   204
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   205
    private static final Class<?> ITERATOR_CLASS = Iterator.class;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   206
    static {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   207
        assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   208
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   209
    private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   210
    private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   211
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
   212
    private static final Integer INT_ZERO = Integer.valueOf(0);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
   213
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   214
    /** Constant data & installation. The only reason the compiler keeps this is because it is assigned
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   215
     *  by reflection in class installation */
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   216
    private final Compiler compiler;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   217
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   218
    /** Is the current code submitted by 'eval' call? */
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   219
    private final boolean evalCode;
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   220
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   221
    /** Call site flags given to the code generator to be used for all generated call sites */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   222
    private final int callSiteFlags;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   223
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   224
    /** How many regexp fields have been emitted */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   225
    private int regexFieldCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   226
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   227
    /** Line number for last statement. If we encounter a new line number, line number bytecode information
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   228
     *  needs to be generated */
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   229
    private int lastLineNumber = -1;
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   230
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   231
    /** When should we stop caching regexp expressions in fields to limit bytecode size? */
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   232
    private static final int MAX_REGEX_FIELDS = 2 * 1024;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   234
    /** Current method emitter */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   235
    private MethodEmitter method;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   236
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   237
    /** Current compile unit */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   238
    private CompileUnit unit;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   239
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   240
    private final DebugLogger log;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   241
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
   242
    /** From what size should we use spill instead of fields for JavaScript objects? */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   243
    private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   244
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
   245
    private final Set<String> emittedMethods = new HashSet<>();
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
   246
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   247
    // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   248
    private final Map<Integer, ContinuationInfo> fnIdToContinuationInfo = new HashMap<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   249
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   250
    private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   251
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   252
    private static final Label METHOD_BOUNDARY = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   253
    private final Deque<Label> catchLabels = new ArrayDeque<>();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   254
    // Number of live locals on entry to (and thus also break from) labeled blocks.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   255
    private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   256
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   257
    //is this a rest of compilation
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   258
    private final int[] continuationEntryPoints;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   259
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   260
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   261
     * Constructor.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   262
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   263
     * @param compiler
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   264
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   265
    CodeGenerator(final Compiler compiler, final int[] continuationEntryPoints) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   266
        super(new CodeGeneratorLexicalContext());
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   267
        this.compiler                = compiler;
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   268
        this.evalCode                = compiler.getSource().isEvalCode();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   269
        this.continuationEntryPoints = continuationEntryPoints;
24764
722a9603b237 8043633: In order to remove global state outside of contexts, make sure Timing class is an instance and not a static global collection of data. Move into Context. Move -Dnashorn.timing to an official logging option.
lagergren
parents: 24760
diff changeset
   270
        this.callSiteFlags           = compiler.getScriptEnvironment()._callsite_flags;
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   271
        this.log                     = initLogger(compiler.getContext());
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   272
    }
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   273
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   274
    @Override
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   275
    public DebugLogger getLogger() {
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   276
        return log;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   277
    }
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   278
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   279
    @Override
24745
3a6e1477362b 8041434: Add synchronization to the common global constants structure
lagergren
parents: 24744
diff changeset
   280
    public DebugLogger initLogger(final Context context) {
3a6e1477362b 8041434: Add synchronization to the common global constants structure
lagergren
parents: 24744
diff changeset
   281
        return context.getLogger(this.getClass());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   282
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   283
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   284
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   285
     * Gets the call site flags, adding the strict flag if the current function
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   286
     * being generated is in strict mode
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   287
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   288
     * @return the correct flags for a call site in the current function
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   289
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
   290
    int getCallSiteFlags() {
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
   291
        return lc.getCurrentFunction().getCallSiteFlags() | callSiteFlags;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   292
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   293
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   294
    /**
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   295
     * Are we generating code for 'eval' code?
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   296
     * @return true if currently compiled code is 'eval' code.
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   297
     */
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   298
    boolean isEvalCode() {
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   299
        return evalCode;
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   300
    }
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   301
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   302
    /**
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   303
     * Load an identity node
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   304
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   305
     * @param identNode an identity node to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   306
     * @return the method generator used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   307
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   308
    private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   309
        checkTemporalDeadZone(identNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   310
        final Symbol symbol = identNode.getSymbol();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   311
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   312
        if (!symbol.isScope()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   313
            final Type type = identNode.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   314
            if(type == Type.UNDEFINED) {
25829
1a5e1de71e57 8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents: 25826
diff changeset
   315
                return method.loadUndefined(resultBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   316
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   317
16209
18e55b352d56 8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents: 16206
diff changeset
   318
            assert symbol.hasSlot() || symbol.isParam();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   319
            return method.load(identNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   320
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   321
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   322
        assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   323
        final int flags = CALLSITE_SCOPE | getCallSiteFlags();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   324
        if (isFastScope(symbol)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   325
            // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   326
            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   327
                method.loadCompilerConstant(SCOPE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   328
                // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   329
                // just a single definitive type, resultBounds.widest.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   330
                loadSharedScopeVar(resultBounds.widest, symbol, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   331
            } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   332
                new LoadFastScopeVar(identNode, resultBounds, flags).emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   333
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   334
        } else {
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   335
            //slow scope load, we have no proto depth
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   336
            new LoadScopeVar(identNode, resultBounds, flags).emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   337
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   338
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   339
        return method;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   340
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   341
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   342
    // Any access to LET and CONST variables before their declaration must throw ReferenceError.
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   343
    // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   344
    private void checkTemporalDeadZone(final IdentNode identNode) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   345
        if (identNode.isDead()) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   346
            method.load(identNode.getSymbol().getName());
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   347
            method.invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   348
        }
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   349
    }
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   350
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   351
    private boolean isRestOf() {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   352
        return continuationEntryPoints != null;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   353
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   354
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   355
    private boolean isOptimisticOrRestOf() {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   356
        return useOptimisticTypes() || isRestOf();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   357
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   358
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   359
    private boolean isCurrentContinuationEntryPoint(final int programPoint) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   360
        return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   361
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   362
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   363
    private int[] getContinuationEntryPoints() {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   364
        return isRestOf() ? continuationEntryPoints : null;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   365
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   366
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   367
    private int getCurrentContinuationEntryPoint() {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   368
        return isRestOf() ? continuationEntryPoints[0] : INVALID_PROGRAM_POINT;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   369
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   370
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   371
    private boolean isContinuationEntryPoint(final int programPoint) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   372
        if (isRestOf()) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   373
            assert continuationEntryPoints != null;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   374
            for (final int cep : continuationEntryPoints) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   375
                if (cep == programPoint) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   376
                    return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   377
                }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   378
            }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   379
        }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   380
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   381
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   382
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   383
    /**
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   384
     * Check if this symbol can be accessed directly with a putfield or getfield or dynamic load
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   385
     *
18618
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17981
diff changeset
   386
     * @param symbol symbol to check for fast scope
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   387
     * @return true if fast scope
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   388
     */
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   389
    private boolean isFastScope(final Symbol symbol) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   390
        if (!symbol.isScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   391
            return false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   392
        }
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   393
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   394
        if (!lc.inDynamicScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   395
            // If there's no with or eval in context, and the symbol is marked as scoped, it is fast scoped. Such a
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   396
            // symbol must either be global, or its defining block must need scope.
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   397
            assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   398
            return true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   399
        }
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   400
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   401
        if (symbol.isGlobal()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   402
            // Shortcut: if there's a with or eval in context, globals can't be fast scoped
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   403
            return false;
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   404
        }
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   405
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   406
        // Otherwise, check if there's a dynamic scope between use of the symbol and its definition
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   407
        final String name = symbol.getName();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   408
        boolean previousWasBlock = false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   409
        for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   410
            final LexicalContextNode node = it.next();
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   411
            if (node instanceof Block) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   412
                // If this block defines the symbol, then we can fast scope the symbol.
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   413
                final Block block = (Block)node;
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   414
                if (block.getExistingSymbol(name) == symbol) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   415
                    assert block.needsScope();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   416
                    return true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   417
                }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   418
                previousWasBlock = true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   419
            } else {
24749
1549c85f8200 8041625: AccessorProperty currentType must only by Object.class when non-primitive, and scoping followup problem for lazily generated with bodies
lagergren
parents: 24747
diff changeset
   420
                if (node instanceof WithNode && previousWasBlock || node instanceof FunctionNode && ((FunctionNode)node).needsDynamicScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   421
                    // If we hit a scope that can have symbols introduced into it at run time before finding the defining
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   422
                    // block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   423
                    // before - its block. Otherwise, we are currently processing the WithNode's expression, and that's
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   424
                    // obviously not subjected to introducing new symbols.
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   425
                    return false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   426
                }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   427
                previousWasBlock = false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   428
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   429
        }
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   430
        // Should've found the symbol defined in a block
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   431
        throw new AssertionError();
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   432
    }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   433
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   434
    private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   435
        assert !isOptimisticOrRestOf();
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   436
        if (isFastScope(symbol)) {
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   437
            method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   438
        } else {
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   439
            method.load(-1);
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   440
        }
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   441
        return lc.getScopeGet(unit, symbol, valueType, flags | CALLSITE_FAST_SCOPE).generateInvoke(method);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   442
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   443
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   444
    private class LoadScopeVar extends OptimisticOperation {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   445
        final IdentNode identNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   446
        private final int flags;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   447
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   448
        LoadScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   449
            super(identNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   450
            this.identNode = identNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   451
            this.flags = flags;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   452
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   453
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   454
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   455
        void loadStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   456
            method.loadCompilerConstant(SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   457
            getProto();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   458
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   459
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   460
        void getProto() {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   461
            //empty
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   462
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   463
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   464
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   465
        void consumeStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   466
            // If this is either __FILE__, __DIR__, or __LINE__ then load the property initially as Object as we'd convert
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   467
            // it anyway for replaceLocationPropertyPlaceholder.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   468
            if(identNode.isCompileTimePropertyName()) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   469
                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   470
                replaceCompileTimeProperty();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   471
            } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   472
                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   473
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   474
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   475
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   476
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   477
    private class LoadFastScopeVar extends LoadScopeVar {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   478
        LoadFastScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   479
            super(identNode, resultBounds, flags | CALLSITE_FAST_SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   480
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   481
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   482
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   483
        void getProto() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   484
            loadFastScopeProto(identNode.getSymbol(), false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   485
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   486
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   487
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   488
    private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   489
        loadFastScopeProto(symbol, true);
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   490
        method.dynamicSet(symbol.getName(), flags | CALLSITE_FAST_SCOPE, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   491
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   492
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   493
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   494
    private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   495
        //walk up the chain from starting block and when we bump into the current function boundary, add the external
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   496
        //information.
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   497
        final FunctionNode fn   = lc.getCurrentFunction();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   498
        final int externalDepth = compiler.getScriptFunctionData(fn.getId()).getExternalSymbolDepth(symbol.getName());
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   499
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   500
        //count the number of scopes from this place to the start of the function
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   501
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   502
        final int internalDepth = FindScopeDepths.findInternalDepth(lc, fn, startingBlock, symbol);
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   503
        final int scopesToStart = FindScopeDepths.findScopesToStart(lc, fn, startingBlock);
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   504
        int depth = 0;
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   505
        if (internalDepth == -1) {
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   506
            depth = scopesToStart + externalDepth;
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   507
        } else {
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   508
            assert internalDepth <= scopesToStart;
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   509
            depth = internalDepth;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   510
        }
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   511
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   512
        return depth;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   513
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   514
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   515
    private void loadFastScopeProto(final Symbol symbol, final boolean swap) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   516
        final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   517
        assert depth != -1 : "Couldn't find scope depth for symbol " + symbol.getName() + " in " + lc.getCurrentFunction();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   518
        if (depth > 0) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   519
            if (swap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   520
                method.swap();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   521
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   522
            for (int i = 0; i < depth; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   523
                method.invoke(ScriptObject.GET_PROTO);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   524
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   525
            if (swap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   526
                method.swap();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   527
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   528
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   529
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   530
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   531
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   532
     * Generate code that loads this node to the stack, not constraining its type
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   533
     *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   534
     * @param expr node to load
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   535
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   536
     * @return the method emitter used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   537
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   538
    private MethodEmitter loadExpressionUnbounded(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   539
        return loadExpression(expr, TypeBounds.UNBOUNDED);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   540
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   541
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   542
    private MethodEmitter loadExpressionAsObject(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   543
        return loadExpression(expr, TypeBounds.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   544
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   545
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   546
    MethodEmitter loadExpressionAsBoolean(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   547
        return loadExpression(expr, TypeBounds.BOOLEAN);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   548
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   549
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   550
    // Test whether conversion from source to target involves a call of ES 9.1 ToPrimitive
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   551
    // with possible side effects from calling an object's toString or valueOf methods.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   552
    private static boolean noToPrimitiveConversion(final Type source, final Type target) {
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   553
        // Object to boolean conversion does not cause ToPrimitive call
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   554
        return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean();
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   555
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   556
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   557
    MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   558
        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   559
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   560
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   561
    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final TypeBounds explicitOperandBounds, final boolean baseAlreadyOnStack, final boolean forceConversionSeparation) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   562
        // ECMAScript 5.1 specification (sections 11.5-11.11 and 11.13) prescribes that when evaluating a binary
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   563
        // expression "LEFT op RIGHT", the order of operations must be: LOAD LEFT, LOAD RIGHT, CONVERT LEFT, CONVERT
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   564
        // RIGHT, EXECUTE OP. Unfortunately, doing it in this order defeats potential optimizations that arise when we
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   565
        // can combine a LOAD with a CONVERT operation (e.g. use a dynamic getter with the conversion target type as its
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   566
        // return value). What we do here is reorder LOAD RIGHT and CONVERT LEFT when possible; it is possible only when
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   567
        // we can prove that executing CONVERT LEFT can't have a side effect that changes the value of LOAD RIGHT.
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   568
        // Basically, if we know that either LEFT already is a primitive value, or does not have to be converted to
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   569
        // a primitive value, or RIGHT is an expression that loads without side effects, then we can do the
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   570
        // reordering and collapse LOAD/CONVERT into a single operation; otherwise we need to do the more costly
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   571
        // separate operations to preserve specification semantics.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   572
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   573
        // Operands' load type should not be narrower than the narrowest of the individual operand types, nor narrower
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   574
        // than the lower explicit bound, but it should also not be wider than
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   575
        final Type lhsType = undefinedToNumber(lhs.getType());
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   576
        final Type rhsType = undefinedToNumber(rhs.getType());
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   577
        final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   578
        final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   579
        if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   580
            // Can reorder. We might still need to separate conversion, but at least we can do it with reordering
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   581
            if (forceConversionSeparation) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   582
                // Can reorder, but can't move conversion into the operand as the operation depends on operands
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   583
                // exact types for its overflow guarantees. E.g. with {L}{%I}expr1 {L}* {L}{%I}expr2 we are not allowed
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   584
                // to merge {L}{%I} into {%L}, as that can cause subsequent overflows; test for JDK-8058610 contains
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   585
                // concrete cases where this could happen.
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   586
                final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   587
                loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   588
                method.convert(operandBounds.within(method.peekType()));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   589
                loadExpression(rhs, safeConvertBounds, false);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   590
                method.convert(operandBounds.within(method.peekType()));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   591
            } else {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   592
                // Can reorder and move conversion into the operand. Combine load and convert into single operations.
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   593
                loadExpression(lhs, operandBounds, baseAlreadyOnStack);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   594
                loadExpression(rhs, operandBounds, false);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   595
            }
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   596
        } else {
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   597
            // Can't reorder. Load and convert separately.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   598
            final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   599
            loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   600
            final Type lhsLoadedType = method.peekType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   601
            loadExpression(rhs, safeConvertBounds, false);
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   602
            final Type convertedLhsType = operandBounds.within(method.peekType());
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   603
            if (convertedLhsType != lhsLoadedType) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   604
                // Do it conditionally, so that if conversion is a no-op we don't introduce a SWAP, SWAP.
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   605
                method.swap().convert(convertedLhsType).swap();
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   606
            }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   607
            method.convert(operandBounds.within(method.peekType()));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   608
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   609
        assert Type.generic(method.peekType()) == operandBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   610
        assert Type.generic(method.peekType(1)) == operandBounds.narrowest;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   611
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   612
        return method;
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   613
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   614
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   615
    private static final Type undefinedToNumber(final Type type) {
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   616
        return type == Type.UNDEFINED ? Type.NUMBER : type;
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   617
    }
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   618
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   619
    private static final class TypeBounds {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   620
        final Type narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   621
        final Type widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   622
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   623
        static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   624
        static final TypeBounds INT = exact(Type.INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   625
        static final TypeBounds OBJECT = exact(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   626
        static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   627
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   628
        static TypeBounds exact(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   629
            return new TypeBounds(type, type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   630
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   631
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   632
        TypeBounds(final Type narrowest, final Type widest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   633
            assert widest    != null && widest    != Type.UNDEFINED && widest != Type.UNKNOWN : widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   634
            assert narrowest != null && narrowest != Type.UNDEFINED : narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   635
            assert !narrowest.widerThan(widest) : narrowest + " wider than " + widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   636
            assert !widest.narrowerThan(narrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   637
            this.narrowest = Type.generic(narrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   638
            this.widest = Type.generic(widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   639
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   640
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   641
        TypeBounds notNarrowerThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   642
            return maybeNew(Type.narrowest(Type.widest(narrowest, type), widest), widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   643
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   644
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   645
        TypeBounds notWiderThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   646
            return maybeNew(Type.narrowest(narrowest, type), Type.narrowest(widest, type));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   647
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   648
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   649
        boolean canBeNarrowerThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   650
            return narrowest.narrowerThan(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   651
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   652
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   653
        TypeBounds maybeNew(final Type newNarrowest, final Type newWidest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   654
            if(newNarrowest == narrowest && newWidest == widest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   655
                return this;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   656
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   657
            return new TypeBounds(newNarrowest, newWidest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   658
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   659
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   660
        TypeBounds booleanToInt() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   661
            return maybeNew(CodeGenerator.booleanToInt(narrowest), CodeGenerator.booleanToInt(widest));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   662
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   663
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   664
        TypeBounds objectToNumber() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   665
            return maybeNew(CodeGenerator.objectToNumber(narrowest), CodeGenerator.objectToNumber(widest));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   666
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   667
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   668
        Type within(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   669
            if(type.narrowerThan(narrowest)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   670
                return narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   671
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   672
            if(type.widerThan(widest)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   673
                return widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   674
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   675
            return type;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   676
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   677
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   678
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   679
        public String toString() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   680
            return "[" + narrowest + ", " + widest + "]";
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   681
        }
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   682
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   683
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   684
    private static Type booleanToInt(final Type t) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   685
        return t == Type.BOOLEAN ? Type.INT : t;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   686
    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   687
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   688
    private static Type objectToNumber(final Type t) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   689
        return t.isObject() ? Type.NUMBER : t;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   690
    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   691
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   692
    MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   693
        if(type == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   694
            return loadExpressionAsBoolean(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   695
        } else if(type == Type.UNDEFINED) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   696
            assert expr.getType() == Type.UNDEFINED;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   697
            return loadExpressionAsObject(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   698
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   699
        // having no upper bound preserves semantics of optimistic operations in the expression (by not having them
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   700
        // converted early) and then applies explicit conversion afterwards.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   701
        return loadExpression(expr, TypeBounds.UNBOUNDED.notNarrowerThan(type)).convert(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   702
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   703
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   704
    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   705
        return loadExpression(expr, resultBounds, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   706
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   707
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   708
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   709
     * Emits code for evaluating an expression and leaving its value on top of the stack, narrowing or widening it if
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   710
     * necessary.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   711
     * @param expr the expression to load
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   712
     * @param resultBounds the incoming type bounds. The value on the top of the stack is guaranteed to not be of narrower
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   713
     * type than the narrowest bound, or wider type than the widest bound after it is loaded.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   714
     * @param baseAlreadyOnStack true if the base of an access or index node is already on the stack. Used to avoid
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   715
     * double evaluation of bases in self-assignment expressions to access and index nodes. {@code Type.OBJECT} is used
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   716
     * to indicate the widest possible type.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   717
     * @return the method emitter
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   718
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   719
    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds, final boolean baseAlreadyOnStack) {
21694
e15e1f8befa0 8028020: Function parameter as last expression in comma in return value causes bad type calculation
attila
parents: 21462
diff changeset
   720
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   721
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   722
         * The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y"
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   723
         * or IndexNode e.g. "x[y]". Both AccessNodes and IndexNodes are
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   724
         * BaseNodes and the logic for loading the base object is reused
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   725
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   726
        final CodeGenerator codegen = this;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   727
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   728
        final Node currentDiscard = codegen.lc.getCurrentDiscard();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   729
        expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   730
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   731
            public boolean enterIdentNode(final IdentNode identNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   732
                loadIdent(identNode, resultBounds);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   733
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   734
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   735
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   736
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   737
            public boolean enterAccessNode(final AccessNode accessNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   738
                new OptimisticOperation(accessNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   739
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   740
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   741
                        if (!baseAlreadyOnStack) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   742
                            loadExpressionAsObject(accessNode.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   743
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   744
                        assert method.peekType().isObject();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   745
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   746
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   747
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   748
                        final int flags = getCallSiteFlags();
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   749
                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction(), accessNode.isIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   750
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   751
                }.emit(baseAlreadyOnStack ? 1 : 0);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   752
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   753
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   754
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   755
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   756
            public boolean enterIndexNode(final IndexNode indexNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   757
                new OptimisticOperation(indexNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   758
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   759
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   760
                        if (!baseAlreadyOnStack) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   761
                            loadExpressionAsObject(indexNode.getBase());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   762
                            loadExpressionUnbounded(indexNode.getIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   763
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   764
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   765
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   766
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   767
                        final int flags = getCallSiteFlags();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   768
                        dynamicGetIndex(flags, indexNode.isFunction());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   769
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   770
                }.emit(baseAlreadyOnStack ? 2 : 0);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   771
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   772
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   773
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   774
            @Override
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   775
            public boolean enterFunctionNode(final FunctionNode functionNode) {
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   776
                // function nodes will always leave a constructed function object on stack, no need to load the symbol
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   777
                // separately as in enterDefault()
20945
11a1b6dc9893 8026397: Fix ambiguity with array conversion, including passing JS NativeArrays in Java variable arity methods' vararg array position
attila
parents: 20928
diff changeset
   778
                lc.pop(functionNode);
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   779
                functionNode.accept(codegen);
20945
11a1b6dc9893 8026397: Fix ambiguity with array conversion, including passing JS NativeArrays in Java variable arity methods' vararg array position
attila
parents: 20928
diff changeset
   780
                // NOTE: functionNode.accept() will produce a different FunctionNode that we discard. This incidentally
11a1b6dc9893 8026397: Fix ambiguity with array conversion, including passing JS NativeArrays in Java variable arity methods' vararg array position
attila
parents: 20928
diff changeset
   781
                // doesn't cause problems as we're never touching FunctionNode again after it's visited here - codegen
11a1b6dc9893 8026397: Fix ambiguity with array conversion, including passing JS NativeArrays in Java variable arity methods' vararg array position
attila
parents: 20928
diff changeset
   782
                // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
11a1b6dc9893 8026397: Fix ambiguity with array conversion, including passing JS NativeArrays in Java variable arity methods' vararg array position
attila
parents: 20928
diff changeset
   783
                // re-push the original functionNode.
11a1b6dc9893 8026397: Fix ambiguity with array conversion, including passing JS NativeArrays in Java variable arity methods' vararg array position
attila
parents: 20928
diff changeset
   784
                lc.push(functionNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   785
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   786
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   787
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   788
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   789
            public boolean enterASSIGN(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   790
                loadASSIGN(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   791
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   792
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   793
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   794
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   795
            public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   796
                loadASSIGN_ADD(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   797
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   798
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   799
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   800
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   801
            public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   802
                loadASSIGN_BIT_AND(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   803
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   804
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   805
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   806
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   807
            public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   808
                loadASSIGN_BIT_OR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   809
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   810
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   811
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   812
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   813
            public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   814
                loadASSIGN_BIT_XOR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   815
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   816
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   817
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   818
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   819
            public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   820
                loadASSIGN_DIV(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   821
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   822
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   823
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   824
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   825
            public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   826
                loadASSIGN_MOD(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   827
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   828
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   829
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   830
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   831
            public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   832
                loadASSIGN_MUL(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   833
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   834
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   835
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   836
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   837
            public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   838
                loadASSIGN_SAR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   839
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   840
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   841
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   842
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   843
            public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   844
                loadASSIGN_SHL(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   845
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   846
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   847
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   848
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   849
            public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   850
                loadASSIGN_SHR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   851
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   852
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   853
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   854
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   855
            public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   856
                loadASSIGN_SUB(binaryNode);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   857
                return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   858
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   859
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   860
            @Override
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   861
            public boolean enterCallNode(final CallNode callNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   862
                return loadCallNode(callNode, resultBounds);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   863
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   864
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   865
            @Override
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   866
            public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   867
                loadLiteral(literalNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   868
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   869
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   870
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   871
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   872
            public boolean enterTernaryNode(final TernaryNode ternaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   873
                loadTernaryNode(ternaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   874
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   875
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   876
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   877
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   878
            public boolean enterADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   879
                loadADD(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   880
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   881
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   882
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   883
            @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   884
            public boolean enterSUB(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   885
                loadSUB(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   886
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   887
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   888
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   889
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   890
            public boolean enterSUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   891
                loadSUB(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   892
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   893
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   894
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   895
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   896
            public boolean enterMUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   897
                loadMUL(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   898
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   899
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   900
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   901
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   902
            public boolean enterDIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   903
                loadDIV(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   904
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   905
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   906
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   907
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   908
            public boolean enterMOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   909
                loadMOD(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   910
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   911
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   912
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   913
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   914
            public boolean enterSAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   915
                loadSAR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   916
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   917
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   918
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   919
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   920
            public boolean enterSHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   921
                loadSHL(binaryNode);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   922
                return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   923
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   924
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   925
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   926
            public boolean enterSHR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   927
                loadSHR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   928
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   929
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   930
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   931
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   932
            public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   933
                loadCOMMALEFT(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   934
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   935
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   936
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   937
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   938
            public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   939
                loadCOMMARIGHT(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   940
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   941
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   942
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   943
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   944
            public boolean enterAND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   945
                loadAND_OR(binaryNode, resultBounds, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   946
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   947
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   948
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   949
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   950
            public boolean enterOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   951
                loadAND_OR(binaryNode, resultBounds, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   952
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   953
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   954
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   955
            @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   956
            public boolean enterNOT(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   957
                loadNOT(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   958
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   959
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   960
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   961
            @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   962
            public boolean enterADD(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   963
                loadADD(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   964
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   965
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   966
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   967
            @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   968
            public boolean enterBIT_NOT(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   969
                loadBIT_NOT(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   970
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   971
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   972
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   973
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   974
            public boolean enterBIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   975
                loadBIT_AND(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   976
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   977
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   978
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   979
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   980
            public boolean enterBIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   981
                loadBIT_OR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   982
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   983
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   984
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   985
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   986
            public boolean enterBIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   987
                loadBIT_XOR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   988
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   989
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   990
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   991
            @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   992
            public boolean enterVOID(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   993
                loadVOID(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   994
                return false;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   995
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   996
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   997
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   998
            public boolean enterEQ(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   999
                loadCmp(binaryNode, Condition.EQ);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1000
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1001
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1002
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1003
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1004
            public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1005
                loadCmp(binaryNode, Condition.EQ);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1006
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1007
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1008
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1009
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1010
            public boolean enterGE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1011
                loadCmp(binaryNode, Condition.GE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1012
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1013
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1014
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1015
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1016
            public boolean enterGT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1017
                loadCmp(binaryNode, Condition.GT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1018
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1019
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1020
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1021
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1022
            public boolean enterLE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1023
                loadCmp(binaryNode, Condition.LE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1024
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1025
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1026
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1027
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1028
            public boolean enterLT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1029
                loadCmp(binaryNode, Condition.LT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1030
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1031
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1032
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1033
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1034
            public boolean enterNE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1035
                loadCmp(binaryNode, Condition.NE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1036
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1037
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1038
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1039
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1040
            public boolean enterNE_STRICT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1041
                loadCmp(binaryNode, Condition.NE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1042
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1043
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1044
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1045
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1046
            public boolean enterObjectNode(final ObjectNode objectNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1047
                loadObjectNode(objectNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1048
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1049
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1050
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1051
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1052
            public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1053
                loadRuntimeNode(runtimeNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1054
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1055
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1056
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1057
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1058
            public boolean enterNEW(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1059
                loadNEW(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1060
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1061
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1062
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1063
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1064
            public boolean enterDECINC(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1065
                loadDECINC(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1066
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1067
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1068
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1069
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1070
            public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1071
                loadExpression(joinExpr.getExpression(), resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1072
                return false;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1073
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1074
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1075
            @Override
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1076
            public boolean enterGetSplitState(final GetSplitState getSplitState) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1077
                method.loadScope();
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1078
                method.invoke(Scope.GET_SPLIT_STATE);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1079
                return false;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1080
            }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1081
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1082
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1083
            public boolean enterDefault(final Node otherNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1084
                // Must have handled all expressions that can legally be encountered.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1085
                throw new AssertionError(otherNode.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1086
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1087
        });
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1088
        if(currentDiscard != expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1089
            coerceStackTop(resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1090
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1091
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1092
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1093
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1094
    private MethodEmitter coerceStackTop(final TypeBounds typeBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1095
        return method.convert(typeBounds.within(method.peekType()));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1096
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1097
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1098
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1099
     * Closes any still open entries for this block's local variables in the bytecode local variable table.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1100
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1101
     * @param block block containing symbols.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1102
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1103
    private void closeBlockVariables(final Block block) {
17518
2225a4f929c0 8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents: 17255
diff changeset
  1104
        for (final Symbol symbol : block.getSymbols()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1105
            if (symbol.isBytecodeLocal()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1106
                method.closeLocalVariable(symbol, block.getBreakLabel());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1107
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1108
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1109
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1110
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1111
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1112
    public boolean enterBlock(final Block block) {
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1113
        final Label entryLabel = block.getEntryLabel();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1114
        if (entryLabel.isBreakTarget()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1115
            // Entry label is a break target only for an inlined finally block.
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1116
            assert !method.isReachable();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1117
            method.breakLabel(entryLabel, lc.getUsedSlotCount());
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1118
        } else {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1119
            method.label(entryLabel);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1120
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1121
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1122
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1123
        }
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1124
        if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1125
            return false;
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1126
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1127
        initLocals(block);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1128
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1129
        assert lc.getUsedSlotCount() == method.getFirstTemp();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1130
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1131
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1132
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1133
    private boolean useOptimisticTypes() {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1134
        return !lc.inSplitNode() && compiler.useOptimisticTypes();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1135
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1136
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1137
    @Override
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1138
    public Node leaveBlock(final Block block) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1139
        popBlockScope(block);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1140
        method.beforeJoinPoint(block);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1141
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1142
        closeBlockVariables(block);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1143
        lc.releaseSlots();
25821
fbb51e67d2a7 8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents: 25423
diff changeset
  1144
        assert !method.isReachable() || (lc.isFunctionBody() ? 0 : lc.getUsedSlotCount()) == method.getFirstTemp() :
fbb51e67d2a7 8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents: 25423
diff changeset
  1145
            "reachable="+method.isReachable() +
fbb51e67d2a7 8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents: 25423
diff changeset
  1146
            " isFunctionBody=" + lc.isFunctionBody() +
fbb51e67d2a7 8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents: 25423
diff changeset
  1147
            " usedSlotCount=" + lc.getUsedSlotCount() +
fbb51e67d2a7 8048869: Reduce compile time by about 5% by removing the Class.casts from the AST nodes
lagergren
parents: 25423
diff changeset
  1148
            " firstTemp=" + method.getFirstTemp();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1149
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1150
        return block;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1151
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1152
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1153
    private void popBlockScope(final Block block) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1154
        final Label breakLabel = block.getBreakLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1155
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1156
        if(!block.needsScope() || lc.isFunctionBody()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1157
            emitBlockBreakLabel(breakLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1158
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1159
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1160
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1161
        final Label beginTryLabel = scopeEntryLabels.pop();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1162
        final Label recoveryLabel = new Label("block_popscope_catch");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1163
        emitBlockBreakLabel(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1164
        final boolean bodyCanThrow = breakLabel.isAfter(beginTryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1165
        if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1166
            method._try(beginTryLabel, breakLabel, recoveryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1167
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1168
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1169
        Label afterCatchLabel = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1170
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1171
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1172
            popScope();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1173
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1174
                afterCatchLabel = new Label("block_after_catch");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1175
                method._goto(afterCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1176
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1177
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1178
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1179
        if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1180
            assert !method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1181
            method._catch(recoveryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1182
            popScopeException();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1183
            method.athrow();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1184
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1185
        if(afterCatchLabel != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1186
            method.label(afterCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1187
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1188
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1189
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1190
    private void emitBlockBreakLabel(final Label breakLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1191
        // TODO: this is totally backwards. Block should not be breakable, LabelNode should be breakable.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1192
        final LabelNode labelNode = lc.getCurrentBlockLabelNode();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1193
        if(labelNode != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1194
            // Only have conversions if we're reachable
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1195
            assert labelNode.getLocalVariableConversion() == null || method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1196
            method.beforeJoinPoint(labelNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1197
            method.breakLabel(breakLabel, labeledBlockBreakLiveLocals.pop());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1198
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1199
            method.label(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1200
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1201
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1202
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1203
    private void popScope() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1204
        popScopes(1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1205
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1206
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1207
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1208
     * Pop scope as part of an exception handler. Similar to {@code popScope()} but also takes care of adjusting the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1209
     * number of scopes that needs to be popped in case a rest-of continuation handler encounters an exception while
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1210
     * performing a ToPrimitive conversion.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1211
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1212
    private void popScopeException() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1213
        popScope();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1214
        final ContinuationInfo ci = getContinuationInfo();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1215
        if(ci != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1216
            final Label catchLabel = ci.catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1217
            if(catchLabel != METHOD_BOUNDARY && catchLabel == catchLabels.peek()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1218
                ++ci.exceptionScopePops;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1219
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1220
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1221
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1222
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1223
    private void popScopesUntil(final LexicalContextNode until) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1224
        popScopes(lc.getScopeNestingLevelTo(until));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1225
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1226
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1227
    private void popScopes(final int count) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1228
        if(count == 0) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1229
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1230
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1231
        assert count > 0; // together with count == 0 check, asserts nonnegative count
25256
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1232
        if (!method.hasScope()) {
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1233
            // We can sometimes invoke this method even if the method has no slot for the scope object. Typical example:
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1234
            // for(;;) { with({}) { break; } }. WithNode normally creates a scope, but if it uses no identifiers and
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1235
            // nothing else forces creation of a scope in the method, we just won't have the :scope local variable.
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1236
            return;
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1237
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1238
        method.loadCompilerConstant(SCOPE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1239
        for(int i = 0; i < count; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1240
            method.invoke(ScriptObject.GET_PROTO);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1241
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1242
        method.storeCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1243
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1244
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1245
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1246
    public boolean enterBreakNode(final BreakNode breakNode) {
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1247
        return enterJumpStatement(breakNode);
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1248
    }
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1249
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1250
    @Override
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1251
    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1252
        return enterJumpStatement(jumpToInlinedFinally);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1253
    }
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1254
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1255
    private boolean enterJumpStatement(final JumpStatement jump) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1256
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1257
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1258
        }
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1259
        enterStatement(jump);
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1260
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1261
        method.beforeJoinPoint(jump);
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1262
        popScopesUntil(jump.getPopScopeLimit(lc));
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1263
        final Label targetLabel = jump.getTargetLabel(lc);
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1264
        targetLabel.markAsBreakTarget();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1265
        method._goto(targetLabel);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1266
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1267
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1268
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1269
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1270
    private int loadArgs(final List<Expression> args) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1271
        final int argCount = args.size();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1272
        // arg have already been converted to objects here.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1273
        if (argCount > LinkerCallSite.ARGLIMIT) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1274
            loadArgsArray(args);
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  1275
            return 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1276
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1277
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1278
        for (final Expression arg : args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1279
            assert arg != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1280
            loadExpressionUnbounded(arg);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1281
        }
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  1282
        return argCount;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1283
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1284
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1285
    private boolean loadCallNode(final CallNode callNode, final TypeBounds resultBounds) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1286
        lineNumber(callNode.getLineNumber());
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1287
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1288
        final List<Expression> args = callNode.getArgs();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1289
        final Expression function = callNode.getFunction();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1290
        final Block currentBlock = lc.getCurrentBlock();
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1291
        final CodeGeneratorLexicalContext codegenLexicalContext = lc;
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1292
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1293
        function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1294
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1295
            private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1296
                final Symbol symbol = identNode.getSymbol();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1297
                final boolean isFastScope = isFastScope(symbol);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1298
                final int scopeCallFlags = flags | (isFastScope ? CALLSITE_FAST_SCOPE : 0);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1299
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1300
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1301
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1302
                        method.loadCompilerConstant(SCOPE);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1303
                        if (isFastScope) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1304
                            method.load(getScopeProtoDepth(currentBlock, symbol));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1305
                        } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1306
                            method.load(-1); // Bypass fast-scope code in shared callsite
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1307
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1308
                        loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1309
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1310
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1311
                    void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1312
                        final Type[] paramTypes = method.getTypesFromStack(args.size());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1313
                        // We have trouble finding e.g. in Type.typeFor(asm.Type) because it can't see the Context class
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1314
                        // loader, so we need to weaken reference signatures to Object.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1315
                        for(int i = 0; i < paramTypes.length; ++i) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1316
                            paramTypes[i] = Type.generic(paramTypes[i]);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1317
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1318
                        // As shared scope calls are only used in non-optimistic compilation, we switch from using
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1319
                        // TypeBounds to just a single definitive type, resultBounds.widest.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1320
                        final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol,
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1321
                                identNode.getType(), resultBounds.widest, paramTypes, scopeCallFlags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1322
                        scopeCall.generateInvoke(method);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1323
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1324
                }.emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1325
                return method;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1326
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1327
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1328
            private void scopeCall(final IdentNode ident, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1329
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1330
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1331
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1332
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1333
                        loadExpressionAsObject(ident); // foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1334
                        // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
24727
attila
parents: 24725 23372
diff changeset
  1335
                        method.loadUndefined(Type.OBJECT); //the 'this'
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1336
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1337
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1338
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1339
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1340
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1341
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1342
                }.emit();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1343
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1344
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1345
            private void evalCall(final IdentNode ident, final int flags) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1346
                final Label invoke_direct_eval  = new Label("invoke_direct_eval");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1347
                final Label is_not_eval  = new Label("is_not_eval");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1348
                final Label eval_done = new Label("eval_done");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1349
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1350
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1351
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1352
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1353
                    void loadStack() {
25242
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1354
                        /**
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1355
                         * We want to load 'eval' to check if it is indeed global builtin eval.
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1356
                         * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1357
                         * would be generated if ident is a "isFunction". But, that would result in a
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1358
                         * bound function from WithObject. We don't want that as bound function as that
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1359
                         * won't be detected as builtin eval. So, we make ident as "not a function" which
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1360
                         * results in "dyn:getProp|getElem|getMethod" being generated and so WithObject
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1361
                         * would return unbounded eval function.
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1362
                         *
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1363
                         * Example:
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1364
                         *
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1365
                         *  var global = this;
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1366
                         *  function func() {
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1367
                         *      with({ eval: global.eval) { eval("var x = 10;") }
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1368
                         *  }
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1369
                         */
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1370
                        loadExpressionAsObject(ident.setIsNotFunction()); // Type.OBJECT as foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1371
                        globalIsEval();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1372
                        method.ifeq(is_not_eval);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1373
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1374
                        // Load up self (scope).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1375
                        method.loadCompilerConstant(SCOPE);
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1376
                        final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1377
                        // load evaluated code
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1378
                        loadExpressionAsObject(evalArgs.get(0));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1379
                        // load second and subsequent args for side-effect
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1380
                        final int numArgs = evalArgs.size();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1381
                        for (int i = 1; i < numArgs; i++) {
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1382
                            loadAndDiscard(evalArgs.get(i));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1383
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1384
                        method._goto(invoke_direct_eval);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1385
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1386
                        method.label(is_not_eval);
25242
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1387
                        // load this time but with dyn:getMethod|getProp|getElem
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1388
                        loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1389
                        // This is some scope 'eval' or global eval replaced by user
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1390
                        // but not the built-in ECMAScript 'eval' function call
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1391
                        method.loadNull();
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1392
                        argsCount = loadArgs(callNode.getArgs());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1393
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1394
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1395
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1396
                    void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1397
                        // Ordinary call
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1398
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1399
                        method._goto(eval_done);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1400
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1401
                        method.label(invoke_direct_eval);
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1402
                        // Special/extra 'eval' arguments. These can be loaded late (in consumeStack) as we know none of
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1403
                        // them can ever be optimistic.
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1404
                        method.loadCompilerConstant(THIS);
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1405
                        method.load(callNode.getEvalArgs().getLocation());
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1406
                        method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1407
                        // direct call to Global.directEval
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1408
                        globalDirectEval();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1409
                        convertOptimisticReturnValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1410
                        coerceStackTop(resultBounds);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1411
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1412
                }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1413
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1414
                method.label(eval_done);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1415
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1416
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1417
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1418
            public boolean enterIdentNode(final IdentNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1419
                final Symbol symbol = node.getSymbol();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1420
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1421
                if (symbol.isScope()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1422
                    final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1423
                    final int useCount = symbol.getUseCount();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1424
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1425
                    // Threshold for generating shared scope callsite is lower for fast scope symbols because we know
17239
6dd68632cdcd 8011065: Problems when script implements an interface with variadic methods
attila
parents: 17233
diff changeset
  1426
                    // we can dial in the correct scope. However, we also need to enable it for non-fast scopes to
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1427
                    // support huge scripts like mandreel.js.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1428
                    if (callNode.isEval()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1429
                        evalCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1430
                    } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  1431
                            || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1432
                            || CodeGenerator.this.lc.inDynamicScope()
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1433
                            || isOptimisticOrRestOf()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1434
                        scopeCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1435
                    } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1436
                        sharedScopeCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1437
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1438
                    assert method.peekType().equals(resultBounds.within(callNode.getType())) : method.peekType() + " != " + resultBounds + "(" + callNode.getType() + ")";
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1439
                } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1440
                    enterDefault(node);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1441
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1442
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1443
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1444
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1445
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1446
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1447
            public boolean enterAccessNode(final AccessNode node) {
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1448
                //check if this is an apply to call node. only real applies, that haven't been
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1449
                //shadowed from their way to the global scope counts
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1450
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1451
                //call nodes have program points.
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1452
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1453
                final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1454
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1455
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1456
                    int argCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1457
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1458
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1459
                        loadExpressionAsObject(node.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1460
                        method.dup();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1461
                        // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1462
                        // a callable object. Nobody in their right mind would optimistically type this call site.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1463
                        assert !node.isOptimistic();
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  1464
                        method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1465
                        method.swap();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1466
                        argCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1467
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1468
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1469
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1470
                        dynamicCall(2 + argCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1471
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1472
                }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1473
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1474
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1475
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1476
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1477
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1478
            public boolean enterFunctionNode(final FunctionNode origCallee) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1479
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1480
                    FunctionNode callee;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1481
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1482
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1483
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1484
                        callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1485
                        if (callee.isStrict()) { // "this" is undefined
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1486
                            method.loadUndefined(Type.OBJECT);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1487
                        } else { // get global from scope (which is the self)
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1488
                            globalInstance();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1489
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1490
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1491
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1492
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1493
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1494
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1495
                        final int flags = getCallSiteFlags();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1496
                        //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1497
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1498
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1499
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1500
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1501
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1502
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1503
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1504
            public boolean enterIndexNode(final IndexNode node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1505
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1506
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1507
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1508
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1509
                        loadExpressionAsObject(node.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1510
                        method.dup();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1511
                        final Type indexType = node.getIndex().getType();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1512
                        if (indexType.isObject() || indexType.isBoolean()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1513
                            loadExpressionAsObject(node.getIndex()); //TODO boolean
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1514
                        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1515
                            loadExpressionUnbounded(node.getIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1516
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1517
                        // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1518
                        // back a callable object. Nobody in their right mind would optimistically type this call site.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1519
                        assert !node.isOptimistic();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1520
                        method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1521
                        method.swap();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1522
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1523
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1524
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1525
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1526
                        final int flags = getCallSiteFlags();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1527
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1528
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1529
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1530
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1531
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1532
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1533
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1534
            protected boolean enterDefault(final Node node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1535
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1536
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1537
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1538
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1539
                        // Load up function.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1540
                        loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
24727
attila
parents: 24725 23372
diff changeset
  1541
                        method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1542
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1543
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1544
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1545
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1546
                            final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1547
                            dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1548
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1549
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1550
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1551
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1552
        });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1553
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1554
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1555
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1556
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1557
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1558
     * Returns the flags with optimistic flag and program point removed.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1559
     * @param flags the flags that need optimism stripped from them.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1560
     * @return flags without optimism
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1561
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1562
    static int nonOptimisticFlags(final int flags) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1563
        return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1564
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1565
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1566
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1567
    public boolean enterContinueNode(final ContinueNode continueNode) {
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1568
        return enterJumpStatement(continueNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1569
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1570
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1571
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1572
    public boolean enterEmptyNode(final EmptyNode emptyNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1573
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1574
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1575
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1576
        enterStatement(emptyNode);
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  1577
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1578
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1579
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1580
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1581
    @Override
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1582
    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1583
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1584
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1585
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1586
        enterStatement(expressionStatement);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1587
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1588
        loadAndDiscard(expressionStatement.getExpression());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1589
        assert method.getStackSize() == 0;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1590
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1591
        return false;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1592
    }
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1593
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1594
    @Override
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1595
    public boolean enterBlockStatement(final BlockStatement blockStatement) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1596
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1597
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1598
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1599
        enterStatement(blockStatement);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1600
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1601
        blockStatement.getBlock().accept(this);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1602
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1603
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1604
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1605
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1606
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1607
    public boolean enterForNode(final ForNode forNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1608
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1609
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1610
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1611
        enterStatement(forNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1612
        if (forNode.isForIn()) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1613
            enterForIn(forNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1614
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1615
            final Expression init = forNode.getInit();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1616
            if (init != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1617
                loadAndDiscard(init);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1618
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1619
            enterForOrWhile(forNode, forNode.getModify());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1620
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1621
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1622
        return false;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1623
    }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1624
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1625
    private void enterForIn(final ForNode forNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1626
        loadExpression(forNode.getModify(), TypeBounds.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1627
        method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1628
        final Symbol iterSymbol = forNode.getIterator();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1629
        final int iterSlot = iterSymbol.getSlot(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1630
        method.store(iterSymbol, ITERATOR_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1631
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1632
        method.beforeJoinPoint(forNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1633
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1634
        final Label continueLabel = forNode.getContinueLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1635
        final Label breakLabel    = forNode.getBreakLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1636
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1637
        method.label(continueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1638
        method.load(ITERATOR_TYPE, iterSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1639
        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "hasNext", boolean.class));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1640
        final JoinPredecessorExpression test = forNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1641
        final Block body = forNode.getBody();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1642
        if(LocalVariableConversion.hasLiveConversion(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1643
            final Label afterConversion = new Label("for_in_after_test_conv");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1644
            method.ifne(afterConversion);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1645
            method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1646
            method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1647
            method.label(afterConversion);
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1648
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1649
            method.ifeq(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1650
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1651
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1652
        new Store<Expression>(forNode.getInit()) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1653
            @Override
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1654
            protected void storeNonDiscard() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1655
                // This expression is neither part of a discard, nor needs to be left on the stack after it was
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1656
                // stored, so we override storeNonDiscard to be a no-op.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1657
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1658
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1659
            @Override
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1660
            protected void evaluate() {
26507
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1661
                new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1662
                    @Override
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1663
                    void loadStack() {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1664
                        method.load(ITERATOR_TYPE, iterSlot);
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1665
                    }
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1666
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1667
                    @Override
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1668
                    void consumeStack() {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1669
                        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1670
                        convertOptimisticReturnValue();
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1671
                    }
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1672
                }.emit();
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1673
            }
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1674
        }.store();
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1675
        body.accept(this);
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1676
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1677
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1678
            method._goto(continueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1679
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1680
        method.label(breakLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1681
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1682
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1683
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1684
     * Initialize the slots in a frame to undefined.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1685
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1686
     * @param block block with local vars.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1687
     */
16168
f0c208287983 8005976: Break out AccessSpecializer into one pass before CodeGenerator instead of iterative applications from CodeGenerator
lagergren
parents: 16152
diff changeset
  1688
    private void initLocals(final Block block) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1689
        lc.onEnterBlock(block);
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1690
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1691
        final boolean isFunctionBody = lc.isFunctionBody();
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1692
        final FunctionNode function = lc.getCurrentFunction();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1693
        if (isFunctionBody) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1694
            initializeMethodParameters(function);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1695
            if(!function.isVarArg()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1696
                expandParameterSlots(function);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1697
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1698
            if (method.hasScope()) {
18853
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1699
                if (function.needsParentScope()) {
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1700
                    method.loadCompilerConstant(CALLEE);
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1701
                    method.invoke(ScriptFunction.GET_SCOPE);
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1702
                } else {
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1703
                    assert function.hasScopeBlock();
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1704
                    method.loadNull();
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1705
                }
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1706
                method.storeCompilerConstant(SCOPE);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1707
            }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1708
            if (function.needsArguments()) {
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1709
                initArguments(function);
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1710
            }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1711
        }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1712
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1713
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1714
         * Determine if block needs scope, if not, just do initSymbols for this block.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1715
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1716
        if (block.needsScope()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1717
            /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1718
             * Determine if function is varargs and consequently variables have to
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1719
             * be in the scope.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1720
             */
16252
3bfe9b68a0fa 8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents: 16240
diff changeset
  1721
            final boolean varsInScope = function.allVarsInScope();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1722
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1723
            // TODO for LET we can do better: if *block* does not contain any eval/with, we don't need its vars in scope.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1724
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1725
            final boolean hasArguments = function.needsArguments();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1726
            final List<MapTuple<Symbol>> tuples = new ArrayList<>();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1727
            final Iterator<IdentNode> paramIter = function.getParameters().iterator();
17518
2225a4f929c0 8013477: Node.setSymbol needs to be copy on write - enable IR snapshots for recompilation based on callsite type specialization. [not enabled by default, hidden by a flag for now]
lagergren
parents: 17255
diff changeset
  1728
            for (final Symbol symbol : block.getSymbols()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1729
                if (symbol.isInternal() || symbol.isThis()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1730
                    continue;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1731
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1732
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1733
                if (symbol.isVar()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1734
                    assert !varsInScope || symbol.isScope();
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1735
                    if (varsInScope || symbol.isScope()) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1736
                        assert symbol.isScope()   : "scope for " + symbol + " should have been set in Lower already " + function.getName();
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1737
                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already" + function.getName();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1738
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1739
                        //this tuple will not be put fielded, as it has no value, just a symbol
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1740
                        tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, null));
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1741
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1742
                        assert symbol.hasSlot() || symbol.slotCount() == 0 : symbol + " should have a slot only, no scope";
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1743
                    }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1744
                } else if (symbol.isParam() && (varsInScope || hasArguments || symbol.isScope())) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1745
                    assert symbol.isScope()   : "scope for " + symbol + " should have been set in AssignSymbols already " + function.getName() + " varsInScope="+varsInScope+" hasArguments="+hasArguments+" symbol.isScope()=" + symbol.isScope();
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1746
                    assert !(hasArguments && symbol.hasSlot())  : "slot for " + symbol + " should have been removed in Lower already " + function.getName();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1747
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1748
                    final Type   paramType;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1749
                    final Symbol paramSymbol;
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1750
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1751
                    if (hasArguments) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1752
                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already ";
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1753
                        paramSymbol = null;
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1754
                        paramType   = null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1755
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1756
                        paramSymbol = symbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1757
                        // NOTE: We're relying on the fact here that Block.symbols is a LinkedHashMap, hence it will
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1758
                        // return symbols in the order they were defined, and parameters are defined in the same order
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1759
                        // they appear in the function. That's why we can have a single pass over the parameter list
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1760
                        // with an iterator, always just scanning forward for the next parameter that matches the symbol
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1761
                        // name.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1762
                        for(;;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1763
                            final IdentNode nextParam = paramIter.next();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1764
                            if(nextParam.getName().equals(symbol.getName())) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1765
                                paramType = nextParam.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1766
                                break;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1767
                            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1768
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1769
                    }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1770
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1771
                    tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, paramType, paramSymbol) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1772
                        //this symbol will be put fielded, we can't initialize it as undefined with a known type
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1773
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1774
                        public Class<?> getValueType() {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1775
                            if (OBJECT_FIELDS_ONLY || value == null || paramType == null) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1776
                                return Object.class;
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1777
                            }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1778
                            return paramType.isBoolean() ? Object.class : paramType.getTypeClass();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1779
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1780
                    });
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1781
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1782
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1783
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1784
            /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1785
             * Create a new object based on the symbols and values, generate
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1786
             * bootstrap code for object
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1787
             */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1788
            new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1789
                @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1790
                protected void loadValue(final Symbol value, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1791
                    method.load(value, type);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1792
                }
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  1793
            }.makeObject(method);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1794
            // program function: merge scope into global
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1795
            if (isFunctionBody && function.isProgram()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1796
                method.invoke(ScriptRuntime.MERGE_SCOPE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1797
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1798
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1799
            method.storeCompilerConstant(SCOPE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1800
            if(!isFunctionBody) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1801
                // Function body doesn't need a try/catch to restore scope, as it'd be a dead store anyway. Allowing it
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1802
                // actually causes issues with UnwarrantedOptimismException handlers as ASM will sort this handler to
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1803
                // the top of the exception handler table, so it'll be triggered instead of the UOE handlers.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1804
                final Label scopeEntryLabel = new Label("scope_entry");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1805
                scopeEntryLabels.push(scopeEntryLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1806
                method.label(scopeEntryLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1807
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1808
        } else if (isFunctionBody && function.isVarArg()) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1809
            // Since we don't have a scope, parameters didn't get assigned array indices by the FieldObjectCreator, so
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1810
            // we need to assign them separately here.
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1811
            int nextParam = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1812
            for (final IdentNode param : function.getParameters()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1813
                param.getSymbol().setFieldIndex(nextParam++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1814
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1815
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1816
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1817
        // Debugging: print symbols? @see --print-symbols flag
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  1818
        printSymbols(block, function, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1819
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1820
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1821
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1822
     * Incoming method parameters are always declared on method entry; declare them in the local variable table.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1823
     * @param function function for which code is being generated.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1824
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1825
    private void initializeMethodParameters(final FunctionNode function) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1826
        final Label functionStart = new Label("fn_start");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1827
        method.label(functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1828
        int nextSlot = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1829
        if(function.needsCallee()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1830
            initializeInternalFunctionParameter(CALLEE, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1831
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1832
        initializeInternalFunctionParameter(THIS, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1833
        if(function.isVarArg()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1834
            initializeInternalFunctionParameter(VARARGS, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1835
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1836
            for(final IdentNode param: function.getParameters()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1837
                final Symbol symbol = param.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1838
                if(symbol.isBytecodeLocal()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1839
                    method.initializeMethodParameter(symbol, param.getType(), functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1840
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1841
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1842
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1843
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1844
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1845
    private void initializeInternalFunctionParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1846
        final Symbol symbol = initializeInternalFunctionOrSplitParameter(cc, fn, functionStart, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1847
        // Internal function params (:callee, this, and :varargs) are never expanded to multiple slots
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1848
        assert symbol.getFirstSlot() == slot;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1849
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1850
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1851
    private Symbol initializeInternalFunctionOrSplitParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1852
        final Symbol symbol = fn.getBody().getExistingSymbol(cc.symbolName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1853
        final Type type = Type.typeFor(cc.type());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1854
        method.initializeMethodParameter(symbol, type, functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1855
        method.onLocalStore(type, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1856
        return symbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1857
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1858
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1859
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1860
     * Parameters come into the method packed into local variable slots next to each other. Nashorn on the other hand
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1861
     * can use 1-6 slots for a local variable depending on all the types it needs to store. When this method is invoked,
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1862
     * the symbols are already allocated such wider slots, but the values are still in tightly packed incoming slots,
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1863
     * and we need to spread them into their new locations.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1864
     * @param function the function for which parameter-spreading code needs to be emitted
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1865
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1866
    private void expandParameterSlots(final FunctionNode function) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1867
        final List<IdentNode> parameters = function.getParameters();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1868
        // Calculate the total number of incoming parameter slots
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1869
        int currentIncomingSlot = function.needsCallee() ? 2 : 1;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1870
        for(final IdentNode parameter: parameters) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1871
            currentIncomingSlot += parameter.getType().getSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1872
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1873
        // Starting from last parameter going backwards, move the parameter values into their new slots.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1874
        for(int i = parameters.size(); i-- > 0;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1875
            final IdentNode parameter = parameters.get(i);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1876
            final Type parameterType = parameter.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1877
            final int typeWidth = parameterType.getSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1878
            currentIncomingSlot -= typeWidth;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1879
            final Symbol symbol = parameter.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1880
            final int slotCount = symbol.slotCount();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1881
            assert slotCount > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1882
            // Scoped parameters must not hold more than one value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1883
            assert symbol.isBytecodeLocal() || slotCount == typeWidth;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1884
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1885
            // Mark it as having its value stored into it by the method invocation.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1886
            method.onLocalStore(parameterType, currentIncomingSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1887
            if(currentIncomingSlot != symbol.getSlot(parameterType)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1888
                method.load(parameterType, currentIncomingSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1889
                method.store(symbol, parameterType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1890
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1891
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1892
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1893
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1894
    private void initArguments(final FunctionNode function) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1895
        method.loadCompilerConstant(VARARGS);
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1896
        if (function.needsCallee()) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1897
            method.loadCompilerConstant(CALLEE);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1898
        } else {
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1899
            // If function is strict mode, "arguments.callee" is not populated, so we don't necessarily need the
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1900
            // caller.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1901
            assert function.isStrict();
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1902
            method.loadNull();
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1903
        }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1904
        method.load(function.getParameters().size());
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1905
        globalAllocateArguments();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1906
        method.storeCompilerConstant(ARGUMENTS);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1907
    }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1908
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1909
    private boolean skipFunction(final FunctionNode functionNode) {
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1910
        final ScriptEnvironment env = compiler.getScriptEnvironment();
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1911
        final boolean lazy = env._lazy_compilation;
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1912
        final boolean onDemand = compiler.isOnDemandCompilation();
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1913
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1914
        // If this is on-demand or lazy compilation, don't compile a nested (not topmost) function.
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1915
        if((onDemand || lazy) && lc.getOutermostFunction() != functionNode) {
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1916
            return true;
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1917
        }
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1918
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1919
        // If lazy compiling with optimistic types, don't compile the program eagerly either. It will soon be
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1920
        // invalidated anyway. In presence of a class cache, this further means that an obsoleted program version
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1921
        // lingers around. Also, currently loading previously persisted optimistic types information only works if
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1922
        // we're on-demand compiling a function, so with this strategy the :program method can also have the warmup
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1923
        // benefit of using previously persisted types.
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  1924
        //
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1925
        // NOTE that this means the first compiled class will effectively just have a :createProgramFunction method, and
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1926
        // the RecompilableScriptFunctionData (RSFD) object in its constants array. It won't even have the :program
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1927
        // method. This is by design. It does mean that we're wasting one compiler execution (and we could minimize this
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1928
        // by just running it up to scope depth calculation, which creates the RSFDs and then this limited codegen).
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1929
        // We could emit an initial separate compile unit with the initial version of :program in it to better utilize
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1930
        // the compilation pipeline, but that would need more invasive changes, as currently the assumption that
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1931
        // :program is emitted into the first compilation unit of the function lives in many places.
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  1932
        return !onDemand && lazy && env._optimistic_types && functionNode.isProgram();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1933
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1934
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1935
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1936
    public boolean enterFunctionNode(final FunctionNode functionNode) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1937
        final int fnId = functionNode.getId();
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  1938
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  1939
        if (skipFunction(functionNode)) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1940
            // In case we are not generating code for the function, we must create or retrieve the function object and
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1941
            // load it on the stack here.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1942
            newFunctionObject(functionNode, false);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1943
            return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1944
        }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1945
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1946
        final String fnName = functionNode.getName();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1947
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1948
        // NOTE: we only emit the method for a function with the given name once. We can have multiple functions with
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1949
        // the same name as a result of inlining finally blocks. However, in the future -- with type specialization,
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1950
        // notably -- we might need to check for both name *and* signature. Of course, even that might not be
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1951
        // sufficient; the function might have a code dependency on the type of the variables in its enclosing scopes,
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1952
        // and the type of such a variable can be different in catch and finally blocks. So, in the future we will have
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1953
        // to decide to either generate a unique method for each inlined copy of the function, maybe figure out its
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1954
        // exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1955
        // worth it, and generate one method with most generic type closure.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1956
        if (!emittedMethods.contains(fnName)) {
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
  1957
            log.info("=== BEGIN ", fnName);
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1958
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1959
            assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode);
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1960
            unit = lc.pushCompileUnit(functionNode.getCompileUnit());
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1961
            assert lc.hasCompileUnits();
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1962
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1963
            final ClassEmitter classEmitter = unit.getClassEmitter();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1964
            pushMethodEmitter(isRestOf() ? classEmitter.restOfMethod(functionNode) : classEmitter.method(functionNode));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1965
            method.setPreventUndefinedLoad();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1966
            if(useOptimisticTypes()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1967
                lc.pushUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1968
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1969
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1970
            // new method - reset last line number
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1971
            lastLineNumber = -1;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1972
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1973
            method.begin();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1974
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1975
            if (isRestOf()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1976
                final ContinuationInfo ci = new ContinuationInfo();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1977
                fnIdToContinuationInfo.put(fnId, ci);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1978
                method.gotoLoopStart(ci.getHandlerLabel());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1979
            }
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1980
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1981
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1982
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1983
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1984
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1985
    private void pushMethodEmitter(final MethodEmitter newMethod) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1986
        method = lc.pushMethodEmitter(newMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1987
        catchLabels.push(METHOD_BOUNDARY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1988
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1989
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1990
    private void popMethodEmitter() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1991
        method = lc.popMethodEmitter(method);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1992
        assert catchLabels.peek() == METHOD_BOUNDARY;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1993
        catchLabels.pop();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1994
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1995
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1996
    @Override
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1997
    public Node leaveFunctionNode(final FunctionNode functionNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1998
        try {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1999
            final boolean markOptimistic;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2000
            if (emittedMethods.add(functionNode.getName())) {
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  2001
                markOptimistic = generateUnwarrantedOptimismExceptionHandlers(functionNode);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2002
                generateContinuationHandler();
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2003
                method.end(); // wrap up this method
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2004
                unit   = lc.popCompileUnit(functionNode.getCompileUnit());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2005
                popMethodEmitter();
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
  2006
                log.info("=== END ", functionNode.getName());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2007
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2008
                markOptimistic = false;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2009
            }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2010
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2011
            FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2012
            if (markOptimistic) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2013
                newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2014
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2015
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2016
            newFunctionObject(newFunctionNode, true);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2017
            return newFunctionNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2018
        } catch (final Throwable t) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2019
            Context.printStackTrace(t);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2020
            final VerifyError e = new VerifyError("Code generation bug in \"" + functionNode.getName() + "\": likely stack misaligned: " + t + " " + functionNode.getSource().getName());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2021
            e.initCause(t);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2022
            throw e;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2023
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2024
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2025
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2026
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2027
    public boolean enterIfNode(final IfNode ifNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2028
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2029
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2030
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2031
        enterStatement(ifNode);
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  2032
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2033
        final Expression test = ifNode.getTest();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2034
        final Block pass = ifNode.getPass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2035
        final Block fail = ifNode.getFail();
27971
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2036
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2037
        if (Expression.isAlwaysTrue(test)) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2038
            loadAndDiscard(test);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2039
            pass.accept(this);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2040
            return false;
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2041
        } else if (Expression.isAlwaysFalse(test)) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2042
            loadAndDiscard(test);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2043
            if (fail != null) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2044
                fail.accept(this);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2045
            }
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2046
            return false;
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2047
        }
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2048
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2049
        final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2050
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2051
        final Label failLabel  = new Label("if_fail");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2052
        final Label afterLabel = (fail == null && !hasFailConversion) ? null : new Label("if_done");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2053
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2054
        emitBranch(test, failLabel, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2055
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2056
        pass.accept(this);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2057
        if(method.isReachable() && afterLabel != null) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2058
            method._goto(afterLabel); //don't fallthru to fail block
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2059
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2060
        method.label(failLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2061
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2062
        if (fail != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2063
            fail.accept(this);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2064
        } else if(hasFailConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2065
            method.beforeJoinPoint(ifNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2066
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2067
27971
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2068
        if(afterLabel != null && afterLabel.isReachable()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2069
            method.label(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2070
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2071
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2072
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2073
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2074
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2075
    private void emitBranch(final Expression test, final Label label, final boolean jumpWhenTrue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2076
        new BranchOptimizer(this, method).execute(test, label, jumpWhenTrue);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2077
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2078
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2079
    private void enterStatement(final Statement statement) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2080
        lineNumber(statement);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2081
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2082
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  2083
    private void lineNumber(final Statement statement) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2084
        lineNumber(statement.getLineNumber());
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2085
    }
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2086
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  2087
    private void lineNumber(final int lineNumber) {
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2088
        if (lineNumber != lastLineNumber && lineNumber != Node.NO_LINE_NUMBER) {
18621
9e756415f82b 8019226: line number not generated for first statement if it is on the same function declaration line
sundar
parents: 18618
diff changeset
  2089
            method.lineNumber(lineNumber);
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2090
            lastLineNumber = lineNumber;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2091
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2092
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2093
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2094
    int getLastLineNumber() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2095
        return lastLineNumber;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2096
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2097
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2098
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2099
     * Load a list of nodes as an array of a specific type
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2100
     * The array will contain the visited nodes.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2101
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2102
     * @param arrayLiteralNode the array of contents
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2103
     * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2104
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2105
     * @return the method generator that was used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2106
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2107
    private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
18633
c2138d47b2c6 8017082: Long array literals were slightly broken
lagergren
parents: 18631
diff changeset
  2108
        assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2109
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2110
        final Expression[]    nodes    = arrayLiteralNode.getValue();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2111
        final Object          presets  = arrayLiteralNode.getPresets();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2112
        final int[]           postsets = arrayLiteralNode.getPostsets();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2113
        final Class<?>        type     = arrayType.getTypeClass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2114
        final List<ArrayUnit> units    = arrayLiteralNode.getUnits();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2115
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2116
        loadConstant(presets);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2117
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2118
        final Type elementType = arrayType.getElementType();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2119
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2120
        if (units != null) {
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2121
            final MethodEmitter savedMethod     = method;
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2122
            final FunctionNode  currentFunction = lc.getCurrentFunction();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2123
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2124
            for (final ArrayUnit arrayUnit : units) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2125
                unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2126
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2127
                final String className = unit.getUnitClassName();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2128
                assert unit != null;
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2129
                final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2130
                final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2131
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2132
                pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2133
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2134
                method.setFunctionNode(currentFunction);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2135
                method.begin();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2136
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2137
                defineCommonSplitMethodParameters();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2138
                defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2139
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2140
                // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2141
                // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2142
                final int arraySlot = fixScopeSlot(currentFunction, 3);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2143
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2144
                lc.enterSplitNode();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2145
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2146
                for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2147
                    method.load(arrayType, arraySlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2148
                    storeElement(nodes, elementType, postsets[i]);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2149
                }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2150
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2151
                method.load(arrayType, arraySlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2152
                method._return();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2153
                lc.exitSplitNode();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2154
                method.end();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2155
                lc.releaseSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2156
                popMethodEmitter();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2157
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2158
                assert method == savedMethod;
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2159
                method.loadCompilerConstant(CALLEE);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2160
                method.swap();
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2161
                method.loadCompilerConstant(THIS);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2162
                method.swap();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2163
                method.loadCompilerConstant(SCOPE);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2164
                method.swap();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2165
                method.invokestatic(className, name, signature);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2166
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2167
                unit = lc.popCompileUnit(unit);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2168
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2169
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2170
            return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2171
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2172
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2173
        if(postsets.length > 0) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2174
            final int arraySlot = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2175
            method.storeTemp(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2176
            for (final int postset : postsets) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2177
                method.load(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2178
                storeElement(nodes, elementType, postset);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2179
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2180
            method.load(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2181
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2182
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2183
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2184
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2185
    private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2186
        method.load(index);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2187
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2188
        final Expression element = nodes[index];
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2189
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2190
        if (element == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2191
            method.loadEmpty(elementType);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2192
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2193
            loadExpressionAsType(element, elementType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2194
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2195
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2196
        method.arraystore();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2197
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2198
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2199
    private MethodEmitter loadArgsArray(final List<Expression> args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2200
        final Object[] array = new Object[args.size()];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2201
        loadConstant(array);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2202
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2203
        for (int i = 0; i < args.size(); i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2204
            method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2205
            method.load(i);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2206
            loadExpression(args.get(i), TypeBounds.OBJECT); // variable arity methods always take objects
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2207
            method.arraystore();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2208
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2209
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2210
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2211
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2212
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2213
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2214
     * Load a constant from the constant array. This is only public to be callable from the objects
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2215
     * subpackage. Do not call directly.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2216
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2217
     * @param string string to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2218
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2219
    void loadConstant(final String string) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2220
        final String       unitClassName = unit.getUnitClassName();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2221
        final ClassEmitter classEmitter  = unit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2222
        final int          index         = compiler.getConstantData().add(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2223
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2224
        method.load(index);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2225
        method.invokestatic(unitClassName, GET_STRING.symbolName(), methodDescriptor(String.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2226
        classEmitter.needGetConstantMethod(String.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2227
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2228
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2229
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2230
     * Load a constant from the constant array. This is only public to be callable from the objects
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2231
     * subpackage. Do not call directly.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2232
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2233
     * @param object object to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2234
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2235
    void loadConstant(final Object object) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2236
        loadConstant(object, unit, method);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2237
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2238
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2239
    private void loadConstant(final Object object, final CompileUnit compileUnit, final MethodEmitter methodEmitter) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2240
        final String       unitClassName = compileUnit.getUnitClassName();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2241
        final ClassEmitter classEmitter  = compileUnit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2242
        final int          index         = compiler.getConstantData().add(object);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2243
        final Class<?>     cls           = object.getClass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2244
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2245
        if (cls == PropertyMap.class) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2246
            methodEmitter.load(index);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2247
            methodEmitter.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2248
            classEmitter.needGetConstantMethod(PropertyMap.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2249
        } else if (cls.isArray()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2250
            methodEmitter.load(index);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2251
            final String methodName = ClassEmitter.getArrayMethodName(cls);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2252
            methodEmitter.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2253
            classEmitter.needGetConstantMethod(cls);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2254
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2255
            methodEmitter.loadConstants().load(index).arrayload();
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
  2256
            if (object instanceof ArrayData) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2257
                methodEmitter.checkcast(ArrayData.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2258
                methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
  2259
            } else if (cls != Object.class) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2260
                methodEmitter.checkcast(cls);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2261
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2262
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2263
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2264
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2265
    private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2266
        methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2267
    }
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2268
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2269
    // literal values
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2270
    private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2271
        final Object value = node.getValue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2272
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2273
        if (value == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2274
            method.loadNull();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2275
        } else if (value instanceof Undefined) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2276
            method.loadUndefined(resultBounds.within(Type.OBJECT));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2277
        } else if (value instanceof String) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2278
            final String string = (String)value;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2279
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  2280
            if (string.length() > MethodEmitter.LARGE_STRING_THRESHOLD / 3) { // 3 == max bytes per encoded char
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2281
                loadConstant(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2282
            } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2283
                method.load(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2284
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2285
        } else if (value instanceof RegexToken) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2286
            loadRegex((RegexToken)value);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2287
        } else if (value instanceof Boolean) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2288
            method.load((Boolean)value);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2289
        } else if (value instanceof Integer) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2290
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2291
                method.load((Integer)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2292
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2293
            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2294
                method.load(((Integer)value).doubleValue());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2295
            } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2296
                method.load(((Integer)value).longValue());
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2297
            } else {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2298
                method.load((Integer)value);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2299
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2300
        } else if (value instanceof Long) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2301
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2302
                method.load((Long)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2303
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2304
            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2305
                method.load(((Long)value).doubleValue());
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2306
            } else {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2307
                method.load((Long)value);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2308
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2309
        } else if (value instanceof Double) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2310
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2311
                method.load((Double)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2312
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2313
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2314
                method.load((Double)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2315
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2316
        } else if (node instanceof ArrayLiteralNode) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2317
            final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2318
            final ArrayType atype = arrayLiteral.getArrayType();
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2319
            loadArray(arrayLiteral, atype);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2320
            globalAllocateArray(atype);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2321
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2322
            throw new UnsupportedOperationException("Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2323
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2324
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2325
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2326
    private MethodEmitter loadRegexToken(final RegexToken value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2327
        method.load(value.getExpression());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2328
        method.load(value.getOptions());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2329
        return globalNewRegExp();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2330
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2331
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2332
    private MethodEmitter loadRegex(final RegexToken regexToken) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2333
        if (regexFieldCount > MAX_REGEX_FIELDS) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2334
            return loadRegexToken(regexToken);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2335
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2336
        // emit field
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2337
        final String       regexName    = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2338
        final ClassEmitter classEmitter = unit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2339
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2340
        classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2341
        regexFieldCount++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2342
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2343
        // get field, if null create new regex, finally clone regex object
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2344
        method.getStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2345
        method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2346
        final Label cachedLabel = new Label("cached");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2347
        method.ifnonnull(cachedLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2348
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2349
        method.pop();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2350
        loadRegexToken(regexToken);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2351
        method.dup();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2352
        method.putStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2353
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2354
        method.label(cachedLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2355
        globalRegExpCopy();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2356
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2357
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2358
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2359
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2360
    /**
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2361
     * Check if a property value contains a particular program point
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2362
     * @param value value
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2363
     * @param pp    program point
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2364
     * @return true if it's there.
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2365
     */
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2366
    private static boolean propertyValueContains(final Expression value, final int pp) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2367
        return new Supplier<Boolean>() {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2368
            boolean contains;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2369
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2370
            @Override
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2371
            public Boolean get() {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2372
                value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2373
                    @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2374
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2375
                        return false;
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2376
                    }
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2377
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2378
                    @Override
24764
722a9603b237 8043633: In order to remove global state outside of contexts, make sure Timing class is an instance and not a static global collection of data. Move into Context. Move -Dnashorn.timing to an official logging option.
lagergren
parents: 24760
diff changeset
  2379
                    public boolean enterObjectNode(final ObjectNode objectNode) {
24760
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2380
                        return false;
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2381
                    }
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2382
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2383
                    @Override
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2384
                    public boolean enterDefault(final Node node) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2385
                        if (contains) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2386
                            return false;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2387
                        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2388
                        if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2389
                            contains = true;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2390
                            return false;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2391
                        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2392
                        return true;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2393
                    }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2394
                });
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2395
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2396
                return contains;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2397
            }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2398
        }.get();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2399
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2400
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2401
    private void loadObjectNode(final ObjectNode objectNode) {
17981
9b8e085aa1fe 8015955: ObjectNode.elements should be stronger typed
attila
parents: 17969
diff changeset
  2402
        final List<PropertyNode> elements = objectNode.getElements();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2403
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2404
        final List<MapTuple<Expression>> tuples = new ArrayList<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2405
        final List<PropertyNode> gettersSetters = new ArrayList<>();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2406
        final int ccp = getCurrentContinuationEntryPoint();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2407
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2408
        Expression protoNode = null;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2409
        boolean restOfProperty = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2410
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2411
        for (final PropertyNode propertyNode : elements) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2412
            final Expression value = propertyNode.getValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2413
            final String key = propertyNode.getKeyName();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2414
            // Just use a pseudo-symbol. We just need something non null; use the name and zero flags.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2415
            final Symbol symbol = value == null ? null : new Symbol(key, 0);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2416
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2417
            if (value == null) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2418
                gettersSetters.add(propertyNode);
24281
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2419
            } else if (propertyNode.getKey() instanceof IdentNode &&
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2420
                       key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2421
                // ES6 draft compliant __proto__ inside object literal
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2422
                // Identifier key and name is __proto__
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2423
                protoNode = value;
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2424
                continue;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2425
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2426
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2427
            restOfProperty |=
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2428
                value != null &&
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2429
                isValid(ccp) &&
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2430
                propertyValueContains(value, ccp);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2431
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2432
            //for literals, a value of null means object type, i.e. the value null or getter setter function
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2433
            //(I think)
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2434
            final Class<?> valueType = (OBJECT_FIELDS_ONLY || value == null || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2435
            tuples.add(new MapTuple<Expression>(key, symbol, Type.typeFor(valueType), value) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2436
                @Override
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2437
                public Class<?> getValueType() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2438
                    return type.getTypeClass();
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2439
                }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2440
            });
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2441
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2442
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2443
        final ObjectCreator<?> oc;
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2444
        if (elements.size() > OBJECT_SPILL_THRESHOLD) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2445
            oc = new SpillObjectCreator(this, tuples);
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2446
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2447
            oc = new FieldObjectCreator<Expression>(this, tuples) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2448
                @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2449
                protected void loadValue(final Expression node, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2450
                    loadExpressionAsType(node, type);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2451
                }};
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2452
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2453
        oc.makeObject(method);
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2454
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2455
        //if this is a rest of method and our continuation point was found as one of the values
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2456
        //in the properties above, we need to reset the map to oc.getMap() in the continuation
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2457
        //handler
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2458
        if (restOfProperty) {
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2459
            final ContinuationInfo ci = getContinuationInfo();
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2460
            // Can be set at most once for a single rest-of method
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2461
            assert ci.getObjectLiteralMap() == null;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2462
            ci.setObjectLiteralMap(oc.getMap());
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2463
            ci.setObjectLiteralStackDepth(method.getStackSize());
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2464
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2465
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2466
        method.dup();
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2467
        if (protoNode != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2468
            loadExpressionAsObject(protoNode);
24772
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2469
            // take care of { __proto__: 34 } or some such!
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2470
            method.convert(Type.OBJECT);
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2471
            method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2472
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2473
            method.invoke(ScriptObject.SET_GLOBAL_OBJECT_PROTO);
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2474
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2475
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2476
        for (final PropertyNode propertyNode : gettersSetters) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2477
            final FunctionNode getter = propertyNode.getGetter();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2478
            final FunctionNode setter = propertyNode.getSetter();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2479
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2480
            assert getter != null || setter != null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2481
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2482
            method.dup().loadKey(propertyNode.getKey());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2483
            if (getter == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2484
                method.loadNull();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2485
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2486
                getter.accept(this);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2487
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2488
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2489
            if (setter == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2490
                method.loadNull();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2491
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2492
                setter.accept(this);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2493
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2494
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2495
            method.invoke(ScriptObject.SET_USER_ACCESSORS);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2496
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2497
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2498
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2499
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2500
    public boolean enterReturnNode(final ReturnNode returnNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2501
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2502
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2503
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2504
        enterStatement(returnNode);
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  2505
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2506
        method.registerReturn();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2507
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2508
        final Type returnType = lc.getCurrentFunction().getReturnType();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2509
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2510
        final Expression expression = returnNode.getExpression();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2511
        if (expression != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2512
            loadExpressionUnbounded(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2513
        } else {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2514
            method.loadUndefined(returnType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2515
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2516
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2517
        method._return(returnType);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2518
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2519
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2520
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2521
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2522
    private boolean undefinedCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2523
        final Request request = runtimeNode.getRequest();
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2524
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2525
        if (!Request.isUndefinedCheck(request)) {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2526
            return false;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2527
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2528
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2529
        final Expression lhs = args.get(0);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2530
        final Expression rhs = args.get(1);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2531
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2532
        final Symbol lhsSymbol = lhs instanceof IdentNode ? ((IdentNode)lhs).getSymbol() : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2533
        final Symbol rhsSymbol = rhs instanceof IdentNode ? ((IdentNode)rhs).getSymbol() : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2534
        // One must be a "undefined" identifier, otherwise we can't get here
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2535
        assert lhsSymbol != null || rhsSymbol != null;
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2536
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2537
        final Symbol undefinedSymbol;
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2538
        if (isUndefinedSymbol(lhsSymbol)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2539
            undefinedSymbol = lhsSymbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2540
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2541
            assert isUndefinedSymbol(rhsSymbol);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2542
            undefinedSymbol = rhsSymbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2543
        }
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2544
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2545
        assert undefinedSymbol != null; //remove warning
24781
00f645e2d28a 8044803: Unnecessary restOf check
attila
parents: 24774
diff changeset
  2546
        if (!undefinedSymbol.isScope()) {
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2547
            return false; //disallow undefined as local var or parameter
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2548
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2549
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2550
        if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2551
            //we load the undefined first. never mind, because this will deoptimize anyway
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2552
            return false;
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2553
        }
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2554
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2555
        if(isDeoptimizedExpression(lhs)) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2556
            // This is actually related to "lhs.getType().isPrimitive()" above: any expression being deoptimized in
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2557
            // the current chain of rest-of compilations used to have a type narrower than Object (so it was primitive).
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2558
            // We must not perform undefined check specialization for them, as then we'd violate the basic rule of
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2559
            // "Thou shalt not alter the stack shape between a deoptimized method and any of its (transitive) rest-ofs."
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2560
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2561
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2562
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2563
        //make sure that undefined has not been overridden or scoped as a local var
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2564
        //between us and global
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2565
        if (!compiler.isGlobalSymbol(lc.getCurrentFunction(), "undefined")) {
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  2566
            return false;
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2567
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2568
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2569
        final boolean isUndefinedCheck = request == Request.IS_UNDEFINED;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2570
        final Expression expr = undefinedSymbol == lhsSymbol ? rhs : lhs;
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2571
        if (expr.getType().isPrimitive()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2572
            loadAndDiscard(expr); //throw away lhs, but it still needs to be evaluated for side effects, even if not in scope, as it can be optimistic
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2573
            method.load(!isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2574
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2575
            final Label checkTrue  = new Label("ud_check_true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2576
            final Label end        = new Label("end");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2577
            loadExpressionAsObject(expr);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2578
            method.loadUndefined(Type.OBJECT);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2579
            method.if_acmpeq(checkTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2580
            method.load(!isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2581
            method._goto(end);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2582
            method.label(checkTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2583
            method.load(isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2584
            method.label(end);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2585
        }
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2586
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2587
        return true;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2588
    }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2589
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2590
    private static boolean isUndefinedSymbol(final Symbol symbol) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2591
        return symbol != null && "undefined".equals(symbol.getName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2592
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2593
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2594
    private static boolean isNullLiteral(final Node node) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2595
        return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2596
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2597
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2598
    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2599
        final Request request = runtimeNode.getRequest();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2600
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2601
        if (!Request.isEQ(request) && !Request.isNE(request)) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2602
            return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2603
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2604
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2605
        assert args.size() == 2 : "EQ or NE or TYPEOF need two args";
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2606
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2607
        Expression lhs = args.get(0);
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2608
        Expression rhs = args.get(1);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2609
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2610
        if (isNullLiteral(lhs)) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2611
            final Expression tmp = lhs;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2612
            lhs = rhs;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2613
            rhs = tmp;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2614
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2615
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2616
        if (!isNullLiteral(rhs)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2617
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2618
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2619
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2620
        if (!lhs.getType().isObject()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2621
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2622
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2623
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2624
        if(isDeoptimizedExpression(lhs)) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2625
            // This is actually related to "!lhs.getType().isObject()" above: any expression being deoptimized in
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2626
            // the current chain of rest-of compilations used to have a type narrower than Object. We must not
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2627
            // perform null check specialization for them, as then we'd no longer be loading aconst_null on stack
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2628
            // and thus violate the basic rule of "Thou shalt not alter the stack shape between a deoptimized
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2629
            // method and any of its (transitive) rest-ofs."
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2630
            // NOTE also that if we had a representation for well-known constants (e.g. null, 0, 1, -1, etc.) in
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2631
            // Label$Stack.localLoads then this wouldn't be an issue, as we would never (somewhat ridiculously)
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2632
            // allocate a temporary local to hold the result of aconst_null before attempting an optimistic
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2633
            // operation.
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2634
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2635
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2636
18631
537b279999e5 8016667: Wrong bytecode when testing/setting due to null check shortcut checking against primitive too
lagergren
parents: 18628
diff changeset
  2637
        // this is a null literal check, so if there is implicit coercion
537b279999e5 8016667: Wrong bytecode when testing/setting due to null check shortcut checking against primitive too
lagergren
parents: 18628
diff changeset
  2638
        // involved like {D}x=null, we will fail - this is very rare
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2639
        final Label trueLabel  = new Label("trueLabel");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2640
        final Label falseLabel = new Label("falseLabel");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2641
        final Label endLabel   = new Label("end");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2642
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2643
        loadExpressionUnbounded(lhs);    //lhs
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2644
        final Label popLabel;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2645
        if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2646
            method.dup(); //lhs lhs
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2647
            popLabel = new Label("pop");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2648
        } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2649
            popLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2650
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2651
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2652
        if (Request.isEQ(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2653
            method.ifnull(!Request.isStrict(request) ? popLabel : trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2654
            if (!Request.isStrict(request)) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2655
                method.loadUndefined(Type.OBJECT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2656
                method.if_acmpeq(trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2657
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2658
            method.label(falseLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2659
            method.load(false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2660
            method._goto(endLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2661
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2662
                method.label(popLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2663
                method.pop();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2664
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2665
            method.label(trueLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2666
            method.load(true);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2667
            method.label(endLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2668
        } else if (Request.isNE(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2669
            method.ifnull(!Request.isStrict(request) ? popLabel : falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2670
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2671
                method.loadUndefined(Type.OBJECT);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2672
                method.if_acmpeq(falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2673
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2674
            method.label(trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2675
            method.load(true);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2676
            method._goto(endLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2677
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2678
                method.label(popLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2679
                method.pop();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2680
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2681
            method.label(falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2682
            method.load(false);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2683
            method.label(endLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2684
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2685
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2686
        assert runtimeNode.getType().isBoolean();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2687
        method.convert(runtimeNode.getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2688
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2689
        return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2690
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2691
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2692
    /**
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2693
     * Was this expression or any of its subexpressions deoptimized in the current recompilation chain of rest-of methods?
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2694
     * @param rootExpr the expression being tested
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2695
     * @return true if the expression or any of its subexpressions was deoptimized in the current recompilation chain.
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2696
     */
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2697
    private boolean isDeoptimizedExpression(final Expression rootExpr) {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2698
        if(!isRestOf()) {
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2699
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2700
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2701
        return new Supplier<Boolean>() {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2702
            boolean contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2703
            @Override
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2704
            public Boolean get() {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2705
                rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2706
                    @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2707
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2708
                        return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2709
                    }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2710
                    @Override
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2711
                    public boolean enterDefault(final Node node) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2712
                        if(!contains && node instanceof Optimistic) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2713
                            final int pp = ((Optimistic)node).getProgramPoint();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2714
                            contains = isValid(pp) && isContinuationEntryPoint(pp);
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2715
                        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2716
                        return !contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2717
                    }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2718
                });
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2719
                return contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2720
            }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2721
        }.get();
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  2722
    }
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  2723
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2724
    private void loadRuntimeNode(final RuntimeNode runtimeNode) {
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2725
        final List<Expression> args = new ArrayList<>(runtimeNode.getArgs());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2726
        if (nullCheck(runtimeNode, args)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2727
           return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2728
        } else if(undefinedCheck(runtimeNode, args)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2729
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2730
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2731
        // Revert a false undefined check to a strict equality check
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2732
        final RuntimeNode newRuntimeNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2733
        final Request request = runtimeNode.getRequest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2734
        if (Request.isUndefinedCheck(request)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2735
            newRuntimeNode = runtimeNode.setRequest(request == Request.IS_UNDEFINED ? Request.EQ_STRICT : Request.NE_STRICT);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2736
        } else {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2737
            newRuntimeNode = runtimeNode;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2738
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2739
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2740
        new OptimisticOperation(newRuntimeNode, TypeBounds.UNBOUNDED) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2741
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2742
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2743
                for (final Expression arg : args) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2744
                    loadExpression(arg, TypeBounds.OBJECT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2745
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2746
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2747
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2748
            void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2749
                method.invokestatic(
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2750
                        CompilerConstants.className(ScriptRuntime.class),
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2751
                        newRuntimeNode.getRequest().toString(),
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2752
                        new FunctionSignature(
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2753
                            false,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2754
                            false,
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2755
                            newRuntimeNode.getType(),
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2756
                            args.size()).toString());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2757
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2758
        }.emit();
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2759
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2760
        method.convert(newRuntimeNode.getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2761
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2762
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2763
    private void defineCommonSplitMethodParameters() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2764
        defineSplitMethodParameter(0, CALLEE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2765
        defineSplitMethodParameter(1, THIS);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2766
        defineSplitMethodParameter(2, SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2767
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2768
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2769
    private void defineSplitMethodParameter(final int slot, final CompilerConstants cc) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2770
        defineSplitMethodParameter(slot, Type.typeFor(cc.type()));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2771
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2772
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2773
    private void defineSplitMethodParameter(final int slot, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2774
        method.defineBlockLocalVariable(slot, slot + type.getSlots());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2775
        method.onLocalStore(type, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2776
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2777
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2778
    private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2779
        // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2780
        final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2781
        final int defaultScopeSlot = SCOPE.slot();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2782
        int newExtraSlot = extraSlot;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2783
        if (actualScopeSlot != defaultScopeSlot) {
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2784
            if (actualScopeSlot == extraSlot) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2785
                newExtraSlot = extraSlot + 1;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2786
                method.defineBlockLocalVariable(newExtraSlot, newExtraSlot + 1);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2787
                method.load(Type.OBJECT, extraSlot);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2788
                method.storeHidden(Type.OBJECT, newExtraSlot);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2789
            } else {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2790
                method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2791
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2792
            method.load(SCOPE_TYPE, defaultScopeSlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2793
            method.storeCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2794
        }
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2795
        return newExtraSlot;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2796
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2797
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2798
    @Override
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2799
    public boolean enterSplitReturn(final SplitReturn splitReturn) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2800
        if (method.isReachable()) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2801
            method.loadUndefined(lc.getCurrentFunction().getReturnType())._return();
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2802
        }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2803
        return false;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2804
    }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2805
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2806
    @Override
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2807
    public boolean enterSetSplitState(final SetSplitState setSplitState) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2808
        if (method.isReachable()) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2809
            method.setSplitState(setSplitState.getState());
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2810
        }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2811
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2812
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2813
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2814
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2815
    public boolean enterSwitchNode(final SwitchNode switchNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2816
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2817
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2818
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2819
        enterStatement(switchNode);
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  2820
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2821
        final Expression     expression  = switchNode.getExpression();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2822
        final List<CaseNode> cases       = switchNode.getCases();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2823
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2824
        if (cases.isEmpty()) {
20569
2386d10eadd3 8026033: Switch should load expression even when there are no cases in it
sundar
parents: 20559
diff changeset
  2825
            // still evaluate expression for side-effects.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2826
            loadAndDiscard(expression);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2827
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2828
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2829
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2830
        final CaseNode defaultCase       = switchNode.getDefaultCase();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2831
        final Label    breakLabel        = switchNode.getBreakLabel();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2832
        final int      liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2833
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2834
        if (defaultCase != null && cases.size() == 1) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2835
            // default case only
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2836
            assert cases.get(0) == defaultCase;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2837
            loadAndDiscard(expression);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2838
            defaultCase.getBody().accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2839
            method.breakLabel(breakLabel, liveLocalsOnBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2840
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2841
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2842
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2843
        // NOTE: it can still change in the tableswitch/lookupswitch case if there's no default case
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2844
        // but we need to add a synthetic default case for local variable conversions
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2845
        Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2846
        final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2847
27970
7b0048b90967 8066225: NPE in MethodEmitter with duplicate integer switch cases
attila
parents: 27969
diff changeset
  2848
        if (switchNode.isUniqueInteger()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2849
            // Tree for sorting values.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2850
            final TreeMap<Integer, Label> tree = new TreeMap<>();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2851
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2852
            // Build up sorted tree.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2853
            for (final CaseNode caseNode : cases) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2854
                final Node test = caseNode.getTest();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2855
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2856
                if (test != null) {
16235
cc200fdc3478 8008206: The allInteger case for SwitchNode generation in CodeGenerator assumes integer LITERALS only.
lagergren
parents: 16233
diff changeset
  2857
                    final Integer value = (Integer)((LiteralNode<?>)test).getValue();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2858
                    final Label   entry = caseNode.getEntry();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2859
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2860
                    // Take first duplicate.
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  2861
                    if (!tree.containsKey(value)) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2862
                        tree.put(value, entry);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2863
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2864
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2865
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2866
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2867
            // Copy values and labels to arrays.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2868
            final int       size   = tree.size();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2869
            final Integer[] values = tree.keySet().toArray(new Integer[size]);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2870
            final Label[]   labels = tree.values().toArray(new Label[size]);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2871
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2872
            // Discern low, high and range.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2873
            final int lo    = values[0];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2874
            final int hi    = values[size - 1];
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2875
            final long range = (long)hi - (long)lo + 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2876
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2877
            // Find an unused value for default.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2878
            int deflt = Integer.MIN_VALUE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2879
            for (final int value : values) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2880
                if (deflt == value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2881
                    deflt++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2882
                } else if (deflt < value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2883
                    break;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2884
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2885
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2886
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2887
            // Load switch expression.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2888
            loadExpressionUnbounded(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2889
            final Type type = expression.getType();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2890
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2891
            // If expression not int see if we can convert, if not use deflt to trigger default.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2892
            if (!type.isInteger()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2893
                method.load(deflt);
18842
3c3be808b593 8019585: Sometimes a var declaration using itself in its init wasn't declared as canBeUndefined, causing erroneous bytecode
lagergren
parents: 18838
diff changeset
  2894
                final Class<?> exprClass = type.getTypeClass();
18628
012cd852f881 8019488: switch on literals result in NoSuchMethodError or VerifyError
sundar
parents: 18621
diff changeset
  2895
                method.invoke(staticCallNoLookup(ScriptRuntime.class, "switchTagAsInt", int.class, exprClass.isPrimitive()? exprClass : Object.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2896
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2897
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2898
            if(hasSkipConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2899
                assert defaultLabel == breakLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2900
                defaultLabel = new Label("switch_skip");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2901
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2902
            // TABLESWITCH needs (range + 3) 32-bit values; LOOKUPSWITCH needs ((size * 2) + 2). Choose the one with
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2903
            // smaller representation, favor TABLESWITCH when they're equal size.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2904
            if (range + 1 <= (size * 2) && range <= Integer.MAX_VALUE) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2905
                final Label[] table = new Label[(int)range];
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2906
                Arrays.fill(table, defaultLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2907
                for (int i = 0; i < size; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2908
                    final int value = values[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2909
                    table[value - lo] = labels[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2910
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2911
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2912
                method.tableswitch(lo, hi, defaultLabel, table);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2913
            } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2914
                final int[] ints = new int[size];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2915
                for (int i = 0; i < size; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2916
                    ints[i] = values[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2917
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2918
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2919
                method.lookupswitch(defaultLabel, ints, labels);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2920
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2921
            // This is a synthetic "default case" used in absence of actual default case, created if we need to apply
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2922
            // local variable conversions if neither case is taken.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2923
            if(hasSkipConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2924
                method.label(defaultLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2925
                method.beforeJoinPoint(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2926
                method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2927
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2928
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2929
            final Symbol tagSymbol = switchNode.getTag();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2930
            // TODO: we could have non-object tag
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2931
            final int tagSlot = tagSymbol.getSlot(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2932
            loadExpressionAsObject(expression);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2933
            method.store(tagSymbol, Type.OBJECT);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2934
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2935
            for (final CaseNode caseNode : cases) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2936
                final Expression test = caseNode.getTest();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2937
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2938
                if (test != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2939
                    method.load(Type.OBJECT, tagSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2940
                    loadExpressionAsObject(test);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2941
                    method.invoke(ScriptRuntime.EQ_STRICT);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2942
                    method.ifne(caseNode.getEntry());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2943
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2944
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2945
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2946
            if (defaultCase != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2947
                method._goto(defaultLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2948
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2949
                method.beforeJoinPoint(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2950
                method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2951
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2952
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2953
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2954
        // First case is only reachable through jump
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2955
        assert !method.isReachable();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2956
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2957
        for (final CaseNode caseNode : cases) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2958
            final Label fallThroughLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2959
            if(caseNode.getLocalVariableConversion() != null && method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2960
                fallThroughLabel = new Label("fallthrough");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2961
                method._goto(fallThroughLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2962
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2963
                fallThroughLabel = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2964
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2965
            method.label(caseNode.getEntry());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2966
            method.beforeJoinPoint(caseNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2967
            if(fallThroughLabel != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2968
                method.label(fallThroughLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2969
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2970
            caseNode.getBody().accept(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2971
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2972
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2973
        method.breakLabel(breakLabel, liveLocalsOnBreak);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2974
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2975
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2976
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2977
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2978
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2979
    public boolean enterThrowNode(final ThrowNode throwNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2980
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2981
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2982
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2983
        enterStatement(throwNode);
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  2984
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  2985
        if (throwNode.isSyntheticRethrow()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2986
            method.beforeJoinPoint(throwNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2987
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  2988
            //do not wrap whatever this is in an ecma exception, just rethrow it
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2989
            final IdentNode exceptionExpr = (IdentNode)throwNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2990
            final Symbol exceptionSymbol = exceptionExpr.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2991
            method.load(exceptionSymbol, EXCEPTION_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2992
            method.checkcast(EXCEPTION_TYPE.getTypeClass());
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  2993
            method.athrow();
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  2994
            return false;
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  2995
        }
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  2996
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2997
        final Source     source     = getCurrentSource();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2998
        final Expression expression = throwNode.getExpression();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2999
        final int        position   = throwNode.position();
20559
9244eb6d195b 8025515: Performance issues with Source.getLine()
hannesw
parents: 20215
diff changeset
  3000
        final int        line       = throwNode.getLineNumber();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3001
        final int        column     = source.getColumn(position);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3002
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3003
        // NOTE: we first evaluate the expression, and only after it was evaluated do we create the new ECMAException
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3004
        // object and then somewhat cumbersomely move it beneath the evaluated expression on the stack. The reason for
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3005
        // this is that if expression is optimistic (or contains an optimistic subexpression), we'd potentially access
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3006
        // the not-yet-<init>ialized object on the stack from the UnwarrantedOptimismException handler, and bytecode
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3007
        // verifier forbids that.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3008
        loadExpressionAsObject(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3009
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3010
        method.load(source.getName());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3011
        method.load(line);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3012
        method.load(column);
22387
81639250d335 8031983: Error objects should capture stack at the constructor
sundar
parents: 21868
diff changeset
  3013
        method.invoke(ECMAException.CREATE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3014
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3015
        method.beforeJoinPoint(throwNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3016
        method.athrow();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3017
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3018
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3019
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3020
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3021
    private Source getCurrentSource() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3022
        return lc.getCurrentFunction().getSource();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3023
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3024
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3025
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3026
    public boolean enterTryNode(final TryNode tryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3027
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3028
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3029
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3030
        enterStatement(tryNode);
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  3031
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3032
        final Block       body        = tryNode.getBody();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3033
        final List<Block> catchBlocks = tryNode.getCatchBlocks();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3034
        final Symbol      vmException = tryNode.getException();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3035
        final Label       entry       = new Label("try");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3036
        final Label       recovery    = new Label("catch");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3037
        final Label       exit        = new Label("end_try");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3038
        final Label       skip        = new Label("skip");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3039
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3040
        method.canThrow(recovery);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3041
        // Effect any conversions that might be observed at the entry of the catch node before entering the try node.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3042
        // This is because even the first instruction in the try block must be presumed to be able to transfer control
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3043
        // to the catch block. Note that this doesn't kill the original values; in this regard it works a lot like
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3044
        // conversions of assignments within the try block.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3045
        method.beforeTry(tryNode, recovery);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3046
        method.label(entry);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3047
        catchLabels.push(recovery);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3048
        try {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3049
            body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3050
        } finally {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3051
            assert catchLabels.peek() == recovery;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3052
            catchLabels.pop();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3053
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3054
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3055
        method.label(exit);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3056
        final boolean bodyCanThrow = exit.isAfter(entry);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3057
        if(!bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3058
            // The body can't throw an exception; don't even bother emitting the catch handlers, they're all dead code.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3059
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3060
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3061
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3062
        method._try(entry, exit, recovery, Throwable.class);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3063
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3064
        if (method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3065
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3066
        }
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3067
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3068
        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3069
            TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3070
            // All inlined finallies end with a jump or a return
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3071
            assert !method.isReachable();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3072
        }
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3073
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3074
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3075
        method._catch(recovery);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3076
        method.store(vmException, EXCEPTION_TYPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3077
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3078
        final int catchBlockCount = catchBlocks.size();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3079
        final Label afterCatch = new Label("after_catch");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3080
        for (int i = 0; i < catchBlockCount; i++) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3081
            assert method.isReachable();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3082
            final Block catchBlock = catchBlocks.get(i);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3083
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3084
            // Because of the peculiarities of the flow control, we need to use an explicit push/enterBlock/leaveBlock
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3085
            // here.
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  3086
            lc.push(catchBlock);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3087
            enterBlock(catchBlock);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3088
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3089
            final CatchNode  catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3090
            final IdentNode  exception          = catchNode.getException();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3091
            final Expression exceptionCondition = catchNode.getExceptionCondition();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3092
            final Block      catchBody          = catchNode.getBody();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3093
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3094
            new Store<IdentNode>(exception) {
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3095
                @Override
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3096
                protected void storeNonDiscard() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3097
                    // This expression is neither part of a discard, nor needs to be left on the stack after it was
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3098
                    // stored, so we override storeNonDiscard to be a no-op.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3099
                }
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  3100
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3101
                @Override
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3102
                protected void evaluate() {
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3103
                    if (catchNode.isSyntheticRethrow()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3104
                        method.load(vmException, EXCEPTION_TYPE);
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3105
                        return;
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3106
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3107
                    /*
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3108
                     * If caught object is an instance of ECMAException, then
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3109
                     * bind obj.thrown to the script catch var. Or else bind the
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3110
                     * caught object itself to the script catch var.
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3111
                     */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3112
                    final Label notEcmaException = new Label("no_ecma_exception");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3113
                    method.load(vmException, EXCEPTION_TYPE).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3114
                    method.checkcast(ECMAException.class); //TODO is this necessary?
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3115
                    method.getField(ECMAException.THROWN);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3116
                    method.label(notEcmaException);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3117
                }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3118
            }.store();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3119
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3120
            final boolean isConditionalCatch = exceptionCondition != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3121
            final Label nextCatch;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3122
            if (isConditionalCatch) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3123
                loadExpressionAsBoolean(exceptionCondition);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3124
                nextCatch = new Label("next_catch");
27823
a591041cf33c 8066232: problem with conditional catch compilation
attila
parents: 27817
diff changeset
  3125
                nextCatch.markAsBreakTarget();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3126
                method.ifeq(nextCatch);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3127
            } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3128
                nextCatch = null;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3129
            }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3130
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3131
            catchBody.accept(this);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3132
            leaveBlock(catchBlock);
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  3133
            lc.pop(catchBlock);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3134
            if(nextCatch != null) {
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3135
                if(method.isReachable()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3136
                    method._goto(afterCatch);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3137
                }
27823
a591041cf33c 8066232: problem with conditional catch compilation
attila
parents: 27817
diff changeset
  3138
                method.breakLabel(nextCatch, lc.getUsedSlotCount());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3139
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3140
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3141
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3142
        // afterCatch could be the same as skip, except that we need to establish that the vmException is dead.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3143
        method.label(afterCatch);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3144
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3145
            method.markDeadLocalVariable(vmException);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3146
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3147
        method.label(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3148
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3149
        // Finally body is always inlined elsewhere so it doesn't need to be emitted
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3150
        assert tryNode.getFinallyBody() == null;
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3151
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3152
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3153
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3154
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3155
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3156
    public boolean enterVarNode(final VarNode varNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3157
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3158
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3159
        }
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3160
        final Expression init = varNode.getInit();
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3161
        final IdentNode identNode = varNode.getName();
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3162
        final Symbol identSymbol = identNode.getSymbol();
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3163
        assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3164
        final boolean needsScope = identSymbol.isScope();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3165
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3166
        if (init == null) {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3167
            if (needsScope && varNode.isBlockScoped()) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3168
                // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3169
                method.loadCompilerConstant(SCOPE);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3170
                method.loadUndefined(Type.OBJECT);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3171
                final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3172
                assert isFastScope(identSymbol);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3173
                storeFastScopeVar(identSymbol, flags);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3174
            }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3175
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3176
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3177
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3178
        enterStatement(varNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3179
        assert method != null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3180
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3181
        if (needsScope) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3182
            method.loadCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3183
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3184
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3185
        if (needsScope) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3186
            loadExpressionUnbounded(init);
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3187
            // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3188
            final int flags = CALLSITE_SCOPE | getCallSiteFlags() | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  3189
            if (isFastScope(identSymbol)) {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  3190
                storeFastScopeVar(identSymbol, flags);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3191
            } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  3192
                method.dynamicSet(identNode.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3193
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3194
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3195
            final Type identType = identNode.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3196
            if(identType == Type.UNDEFINED) {
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3197
                // The initializer is either itself undefined (explicit assignment of undefined to undefined),
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3198
                // or the left hand side is a dead variable.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3199
                assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3200
                loadAndDiscard(init);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3201
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3202
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3203
            loadExpressionAsType(init, identType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3204
            storeIdentWithCatchConversion(identNode, identType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3205
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3206
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3207
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3208
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3209
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3210
    private void storeIdentWithCatchConversion(final IdentNode identNode, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3211
        // Assignments happening in try/catch blocks need to ensure that they also store a possibly wider typed value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3212
        // that will be live at the exit from the try block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3213
        final LocalVariableConversion conversion = identNode.getLocalVariableConversion();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3214
        final Symbol symbol = identNode.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3215
        if(conversion != null && conversion.isLive()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3216
            assert symbol == conversion.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3217
            assert symbol.isBytecodeLocal();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3218
            // Only a single conversion from the target type to the join type is expected.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3219
            assert conversion.getNext() == null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3220
            assert conversion.getFrom() == type;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3221
            // We must propagate potential type change to the catch block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3222
            final Label catchLabel = catchLabels.peek();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3223
            assert catchLabel != METHOD_BOUNDARY; // ident conversion only exists in try blocks
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3224
            assert catchLabel.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3225
            final Type joinType = conversion.getTo();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3226
            final Label.Stack catchStack = catchLabel.getStack();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3227
            final int joinSlot = symbol.getSlot(joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3228
            // With nested try/catch blocks (incl. synthetic ones for finally), we can have a supposed conversion for
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3229
            // the exception symbol in the nested catch, but it isn't live in the outer catch block, so prevent doing
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3230
            // conversions for it. E.g. in "try { try { ... } catch(e) { e = 1; } } catch(e2) { ... }", we must not
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3231
            // introduce an I->O conversion on "e = 1" assignment as "e" is not live in "catch(e2)".
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3232
            if(catchStack.getUsedSlotsWithLiveTemporaries() > joinSlot) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3233
                method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3234
                method.convert(joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3235
                method.store(symbol, joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3236
                catchLabel.getStack().onLocalStore(joinType, joinSlot, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3237
                method.canThrow(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3238
                // Store but keep the previous store live too.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3239
                method.store(symbol, type, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3240
                return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3241
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3242
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3243
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3244
        method.store(symbol, type, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3245
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3246
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3247
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3248
    public boolean enterWhileNode(final WhileNode whileNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3249
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3250
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3251
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3252
        if(whileNode.isDoWhile()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3253
            enterDoWhile(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3254
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3255
            enterStatement(whileNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3256
            enterForOrWhile(whileNode, null);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3257
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3258
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3259
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3260
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3261
    private void enterForOrWhile(final LoopNode loopNode, final JoinPredecessorExpression modify) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3262
        // NOTE: the usual pattern for compiling test-first loops is "GOTO test; body; test; IFNE body". We use the less
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3263
        // conventional "test; IFEQ break; body; GOTO test; break;". It has one extra unconditional GOTO in each repeat
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3264
        // of the loop, but it's not a problem for modern JIT compilers. We do this because our local variable type
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3265
        // tracking is unfortunately not really prepared for out-of-order execution, e.g. compiling the following
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3266
        // contrived but legal JavaScript code snippet would fail because the test changes the type of "i" from object
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3267
        // to double: var i = {valueOf: function() { return 1} }; while(--i >= 0) { ... }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3268
        // Instead of adding more complexity to the local variable type tracking, we instead choose to emit this
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3269
        // different code shape.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3270
        final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3271
        final JoinPredecessorExpression test = loopNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3272
        if(Expression.isAlwaysFalse(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3273
            loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3274
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3275
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3276
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3277
        method.beforeJoinPoint(loopNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3278
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3279
        final Label continueLabel = loopNode.getContinueLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3280
        final Label repeatLabel = modify != null ? new Label("for_repeat") : continueLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3281
        method.label(repeatLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3282
        final int liveLocalsOnContinue = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3283
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3284
        final Block   body                  = loopNode.getBody();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3285
        final Label   breakLabel            = loopNode.getBreakLabel();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3286
        final boolean testHasLiveConversion = test != null && LocalVariableConversion.hasLiveConversion(test);
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3287
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3288
        if(Expression.isAlwaysTrue(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3289
            if(test != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3290
                loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3291
                if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3292
                    method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3293
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3294
            }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3295
        } else if (test != null) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3296
            if (testHasLiveConversion) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3297
                emitBranch(test.getExpression(), body.getEntryLabel(), true);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3298
                method.beforeJoinPoint(test);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3299
                method._goto(breakLabel);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3300
            } else {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3301
                emitBranch(test.getExpression(), breakLabel, false);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3302
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3303
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3304
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3305
        body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3306
        if(repeatLabel != continueLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3307
            emitContinueLabel(continueLabel, liveLocalsOnContinue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3308
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3309
27977
42799be30dcd 8067219: NPE in ScriptObject.clone() when running with object fields
hannesw
parents: 27976
diff changeset
  3310
        if (loopNode.hasPerIterationScope() && lc.getCurrentBlock().needsScope()) {
27817
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3311
            // ES6 for loops with LET init need a new scope for each iteration. We just create a shallow copy here.
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3312
            method.loadCompilerConstant(SCOPE);
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3313
            method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3314
            method.storeCompilerConstant(SCOPE);
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3315
        }
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3316
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3317
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3318
            if(modify != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3319
                lineNumber(loopNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3320
                loadAndDiscard(modify);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3321
                method.beforeJoinPoint(modify);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3322
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3323
            method._goto(repeatLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3324
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3325
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3326
        method.breakLabel(breakLabel, liveLocalsOnBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3327
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3328
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3329
    private void emitContinueLabel(final Label continueLabel, final int liveLocals) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3330
        final boolean reachable = method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3331
        method.breakLabel(continueLabel, liveLocals);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3332
        // If we reach here only through a continue statement (e.g. body does not exit normally) then the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3333
        // continueLabel can have extra non-temp symbols (e.g. exception from a try/catch contained in the body). We
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3334
        // must make sure those are thrown away.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3335
        if(!reachable) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3336
            method.undefineLocalVariables(lc.getUsedSlotCount(), false);
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3337
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3338
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3339
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3340
    private void enterDoWhile(final WhileNode whileNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3341
        final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3342
        method.beforeJoinPoint(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3343
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3344
        final Block body = whileNode.getBody();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3345
        body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3346
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3347
        emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3348
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3349
            lineNumber(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3350
            final JoinPredecessorExpression test = whileNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3351
            final Label bodyEntryLabel = body.getEntryLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3352
            final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3353
            if(Expression.isAlwaysFalse(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3354
                loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3355
                if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3356
                    method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3357
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3358
            } else if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3359
                // If we have conversions after the test in do-while, they need to be effected on both branches.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3360
                final Label beforeExit = new Label("do_while_preexit");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3361
                emitBranch(test.getExpression(), beforeExit, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3362
                method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3363
                method._goto(bodyEntryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3364
                method.label(beforeExit);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3365
                method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3366
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3367
                emitBranch(test.getExpression(), bodyEntryLabel, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3368
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3369
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3370
        method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3371
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3372
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3373
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3374
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3375
    public boolean enterWithNode(final WithNode withNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3376
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3377
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3378
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3379
        enterStatement(withNode);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3380
        final Expression expression = withNode.getExpression();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3381
        final Block      body       = withNode.getBody();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3382
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3383
        // It is possible to have a "pathological" case where the with block does not reference *any* identifiers. It's
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3384
        // pointless, but legal. In that case, if nothing else in the method forced the assignment of a slot to the
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3385
        // scope object, its' possible that it won't have a slot assigned. In this case we'll only evaluate expression
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3386
        // for its side effect and visit the body, and not bother opening and closing a WithObject.
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3387
        final boolean hasScope = method.hasScope();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3388
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  3389
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3390
            method.loadCompilerConstant(SCOPE);
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3391
        }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3392
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3393
        loadExpressionAsObject(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3394
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3395
        final Label tryLabel;
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  3396
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3397
            // Construct a WithObject if we have a scope
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3398
            method.invoke(ScriptRuntime.OPEN_WITH);
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3399
            method.storeCompilerConstant(SCOPE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3400
            tryLabel = new Label("with_try");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3401
            method.label(tryLabel);
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3402
        } else {
20215
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3403
            // We just loaded the expression for its side effect and to check
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3404
            // for null or undefined value.
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3405
            globalCheckObjectCoercible();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3406
            tryLabel = null;
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3407
        }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3408
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3409
        // Always process body
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3410
        body.accept(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3411
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
  3412
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3413
            // Ensure we always close the WithObject
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3414
            final Label endLabel   = new Label("with_end");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3415
            final Label catchLabel = new Label("with_catch");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3416
            final Label exitLabel  = new Label("with_exit");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3417
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3418
            method.label(endLabel);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3419
            // Somewhat conservatively presume that if the body is not empty, it can throw an exception. In any case,
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3420
            // we must prevent trying to emit a try-catch for empty range, as it causes a verification error.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3421
            final boolean bodyCanThrow = endLabel.isAfter(tryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3422
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3423
                method._try(tryLabel, endLabel, catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3424
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3425
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3426
            final boolean reachable = method.isReachable();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3427
            if(reachable) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3428
                popScope();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3429
                if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3430
                    method._goto(exitLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3431
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3432
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3433
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3434
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3435
                method._catch(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3436
                popScopeException();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3437
                method.athrow();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3438
                if(reachable) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3439
                    method.label(exitLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3440
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3441
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3442
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3443
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3444
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3445
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3446
    private void loadADD(final UnaryNode unaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3447
        loadExpression(unaryNode.getExpression(), resultBounds.booleanToInt().notWiderThan(Type.NUMBER));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3448
        if(method.peekType() == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3449
            // It's a no-op in bytecode, but we must make sure it is treated as an int for purposes of type signatures
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3450
            method.convert(Type.INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3451
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3452
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3453
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3454
    private void loadBIT_NOT(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3455
        loadExpression(unaryNode.getExpression(), TypeBounds.INT).load(-1).xor();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3456
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3457
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3458
    private void loadDECINC(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3459
        final Expression operand     = unaryNode.getExpression();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3460
        final Type       type        = unaryNode.getType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3461
        final TypeBounds typeBounds  = new TypeBounds(type, Type.NUMBER);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3462
        final TokenType  tokenType   = unaryNode.tokenType();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3463
        final boolean    isPostfix   = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3464
        final boolean    isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3465
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3466
        assert !type.isObject();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3467
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3468
        new SelfModifyingStore<UnaryNode>(unaryNode, operand) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3469
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3470
            private void loadRhs() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3471
                loadExpression(operand, typeBounds, true);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3472
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3473
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3474
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3475
            protected void evaluate() {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3476
                if(isPostfix) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3477
                    loadRhs();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3478
                } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3479
                    new OptimisticOperation(unaryNode, typeBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3480
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3481
                        void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3482
                            loadRhs();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3483
                            loadMinusOne();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3484
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3485
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3486
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3487
                            doDecInc(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3488
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3489
                    }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(operand));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3490
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3491
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3492
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3493
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3494
            protected void storeNonDiscard() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3495
                super.storeNonDiscard();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3496
                if (isPostfix) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3497
                    new OptimisticOperation(unaryNode, typeBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3498
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3499
                        void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3500
                            loadMinusOne();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3501
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3502
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3503
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3504
                            doDecInc(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3505
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3506
                    }.emit(1); // 1 for non-incremented result on the top of the stack pushed in evaluate()
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3507
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3508
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3509
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3510
            private void loadMinusOne() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3511
                if (type.isInteger()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3512
                    method.load(isIncrement ? 1 : -1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3513
                } else if (type.isLong()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3514
                    method.load(isIncrement ? 1L : -1L);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3515
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3516
                    method.load(isIncrement ? 1.0 : -1.0);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3517
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3518
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3519
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3520
            private void doDecInc(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3521
                method.add(programPoint);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3522
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3523
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3524
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3525
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3526
    private static int getOptimisticIgnoreCountForSelfModifyingExpression(final Expression target) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3527
        return target instanceof AccessNode ? 1 : target instanceof IndexNode ? 2 : 0;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3528
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3529
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3530
    private void loadAndDiscard(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3531
        // TODO: move checks for discarding to actual expression load code (e.g. as we do with void). That way we might
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3532
        // be able to eliminate even more checks.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3533
        if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3534
            assert lc.getCurrentDiscard() != expr;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3535
            // Don't bother evaluating expressions without side effects. Typical usage is "void 0" for reliably generating
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3536
            // undefined.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3537
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3538
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3539
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3540
        lc.pushDiscard(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3541
        loadExpression(expr, TypeBounds.UNBOUNDED);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3542
        if (lc.getCurrentDiscard() == expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3543
            assert !expr.isAssignment();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3544
            // NOTE: if we had a way to load with type void, we could avoid popping
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3545
            method.pop();
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  3546
            lc.popDiscard();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3547
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3548
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3549
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3550
    private void loadNEW(final UnaryNode unaryNode) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3551
        final CallNode callNode = (CallNode)unaryNode.getExpression();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3552
        final List<Expression> args   = callNode.getArgs();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3553
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3554
        // Load function reference.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3555
        loadExpressionAsObject(callNode.getFunction()); // must detect type error
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3556
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  3557
        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3558
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3559
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3560
    private void loadNOT(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3561
        final Expression expr = unaryNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3562
        if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3563
            // !!x is idiomatic boolean cast in JavaScript
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3564
            loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3565
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3566
            final Label trueLabel  = new Label("true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3567
            final Label afterLabel = new Label("after");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3568
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3569
            emitBranch(expr, trueLabel, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3570
            method.load(true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3571
            method._goto(afterLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3572
            method.label(trueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3573
            method.load(false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3574
            method.label(afterLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3575
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3576
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3577
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3578
    private void loadSUB(final UnaryNode unaryNode, final TypeBounds resultBounds) {
24774
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3579
        final Type type = unaryNode.getType();
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3580
        assert type.isNumeric();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3581
        final TypeBounds numericBounds = resultBounds.booleanToInt();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3582
        new OptimisticOperation(unaryNode, numericBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3583
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3584
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3585
                final Expression expr = unaryNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3586
                loadExpression(expr, numericBounds.notWiderThan(Type.NUMBER));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3587
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3588
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3589
            void consumeStack() {
24774
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3590
                // Must do an explicit conversion to the operation's type when it's double so that we correctly handle
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3591
                // negation of an int 0 to a double -0. With this, we get the correct negation of a local variable after
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3592
                // it deoptimized, e.g. "iload_2; i2d; dneg". Without this, we get "iload_2; ineg; i2d".
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3593
                if(type.isNumber()) {
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3594
                    method.convert(type);
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3595
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3596
                method.neg(getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3597
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3598
        }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3599
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3600
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3601
    public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3602
        loadAndDiscard(unaryNode.getExpression());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3603
        if(lc.getCurrentDiscard() == unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3604
            lc.popDiscard();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3605
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3606
            method.loadUndefined(resultBounds.widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3607
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3608
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3609
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3610
    public void loadADD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3611
        new OptimisticOperation(binaryNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3612
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3613
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3614
                final TypeBounds operandBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3615
                final boolean isOptimistic = isValid(getProgramPoint());
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3616
                boolean forceConversionSeparation = false;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3617
                if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3618
                    operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3619
                } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3620
                    // Non-optimistic, non-FP +. Allow it to overflow.
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3621
                    final Type widestOperationType = binaryNode.getWidestOperationType();
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3622
                    operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3623
                    forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3624
                }
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3625
                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3626
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3627
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3628
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3629
            void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3630
                method.add(getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3631
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3632
        }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3633
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3634
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3635
    private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3636
        final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3637
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3638
        final Label skip = new Label("skip");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3639
        if(narrowestOperandType == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3640
            // optimize all-boolean logical expressions
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3641
            final Label onTrue = new Label("andor_true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3642
            emitBranch(binaryNode, onTrue, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3643
            method.load(false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3644
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3645
            method.label(onTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3646
            method.load(true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3647
            method.label(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3648
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3649
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3650
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3651
        final TypeBounds outBounds = resultBounds.notNarrowerThan(narrowestOperandType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3652
        final JoinPredecessorExpression lhs = (JoinPredecessorExpression)binaryNode.lhs();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3653
        final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3654
        final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3655
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3656
        loadExpression(lhs, outBounds).dup().convert(Type.BOOLEAN);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3657
        if (isAnd) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3658
            if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3659
                method.ifne(evalRhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3660
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3661
                method.ifeq(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3662
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3663
        } else if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3664
            method.ifeq(evalRhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3665
        } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3666
            method.ifne(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3667
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3668
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3669
        if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3670
            method.beforeJoinPoint(lhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3671
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3672
            method.label(evalRhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3673
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3674
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3675
        method.pop();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3676
        final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3677
        loadExpression(rhs, outBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3678
        method.beforeJoinPoint(rhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3679
        method.label(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3680
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3681
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3682
    private static boolean isLocalVariable(final Expression lhs) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3683
        return lhs instanceof IdentNode && isLocalVariable((IdentNode)lhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3684
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3685
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3686
    private static boolean isLocalVariable(final IdentNode lhs) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3687
        return lhs.getSymbol().isBytecodeLocal();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3688
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3689
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3690
    // NOTE: does not use resultBounds as the assignment is driven by the type of the RHS
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3691
    private void loadASSIGN(final BinaryNode binaryNode) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3692
        final Expression lhs = binaryNode.lhs();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3693
        final Expression rhs = binaryNode.rhs();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3694
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3695
        final Type rhsType = rhs.getType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3696
        // Detect dead assignments
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3697
        if(lhs instanceof IdentNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3698
            final Symbol symbol = ((IdentNode)lhs).getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3699
            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.getCurrentDiscard() == binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3700
                loadAndDiscard(rhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3701
                lc.popDiscard();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3702
                method.markDeadLocalVariable(symbol);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3703
                return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3704
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3705
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3706
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3707
        new Store<BinaryNode>(binaryNode, lhs) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3708
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3709
            protected void evaluate() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3710
                // NOTE: we're loading with "at least as wide as" so optimistic operations on the right hand side
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3711
                // remain optimistic, and then explicitly convert to the required type if needed.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3712
                loadExpressionAsType(rhs, rhsType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3713
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3714
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3715
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3716
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3717
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3718
     * Binary self-assignment that can be optimistic: +=, -=, *=, and /=.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3719
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3720
    private abstract class BinaryOptimisticSelfAssignment extends SelfModifyingStore<BinaryNode> {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3721
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3722
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3723
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3724
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3725
         * @param node the assign op node
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3726
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3727
        BinaryOptimisticSelfAssignment(final BinaryNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3728
            super(node, node.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3729
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3730
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3731
        protected abstract void op(OptimisticOperation oo);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3732
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3733
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3734
        protected void evaluate() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3735
            final Expression lhs = assignNode.lhs();
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3736
            final Expression rhs = assignNode.rhs();
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3737
            final Type widestOperationType = assignNode.getWidestOperationType();
27969
c03b64ccbd0f 8066227: CodeGenerator load unitialized slot
attila
parents: 27968
diff changeset
  3738
            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widestOperationType);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3739
            new OptimisticOperation(assignNode, bounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3740
                @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3741
                void loadStack() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3742
                    final boolean forceConversionSeparation;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3743
                    if (isValid(getProgramPoint()) || widestOperationType == Type.NUMBER) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3744
                        forceConversionSeparation = false;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3745
                    } else {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3746
                        final Type operandType = Type.widest(booleanToInt(objectToNumber(lhs.getType())), booleanToInt(objectToNumber(rhs.getType())));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3747
                        forceConversionSeparation = operandType.narrowerThan(widestOperationType);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3748
                    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3749
                    loadBinaryOperands(lhs, rhs, bounds, true, forceConversionSeparation);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3750
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3751
                @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3752
                void consumeStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3753
                    op(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3754
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3755
            }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(lhs));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3756
            method.convert(assignNode.getType());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3757
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3758
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3759
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3760
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3761
     * Non-optimistic binary self-assignment operation. Basically, everything except +=, -=, *=, and /=.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3762
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3763
    private abstract class BinarySelfAssignment extends SelfModifyingStore<BinaryNode> {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3764
        BinarySelfAssignment(final BinaryNode node) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3765
            super(node, node.lhs());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3766
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3767
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3768
        protected abstract void op();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3769
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3770
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3771
        protected void evaluate() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3772
            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3773
            op();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3774
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3775
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3776
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3777
    private void loadASSIGN_ADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3778
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3779
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3780
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3781
                assert !(binaryNode.getType().isObject() && oo.isOptimistic);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3782
                method.add(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3783
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3784
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3785
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3786
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3787
    private void loadASSIGN_BIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3788
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3789
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3790
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3791
                method.and();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3792
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3793
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3794
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3795
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3796
    private void loadASSIGN_BIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3797
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3798
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3799
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3800
                method.or();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3801
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3802
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3803
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3804
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3805
    private void loadASSIGN_BIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3806
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3807
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3808
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3809
                method.xor();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3810
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3811
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3812
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3813
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3814
    private void loadASSIGN_DIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3815
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3816
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3817
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3818
                method.div(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3819
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3820
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3821
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3822
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3823
    private void loadASSIGN_MOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3824
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3825
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3826
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3827
                method.rem(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3828
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3829
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3830
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3831
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3832
    private void loadASSIGN_MUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3833
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3834
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3835
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3836
                method.mul(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3837
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3838
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3839
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3840
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3841
    private void loadASSIGN_SAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3842
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3843
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3844
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3845
                method.sar();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3846
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3847
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3848
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3849
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3850
    private void loadASSIGN_SHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3851
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3852
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3853
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3854
                method.shl();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3855
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3856
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3857
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3858
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3859
    private void loadASSIGN_SHR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3860
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3861
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3862
            protected void op() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3863
                doSHR();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3864
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3865
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3866
        }.store();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3867
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3868
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3869
    private void doSHR() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3870
        // TODO: make SHR optimistic
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3871
        method.shr();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3872
        toUint();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3873
    }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3874
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3875
    private void toUint() {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3876
        JSType.TO_UINT32_I.invoke(method);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3877
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3878
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3879
    private void loadASSIGN_SUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3880
        new BinaryOptimisticSelfAssignment(binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3881
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3882
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3883
                method.sub(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3884
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3885
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3886
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3887
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3888
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3889
     * Helper class for binary arithmetic ops
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3890
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3891
    private abstract class BinaryArith {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3892
        protected abstract void op(int programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3893
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3894
        protected void evaluate(final BinaryNode node, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3895
            final TypeBounds numericBounds = resultBounds.booleanToInt().objectToNumber();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3896
            new OptimisticOperation(node, numericBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3897
                @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3898
                void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3899
                    final TypeBounds operandBounds;
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3900
                    boolean forceConversionSeparation = false;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3901
                    if(numericBounds.narrowest == Type.NUMBER) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3902
                        // Result should be double always. Propagate it into the operands so we don't have lots of I2D
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3903
                        // and L2D after operand evaluation.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3904
                        assert numericBounds.widest == Type.NUMBER;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3905
                        operandBounds = numericBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3906
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3907
                        final boolean isOptimistic = isValid(getProgramPoint());
27358
8898e06e68c1 8061957: Some arithmetic operations have unnecessary widening
attila
parents: 27212
diff changeset
  3908
                        if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3909
                            operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3910
                        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3911
                            // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3912
                            operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3913
                                    numericBounds.widest), Type.NUMBER);
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3914
                            forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3915
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3916
                    }
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3917
                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3918
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3919
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3920
                @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3921
                void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3922
                    op(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3923
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3924
            }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3925
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3926
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3927
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3928
    private void loadBIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3929
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3930
        method.and();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3931
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3932
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3933
    private void loadBIT_OR(final BinaryNode binaryNode) {
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3934
        // Optimize x|0 to (int)x
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3935
        if (isRhsZero(binaryNode)) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3936
            loadExpressionAsType(binaryNode.lhs(), Type.INT);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3937
        } else {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3938
            loadBinaryOperands(binaryNode);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3939
            method.or();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3940
        }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3941
    }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3942
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3943
    private static boolean isRhsZero(final BinaryNode binaryNode) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  3944
        final Expression rhs = binaryNode.rhs();
27365
6dd6e324d1c7 8057825: Bug in apply specialization - if an apply specialization that is available doesn't fit, a new one wouldn't be installed, if the new code generated as a specialization didn't manage to do the apply specialization. Basically changing a conditional to an unconditional.
lagergren
parents: 27358
diff changeset
  3945
        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3946
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3947
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3948
    private void loadBIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3949
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3950
        method.xor();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3951
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3952
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3953
    private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3954
        loadAndDiscard(binaryNode.lhs());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3955
        loadExpression(binaryNode.rhs(), resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3956
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3957
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3958
    private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3959
        loadExpression(binaryNode.lhs(), resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3960
        loadAndDiscard(binaryNode.rhs());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3961
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3962
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3963
    private void loadDIV(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3964
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3965
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3966
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3967
                method.div(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3968
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3969
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3970
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3971
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3972
    private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3973
        assert comparisonOperandsArePrimitive(binaryNode) : binaryNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3974
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3975
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3976
        final Label trueLabel  = new Label("trueLabel");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3977
        final Label afterLabel = new Label("skip");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3978
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3979
        method.conditionalJump(cond, trueLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3980
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3981
        method.load(Boolean.FALSE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3982
        method._goto(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3983
        method.label(trueLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3984
        method.load(Boolean.TRUE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3985
        method.label(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3986
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3987
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3988
    private static boolean comparisonOperandsArePrimitive(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3989
        final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3990
        return widest.isNumeric() || widest.isBoolean();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3991
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3992
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3993
    private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3994
        new BinaryArith() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3995
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3996
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3997
                method.rem(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3998
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3999
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4000
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4001
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4002
    private void loadMUL(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4003
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4004
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4005
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4006
                method.mul(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4007
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4008
        }.evaluate(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4009
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4010
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4011
    private void loadSAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4012
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4013
        method.sar();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4014
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4015
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4016
    private void loadSHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4017
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4018
        method.shl();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4019
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4020
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4021
    private void loadSHR(final BinaryNode binaryNode) {
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4022
        // Optimize x >>> 0 to (uint)x
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4023
        if (isRhsZero(binaryNode)) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4024
            loadExpressionAsType(binaryNode.lhs(), Type.INT);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4025
            toUint();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4026
        } else {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4027
            loadBinaryOperands(binaryNode);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4028
            doSHR();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4029
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4030
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4031
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4032
    private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4033
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4034
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4035
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4036
                method.sub(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4037
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4038
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4039
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4040
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4041
    @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4042
    public boolean enterLabelNode(final LabelNode labelNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4043
        labeledBlockBreakLiveLocals.push(lc.getUsedSlotCount());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4044
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4045
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4046
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4047
    @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4048
    protected boolean enterDefault(final Node node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4049
        throw new AssertionError("Code generator entered node of type " + node.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4050
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4051
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4052
    private void loadTernaryNode(final TernaryNode ternaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4053
        final Expression test = ternaryNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4054
        final JoinPredecessorExpression trueExpr  = ternaryNode.getTrueExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4055
        final JoinPredecessorExpression falseExpr = ternaryNode.getFalseExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4056
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4057
        final Label falseLabel = new Label("ternary_false");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4058
        final Label exitLabel  = new Label("ternary_exit");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4059
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4060
        final Type outNarrowest = Type.narrowest(resultBounds.widest, Type.generic(Type.widestReturnType(trueExpr.getType(), falseExpr.getType())));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4061
        final TypeBounds outBounds = resultBounds.notNarrowerThan(outNarrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4062
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4063
        emitBranch(test, falseLabel, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4064
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4065
        loadExpression(trueExpr.getExpression(), outBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4066
        assert Type.generic(method.peekType()) == outBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4067
        method.beforeJoinPoint(trueExpr);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4068
        method._goto(exitLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4069
        method.label(falseLabel);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4070
        loadExpression(falseExpr.getExpression(), outBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4071
        assert Type.generic(method.peekType()) == outBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4072
        method.beforeJoinPoint(falseExpr);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4073
        method.label(exitLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4074
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4075
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4076
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4077
     * Generate all shared scope calls generated during codegen.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4078
     */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4079
    void generateScopeCalls() {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  4080
        for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4081
            scopeAccess.generateScopeCall();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4082
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4083
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4084
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4085
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4086
     * Debug code used to print symbols
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4087
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4088
     * @param block the block we are in
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4089
     * @param function the function we are in
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4090
     * @param ident identifier for block or function where applicable
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4091
     */
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4092
    private void printSymbols(final Block block, final FunctionNode function, final String ident) {
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4093
        if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4094
            final PrintWriter out = compiler.getScriptEnvironment().getErr();
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4095
            out.println("[BLOCK in '" + ident + "']");
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4096
            if (!block.printSymbols(out)) {
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4097
                out.println("<no symbols>");
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4098
            }
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4099
            out.println();
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4100
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4101
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4102
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4103
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4104
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4105
     * The difference between a store and a self modifying store is that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4106
     * the latter may load part of the target on the stack, e.g. the base
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4107
     * of an AccessNode or the base and index of an IndexNode. These are used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4108
     * both as target and as an extra source. Previously it was problematic
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4109
     * for self modifying stores if the target/lhs didn't belong to one
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4110
     * of three trivial categories: IdentNode, AcessNodes, IndexNodes. In that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4111
     * case it was evaluated and tagged as "resolved", which meant at the second
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4112
     * time the lhs of this store was read (e.g. in a = a (second) + b for a += b,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4113
     * it would be evaluated to a nop in the scope and cause stack underflow
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4114
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4115
     * see NASHORN-703
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4116
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4117
     * @param <T>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4118
     */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4119
    private abstract class SelfModifyingStore<T extends Expression> extends Store<T> {
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4120
        protected SelfModifyingStore(final T assignNode, final Expression target) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4121
            super(assignNode, target);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4122
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4123
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4124
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4125
        protected boolean isSelfModifying() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4126
            return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4127
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4128
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4129
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4130
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4131
     * Helper class to generate stores
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4132
     */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4133
    private abstract class Store<T extends Expression> {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4134
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4135
        /** An assignment node, e.g. x += y */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4136
        protected final T assignNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4137
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4138
        /** The target node to store to, e.g. x */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4139
        private final Expression target;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4140
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4141
        /** How deep on the stack do the arguments go if this generates an indy call */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4142
        private int depth;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4143
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4144
        /** If we have too many arguments, we need temporary storage, this is stored in 'quick' */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4145
        private IdentNode quick;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4146
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4147
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4148
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4149
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4150
         * @param assignNode the node representing the whole assignment
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4151
         * @param target     the target node of the assignment (destination)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4152
         */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4153
        protected Store(final T assignNode, final Expression target) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4154
            this.assignNode = assignNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4155
            this.target = target;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4156
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4157
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4158
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4159
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4160
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4161
         * @param assignNode the node representing the whole assignment
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4162
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4163
        protected Store(final T assignNode) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4164
            this(assignNode, assignNode);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4165
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4166
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4167
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4168
         * Is this a self modifying store operation, e.g. *= or ++
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4169
         * @return true if self modifying store
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4170
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4171
        protected boolean isSelfModifying() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4172
            return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4173
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4174
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4175
        private void prologue() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4176
            /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4177
             * This loads the parts of the target, e.g base and index. they are kept
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4178
             * on the stack throughout the store and used at the end to execute it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4179
             */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4180
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  4181
            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4182
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4183
                public boolean enterIdentNode(final IdentNode node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4184
                    if (node.getSymbol().isScope()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4185
                        method.loadCompilerConstant(SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4186
                        depth += Type.SCOPE.getSlots();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4187
                        assert depth == 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4188
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4189
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4190
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4191
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4192
                private void enterBaseNode() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4193
                    assert target instanceof BaseNode : "error - base node " + target + " must be instanceof BaseNode";
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4194
                    final BaseNode   baseNode = (BaseNode)target;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4195
                    final Expression base     = baseNode.getBase();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4196
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4197
                    loadExpressionAsObject(base);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4198
                    depth += Type.OBJECT.getSlots();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4199
                    assert depth == 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4200
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4201
                    if (isSelfModifying()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4202
                        method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4203
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4204
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4205
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4206
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4207
                public boolean enterAccessNode(final AccessNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4208
                    enterBaseNode();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4209
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4210
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4211
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4212
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4213
                public boolean enterIndexNode(final IndexNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4214
                    enterBaseNode();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4215
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4216
                    final Expression index = node.getIndex();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4217
                    if (!index.getType().isNumeric()) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  4218
                        // could be boolean here as well
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4219
                        loadExpressionAsObject(index);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  4220
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4221
                        loadExpressionUnbounded(index);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4222
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4223
                    depth += index.getType().getSlots();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4224
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4225
                    if (isSelfModifying()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4226
                        //convert "base base index" to "base index base index"
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4227
                        method.dup(1);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4228
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4229
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4230
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4231
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4232
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4233
            });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4234
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4235
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4236
        /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4237
         * Generates an extra local variable, always using the same slot, one that is available after the end of the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4238
         * frame.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4239
         *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4240
         * @param type the type of the variable
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4241
         *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4242
         * @return the quick variable
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4243
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4244
        private IdentNode quickLocalVariable(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4245
            final String name = lc.getCurrentFunction().uniqueName(QUICK_PREFIX.symbolName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4246
            final Symbol symbol = new Symbol(name, IS_INTERNAL | HAS_SLOT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4247
            symbol.setHasSlotFor(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4248
            symbol.setFirstSlot(lc.quickSlot(type));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4249
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4250
            final IdentNode quickIdent = IdentNode.createInternalIdentifier(symbol).setType(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4251
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4252
            return quickIdent;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4253
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4254
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4255
        // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4256
        protected void storeNonDiscard() {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  4257
            if (lc.getCurrentDiscard() == assignNode) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4258
                assert assignNode.isAssignment();
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  4259
                lc.popDiscard();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4260
                return;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4261
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4262
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4263
            if (method.dup(depth) == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4264
                method.dup();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4265
                final Type quickType = method.peekType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4266
                this.quick = quickLocalVariable(quickType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4267
                final Symbol quickSymbol = quick.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4268
                method.storeTemp(quickType, quickSymbol.getFirstSlot());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4269
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4270
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4271
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4272
        private void epilogue() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4273
            /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4274
             * Take the original target args from the stack and use them
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4275
             * together with the value to be stored to emit the store code
16201
889ddb179cdf 8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents: 16190
diff changeset
  4276
             *
889ddb179cdf 8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents: 16190
diff changeset
  4277
             * The case that targetSymbol is in scope (!hasSlot) and we actually
889ddb179cdf 8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents: 16190
diff changeset
  4278
             * need to do a conversion on non-equivalent types exists, but is
889ddb179cdf 8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents: 16190
diff changeset
  4279
             * very rare. See for example test/script/basic/access-specializer.js
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4280
             */
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  4281
            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4282
                @Override
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4283
                protected boolean enterDefault(final Node node) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4284
                    throw new AssertionError("Unexpected node " + node + " in store epilogue");
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  4285
                }
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4286
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4287
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4288
                public boolean enterIdentNode(final IdentNode node) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4289
                    final Symbol symbol = node.getSymbol();
16226
0e4f37e6cc40 8007915: Nashorn IR, codegen, parser packages and Context instance should be inaccessible to user code
sundar
parents: 16225
diff changeset
  4290
                    assert symbol != null;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4291
                    if (symbol.isScope()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4292
                        final int flags = CALLSITE_SCOPE | getCallSiteFlags();
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  4293
                        if (isFastScope(symbol)) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4294
                            storeFastScopeVar(symbol, flags);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4295
                        } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4296
                            method.dynamicSet(node.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4297
                        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4298
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4299
                        final Type storeType = assignNode.getType();
26241
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4300
                        if (symbol.hasSlotFor(storeType)) {
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4301
                            // Only emit a convert for a store known to be live; converts for dead stores can
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4302
                            // give us an unnecessary ClassCastException.
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4303
                            method.convert(storeType);
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4304
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4305
                        storeIdentWithCatchConversion(node, storeType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4306
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4307
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4308
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4309
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4310
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4311
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4312
                public boolean enterAccessNode(final AccessNode node) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4313
                    method.dynamicSet(node.getProperty(), getCallSiteFlags(), node.isIndex());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4314
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4315
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4316
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4317
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4318
                public boolean enterIndexNode(final IndexNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4319
                    method.dynamicSetIndex(getCallSiteFlags());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4320
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4321
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4322
            });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4323
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4324
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4325
            // whatever is on the stack now is the final answer
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4326
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4327
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4328
        protected abstract void evaluate();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4329
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4330
        void store() {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4331
            if (target instanceof IdentNode) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4332
                checkTemporalDeadZone((IdentNode)target);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4333
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4334
            prologue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4335
            evaluate(); // leaves an operation of whatever the operationType was on the stack
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4336
            storeNonDiscard();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4337
            epilogue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4338
            if (quick != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4339
                method.load(quick);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4340
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4341
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4342
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4343
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4344
    private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4345
        assert lc.peek() == functionNode;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4346
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  4347
        final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4348
24784
ed11bdcc878a 8044816: On-demand compiled top-level program doesn't need :createProgramFunction
attila
parents: 24781
diff changeset
  4349
        if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4350
            final MethodEmitter createFunction = functionNode.getCompileUnit().getClassEmitter().method(
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4351
                    EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(),
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4352
                    ScriptFunction.class, ScriptObject.class);
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4353
            createFunction.begin();
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4354
            loadConstantsAndIndex(data, createFunction);
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4355
            createFunction.load(SCOPE_TYPE, 0);
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4356
            createFunction.invoke(CREATE_FUNCTION_OBJECT);
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4357
            createFunction._return();
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4358
            createFunction.end();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4359
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4360
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  4361
        if (addInitializer && !compiler.isOnDemandCompilation()) {
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  4362
            compiler.addFunctionInitializer(data, functionNode);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4363
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4364
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4365
        // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4366
        // generated in its outer context that'd need it as a callee).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4367
        if (lc.getOutermostFunction() == functionNode) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4368
            return;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4369
        }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4370
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4371
        loadConstantsAndIndex(data, method);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4372
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4373
        if (functionNode.needsParentScope()) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  4374
            method.loadCompilerConstant(SCOPE);
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4375
            method.invoke(CREATE_FUNCTION_OBJECT);
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  4376
        } else {
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4377
            method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4378
        }
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  4379
    }
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  4380
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
  4381
    // calls on Global class.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4382
    private MethodEmitter globalInstance() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4383
        return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';');
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4384
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4385
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4386
    private MethodEmitter globalAllocateArguments() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4387
        return method.invokestatic(GLOBAL_OBJECT, "allocateArguments", methodDescriptor(ScriptObject.class, Object[].class, Object.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4388
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4389
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4390
    private MethodEmitter globalNewRegExp() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4391
        return method.invokestatic(GLOBAL_OBJECT, "newRegExp", methodDescriptor(Object.class, String.class, String.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4392
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4393
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4394
    private MethodEmitter globalRegExpCopy() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4395
        return method.invokestatic(GLOBAL_OBJECT, "regExpCopy", methodDescriptor(Object.class, Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4396
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4397
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4398
    private MethodEmitter globalAllocateArray(final ArrayType type) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4399
        //make sure the native array is treated as an array type
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4400
        return method.invokestatic(GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4401
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4402
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4403
    private MethodEmitter globalIsEval() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4404
        return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4405
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4406
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4407
    private MethodEmitter globalReplaceLocationPropertyPlaceholder() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4408
        return method.invokestatic(GLOBAL_OBJECT, "replaceLocationPropertyPlaceholder", methodDescriptor(Object.class, Object.class, Object.class));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4409
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4410
20215
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4411
    private MethodEmitter globalCheckObjectCoercible() {
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4412
        return method.invokestatic(GLOBAL_OBJECT, "checkObjectCoercible", methodDescriptor(void.class, Object.class));
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4413
    }
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4414
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4415
    private MethodEmitter globalDirectEval() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4416
        return method.invokestatic(GLOBAL_OBJECT, "directEval",
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  4417
                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4418
    }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4419
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4420
    private abstract class OptimisticOperation {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4421
        private final boolean isOptimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4422
        // expression and optimistic are the same reference
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4423
        private final Expression expression;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4424
        private final Optimistic optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4425
        private final TypeBounds resultBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4426
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4427
        OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4428
            this.optimistic = optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4429
            this.expression = (Expression)optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4430
            this.resultBounds = resultBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4431
            this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() &&
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4432
                    // Operation is only effectively optimistic if its type, after being coerced into the result bounds
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4433
                    // is narrower than the upper bound.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4434
                    resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4435
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4436
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4437
        MethodEmitter emit() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4438
            return emit(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4439
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4440
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4441
        MethodEmitter emit(final int ignoredArgCount) {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4442
            final int     programPoint                  = optimistic.getProgramPoint();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4443
            final boolean optimisticOrContinuation      = isOptimistic || isContinuationEntryPoint(programPoint);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4444
            final boolean currentContinuationEntryPoint = isCurrentContinuationEntryPoint(programPoint);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4445
            final int     stackSizeOnEntry              = method.getStackSize() - ignoredArgCount;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4446
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4447
            // First store the values on the stack opportunistically into local variables. Doing it before loadStack()
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4448
            // allows us to not have to pop/load any arguments that are pushed onto it by loadStack() in the second
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4449
            // storeStack().
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4450
            storeStack(ignoredArgCount, optimisticOrContinuation);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4451
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4452
            // Now, load the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4453
            loadStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4454
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4455
            // Now store the values on the stack ultimately into local variables. In vast majority of cases, this is
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4456
            // (aside from creating the local types map) a no-op, as the first opportunistic stack store will already
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4457
            // store all variables. However, there can be operations in the loadStack() that invalidate some of the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4458
            // stack stores, e.g. in "x[i] = x[++i]", "++i" will invalidate the already stored value for "i". In such
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4459
            // unfortunate cases this second storeStack() will restore the invariant that everything on the stack is
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4460
            // stored into a local variable, although at the cost of doing a store/load on the loaded arguments as well.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4461
            final int liveLocalsCount = storeStack(method.getStackSize() - stackSizeOnEntry, optimisticOrContinuation);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4462
            assert optimisticOrContinuation == (liveLocalsCount != -1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4463
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4464
            final Label beginTry;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4465
            final Label catchLabel;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4466
            final Label afterConsumeStack = isOptimistic || currentContinuationEntryPoint ? new Label("after_consume_stack") : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4467
            if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4468
                beginTry = new Label("try_optimistic");
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4469
                final String catchLabelName = (afterConsumeStack == null ? "" : afterConsumeStack.toString()) + "_handler";
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4470
                catchLabel = new Label(catchLabelName);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4471
                method.label(beginTry);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4472
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4473
                beginTry = catchLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4474
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4475
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4476
            consumeStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4477
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4478
            if(isOptimistic) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4479
                method._try(beginTry, afterConsumeStack, catchLabel, UnwarrantedOptimismException.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4480
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4481
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4482
            if(isOptimistic || currentContinuationEntryPoint) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4483
                method.label(afterConsumeStack);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4484
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4485
                final int[] localLoads = method.getLocalLoadsOnStack(0, stackSizeOnEntry);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4486
                assert everyStackValueIsLocalLoad(localLoads) : Arrays.toString(localLoads) + ", " + stackSizeOnEntry + ", " + ignoredArgCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4487
                final List<Type> localTypesList = method.getLocalVariableTypes();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4488
                final int usedLocals = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4489
                final List<Type> localTypes = method.getWidestLiveLocals(localTypesList.subList(0, usedLocals));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4490
                assert everyLocalLoadIsValid(localLoads, usedLocals) : Arrays.toString(localLoads) + " ~ " + localTypes;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4491
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4492
                if(isOptimistic) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4493
                    addUnwarrantedOptimismHandlerLabel(localTypes, catchLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4494
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4495
                if(currentContinuationEntryPoint) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4496
                    final ContinuationInfo ci = getContinuationInfo();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4497
                    assert ci != null : "no continuation info found for " + lc.getCurrentFunction();
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4498
                    assert !ci.hasTargetLabel(); // No duplicate program points
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4499
                    ci.setTargetLabel(afterConsumeStack);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4500
                    ci.getHandlerLabel().markAsOptimisticContinuationHandlerFor(afterConsumeStack);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4501
                    // Can't rely on targetLabel.stack.localVariableTypes.length, as it can be higher due to effectively
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4502
                    // dead local variables.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4503
                    ci.lvarCount = localTypes.size();
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4504
                    ci.setStackStoreSpec(localLoads);
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4505
                    ci.setStackTypes(Arrays.copyOf(method.getTypesFromStack(method.getStackSize()), stackSizeOnEntry));
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4506
                    assert ci.getStackStoreSpec().length == ci.getStackTypes().length;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4507
                    ci.setReturnValueType(method.peekType());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4508
                    ci.lineNumber = getLastLineNumber();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4509
                    ci.catchLabel = catchLabels.peek();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4510
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4511
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4512
            return method;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4513
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4514
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4515
        /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4516
         * Stores the current contents of the stack into local variables so they are not lost before invoking something that
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4517
         * can result in an {@code UnwarantedOptimizationException}.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4518
         * @param ignoreArgCount the number of topmost arguments on stack to ignore when deciding on the shape of the catch
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4519
         * block. Those are used in the situations when we could not place the call to {@code storeStack} early enough
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4520
         * (before emitting code for pushing the arguments that the optimistic call will pop). This is admittedly a
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4521
         * deficiency in the design of the code generator when it deals with self-assignments and we should probably look
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4522
         * into fixing it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4523
         * @return types of the significant local variables after the stack was stored (types for local variables used
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4524
         * for temporary storage of ignored arguments are not returned).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4525
         * @param optimisticOrContinuation if false, this method should not execute
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4526
         * a label for a catch block for the {@code UnwarantedOptimizationException}, suitable for capturing the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4527
         * currently live local variables, tailored to their types.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4528
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4529
        private int storeStack(final int ignoreArgCount, final boolean optimisticOrContinuation) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4530
            if(!optimisticOrContinuation) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4531
                return -1; // NOTE: correct value to return is lc.getUsedSlotCount(), but it wouldn't be used anyway
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4532
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4533
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4534
            final int stackSize = method.getStackSize();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4535
            final Type[] stackTypes = method.getTypesFromStack(stackSize);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4536
            final int[] localLoadsOnStack = method.getLocalLoadsOnStack(0, stackSize);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4537
            final int usedSlots = method.getUsedSlotsWithLiveTemporaries();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4538
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4539
            final int firstIgnored = stackSize - ignoreArgCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4540
            // Find the first value on the stack (from the bottom) that is not a load from a local variable.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4541
            int firstNonLoad = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4542
            while(firstNonLoad < firstIgnored && localLoadsOnStack[firstNonLoad] != Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4543
                firstNonLoad++;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4544
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4545
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4546
            // Only do the store/load if first non-load is not an ignored argument. Otherwise, do nothing and return
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4547
            // the number of used slots as the number of live local variables.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4548
            if(firstNonLoad >= firstIgnored) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4549
                return usedSlots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4550
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4551
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4552
            // Find the number of new temporary local variables that we need; it's the number of values on the stack that
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4553
            // are not direct loads of existing local variables.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4554
            int tempSlotsNeeded = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4555
            for(int i = firstNonLoad; i < stackSize; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4556
                if(localLoadsOnStack[i] == Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4557
                    tempSlotsNeeded += stackTypes[i].getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4558
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4559
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4560
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4561
            // Ensure all values on the stack that weren't directly loaded from a local variable are stored in a local
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4562
            // variable. We're starting from highest local variable index, so that in case ignoreArgCount > 0 the ignored
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4563
            // ones end up at the end of the local variable table.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4564
            int lastTempSlot = usedSlots + tempSlotsNeeded;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4565
            int ignoreSlotCount = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4566
            for(int i = stackSize; i -- > firstNonLoad;) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4567
                final int loadSlot = localLoadsOnStack[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4568
                if(loadSlot == Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4569
                    final Type type = stackTypes[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4570
                    final int slots = type.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4571
                    lastTempSlot -= slots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4572
                    if(i >= firstIgnored) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4573
                        ignoreSlotCount += slots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4574
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4575
                    method.storeTemp(type, lastTempSlot);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4576
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4577
                    method.pop();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4578
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4579
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4580
            assert lastTempSlot == usedSlots; // used all temporary locals
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4581
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4582
            final List<Type> localTypesList = method.getLocalVariableTypes();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4583
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4584
            // Load values back on stack.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4585
            for(int i = firstNonLoad; i < stackSize; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4586
                final int loadSlot = localLoadsOnStack[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4587
                final Type stackType = stackTypes[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4588
                final boolean isLoad = loadSlot != Label.Stack.NON_LOAD;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4589
                final int lvarSlot = isLoad ? loadSlot : lastTempSlot;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4590
                final Type lvarType = localTypesList.get(lvarSlot);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4591
                method.load(lvarType, lvarSlot);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4592
                if(isLoad) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4593
                    // Conversion operators (I2L etc.) preserve "load"-ness of the value despite the fact that, in the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4594
                    // strict sense they are creating a derived value from the loaded value. This special behavior of
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4595
                    // on-stack conversion operators is necessary to accommodate for differences in local variable types
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4596
                    // after deoptimization; having a conversion operator throw away "load"-ness would create different
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4597
                    // local variable table shapes between optimism-failed code and its deoptimized rest-of method).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4598
                    // After we load the value back, we need to redo the conversion to the stack type if stack type is
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4599
                    // different.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4600
                    // NOTE: this would only strictly be necessary for widening conversions (I2L, L2D, I2D), and not for
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4601
                    // narrowing ones (L2I, D2L, D2I) as only widening conversions are the ones that can get eliminated
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4602
                    // in a deoptimized method, as their original input argument got widened. Maybe experiment with
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4603
                    // throwing away "load"-ness for narrowing conversions in MethodEmitter.convert()?
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4604
                    method.convert(stackType);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4605
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4606
                    // temporary stores never needs a convert, as their type is always the same as the stack type.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4607
                    assert lvarType == stackType;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4608
                    lastTempSlot += lvarType.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4609
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4610
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4611
            // used all temporaries
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4612
            assert lastTempSlot == usedSlots + tempSlotsNeeded;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4613
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4614
            return lastTempSlot - ignoreSlotCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4615
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4616
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4617
        private void addUnwarrantedOptimismHandlerLabel(final List<Type> localTypes, final Label label) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4618
            final String lvarTypesDescriptor = getLvarTypesDescriptor(localTypes);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4619
            final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.getUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4620
            Collection<Label> labels = unwarrantedOptimismHandlers.get(lvarTypesDescriptor);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4621
            if(labels == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4622
                labels = new LinkedList<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4623
                unwarrantedOptimismHandlers.put(lvarTypesDescriptor, labels);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4624
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4625
            method.markLabelAsOptimisticCatchHandler(label, localTypes.size());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4626
            labels.add(label);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4627
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4628
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4629
        abstract void loadStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4630
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4631
        // Make sure that whatever indy call site you emit from this method uses {@code getCallSiteFlagsOptimistic(node)}
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4632
        // or otherwise ensure optimistic flag is correctly set in the call site, otherwise it doesn't make much sense
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4633
        // to use OptimisticExpression for emitting it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4634
        abstract void consumeStack();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4635
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4636
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4637
         * Emits the correct dynamic getter code. Normally just delegates to method emitter, except when the target
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4638
         * expression is optimistic, and the desired type is narrower than the optimistic type. In that case, it'll emit a
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4639
         * dynamic getter with its original optimistic type, and explicitly insert a narrowing conversion. This way we can
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4640
         * preserve the optimism of the values even if they're subsequently immediately coerced into a narrower type. This
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4641
         * is beneficial because in this case we can still presume that since the original getter was optimistic, the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4642
         * conversion has no side effects.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4643
         * @param name the name of the property being get
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4644
         * @param flags call site flags
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4645
         * @param isMethod whether we're preferrably retrieving a function
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4646
         * @return the current method emitter
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4647
         */
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4648
        MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4649
            if(isOptimistic) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4650
                return method.dynamicGet(getOptimisticCoercedType(), name, getOptimisticFlags(flags), isMethod, isIndex);
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4651
            }
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4652
            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod, isIndex);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4653
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4654
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4655
        MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4656
            if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4657
                return method.dynamicGetIndex(getOptimisticCoercedType(), getOptimisticFlags(flags), isMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4658
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4659
            return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4660
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4661
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4662
        MethodEmitter dynamicCall(final int argCount, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4663
            if (isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4664
                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4665
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4666
            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4667
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4668
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4669
        int getOptimisticFlags(final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4670
            return flags | CALLSITE_OPTIMISTIC | (optimistic.getProgramPoint() << CALLSITE_PROGRAM_POINT_SHIFT); //encode program point in high bits
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4671
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4672
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4673
        int getProgramPoint() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4674
            return isOptimistic ? optimistic.getProgramPoint() : INVALID_PROGRAM_POINT;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4675
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4676
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4677
        void convertOptimisticReturnValue() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4678
            if (isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4679
                final Type optimisticType = getOptimisticCoercedType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4680
                if(!optimisticType.isObject()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4681
                    method.load(optimistic.getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4682
                    if(optimisticType.isInteger()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4683
                        method.invoke(ENSURE_INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4684
                    } else if(optimisticType.isLong()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4685
                        method.invoke(ENSURE_LONG);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4686
                    } else if(optimisticType.isNumber()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4687
                        method.invoke(ENSURE_NUMBER);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4688
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4689
                        throw new AssertionError(optimisticType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4690
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4691
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4692
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4693
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4694
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4695
        void replaceCompileTimeProperty() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4696
            final IdentNode identNode = (IdentNode)expression;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4697
            final String name = identNode.getSymbol().getName();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4698
            if (CompilerConstants.__FILE__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4699
                replaceCompileTimeProperty(getCurrentSource().getName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4700
            } else if (CompilerConstants.__DIR__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4701
                replaceCompileTimeProperty(getCurrentSource().getBase());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4702
            } else if (CompilerConstants.__LINE__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4703
                replaceCompileTimeProperty(getCurrentSource().getLine(identNode.position()));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4704
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4705
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4706
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4707
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4708
         * When an ident with name __FILE__, __DIR__, or __LINE__ is loaded, we'll try to look it up as any other
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4709
         * identifier. However, if it gets all the way up to the Global object, it will send back a special value that
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4710
         * represents a placeholder for these compile-time location properties. This method will generate code that loads
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4711
         * the value of the compile-time location property and then invokes a method in Global that will replace the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4712
         * placeholder with the value. Effectively, if the symbol for these properties is defined anywhere in the lexical
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4713
         * scope, they take precedence, but if they aren't, then they resolve to the compile-time location property.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4714
         * @param propertyValue the actual value of the property
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4715
         */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4716
        private void replaceCompileTimeProperty(final Object propertyValue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4717
            assert method.peekType().isObject();
25826
3d2dd01a3a4a 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval()
sundar
parents: 25821
diff changeset
  4718
            if(propertyValue instanceof String || propertyValue == null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4719
                method.load((String)propertyValue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4720
            } else if(propertyValue instanceof Integer) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4721
                method.load(((Integer)propertyValue).intValue());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4722
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4723
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4724
                throw new AssertionError();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4725
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4726
            globalReplaceLocationPropertyPlaceholder();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4727
            convertOptimisticReturnValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4728
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4729
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4730
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4731
         * Returns the type that should be used as the return type of the dynamic invocation that is emitted as the code
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4732
         * for the current optimistic operation. If the type bounds is exact boolean or narrower than the expression's
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4733
         * optimistic type, then the optimistic type is returned, otherwise the coercing type. Effectively, this method
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4734
         * allows for moving the coercion into the optimistic type when it won't adversely affect the optimistic
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4735
         * evaluation semantics, and for preserving the optimistic type and doing a separate coercion when it would
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4736
         * affect it.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4737
         * @return
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4738
         */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4739
        private Type getOptimisticCoercedType() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4740
            final Type optimisticType = expression.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4741
            assert resultBounds.widest.widerThan(optimisticType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4742
            final Type narrowest = resultBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4743
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4744
            if(narrowest.isBoolean() || narrowest.narrowerThan(optimisticType)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4745
                assert !optimisticType.isObject();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4746
                return optimisticType;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4747
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4748
            assert !narrowest.isObject();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4749
            return narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4750
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4751
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4752
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4753
    private static boolean isOptimistic(final Optimistic optimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4754
        if(!optimistic.canBeOptimistic()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4755
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4756
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4757
        final Expression expr = (Expression)optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4758
        return expr.getType().narrowerThan(expr.getWidestOperationType());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4759
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4760
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  4761
    private static boolean everyLocalLoadIsValid(final int[] loads, final int localCount) {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4762
        for (final int load : loads) {
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4763
            if(load < 0 || load >= localCount) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4764
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4765
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4766
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4767
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4768
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4769
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4770
    private static boolean everyStackValueIsLocalLoad(final int[] loads) {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4771
        for (final int load : loads) {
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4772
            if(load == Label.Stack.NON_LOAD) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4773
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4774
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4775
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4776
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4777
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4778
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4779
    private String getLvarTypesDescriptor(final List<Type> localVarTypes) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4780
        final int count = localVarTypes.size();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4781
        final StringBuilder desc = new StringBuilder(count);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4782
        for(int i = 0; i < count;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4783
            i += appendType(desc, localVarTypes.get(i));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4784
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4785
        return method.markSymbolBoundariesInLvarTypesDescriptor(desc.toString());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4786
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4787
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4788
    private static int appendType(final StringBuilder b, final Type t) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4789
        b.append(t.getBytecodeStackType());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4790
        return t.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4791
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4792
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4793
    private static int countSymbolsInLvarTypeDescriptor(final String lvarTypeDescriptor) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4794
        int count = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4795
        for(int i = 0; i < lvarTypeDescriptor.length(); ++i) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4796
            if(Character.isUpperCase(lvarTypeDescriptor.charAt(i))) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4797
                ++count;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4798
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4799
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4800
        return count;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4801
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4802
    }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4803
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4804
     * Generates all the required {@code UnwarrantedOptimismException} handlers for the current function. The employed
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4805
     * strategy strives to maximize code reuse. Every handler constructs an array to hold the local variables, then
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4806
     * fills in some trailing part of the local variables (those for which it has a unique suffix in the descriptor),
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4807
     * then jumps to a handler for a prefix that's shared with other handlers. A handler that fills up locals up to
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4808
     * position 0 will not jump to a prefix handler (as it has no prefix), but instead end with constructing and
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4809
     * throwing a {@code RewriteException}. Since we lexicographically sort the entries, we only need to check every
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4810
     * entry to its immediately preceding one for longest matching prefix.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4811
     * @return true if there is at least one exception handler
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4812
     */
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  4813
    private boolean generateUnwarrantedOptimismExceptionHandlers(final FunctionNode fn) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4814
        if(!useOptimisticTypes()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4815
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4816
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4817
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4818
        // Take the mapping of lvarSpecs -> labels, and turn them into a descending lexicographically sorted list of
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4819
        // handler specifications.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4820
        final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.popUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4821
        if(unwarrantedOptimismHandlers.isEmpty()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4822
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4823
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4824
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4825
        method.lineNumber(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4826
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4827
        final List<OptimismExceptionHandlerSpec> handlerSpecs = new ArrayList<>(unwarrantedOptimismHandlers.size() * 4/3);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4828
        for(final String spec: unwarrantedOptimismHandlers.keySet()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4829
            handlerSpecs.add(new OptimismExceptionHandlerSpec(spec, true));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4830
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4831
        Collections.sort(handlerSpecs, Collections.reverseOrder());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4832
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4833
        // Map of local variable specifications to labels for populating the array for that local variable spec.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4834
        final Map<String, Label> delegationLabels = new HashMap<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4835
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4836
        // Do everything in a single pass over the handlerSpecs list. Note that the list can actually grow as we're
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4837
        // passing through it as we might add new prefix handlers into it, so can't hoist size() outside of the loop.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4838
        for(int handlerIndex = 0; handlerIndex < handlerSpecs.size(); ++handlerIndex) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4839
            final OptimismExceptionHandlerSpec spec = handlerSpecs.get(handlerIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4840
            final String lvarSpec = spec.lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4841
            if(spec.catchTarget) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4842
                assert !method.isReachable();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4843
                // Start a catch block and assign the labels for this lvarSpec with it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4844
                method._catch(unwarrantedOptimismHandlers.get(lvarSpec));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4845
                // This spec is a catch target, so emit array creation code. The length of the array is the number of
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4846
                // symbols - the number of uppercase characters.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4847
                method.load(countSymbolsInLvarTypeDescriptor(lvarSpec));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4848
                method.newarray(Type.OBJECT_ARRAY);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4849
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4850
            if(spec.delegationTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4851
                // If another handler can delegate to this handler as its prefix, then put a jump target here for the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4852
                // shared code (after the array creation code, which is never shared).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4853
                method.label(delegationLabels.get(lvarSpec)); // label must exist
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4854
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4855
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4856
            final boolean lastHandler = handlerIndex == handlerSpecs.size() - 1;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4857
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4858
            int lvarIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4859
            final int firstArrayIndex;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4860
            final int firstLvarIndex;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4861
            Label delegationLabel;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4862
            final String commonLvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4863
            if(lastHandler) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4864
                // Last handler block, doesn't delegate to anything.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4865
                lvarIndex = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4866
                firstLvarIndex = 0;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4867
                firstArrayIndex = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4868
                delegationLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4869
                commonLvarSpec = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4870
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4871
                // Not yet the last handler block, will definitely delegate to another handler; let's figure out which
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4872
                // one. It can be an already declared handler further down the list, or it might need to declare a new
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4873
                // prefix handler.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4874
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4875
                // Since we're lexicographically ordered, the common prefix handler is defined by the common prefix of
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4876
                // this handler and the next handler on the list.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4877
                final int nextHandlerIndex = handlerIndex + 1;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4878
                final String nextLvarSpec = handlerSpecs.get(nextHandlerIndex).lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4879
                commonLvarSpec = commonPrefix(lvarSpec, nextLvarSpec);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4880
                // We don't chop symbols in half
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4881
                assert Character.isUpperCase(commonLvarSpec.charAt(commonLvarSpec.length() - 1));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4882
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4883
                // Let's find if we already have a declaration for such handler, or we need to insert it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4884
                {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4885
                    boolean addNewHandler = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4886
                    int commonHandlerIndex = nextHandlerIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4887
                    for(; commonHandlerIndex < handlerSpecs.size(); ++commonHandlerIndex) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4888
                        final OptimismExceptionHandlerSpec forwardHandlerSpec = handlerSpecs.get(commonHandlerIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4889
                        final String forwardLvarSpec = forwardHandlerSpec.lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4890
                        if(forwardLvarSpec.equals(commonLvarSpec)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4891
                            // We already have a handler for the common prefix.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4892
                            addNewHandler = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4893
                            // Make sure we mark it as a delegation target.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4894
                            forwardHandlerSpec.delegationTarget = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4895
                            break;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4896
                        } else if(!forwardLvarSpec.startsWith(commonLvarSpec)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4897
                            break;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4898
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4899
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4900
                    if(addNewHandler) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4901
                        // We need to insert a common prefix handler. Note handlers created with catchTarget == false
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4902
                        // will automatically have delegationTarget == true (because that's the only reason for their
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4903
                        // existence).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4904
                        handlerSpecs.add(commonHandlerIndex, new OptimismExceptionHandlerSpec(commonLvarSpec, false));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4905
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4906
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4907
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4908
                firstArrayIndex = countSymbolsInLvarTypeDescriptor(commonLvarSpec);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4909
                lvarIndex = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4910
                for(int j = 0; j < commonLvarSpec.length(); ++j) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4911
                    lvarIndex += CodeGeneratorLexicalContext.getTypeForSlotDescriptor(commonLvarSpec.charAt(j)).getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4912
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4913
                firstLvarIndex = lvarIndex;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4914
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4915
                // Create a delegation label if not already present
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4916
                delegationLabel = delegationLabels.get(commonLvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4917
                if(delegationLabel == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4918
                    // uo_pa == "unwarranted optimism, populate array"
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4919
                    delegationLabel = new Label("uo_pa_" + commonLvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4920
                    delegationLabels.put(commonLvarSpec, delegationLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4921
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4922
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4923
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4924
            // Load local variables handled by this handler on stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4925
            int args = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4926
            boolean symbolHadValue = false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4927
            for(int typeIndex = commonLvarSpec == null ? 0 : commonLvarSpec.length(); typeIndex < lvarSpec.length(); ++typeIndex) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4928
                final char typeDesc = lvarSpec.charAt(typeIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4929
                final Type lvarType = CodeGeneratorLexicalContext.getTypeForSlotDescriptor(typeDesc);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4930
                if (!lvarType.isUnknown()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4931
                    method.load(lvarType, lvarIndex);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4932
                    symbolHadValue = true;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4933
                    args++;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4934
                } else if(typeDesc == 'U' && !symbolHadValue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4935
                    // Symbol boundary with undefined last value. Check if all previous values for this symbol were also
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4936
                    // undefined; if so, emit one explicit Undefined. This serves to ensure that we're emiting exactly
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4937
                    // one value for every symbol that uses local slots. While we could in theory ignore symbols that
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4938
                    // are undefined (in other words, dead) at the point where this exception was thrown, unfortunately
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4939
                    // we can't do it in practice. The reason for this is that currently our liveness analysis is
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4940
                    // coarse (it can determine whether a symbol has not been read with a particular type anywhere in
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4941
                    // the function being compiled, but that's it), and a symbol being promoted to Object due to a
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4942
                    // deoptimization will suddenly show up as "live for Object type", and previously dead U->O
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4943
                    // conversions on loop entries will suddenly become alive in the deoptimized method which will then
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4944
                    // expect a value for that slot in its continuation handler. If we had precise liveness analysis, we
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4945
                    // could go back to excluding known dead symbols from the payload of the RewriteException.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4946
                    if(method.peekType() == Type.UNDEFINED) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4947
                        method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4948
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4949
                        method.loadUndefined(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4950
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4951
                    args++;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4952
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4953
                if(Character.isUpperCase(typeDesc)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4954
                    // Reached symbol boundary; reset flag for the next symbol.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4955
                    symbolHadValue = false;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4956
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4957
                lvarIndex += lvarType.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4958
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4959
            assert args > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4960
            // Delegate actual storing into array to an array populator utility method.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4961
            //on the stack:
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4962
            // object array to be populated
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4963
            // start index
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4964
            // a lot of types
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4965
            method.dynamicArrayPopulatorCall(args + 1, firstArrayIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4966
            if(delegationLabel != null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4967
                // We cascade to a prefix handler to fill out the rest of the local variables and throw the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4968
                // RewriteException.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4969
                assert !lastHandler;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4970
                assert commonLvarSpec != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4971
                // Must undefine the local variables that we have already processed for the sake of correct join on the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4972
                // delegate label
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4973
                method.undefineLocalVariables(firstLvarIndex, true);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4974
                final OptimismExceptionHandlerSpec nextSpec = handlerSpecs.get(handlerIndex + 1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4975
                // If the delegate immediately follows, and it's not a catch target (so it doesn't have array setup
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4976
                // code) don't bother emitting a jump, as we'd just jump to the next instruction.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4977
                if(!nextSpec.lvarSpec.equals(commonLvarSpec) || nextSpec.catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4978
                    method._goto(delegationLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4979
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4980
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4981
                assert lastHandler;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4982
                // Nothing to delegate to, so this handler must create and throw the RewriteException.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4983
                // At this point we have the UnwarrantedOptimismException and the Object[] with local variables on
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4984
                // stack. We need to create a RewriteException, push two references to it below the constructor
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4985
                // arguments, invoke the constructor, and throw the exception.
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  4986
                loadConstant(getByteCodeSymbolNames(fn));
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4987
                if (isRestOf()) {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4988
                    loadConstant(getContinuationEntryPoints());
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
  4989
                    method.invoke(CREATE_REWRITE_EXCEPTION_REST_OF);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4990
                } else {
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
  4991
                    method.invoke(CREATE_REWRITE_EXCEPTION);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4992
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4993
                method.athrow();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4994
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4995
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4996
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4997
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4998
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  4999
    private static String[] getByteCodeSymbolNames(final FunctionNode fn) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5000
        // Only names of local variables on the function level are captured. This information is used to reduce
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5001
        // deoptimizations, so as much as we can capture will help. We rely on the fact that function wide variables are
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5002
        // all live all the time, so the array passed to rewrite exception contains one element for every slotted symbol
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5003
        // here.
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5004
        final List<String> names = new ArrayList<>();
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5005
        for (final Symbol symbol: fn.getBody().getSymbols()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5006
            if (symbol.hasSlot()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5007
                if (symbol.isScope()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5008
                    // slot + scope can only be true for parameters
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5009
                    assert symbol.isParam();
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5010
                    names.add(null);
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5011
                } else {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5012
                    names.add(symbol.getName());
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5013
                }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5014
            }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5015
        }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5016
        return names.toArray(new String[names.size()]);
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5017
    }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5018
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  5019
    private static String commonPrefix(final String s1, final String s2) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5020
        final int l1 = s1.length();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5021
        final int l = Math.min(l1, s2.length());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5022
        int lms = -1; // last matching symbol
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5023
        for(int i = 0; i < l; ++i) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5024
            final char c1 = s1.charAt(i);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5025
            if(c1 != s2.charAt(i)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5026
                return s1.substring(0, lms + 1);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5027
            } else if(Character.isUpperCase(c1)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5028
                lms = i;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5029
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5030
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5031
        return l == l1 ? s1 : s2;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5032
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5033
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5034
    private static class OptimismExceptionHandlerSpec implements Comparable<OptimismExceptionHandlerSpec> {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5035
        private final String lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5036
        private final boolean catchTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5037
        private boolean delegationTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5038
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  5039
        OptimismExceptionHandlerSpec(final String lvarSpec, final boolean catchTarget) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5040
            this.lvarSpec = lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5041
            this.catchTarget = catchTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5042
            if(!catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5043
                delegationTarget = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5044
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5045
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5046
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5047
        @Override
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  5048
        public int compareTo(final OptimismExceptionHandlerSpec o) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5049
            return lvarSpec.compareTo(o.lvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5050
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5051
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5052
        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5053
        public String toString() {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5054
            final StringBuilder b = new StringBuilder(64).append("[HandlerSpec ").append(lvarSpec);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5055
            if(catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5056
                b.append(", catchTarget");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5057
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5058
            if(delegationTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5059
                b.append(", delegationTarget");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5060
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5061
            return b.append("]").toString();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5062
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5063
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5064
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5065
    private static class ContinuationInfo {
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5066
        private final Label handlerLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5067
        private Label targetLabel; // Label for the target instruction.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5068
        int lvarCount;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5069
        // Indices of local variables that need to be loaded on the stack when this node completes
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5070
        private int[] stackStoreSpec;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5071
        // Types of values loaded on the stack
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5072
        private Type[] stackTypes;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5073
        // If non-null, this node should perform the requisite type conversion
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5074
        private Type returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5075
        // If we are in the middle of an object literal initialization, we need to update the map
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5076
        private PropertyMap objectLiteralMap;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5077
        // Object literal stack depth for object literal - not necessarly top if property is a tree
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5078
        private int objectLiteralStackDepth = -1;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5079
        // The line number at the continuation point
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5080
        private int lineNumber;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5081
        // The active catch label, in case the continuation point is in a try/catch block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5082
        private Label catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5083
        // The number of scopes that need to be popped before control is transferred to the catch label.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5084
        private int exceptionScopePops;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5085
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5086
        ContinuationInfo() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5087
            this.handlerLabel = new Label("continuation_handler");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5088
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5089
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5090
        Label getHandlerLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5091
            return handlerLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5092
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5093
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5094
        boolean hasTargetLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5095
            return targetLabel != null;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5096
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5097
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5098
        Label getTargetLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5099
            return targetLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5100
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5101
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5102
        void setTargetLabel(final Label targetLabel) {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5103
            this.targetLabel = targetLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5104
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5105
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5106
        int[] getStackStoreSpec() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5107
            return stackStoreSpec.clone();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5108
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5109
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5110
        void setStackStoreSpec(final int[] stackStoreSpec) {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5111
            this.stackStoreSpec = stackStoreSpec;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5112
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5113
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5114
        Type[] getStackTypes() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5115
            return stackTypes.clone();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5116
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5117
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5118
        void setStackTypes(final Type[] stackTypes) {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5119
            this.stackTypes = stackTypes;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5120
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5121
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5122
        Type getReturnValueType() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5123
            return returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5124
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5125
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5126
        void setReturnValueType(final Type returnValueType) {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5127
            this.returnValueType = returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5128
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5129
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5130
        int getObjectLiteralStackDepth() {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5131
            return objectLiteralStackDepth;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5132
        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5133
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5134
        void setObjectLiteralStackDepth(final int objectLiteralStackDepth) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5135
            this.objectLiteralStackDepth = objectLiteralStackDepth;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5136
        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5137
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5138
        PropertyMap getObjectLiteralMap() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5139
            return objectLiteralMap;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5140
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5141
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5142
        void setObjectLiteralMap(final PropertyMap objectLiteralMap) {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5143
            this.objectLiteralMap = objectLiteralMap;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5144
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5145
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5146
        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5147
        public String toString() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5148
             return "[localVariableTypes=" + targetLabel.getStack().getLocalVariableTypesCopy() + ", stackStoreSpec=" +
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5149
                     Arrays.toString(stackStoreSpec) + ", returnValueType=" + returnValueType + "]";
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5150
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5151
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5152
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5153
    private ContinuationInfo getContinuationInfo() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5154
        return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5155
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5156
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5157
    private void generateContinuationHandler() {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  5158
        if (!isRestOf()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5159
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5160
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5161
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5162
        final ContinuationInfo ci = getContinuationInfo();
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5163
        method.label(ci.getHandlerLabel());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5164
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5165
        // There should never be an exception thrown from the continuation handler, but in case there is (meaning,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5166
        // Nashorn has a bug), then line number 0 will be an indication of where it came from (line numbers are Uint16).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5167
        method.lineNumber(0);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5168
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5169
        final Label.Stack stack = ci.getTargetLabel().getStack();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5170
        final List<Type> lvarTypes = stack.getLocalVariableTypesCopy();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5171
        final BitSet symbolBoundary = stack.getSymbolBoundaryCopy();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5172
        final int lvarCount = ci.lvarCount;
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 24729
diff changeset
  5173
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 24729
diff changeset
  5174
        final Type rewriteExceptionType = Type.typeFor(RewriteException.class);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5175
        // Store the RewriteException into an unused local variable slot.
24731
ab0c8fc915ae 8038406: Testability: as a first step of moving loggers away from the process global space, the Debug object now supports logging POJOs from log entries as an event queue, which can be introspected from test scripts. This is way better than screen scraping brittle and subject-to-change log output.
lagergren
parents: 24729
diff changeset
  5176
        method.load(rewriteExceptionType, 0);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5177
        method.storeTemp(rewriteExceptionType, lvarCount);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5178
        // Get local variable array
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5179
        method.load(rewriteExceptionType, 0);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5180
        method.invoke(RewriteException.GET_BYTECODE_SLOTS);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5181
        // Store local variables. Note that deoptimization might introduce new value types for existing local variables,
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5182
        // so we must use both liveLocals and symbolBoundary, as in some cases (when the continuation is inside of a try
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5183
        // block) we need to store the incoming value into multiple slots. The optimism exception handlers will have
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5184
        // exactly one array element for every symbol that uses bytecode storage. If in the originating method the value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5185
        // was undefined, there will be an explicit Undefined value in the array.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5186
        int arrayIndex = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5187
        for(int lvarIndex = 0; lvarIndex < lvarCount;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5188
            final Type lvarType = lvarTypes.get(lvarIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5189
            if(!lvarType.isUnknown()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5190
                method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5191
                method.load(arrayIndex).arrayload();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5192
                final Class<?> typeClass = lvarType.getTypeClass();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5193
                // Deoptimization in array initializers can cause arrays to undergo component type widening
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5194
                if(typeClass == long[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5195
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5196
                    method.invoke(RewriteException.TO_LONG_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5197
                } else if(typeClass == double[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5198
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5199
                    method.invoke(RewriteException.TO_DOUBLE_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5200
                } else if(typeClass == Object[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5201
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5202
                    method.invoke(RewriteException.TO_OBJECT_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5203
                } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5204
                    if(!(typeClass.isPrimitive() || typeClass == Object.class)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5205
                        // NOTE: this can only happen with dead stores. E.g. for the program "1; []; f();" in which the
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5206
                        // call to f() will deoptimize the call site, but it'll expect :return to have the type
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5207
                        // NativeArray. However, in the more optimal version, :return's only live type is int, therefore
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5208
                        // "{O}:return = []" is a dead store, and the variable will be sent into the continuation as
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5209
                        // Undefined, however NativeArray can't hold Undefined instance.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5210
                        method.loadType(Type.getInternalName(typeClass));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5211
                        method.invoke(RewriteException.INSTANCE_OR_NULL);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5212
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5213
                    method.convert(lvarType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5214
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5215
                method.storeHidden(lvarType, lvarIndex, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5216
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5217
            final int nextLvarIndex = lvarIndex + lvarType.getSlots();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5218
            if(symbolBoundary.get(nextLvarIndex - 1)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5219
                ++arrayIndex;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5220
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5221
            lvarIndex = nextLvarIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5222
        }
26250
84bbd0e8b2b2 8056025: CompilationPhase.setStates() is hot in class installation phase
attila
parents: 26241
diff changeset
  5223
        if (AssertsEnabled.assertsEnabled()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5224
            method.load(arrayIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5225
            method.invoke(RewriteException.ASSERT_ARRAY_LENGTH);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5226
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5227
            method.pop();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5228
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5229
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5230
        final int[]   stackStoreSpec = ci.getStackStoreSpec();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5231
        final Type[]  stackTypes     = ci.getStackTypes();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5232
        final boolean isStackEmpty   = stackStoreSpec.length == 0;
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5233
        boolean replacedObjectLiteralMap = false;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5234
        if(!isStackEmpty) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5235
            // Load arguments on the stack
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5236
            final int objectLiteralStackDepth = ci.getObjectLiteralStackDepth();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5237
            for(int i = 0; i < stackStoreSpec.length; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5238
                final int slot = stackStoreSpec[i];
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5239
                method.load(lvarTypes.get(slot), slot);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5240
                method.convert(stackTypes[i]);
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5241
                // stack: s0=object literal being initialized
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5242
                // change map of s0 so that the property we are initilizing when we failed
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5243
                // is now ci.returnValueType
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5244
                if (i == objectLiteralStackDepth) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5245
                    method.dup();
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5246
                    assert ci.getObjectLiteralMap() != null;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5247
                    assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object";
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5248
                    loadConstant(ci.getObjectLiteralMap());
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5249
                    method.invoke(ScriptObject.SET_MAP);
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5250
                    replacedObjectLiteralMap = true;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5251
                }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5252
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5253
        }
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5254
        // Must have emitted the code for replacing the map of an object literal if we have a set object literal stack depth
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5255
        assert ci.getObjectLiteralStackDepth() == -1 || replacedObjectLiteralMap;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5256
        // Load RewriteException back.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5257
        method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5258
        // Get rid of the stored reference
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5259
        method.loadNull();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5260
        method.storeHidden(Type.OBJECT, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5261
        // Mark it dead
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5262
        method.markDeadSlots(lvarCount, Type.OBJECT.getSlots());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5263
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5264
        // Load return value on the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5265
        method.invoke(RewriteException.GET_RETURN_VALUE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5266
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5267
        final Type returnValueType = ci.getReturnValueType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5268
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5269
        // Set up an exception handler for primitive type conversion of return value if needed
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5270
        boolean needsCatch = false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5271
        final Label targetCatchLabel = ci.catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5272
        Label _try = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5273
        if(returnValueType.isPrimitive()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5274
            // If the conversion throws an exception, we want to report the line number of the continuation point.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5275
            method.lineNumber(ci.lineNumber);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5276
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5277
            if(targetCatchLabel != METHOD_BOUNDARY) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5278
                _try = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5279
                method.label(_try);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5280
                needsCatch = true;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5281
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5282
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5283
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5284
        // Convert return value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5285
        method.convert(returnValueType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5286
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5287
        final int scopePopCount = needsCatch ? ci.exceptionScopePops : 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5288
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5289
        // Declare a try/catch for the conversion. If no scopes need to be popped until the target catch block, just
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5290
        // jump into it. Otherwise, we'll need to create a scope-popping catch block below.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5291
        final Label catchLabel = scopePopCount > 0 ? new Label("") : targetCatchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5292
        if(needsCatch) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5293
            final Label _end_try = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5294
            method.label(_end_try);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5295
            method._try(_try, _end_try, catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5296
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5297
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5298
        // Jump to continuation point
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5299
        method._goto(ci.getTargetLabel());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5300
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5301
        // Make a scope-popping exception delegate if needed
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5302
        if(catchLabel != targetCatchLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5303
            method.lineNumber(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5304
            assert scopePopCount > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5305
            method._catch(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5306
            popScopes(scopePopCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5307
            method.uncheckedGoto(targetCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5308
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5309
    }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  5310
}