src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
author attila
Wed, 20 Dec 2017 17:36:50 +0100
changeset 48354 c96d4c720995
parent 48247 fa5a47cad0c9
child 48430 68c6f57c40d4
permissions -rw-r--r--
8193371: Use Dynalink REMOVE operation in Nashorn Reviewed-by: hannesw, sundar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     1
/*
35407
204abe4d8cbc 8147591: Revisit Collection.toArray(new T[size]) calls in nashorn and dynalink code
mhaupt
parents: 34732
diff changeset
     2
 * Copyright (c) 2010, 2016, 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;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
    46
import static jdk.nashorn.internal.ir.Symbol.HAS_SLOT;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    47
import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    48
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    49
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
    50
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
    51
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    52
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    53
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    54
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    55
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    56
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    57
import java.io.PrintWriter;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    58
import java.util.ArrayDeque;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    59
import java.util.ArrayList;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    60
import java.util.Arrays;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
    61
import java.util.BitSet;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    62
import java.util.Collection;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    63
import java.util.Collections;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    64
import java.util.Deque;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    65
import java.util.EnumSet;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    66
import java.util.HashMap;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
    67
import java.util.HashSet;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    68
import java.util.Iterator;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    69
import java.util.LinkedList;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    70
import java.util.List;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    71
import java.util.Map;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
    72
import java.util.Set;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    73
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
    74
import java.util.function.Supplier;
26250
84bbd0e8b2b2 8056025: CompilationPhase.setStates() is hot in class installation phase
attila
parents: 26241
diff changeset
    75
import jdk.nashorn.internal.AssertsEnabled;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
    76
import jdk.nashorn.internal.IntDeque;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    77
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    78
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    79
import jdk.nashorn.internal.codegen.types.ArrayType;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    80
import jdk.nashorn.internal.codegen.types.Type;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    81
import jdk.nashorn.internal.ir.AccessNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    82
import jdk.nashorn.internal.ir.BaseNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    83
import jdk.nashorn.internal.ir.BinaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    84
import jdk.nashorn.internal.ir.Block;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
    85
import jdk.nashorn.internal.ir.BlockStatement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    86
import jdk.nashorn.internal.ir.BreakNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    87
import jdk.nashorn.internal.ir.CallNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    88
import jdk.nashorn.internal.ir.CaseNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    89
import jdk.nashorn.internal.ir.CatchNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    90
import jdk.nashorn.internal.ir.ContinueNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    91
import jdk.nashorn.internal.ir.EmptyNode;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
    92
import jdk.nashorn.internal.ir.Expression;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
    93
import jdk.nashorn.internal.ir.ExpressionStatement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    94
import jdk.nashorn.internal.ir.ForNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    95
import jdk.nashorn.internal.ir.FunctionNode;
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
    96
import jdk.nashorn.internal.ir.GetSplitState;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    97
import jdk.nashorn.internal.ir.IdentNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    98
import jdk.nashorn.internal.ir.IfNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    99
import jdk.nashorn.internal.ir.IndexNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   100
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
   101
import jdk.nashorn.internal.ir.JumpStatement;
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
   102
import jdk.nashorn.internal.ir.JumpToInlinedFinally;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   103
import jdk.nashorn.internal.ir.LabelNode;
17968
108ba976aa02 8015684: FieldObjectCreator.putField ignores getValueType
attila
parents: 17778
diff changeset
   104
import jdk.nashorn.internal.ir.LexicalContext;
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   105
import jdk.nashorn.internal.ir.LexicalContextNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   106
import jdk.nashorn.internal.ir.LiteralNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   107
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   108
import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   109
import jdk.nashorn.internal.ir.LocalVariableConversion;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   110
import jdk.nashorn.internal.ir.LoopNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   111
import jdk.nashorn.internal.ir.Node;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   112
import jdk.nashorn.internal.ir.ObjectNode;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   113
import jdk.nashorn.internal.ir.Optimistic;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   114
import jdk.nashorn.internal.ir.PropertyNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   115
import jdk.nashorn.internal.ir.ReturnNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   116
import jdk.nashorn.internal.ir.RuntimeNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   117
import jdk.nashorn.internal.ir.RuntimeNode.Request;
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   118
import jdk.nashorn.internal.ir.SetSplitState;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   119
import jdk.nashorn.internal.ir.SplitReturn;
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
   120
import jdk.nashorn.internal.ir.Splittable;
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
   121
import jdk.nashorn.internal.ir.Statement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   122
import jdk.nashorn.internal.ir.SwitchNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   123
import jdk.nashorn.internal.ir.Symbol;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   124
import jdk.nashorn.internal.ir.TernaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   125
import jdk.nashorn.internal.ir.ThrowNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   126
import jdk.nashorn.internal.ir.TryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   127
import jdk.nashorn.internal.ir.UnaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   128
import jdk.nashorn.internal.ir.VarNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   129
import jdk.nashorn.internal.ir.WhileNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   130
import jdk.nashorn.internal.ir.WithNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   131
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
32888
24f99be3d5ab 8134502: introduce abstraction for basic NodeVisitor usage
attila
parents: 32784
diff changeset
   132
import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   133
import jdk.nashorn.internal.objects.Global;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   134
import jdk.nashorn.internal.parser.Lexer.RegexToken;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   135
import jdk.nashorn.internal.parser.TokenType;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   136
import jdk.nashorn.internal.runtime.Context;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   137
import jdk.nashorn.internal.runtime.Debug;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   138
import jdk.nashorn.internal.runtime.ECMAException;
17241
c337fefb8c84 8012334: ToUint32, ToInt32, and ToUint16 don't conform to spec
hannesw
parents: 17239
diff changeset
   139
import jdk.nashorn.internal.runtime.JSType;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   140
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   141
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
   142
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   143
import jdk.nashorn.internal.runtime.RewriteException;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   144
import jdk.nashorn.internal.runtime.Scope;
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
   145
import jdk.nashorn.internal.runtime.ScriptEnvironment;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   146
import jdk.nashorn.internal.runtime.ScriptFunction;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   147
import jdk.nashorn.internal.runtime.ScriptObject;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   148
import jdk.nashorn.internal.runtime.ScriptRuntime;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   149
import jdk.nashorn.internal.runtime.Source;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   150
import jdk.nashorn.internal.runtime.Undefined;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   151
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
   152
import jdk.nashorn.internal.runtime.arrays.ArrayData;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   153
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
48354
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
   154
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   155
import jdk.nashorn.internal.runtime.logging.DebugLogger;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   156
import jdk.nashorn.internal.runtime.logging.Loggable;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   157
import jdk.nashorn.internal.runtime.logging.Logger;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   158
import jdk.nashorn.internal.runtime.options.Options;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   159
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   160
/**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   161
 * This is the lowest tier of the code generator. It takes lowered ASTs emitted
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   162
 * from Lower and emits Java byte code. The byte code emission logic is broken
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   163
 * out into MethodEmitter. MethodEmitter works internally with a type stack, and
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   164
 * 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
   165
 * number of special cases on the form
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   166
 * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   167
 * if (type == INT) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   168
 *     visitInsn(ILOAD, slot);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   169
 * } else if (type == DOUBLE) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   170
 *     visitInsn(DOUBLE, slot);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   171
 * }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   172
 * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   173
 * This quickly became apparent when the code generator was generalized to work
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   174
 * with all types, and not just numbers or objects.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   175
 * <p>
30391
62dcad329b26 8079349: Eliminate dead code around Nashorn code generator
attila
parents: 30390
diff changeset
   176
 * The CodeGenerator visits nodes only once and emits bytecode for them.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   177
 */
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   178
@Logger(name="codegen")
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   179
final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   180
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   181
    private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   182
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   183
    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
   184
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   185
    private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   186
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   187
    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
   188
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   189
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   190
    private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   191
            "ensureInt", int.class, Object.class, int.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   192
    private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   193
            "ensureNumber", double.class, Object.class, int.class);
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   194
32527
b105632002c5 8027137: Merge ScriptFunction and ScriptFunctionImpl
sundar
parents: 32316
diff changeset
   195
    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   196
            "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
32527
b105632002c5 8027137: Merge ScriptFunction and ScriptFunctionImpl
sundar
parents: 32316
diff changeset
   197
    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   198
            "create", ScriptFunction.class, Object[].class, int.class);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   199
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   200
    private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   201
            "toNumberForEq", double.class, Object.class);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   202
    private static final Call TO_NUMBER_FOR_STRICT_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   203
            "toNumberForStrictEq", double.class, Object.class);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   204
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   205
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   206
    private static final Class<?> ITERATOR_CLASS = Iterator.class;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   207
    static {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   208
        assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   209
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   210
    private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   211
    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
   212
31549
b627094c5649 8130734: Apply transformations found by netbeans Refactor->Inspect and transform menu
sundar
parents: 30697
diff changeset
   213
    private static final Integer INT_ZERO = 0;
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
   214
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   215
    /** 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
   216
     *  by reflection in class installation */
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   217
    private final Compiler compiler;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   218
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   219
    /** 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
   220
    private final boolean evalCode;
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   221
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   222
    /** 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
   223
    private final int callSiteFlags;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   224
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   225
    /** How many regexp fields have been emitted */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   226
    private int regexFieldCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   227
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
   228
    /** 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
   229
     *  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
   230
    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
   231
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
    /** 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
   233
    private static final int MAX_REGEX_FIELDS = 2 * 1024;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   234
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   235
    /** Current method emitter */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   236
    private MethodEmitter method;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   237
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   238
    /** Current compile unit */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   239
    private CompileUnit unit;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   240
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   241
    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
   242
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
   243
    /** From what size should we use spill instead of fields for JavaScript objects? */
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
   244
    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
   245
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
   246
    private final Set<String> emittedMethods = new HashSet<>();
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
   247
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   248
    // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
32316
5d7dd8dc7729 8133785: SharedScopeCall should be enabled for non-optimistic call sites in optimistic compilation
attila
parents: 32049
diff changeset
   249
    private ContinuationInfo continuationInfo;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   250
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   251
    private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   252
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   253
    private static final Label METHOD_BOUNDARY = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   254
    private final Deque<Label> catchLabels = new ArrayDeque<>();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   255
    // 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
   256
    private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   257
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   258
    //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
   259
    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
   260
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
   261
    // Scope object creators needed for for-of and for-in loops
41422
97eda72f53b6 8167117: insert missing final keywords
attila
parents: 41238
diff changeset
   262
    private final Deque<FieldObjectCreator<?>> scopeObjectCreators = new ArrayDeque<>();
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
   263
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   264
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   265
     * Constructor.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   266
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   267
     * @param compiler
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   268
     */
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
    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
   270
        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
   271
        this.compiler                = compiler;
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   272
        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
   273
        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
   274
        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
   275
        this.log                     = initLogger(compiler.getContext());
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   276
    }
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
    @Override
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   279
    public DebugLogger getLogger() {
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   280
        return log;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   281
    }
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   282
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   283
    @Override
24745
3a6e1477362b 8041434: Add synchronization to the common global constants structure
lagergren
parents: 24744
diff changeset
   284
    public DebugLogger initLogger(final Context context) {
3a6e1477362b 8041434: Add synchronization to the common global constants structure
lagergren
parents: 24744
diff changeset
   285
        return context.getLogger(this.getClass());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   286
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   287
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   288
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   289
     * Gets the call site flags, adding the strict flag if the current function
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   290
     * being generated is in strict mode
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   291
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   292
     * @return the correct flags for a call site in the current function
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   293
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
   294
    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
   295
        return lc.getCurrentFunction().getCallSiteFlags() | callSiteFlags;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   296
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   297
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   298
    /**
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   299
     * Gets the flags for a scope call site.
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   300
     * @param symbol a scope symbol
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   301
     * @return the correct flags for the scope call site
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   302
     */
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   303
    private int getScopeCallSiteFlags(final Symbol symbol) {
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   304
        assert symbol.isScope();
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   305
        final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   306
        if (isEvalCode() && symbol.isGlobal()) {
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   307
            return flags; // Don't set fast-scope flag on non-declared globals in eval code - see JDK-8077955.
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   308
        }
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   309
        return isFastScope(symbol) ? flags | CALLSITE_FAST_SCOPE : flags;
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   310
    }
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   311
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   312
    /**
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   313
     * Are we generating code for 'eval' code?
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   314
     * @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
   315
     */
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   316
    boolean isEvalCode() {
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   317
        return evalCode;
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   318
    }
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   319
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   320
    /**
29834
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   321
     * Are we using dual primitive/object field representation?
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   322
     * @return true if using dual field representation, false for object-only fields
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   323
     */
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   324
    boolean useDualFields() {
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   325
        return compiler.getContext().useDualFields();
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   326
    }
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   327
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
   328
    /**
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   329
     * Load an identity node
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   330
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   331
     * @param identNode an identity node to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   332
     * @return the method generator used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   333
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   334
    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
   335
        checkTemporalDeadZone(identNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   336
        final Symbol symbol = identNode.getSymbol();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   337
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   338
        if (!symbol.isScope()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   339
            final Type type = identNode.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   340
            if(type == Type.UNDEFINED) {
25829
1a5e1de71e57 8051439: Wrong type calculated for ADD operator with undefined operand
attila
parents: 25826
diff changeset
   341
                return method.loadUndefined(resultBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   342
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   343
16209
18e55b352d56 8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents: 16206
diff changeset
   344
            assert symbol.hasSlot() || symbol.isParam();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   345
            return method.load(identNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   346
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   347
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   348
        assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   349
        final int flags = getScopeCallSiteFlags(symbol);
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   350
        if (!isFastScope(symbol)) {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   351
            // slow scope load, prototype chain must be inspected at runtime
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   352
            new LoadScopeVar(identNode, resultBounds, flags).emit();
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   353
        } else if (identNode.isCompileTimePropertyName() || symbol.getUseCount() < SharedScopeCall.SHARED_GET_THRESHOLD) {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   354
            // fast scope load with known prototype depth
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   355
            new LoadFastScopeVar(identNode, resultBounds, flags).emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   356
        } else {
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   357
            // Only generate shared scope getter for often used fast-scope symbols.
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   358
            new OptimisticOperation(identNode, resultBounds) {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   359
                @Override
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   360
                void loadStack() {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   361
                    method.loadCompilerConstant(SCOPE);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   362
                    final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   363
                    assert depth >= 0;
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   364
                    method.load(depth);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   365
                    method.load(getProgramPoint());
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   366
                }
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   367
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   368
                @Override
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   369
                void consumeStack() {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   370
                    final Type resultType = isOptimistic ? getOptimisticCoercedType() : resultBounds.widest;
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   371
                    lc.getScopeGet(unit, symbol, resultType, flags, isOptimistic).generateInvoke(method);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   372
                }
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   373
            }.emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   374
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   375
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   376
        return method;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   377
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   378
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   379
    // 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
   380
    // 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
   381
    private void checkTemporalDeadZone(final IdentNode identNode) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   382
        if (identNode.isDead()) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   383
            method.load(identNode.getSymbol().getName()).invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   384
        }
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   385
    }
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   386
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   387
    // Runtime check for assignment to ES6 const
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   388
    private void checkAssignTarget(final Expression expression) {
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   389
        if (expression instanceof IdentNode && ((IdentNode)expression).getSymbol().isConst()) {
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   390
            method.load(((IdentNode)expression).getSymbol().getName()).invoke(ScriptRuntime.THROW_CONST_TYPE_ERROR);
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   391
        }
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   392
    }
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   393
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   394
    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
   395
        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
   396
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   397
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   398
    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
   399
        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
   400
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   401
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   402
    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
   403
        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
   404
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   405
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   406
    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
   407
        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
   408
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   409
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   410
    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
   411
        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
   412
            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
   413
            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
   414
                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
   415
                    return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   416
                }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   417
            }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   418
        }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   419
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   420
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   421
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   422
    /**
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   423
     * 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
   424
     *
18618
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17981
diff changeset
   425
     * @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
   426
     * @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
   427
     */
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   428
    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
   429
        if (!symbol.isScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   430
            return false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   431
        }
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
   432
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
   433
        if (!lc.inDynamicScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   434
            // 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
   435
            // 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
   436
            assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   437
            return true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   438
        }
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
   439
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
   440
        if (symbol.isGlobal()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   441
            // 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
   442
            return false;
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   443
        }
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
   444
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   445
        // 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
   446
        final String name = symbol.getName();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   447
        boolean previousWasBlock = false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   448
        for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   449
            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
   450
            if (node instanceof Block) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   451
                // 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
   452
                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
   453
                if (block.getExistingSymbol(name) == symbol) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   454
                    assert block.needsScope();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   455
                    return true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   456
                }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   457
                previousWasBlock = true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   458
            } 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
   459
                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
   460
                    // 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
   461
                    // 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
   462
                    // 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
   463
                    // obviously not subjected to introducing new symbols.
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   464
                    return false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   465
                }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   466
                previousWasBlock = false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   467
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   468
        }
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   469
        // Should've found the symbol defined in a block
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   470
        throw new AssertionError();
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   471
    }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   472
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   473
    private class LoadScopeVar extends OptimisticOperation {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   474
        final IdentNode identNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   475
        private final int flags;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   476
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   477
        LoadScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   478
            super(identNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   479
            this.identNode = identNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   480
            this.flags = flags;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   481
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   482
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   483
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   484
        void loadStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   485
            method.loadCompilerConstant(SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   486
            getProto();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   487
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   488
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   489
        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
   490
            //empty
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   491
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   492
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   493
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   494
        void consumeStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   495
            // 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
   496
            // it anyway for replaceLocationPropertyPlaceholder.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   497
            if(identNode.isCompileTimePropertyName()) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   498
                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   499
                replaceCompileTimeProperty();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   500
            } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   501
                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   502
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   503
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   504
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   505
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   506
    private class LoadFastScopeVar extends LoadScopeVar {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   507
        LoadFastScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   508
            super(identNode, resultBounds, flags);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   509
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   510
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   511
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   512
        void getProto() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   513
            loadFastScopeProto(identNode.getSymbol(), false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   514
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   515
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   516
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   517
    private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   518
        loadFastScopeProto(symbol, true);
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   519
        method.dynamicSet(symbol.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   520
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   521
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   522
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   523
    private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   524
        //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
   525
        //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
   526
        final FunctionNode fn   = lc.getCurrentFunction();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   527
        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
   528
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
   529
        //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
   530
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
   531
        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
   532
        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
   533
        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
   534
        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
   535
            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
   536
        } 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
   537
            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
   538
            depth = internalDepth;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   539
        }
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
   540
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
   541
        return depth;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   542
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   543
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   544
    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
   545
        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
   546
        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
   547
        if (depth > 0) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   548
            if (swap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   549
                method.swap();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   550
            }
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   551
            invokeGetProto(depth);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   552
            if (swap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   553
                method.swap();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   554
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   555
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   556
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   557
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   558
    private void invokeGetProto(final int depth) {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   559
        assert depth > 0;
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   560
        if (depth > 1) {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   561
            method.load(depth);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   562
            method.invoke(ScriptObject.GET_PROTO_DEPTH);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   563
        } else {
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   564
            method.invoke(ScriptObject.GET_PROTO);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   565
        }
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   566
    }
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
   567
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   568
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   569
     * Generate code that loads this node to the stack, not constraining its type
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   570
     *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   571
     * @param expr node to load
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   572
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   573
     * @return the method emitter used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   574
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   575
    private MethodEmitter loadExpressionUnbounded(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   576
        return loadExpression(expr, TypeBounds.UNBOUNDED);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   577
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   578
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   579
    private MethodEmitter loadExpressionAsObject(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   580
        return loadExpression(expr, TypeBounds.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   581
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   582
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   583
    MethodEmitter loadExpressionAsBoolean(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   584
        return loadExpression(expr, TypeBounds.BOOLEAN);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   585
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   586
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   587
    // 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
   588
    // with possible side effects from calling an object's toString or valueOf methods.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   589
    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
   590
        // Object to boolean conversion does not cause ToPrimitive call
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   591
        return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean();
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   592
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   593
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   594
    MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   595
        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   596
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   597
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   598
    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
   599
        // 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
   600
        // 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
   601
        // 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
   602
        // 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
   603
        // 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
   604
        // 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
   605
        // 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
   606
        // 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
   607
        // 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
   608
        // separate operations to preserve specification semantics.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   609
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   610
        // 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
   611
        // 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
   612
        final Type lhsType = undefinedToNumber(lhs.getType());
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   613
        final Type rhsType = undefinedToNumber(rhs.getType());
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   614
        final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   615
        final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   616
        if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   617
            // 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
   618
            if (forceConversionSeparation) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   619
                // 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
   620
                // 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
   621
                // 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
   622
                // concrete cases where this could happen.
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   623
                final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   624
                loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   625
                method.convert(operandBounds.within(method.peekType()));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   626
                loadExpression(rhs, safeConvertBounds, false);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   627
                method.convert(operandBounds.within(method.peekType()));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   628
            } else {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   629
                // 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
   630
                loadExpression(lhs, operandBounds, baseAlreadyOnStack);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   631
                loadExpression(rhs, operandBounds, false);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   632
            }
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   633
        } else {
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   634
            // Can't reorder. Load and convert separately.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   635
            final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   636
            loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   637
            final Type lhsLoadedType = method.peekType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   638
            loadExpression(rhs, safeConvertBounds, false);
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   639
            final Type convertedLhsType = operandBounds.within(method.peekType());
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   640
            if (convertedLhsType != lhsLoadedType) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   641
                // 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
   642
                method.swap().convert(convertedLhsType).swap();
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   643
            }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   644
            method.convert(operandBounds.within(method.peekType()));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   645
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   646
        assert Type.generic(method.peekType()) == operandBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   647
        assert Type.generic(method.peekType(1)) == operandBounds.narrowest;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   648
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   649
        return method;
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   650
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   651
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   652
    /**
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   653
     * Similar to {@link #loadBinaryOperands(BinaryNode)} but used specifically for loading operands of
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   654
     * relational and equality comparison operators where at least one argument is non-object. (When both
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   655
     * arguments are objects, we use {@link ScriptRuntime#EQ(Object, Object)}, {@link ScriptRuntime#LT(Object, Object)}
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   656
     * etc. methods instead. Additionally, {@code ScriptRuntime} methods are used for strict (in)equality comparison
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   657
     * of a boolean to anything that isn't a boolean.) This method handles the special case where one argument
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   658
     * is an object and another is a primitive. Naively, these could also be delegated to {@code ScriptRuntime} methods
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   659
     * by boxing the primitive. However, in all such cases the comparison is performed on numeric values, so it is
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   660
     * possible to strength-reduce the operation by taking the number value of the object argument instead and
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   661
     * comparing that to the primitive value ("primitive" will always be int, long, double, or boolean, and booleans
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   662
     * compare as ints in these cases, so they're essentially numbers too). This method will emit code for loading
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   663
     * arguments for such strength-reduced comparison. When both arguments are primitives, it just delegates to
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   664
     * {@link #loadBinaryOperands(BinaryNode)}.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   665
     *
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   666
     * @param cmp the comparison operation for which the operands need to be loaded on stack.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   667
     * @return the current method emitter.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   668
     */
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   669
    MethodEmitter loadComparisonOperands(final BinaryNode cmp) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   670
        final Expression lhs = cmp.lhs();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   671
        final Expression rhs = cmp.rhs();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   672
        final Type lhsType = lhs.getType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   673
        final Type rhsType = rhs.getType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   674
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   675
        // Only used when not both are object, for that we have ScriptRuntime.LT etc.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   676
        assert !(lhsType.isObject() && rhsType.isObject());
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   677
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   678
        if (lhsType.isObject() || rhsType.isObject()) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   679
            // We can reorder CONVERT LEFT and LOAD RIGHT only if either the left is a primitive, or the right
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   680
            // is a local. This is more strict than loadBinaryNode reorder criteria, as it can allow JS primitive
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   681
            // types too (notably: String is a JS primitive, but not a JVM primitive). We disallow String otherwise
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   682
            // we would prematurely convert it to number when comparing to an optimistic expression, e.g. in
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   683
            // "Hello" === String("Hello") the RHS starts out as an optimistic-int function call. If we allowed
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   684
            // reordering, we'd end up with ToNumber("Hello") === {I%}String("Hello") that is obviously incorrect.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   685
            final boolean canReorder = lhsType.isPrimitive() || rhs.isLocal();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   686
            // If reordering is allowed, and we're using a relational operator (that is, <, <=, >, >=) and not an
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   687
            // (in)equality operator, then we encourage combining of LOAD and CONVERT into a single operation.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   688
            // This is because relational operators' semantics prescribes vanilla ToNumber() conversion, while
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   689
            // (in)equality operators need the specialized JSType.toNumberFor[Strict]Equals. E.g. in the code snippet
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   690
            // "i < obj.size" (where i is primitive and obj.size is statically an object), ".size" will thus be allowed
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   691
            // to compile as:
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents: 32888
diff changeset
   692
            //   invokedynamic GET_PROPERTY:size(Object;)D
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   693
            // instead of the more costly:
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents: 32888
diff changeset
   694
            //   invokedynamic GET_PROPERTY:size(Object;)Object
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   695
            //   invokestatic JSType.toNumber(Object)D
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   696
            // Note also that even if this is allowed, we're only using it on operands that are non-optimistic, as
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   697
            // otherwise the logic for determining effective optimistic-ness would turn an optimistic double return
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   698
            // into a freely coercible one, which would be wrong.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   699
            final boolean canCombineLoadAndConvert = canReorder && cmp.isRelational();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   700
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   701
            // LOAD LEFT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   702
            loadExpression(lhs, canCombineLoadAndConvert && !lhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   703
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   704
            final Type lhsLoadedType = method.peekType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   705
            final TokenType tt = cmp.tokenType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   706
            if (canReorder) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   707
                // Can reorder CONVERT LEFT and LOAD RIGHT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   708
                emitObjectToNumberComparisonConversion(method, tt);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   709
                loadExpression(rhs, canCombineLoadAndConvert && !rhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   710
            } else {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   711
                // Can't reorder CONVERT LEFT and LOAD RIGHT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   712
                loadExpression(rhs, TypeBounds.UNBOUNDED);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   713
                if (lhsLoadedType != Type.NUMBER) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   714
                    method.swap();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   715
                    emitObjectToNumberComparisonConversion(method, tt);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   716
                    method.swap();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   717
                }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   718
            }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   719
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   720
            // CONVERT RIGHT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   721
            emitObjectToNumberComparisonConversion(method, tt);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   722
            return method;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   723
        }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   724
        // For primitive operands, just don't do anything special.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   725
        return loadBinaryOperands(cmp);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   726
    }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   727
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   728
    private static void emitObjectToNumberComparisonConversion(final MethodEmitter method, final TokenType tt) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   729
        switch(tt) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   730
        case EQ:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   731
        case NE:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   732
            if (method.peekType().isObject()) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   733
                TO_NUMBER_FOR_EQ.invoke(method);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   734
                return;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   735
            }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   736
            break;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   737
        case EQ_STRICT:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   738
        case NE_STRICT:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   739
            if (method.peekType().isObject()) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   740
                TO_NUMBER_FOR_STRICT_EQ.invoke(method);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   741
                return;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   742
            }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   743
            break;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   744
        default:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   745
            break;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   746
        }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   747
        method.convert(Type.NUMBER);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   748
    }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   749
31549
b627094c5649 8130734: Apply transformations found by netbeans Refactor->Inspect and transform menu
sundar
parents: 30697
diff changeset
   750
    private static Type undefinedToNumber(final Type type) {
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   751
        return type == Type.UNDEFINED ? Type.NUMBER : type;
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   752
    }
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   753
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   754
    private static final class TypeBounds {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   755
        final Type narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   756
        final Type widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   757
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   758
        static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   759
        static final TypeBounds INT = exact(Type.INT);
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   760
        static final TypeBounds NUMBER = exact(Type.NUMBER);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   761
        static final TypeBounds OBJECT = exact(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   762
        static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   763
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   764
        static TypeBounds exact(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   765
            return new TypeBounds(type, type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   766
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   767
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   768
        TypeBounds(final Type narrowest, final Type widest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   769
            assert widest    != null && widest    != Type.UNDEFINED && widest != Type.UNKNOWN : widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   770
            assert narrowest != null && narrowest != Type.UNDEFINED : narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   771
            assert !narrowest.widerThan(widest) : narrowest + " wider than " + widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   772
            assert !widest.narrowerThan(narrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   773
            this.narrowest = Type.generic(narrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   774
            this.widest = Type.generic(widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   775
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   776
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   777
        TypeBounds notNarrowerThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   778
            return maybeNew(Type.narrowest(Type.widest(narrowest, type), widest), widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   779
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   780
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   781
        TypeBounds notWiderThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   782
            return maybeNew(Type.narrowest(narrowest, type), Type.narrowest(widest, type));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   783
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   784
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   785
        boolean canBeNarrowerThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   786
            return narrowest.narrowerThan(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   787
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   788
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   789
        TypeBounds maybeNew(final Type newNarrowest, final Type newWidest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   790
            if(newNarrowest == narrowest && newWidest == widest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   791
                return this;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   792
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   793
            return new TypeBounds(newNarrowest, newWidest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   794
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   795
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   796
        TypeBounds booleanToInt() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   797
            return maybeNew(CodeGenerator.booleanToInt(narrowest), CodeGenerator.booleanToInt(widest));
24751
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
        TypeBounds objectToNumber() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   801
            return maybeNew(CodeGenerator.objectToNumber(narrowest), CodeGenerator.objectToNumber(widest));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   802
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   803
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   804
        Type within(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   805
            if(type.narrowerThan(narrowest)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   806
                return narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   807
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   808
            if(type.widerThan(widest)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   809
                return widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   810
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   811
            return type;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   812
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   813
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   814
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   815
        public String toString() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   816
            return "[" + narrowest + ", " + widest + "]";
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   817
        }
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   818
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   819
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   820
    private static Type booleanToInt(final Type t) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   821
        return t == Type.BOOLEAN ? Type.INT : t;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   822
    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   823
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   824
    private static Type objectToNumber(final Type t) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   825
        return t.isObject() ? Type.NUMBER : t;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   826
    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   827
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   828
    MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   829
        if(type == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   830
            return loadExpressionAsBoolean(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   831
        } else if(type == Type.UNDEFINED) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   832
            assert expr.getType() == Type.UNDEFINED;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   833
            return loadExpressionAsObject(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   834
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   835
        // 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
   836
        // converted early) and then applies explicit conversion afterwards.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   837
        return loadExpression(expr, TypeBounds.UNBOUNDED.notNarrowerThan(type)).convert(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   838
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   839
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   840
    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   841
        return loadExpression(expr, resultBounds, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   842
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   843
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   844
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   845
     * 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
   846
     * necessary.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   847
     * @param expr the expression to load
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   848
     * @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
   849
     * 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
   850
     * @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
   851
     * 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
   852
     * to indicate the widest possible type.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   853
     * @return the method emitter
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   854
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   855
    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
   856
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   857
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   858
         * The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y"
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   859
         * or IndexNode e.g. "x[y]". Both AccessNodes and IndexNodes are
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   860
         * BaseNodes and the logic for loading the base object is reused
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   861
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   862
        final CodeGenerator codegen = this;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   863
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
   864
        final boolean isCurrentDiscard = codegen.lc.isCurrentDiscard(expr);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   865
        expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   866
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   867
            public boolean enterIdentNode(final IdentNode identNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   868
                loadIdent(identNode, resultBounds);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   869
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   870
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   871
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   872
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   873
            public boolean enterAccessNode(final AccessNode accessNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   874
                new OptimisticOperation(accessNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   875
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   876
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   877
                        if (!baseAlreadyOnStack) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   878
                            loadExpressionAsObject(accessNode.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   879
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   880
                        assert method.peekType().isObject();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   881
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   882
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   883
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   884
                        final int flags = getCallSiteFlags();
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   885
                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction(), accessNode.isIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   886
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   887
                }.emit(baseAlreadyOnStack ? 1 : 0);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   888
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   889
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   890
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   891
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   892
            public boolean enterIndexNode(final IndexNode indexNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   893
                new OptimisticOperation(indexNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   894
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   895
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   896
                        if (!baseAlreadyOnStack) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   897
                            loadExpressionAsObject(indexNode.getBase());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   898
                            loadExpressionUnbounded(indexNode.getIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   899
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   900
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   901
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   902
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   903
                        final int flags = getCallSiteFlags();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   904
                        dynamicGetIndex(flags, indexNode.isFunction());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   905
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   906
                }.emit(baseAlreadyOnStack ? 2 : 0);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   907
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   908
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   909
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   910
            @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
   911
            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
   912
                // 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
   913
                // 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
   914
                lc.pop(functionNode);
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   915
                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
   916
                // 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
   917
                // 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
   918
                // 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
   919
                // 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
   920
                lc.push(functionNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   921
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   922
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   923
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   924
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   925
            public boolean enterASSIGN(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   926
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   927
                loadASSIGN(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 enterASSIGN_ADD(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   933
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   934
                loadASSIGN_ADD(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   935
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   936
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   937
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   938
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   939
            public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   940
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   941
                loadASSIGN_BIT_AND(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   942
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   943
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   944
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   945
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   946
            public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   947
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   948
                loadASSIGN_BIT_OR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   949
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   950
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   951
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   952
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   953
            public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   954
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   955
                loadASSIGN_BIT_XOR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   956
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   957
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   958
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   959
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   960
            public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   961
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   962
                loadASSIGN_DIV(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   963
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   964
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   965
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   966
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   967
            public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   968
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   969
                loadASSIGN_MOD(binaryNode);
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 enterASSIGN_MUL(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   975
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   976
                loadASSIGN_MUL(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   977
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   978
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   979
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   980
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   981
            public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   982
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   983
                loadASSIGN_SAR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   984
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   985
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   986
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   987
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   988
            public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   989
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   990
                loadASSIGN_SHL(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   991
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   992
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   993
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   994
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   995
            public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   996
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   997
                loadASSIGN_SHR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   998
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   999
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1000
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1001
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1002
            public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
  1003
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1004
                loadASSIGN_SUB(binaryNode);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1005
                return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1006
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1007
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1008
            @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
  1009
            public boolean enterCallNode(final CallNode callNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1010
                return loadCallNode(callNode, resultBounds);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1011
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1012
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1013
            @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
  1014
            public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1015
                loadLiteral(literalNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1016
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1017
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1018
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1019
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1020
            public boolean enterTernaryNode(final TernaryNode ternaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1021
                loadTernaryNode(ternaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1022
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1023
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1024
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1025
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1026
            public boolean enterADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1027
                loadADD(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1028
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1029
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1030
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1031
            @Override
46169
b385216af0ed 8185252: Unary minus and plus use wrong node Kind
hannesw
parents: 42383
diff changeset
  1032
            public boolean enterNEG(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1033
                loadSUB(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1034
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1035
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1036
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1037
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1038
            public boolean enterSUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1039
                loadSUB(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1040
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1041
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1042
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1043
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1044
            public boolean enterMUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1045
                loadMUL(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1046
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1047
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1048
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1049
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1050
            public boolean enterDIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1051
                loadDIV(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1052
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1053
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1054
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1055
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1056
            public boolean enterMOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1057
                loadMOD(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1058
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1059
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1060
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1061
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1062
            public boolean enterSAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1063
                loadSAR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1064
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1065
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1066
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1067
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1068
            public boolean enterSHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1069
                loadSHL(binaryNode);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1070
                return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1071
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1072
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1073
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1074
            public boolean enterSHR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1075
                loadSHR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1076
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1077
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1078
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1079
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1080
            public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1081
                loadCOMMALEFT(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1082
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1083
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1084
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1085
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1086
            public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1087
                loadCOMMARIGHT(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1088
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1089
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1090
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1091
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1092
            public boolean enterAND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1093
                loadAND_OR(binaryNode, resultBounds, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1094
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1095
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1096
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1097
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1098
            public boolean enterOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1099
                loadAND_OR(binaryNode, resultBounds, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1100
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1101
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1102
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1103
            @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
  1104
            public boolean enterNOT(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1105
                loadNOT(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1106
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1107
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1108
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1109
            @Override
46169
b385216af0ed 8185252: Unary minus and plus use wrong node Kind
hannesw
parents: 42383
diff changeset
  1110
            public boolean enterPOS(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1111
                loadADD(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1112
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1113
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1114
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1115
            @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
  1116
            public boolean enterBIT_NOT(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1117
                loadBIT_NOT(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1118
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1119
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1120
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1121
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1122
            public boolean enterBIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1123
                loadBIT_AND(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1124
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1125
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1126
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1127
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1128
            public boolean enterBIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1129
                loadBIT_OR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1130
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1131
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1132
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1133
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1134
            public boolean enterBIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1135
                loadBIT_XOR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1136
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1137
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1138
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1139
            @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
  1140
            public boolean enterVOID(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1141
                loadVOID(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1142
                return false;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1143
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1144
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1145
            @Override
48354
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  1146
            public boolean enterDELETE(final UnaryNode unaryNode) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  1147
                loadDELETE(unaryNode);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  1148
                return false;
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  1149
            }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  1150
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  1151
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1152
            public boolean enterEQ(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1153
                loadCmp(binaryNode, Condition.EQ);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1154
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1155
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1156
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1157
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1158
            public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1159
                loadCmp(binaryNode, Condition.EQ);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1160
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1161
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1162
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1163
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1164
            public boolean enterGE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1165
                loadCmp(binaryNode, Condition.GE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1166
                return false;
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
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1170
            public boolean enterGT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1171
                loadCmp(binaryNode, Condition.GT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1172
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1173
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1174
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1175
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1176
            public boolean enterLE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1177
                loadCmp(binaryNode, Condition.LE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1178
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1179
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1180
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1181
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1182
            public boolean enterLT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1183
                loadCmp(binaryNode, Condition.LT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1184
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1185
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1186
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1187
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1188
            public boolean enterNE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1189
                loadCmp(binaryNode, Condition.NE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1190
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1191
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1192
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1193
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1194
            public boolean enterNE_STRICT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1195
                loadCmp(binaryNode, Condition.NE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1196
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1197
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1198
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1199
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1200
            public boolean enterObjectNode(final ObjectNode objectNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1201
                loadObjectNode(objectNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1202
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1203
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1204
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1205
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1206
            public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1207
                loadRuntimeNode(runtimeNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1208
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1209
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1210
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1211
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1212
            public boolean enterNEW(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1213
                loadNEW(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1214
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1215
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1216
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1217
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1218
            public boolean enterDECINC(final UnaryNode unaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
  1219
                checkAssignTarget(unaryNode.getExpression());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1220
                loadDECINC(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1221
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1222
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1223
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1224
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1225
            public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  1226
                loadMaybeDiscard(joinExpr, joinExpr.getExpression(), resultBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1227
                return false;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1228
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1229
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1230
            @Override
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1231
            public boolean enterGetSplitState(final GetSplitState getSplitState) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1232
                method.loadScope();
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1233
                method.invoke(Scope.GET_SPLIT_STATE);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1234
                return false;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1235
            }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1236
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1237
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1238
            public boolean enterDefault(final Node otherNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1239
                // Must have handled all expressions that can legally be encountered.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1240
                throw new AssertionError(otherNode.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1241
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1242
        });
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  1243
        if(!isCurrentDiscard) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1244
            coerceStackTop(resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1245
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1246
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1247
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1248
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1249
    private MethodEmitter coerceStackTop(final TypeBounds typeBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1250
        return method.convert(typeBounds.within(method.peekType()));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1251
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1252
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1253
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1254
     * 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
  1255
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1256
     * @param block block containing symbols.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1257
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1258
    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
  1259
        for (final Symbol symbol : block.getSymbols()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1260
            if (symbol.isBytecodeLocal()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1261
                method.closeLocalVariable(symbol, block.getBreakLabel());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1262
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1263
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1264
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1265
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1266
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1267
    public boolean enterBlock(final Block block) {
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1268
        final Label entryLabel = block.getEntryLabel();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1269
        if (entryLabel.isBreakTarget()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1270
            // Entry label is a break target only for an inlined finally block.
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1271
            assert !method.isReachable();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1272
            method.breakLabel(entryLabel, lc.getUsedSlotCount());
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1273
        } else {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1274
            method.label(entryLabel);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1275
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1276
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1277
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1278
        }
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1279
        if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1280
            return false;
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1281
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1282
        initLocals(block);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1283
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1284
        assert lc.getUsedSlotCount() == method.getFirstTemp();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1285
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1286
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1287
30390
357f9a3f9394 8079269: Optimistic rewrite in object literal causes ArrayIndexOutOfBoundsException
attila
parents: 30056
diff changeset
  1288
    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
  1289
        return !lc.inSplitNode() && compiler.useOptimisticTypes();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1290
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1291
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1292
    @Override
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1293
    public Node leaveBlock(final Block block) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1294
        popBlockScope(block);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1295
        method.beforeJoinPoint(block);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1296
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1297
        closeBlockVariables(block);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1298
        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
  1299
        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
  1300
            "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
  1301
            " 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
  1302
            " 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
  1303
            " firstTemp=" + method.getFirstTemp();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1304
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1305
        return block;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1306
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1307
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1308
    private void popBlockScope(final Block block) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1309
        final Label breakLabel = block.getBreakLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1310
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1311
        if (block.providesScopeCreator()) {
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1312
            scopeObjectCreators.pop();
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1313
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1314
        if(!block.needsScope() || lc.isFunctionBody()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1315
            emitBlockBreakLabel(breakLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1316
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1317
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1318
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1319
        final Label beginTryLabel = scopeEntryLabels.pop();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1320
        final Label recoveryLabel = new Label("block_popscope_catch");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1321
        emitBlockBreakLabel(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1322
        final boolean bodyCanThrow = breakLabel.isAfter(beginTryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1323
        if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1324
            method._try(beginTryLabel, breakLabel, recoveryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1325
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1326
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1327
        Label afterCatchLabel = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1328
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1329
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1330
            popScope();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1331
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1332
                afterCatchLabel = new Label("block_after_catch");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1333
                method._goto(afterCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1334
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1335
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1336
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1337
        if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1338
            assert !method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1339
            method._catch(recoveryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1340
            popScopeException();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1341
            method.athrow();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1342
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1343
        if(afterCatchLabel != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1344
            method.label(afterCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1345
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1346
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1347
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1348
    private void emitBlockBreakLabel(final Label breakLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1349
        // 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
  1350
        final LabelNode labelNode = lc.getCurrentBlockLabelNode();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1351
        if(labelNode != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1352
            // Only have conversions if we're reachable
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1353
            assert labelNode.getLocalVariableConversion() == null || method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1354
            method.beforeJoinPoint(labelNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1355
            method.breakLabel(breakLabel, labeledBlockBreakLiveLocals.pop());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1356
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1357
            method.label(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1358
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1359
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1360
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1361
    private void popScope() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1362
        popScopes(1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1363
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1364
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1365
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1366
     * 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
  1367
     * 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
  1368
     * performing a ToPrimitive conversion.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1369
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1370
    private void popScopeException() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1371
        popScope();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1372
        final ContinuationInfo ci = getContinuationInfo();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1373
        if(ci != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1374
            final Label catchLabel = ci.catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1375
            if(catchLabel != METHOD_BOUNDARY && catchLabel == catchLabels.peek()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1376
                ++ci.exceptionScopePops;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1377
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1378
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1379
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1380
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1381
    private void popScopesUntil(final LexicalContextNode until) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1382
        popScopes(lc.getScopeNestingLevelTo(until));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1383
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1384
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1385
    private void popScopes(final int count) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1386
        if(count == 0) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1387
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1388
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1389
        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
  1390
        if (!method.hasScope()) {
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1391
            // 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
  1392
            // 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
  1393
            // 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
  1394
            return;
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1395
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1396
        method.loadCompilerConstant(SCOPE);
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1397
        invokeGetProto(count);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1398
        method.storeCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1399
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1400
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1401
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1402
    public boolean enterBreakNode(final BreakNode breakNode) {
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1403
        return enterJumpStatement(breakNode);
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1404
    }
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1405
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1406
    @Override
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1407
    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1408
        return enterJumpStatement(jumpToInlinedFinally);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1409
    }
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1410
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1411
    private boolean enterJumpStatement(final JumpStatement jump) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1412
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1413
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1414
        }
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1415
        enterStatement(jump);
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1416
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1417
        method.beforeJoinPoint(jump);
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1418
        popScopesUntil(jump.getPopScopeLimit(lc));
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1419
        final Label targetLabel = jump.getTargetLabel(lc);
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1420
        targetLabel.markAsBreakTarget();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1421
        method._goto(targetLabel);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1422
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1423
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1424
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1425
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1426
    private int loadArgs(final List<Expression> args) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1427
        final int argCount = args.size();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1428
        // arg have already been converted to objects here.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1429
        if (argCount > LinkerCallSite.ARGLIMIT) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1430
            loadArgsArray(args);
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  1431
            return 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1432
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1433
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1434
        for (final Expression arg : args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1435
            assert arg != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1436
            loadExpressionUnbounded(arg);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1437
        }
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  1438
        return argCount;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1439
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1440
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1441
    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
  1442
        lineNumber(callNode.getLineNumber());
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1443
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1444
        final List<Expression> args = callNode.getArgs();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1445
        final Expression function = callNode.getFunction();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1446
        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
  1447
        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
  1448
32888
24f99be3d5ab 8134502: introduce abstraction for basic NodeVisitor usage
attila
parents: 32784
diff changeset
  1449
        function.accept(new SimpleNodeVisitor() {
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1450
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
  1451
            private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1452
                final Symbol symbol = identNode.getSymbol();
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1453
                assert isFastScope(symbol);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1454
24751
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
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1457
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1458
                        method.loadCompilerConstant(SCOPE);
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1459
                        final int depth = getScopeProtoDepth(currentBlock, symbol);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1460
                        assert depth >= 0;
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1461
                        method.load(depth);
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1462
                        method.load(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1463
                        loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1464
                    }
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1465
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1466
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1467
                    void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1468
                        final Type[] paramTypes = method.getTypesFromStack(args.size());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1469
                        // 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
  1470
                        // loader, so we need to weaken reference signatures to Object.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1471
                        for(int i = 0; i < paramTypes.length; ++i) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1472
                            paramTypes[i] = Type.generic(paramTypes[i]);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1473
                        }
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1474
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1475
                        final Type resultType = isOptimistic ? getOptimisticCoercedType() : resultBounds.widest;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1476
                        final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol,
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1477
                                identNode.getType(), resultType, paramTypes, flags, isOptimistic);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1478
                        scopeCall.generateInvoke(method);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1479
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1480
                }.emit();
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1481
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1482
                return method;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1483
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1484
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1485
            private void scopeCall(final IdentNode ident, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1486
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1487
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1488
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1489
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1490
                        loadExpressionAsObject(ident); // foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1491
                        // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
24727
attila
parents: 24725 23372
diff changeset
  1492
                        method.loadUndefined(Type.OBJECT); //the 'this'
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1493
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1494
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1495
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1496
                    void consumeStack() {
32048
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  1497
                        dynamicCall(2 + argsCount, flags, ident.getName());
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();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1500
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1501
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1502
            private void evalCall(final IdentNode ident, final int flags) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1503
                final Label invoke_direct_eval  = new Label("invoke_direct_eval");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1504
                final Label is_not_eval  = new Label("is_not_eval");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1505
                final Label eval_done = new Label("eval_done");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1506
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1507
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1508
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1509
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1510
                    void loadStack() {
32534
b3ec7f3b3c2a 8136349: Typos patch for nashorn sources submitted on Sep 10, 2015
sundar
parents: 32527
diff changeset
  1511
                        /*
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
  1512
                         * We want to load 'eval' to check if it is indeed global builtin eval.
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents: 32888
diff changeset
  1513
                         * If this eval call is inside a 'with' statement, GET_METHOD_PROPERTY
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
  1514
                         * 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
  1515
                         * 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
  1516
                         * won't be detected as builtin eval. So, we make ident as "not a function" which
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents: 32888
diff changeset
  1517
                         * results in GET_PROPERTY being generated and so WithObject
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
  1518
                         * 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
  1519
                         *
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
  1520
                         * 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
  1521
                         *
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
  1522
                         *  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
  1523
                         *  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
  1524
                         *      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
  1525
                         *  }
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
  1526
                         */
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
  1527
                        loadExpressionAsObject(ident.setIsNotFunction()); // Type.OBJECT as foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1528
                        globalIsEval();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1529
                        method.ifeq(is_not_eval);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1530
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1531
                        // Load up self (scope).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1532
                        method.loadCompilerConstant(SCOPE);
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1533
                        final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1534
                        // load evaluated code
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1535
                        loadExpressionAsObject(evalArgs.get(0));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1536
                        // 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
  1537
                        final int numArgs = evalArgs.size();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1538
                        for (int i = 1; i < numArgs; i++) {
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1539
                            loadAndDiscard(evalArgs.get(i));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1540
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1541
                        method._goto(invoke_direct_eval);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1542
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1543
                        method.label(is_not_eval);
33343
23abd10384a5 8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents: 32888
diff changeset
  1544
                        // load this time but with GET_METHOD_PROPERTY
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
  1545
                        loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1546
                        // This is some scope 'eval' or global eval replaced by user
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1547
                        // but not the built-in ECMAScript 'eval' function call
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1548
                        method.loadNull();
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1549
                        argsCount = loadArgs(callNode.getArgs());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1550
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1551
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1552
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1553
                    void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1554
                        // Ordinary call
32048
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  1555
                        dynamicCall(2 + argsCount, flags, "eval");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1556
                        method._goto(eval_done);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1557
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1558
                        method.label(invoke_direct_eval);
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1559
                        // 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
  1560
                        // them can ever be optimistic.
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1561
                        method.loadCompilerConstant(THIS);
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1562
                        method.load(callNode.getEvalArgs().getLocation());
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1563
                        method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1564
                        // direct call to Global.directEval
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1565
                        globalDirectEval();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1566
                        convertOptimisticReturnValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1567
                        coerceStackTop(resultBounds);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1568
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1569
                }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1570
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1571
                method.label(eval_done);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1572
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1573
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1574
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1575
            public boolean enterIdentNode(final IdentNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1576
                final Symbol symbol = node.getSymbol();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1577
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1578
                if (symbol.isScope()) {
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
  1579
                    final int flags = getScopeCallSiteFlags(symbol);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1580
                    final int useCount = symbol.getUseCount();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1581
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1582
                    // We only use shared scope calls for fast scopes
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1583
                    if (callNode.isEval()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1584
                        evalCall(node, flags);
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  1585
                    } else if (!isFastScope(symbol) || symbol.getUseCount() < SharedScopeCall.SHARED_CALL_THRESHOLD) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1586
                        scopeCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1587
                    } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1588
                        sharedScopeCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1589
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1590
                    assert method.peekType().equals(resultBounds.within(callNode.getType())) : method.peekType() + " != " + resultBounds + "(" + callNode.getType() + ")";
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1591
                } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1592
                    enterDefault(node);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1593
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1594
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1595
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1596
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1597
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1598
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1599
            public boolean enterAccessNode(final AccessNode node) {
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1600
                //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
  1601
                //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
  1602
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1603
                //call nodes have program points.
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1604
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1605
                final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1606
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1607
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1608
                    int argCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1609
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1610
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1611
                        loadExpressionAsObject(node.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1612
                        method.dup();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1613
                        // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1614
                        // a callable object. Nobody in their right mind would optimistically type this call site.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1615
                        assert !node.isOptimistic();
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  1616
                        method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1617
                        method.swap();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1618
                        argCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1619
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1620
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1621
                    void consumeStack() {
32049
af8f6292d54d 8133119: Error message associated with TypeError for call and new should include stringified Node
sundar
parents: 32048
diff changeset
  1622
                        dynamicCall(2 + argCount, flags, node.toString(false));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1623
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1624
                }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1625
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1626
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1627
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1628
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1629
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1630
            public boolean enterFunctionNode(final FunctionNode origCallee) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1631
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1632
                    FunctionNode callee;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1633
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1634
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1635
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1636
                        callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1637
                        if (callee.isStrict()) { // "this" is undefined
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1638
                            method.loadUndefined(Type.OBJECT);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1639
                        } else { // get global from scope (which is the self)
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1640
                            globalInstance();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1641
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1642
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1643
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1644
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1645
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1646
                    void consumeStack() {
32784
f7e0a3e05aa1 8137134: invokespecial on indirect super interface is generated by Java adapter generator
sundar
parents: 32781
diff changeset
  1647
                        dynamicCall(2 + argsCount, getCallSiteFlags(), null);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1648
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1649
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1650
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1651
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1652
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1653
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1654
            public boolean enterIndexNode(final IndexNode node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1655
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1656
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1657
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1658
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1659
                        loadExpressionAsObject(node.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1660
                        method.dup();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1661
                        final Type indexType = node.getIndex().getType();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1662
                        if (indexType.isObject() || indexType.isBoolean()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1663
                            loadExpressionAsObject(node.getIndex()); //TODO boolean
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1664
                        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1665
                            loadExpressionUnbounded(node.getIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1666
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1667
                        // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1668
                        // back a callable object. Nobody in their right mind would optimistically type this call site.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1669
                        assert !node.isOptimistic();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1670
                        method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1671
                        method.swap();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1672
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1673
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1674
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1675
                    void consumeStack() {
32049
af8f6292d54d 8133119: Error message associated with TypeError for call and new should include stringified Node
sundar
parents: 32048
diff changeset
  1676
                        dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1677
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1678
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1679
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1680
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1681
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1682
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1683
            protected boolean enterDefault(final Node node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1684
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1685
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1686
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1687
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1688
                        // Load up function.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1689
                        loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
24727
attila
parents: 24725 23372
diff changeset
  1690
                        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
  1691
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1692
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1693
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1694
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1695
                            final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
32049
af8f6292d54d 8133119: Error message associated with TypeError for call and new should include stringified Node
sundar
parents: 32048
diff changeset
  1696
                            dynamicCall(2 + argsCount, flags, node.toString(false));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1697
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1698
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1699
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1700
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1701
        });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1702
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1703
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1704
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1705
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1706
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1707
     * Returns the flags with optimistic flag and program point removed.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1708
     * @param flags the flags that need optimism stripped from them.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1709
     * @return flags without optimism
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1710
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1711
    static int nonOptimisticFlags(final int flags) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1712
        return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1713
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1714
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1715
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1716
    public boolean enterContinueNode(final ContinueNode continueNode) {
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1717
        return enterJumpStatement(continueNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1718
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1719
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1720
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1721
    public boolean enterEmptyNode(final EmptyNode emptyNode) {
30391
62dcad329b26 8079349: Eliminate dead code around Nashorn code generator
attila
parents: 30390
diff changeset
  1722
        // Don't even record the line number, it's irrelevant as there's no code.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1723
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1724
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1725
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1726
    @Override
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1727
    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1728
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1729
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1730
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1731
        enterStatement(expressionStatement);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1732
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1733
        loadAndDiscard(expressionStatement.getExpression());
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  1734
        assert method.getStackSize() == 0 : "stack not empty in " + expressionStatement;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1735
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1736
        return false;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1737
    }
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1738
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1739
    @Override
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1740
    public boolean enterBlockStatement(final BlockStatement blockStatement) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1741
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1742
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1743
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1744
        enterStatement(blockStatement);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1745
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1746
        blockStatement.getBlock().accept(this);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1747
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1748
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1749
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1750
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1751
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1752
    public boolean enterForNode(final ForNode forNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1753
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1754
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1755
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1756
        enterStatement(forNode);
36696
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1757
        if (forNode.isForInOrOf()) {
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
  1758
            enterForIn(forNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1759
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1760
            final Expression init = forNode.getInit();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1761
            if (init != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1762
                loadAndDiscard(init);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1763
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1764
            enterForOrWhile(forNode, forNode.getModify());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1765
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1766
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1767
        return false;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1768
    }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1769
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1770
    private void enterForIn(final ForNode forNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1771
        loadExpression(forNode.getModify(), TypeBounds.OBJECT);
36696
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1772
        if (forNode.isForEach()) {
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1773
            method.invoke(ScriptRuntime.TO_VALUE_ITERATOR);
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1774
        } else if (forNode.isForIn()) {
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1775
            method.invoke(ScriptRuntime.TO_PROPERTY_ITERATOR);
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1776
        } else if (forNode.isForOf()) {
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1777
            method.invoke(ScriptRuntime.TO_ES6_ITERATOR);
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1778
        } else {
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1779
            throw new IllegalArgumentException("Unexpected for node");
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  1780
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1781
        final Symbol iterSymbol = forNode.getIterator();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1782
        final int iterSlot = iterSymbol.getSlot(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1783
        method.store(iterSymbol, ITERATOR_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1784
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1785
        method.beforeJoinPoint(forNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1786
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1787
        final Label continueLabel = forNode.getContinueLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1788
        final Label breakLabel    = forNode.getBreakLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1789
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1790
        method.label(continueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1791
        method.load(ITERATOR_TYPE, iterSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1792
        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "hasNext", boolean.class));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1793
        final JoinPredecessorExpression test = forNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1794
        final Block body = forNode.getBody();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1795
        if(LocalVariableConversion.hasLiveConversion(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1796
            final Label afterConversion = new Label("for_in_after_test_conv");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1797
            method.ifne(afterConversion);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1798
            method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1799
            method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1800
            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
  1801
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1802
            method.ifeq(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1803
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1804
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1805
        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
  1806
            @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
  1807
            protected void storeNonDiscard() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1808
                // 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
  1809
                // stored, so we override storeNonDiscard to be a no-op.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1810
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1811
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
  1812
            @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
  1813
            protected void evaluate() {
26507
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1814
                new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1815
                    @Override
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1816
                    void loadStack() {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1817
                        method.load(ITERATOR_TYPE, iterSlot);
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1818
                    }
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1819
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1820
                    @Override
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1821
                    void consumeStack() {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1822
                        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1823
                        convertOptimisticReturnValue();
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1824
                    }
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1825
                }.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
  1826
            }
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
  1827
        }.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
  1828
        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
  1829
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1830
        if (forNode.needsScopeCreator() && lc.getCurrentBlock().providesScopeCreator()) {
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1831
            // for-in loops with lexical declaration need a new scope for each iteration.
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1832
            final FieldObjectCreator<?> creator = scopeObjectCreators.peek();
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1833
            assert creator != null;
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1834
            creator.createForInIterationScope(method);
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1835
            method.storeCompilerConstant(SCOPE);
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1836
        }
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1837
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1838
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1839
            method._goto(continueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1840
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1841
        method.label(breakLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1842
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1843
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1844
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1845
     * Initialize the slots in a frame to undefined.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1846
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1847
     * @param block block with local vars.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1848
     */
16168
f0c208287983 8005976: Break out AccessSpecializer into one pass before CodeGenerator instead of iterative applications from CodeGenerator
lagergren
parents: 16152
diff changeset
  1849
    private void initLocals(final Block block) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1850
        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
  1851
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
  1852
        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
  1853
        final FunctionNode function = lc.getCurrentFunction();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1854
        if (isFunctionBody) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1855
            initializeMethodParameters(function);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1856
            if(!function.isVarArg()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1857
                expandParameterSlots(function);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1858
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1859
            if (method.hasScope()) {
18853
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1860
                if (function.needsParentScope()) {
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1861
                    method.loadCompilerConstant(CALLEE);
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1862
                    method.invoke(ScriptFunction.GET_SCOPE);
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1863
                } else {
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1864
                    assert function.hasScopeBlock();
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1865
                    method.loadNull();
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1866
                }
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1867
                method.storeCompilerConstant(SCOPE);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1868
            }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1869
            if (function.needsArguments()) {
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1870
                initArguments(function);
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1871
            }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1872
        }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1873
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1874
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1875
         * Determine if block needs scope, if not, just do initSymbols for this block.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1876
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1877
        if (block.needsScope()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1878
            /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1879
             * Determine if function is varargs and consequently variables have to
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1880
             * be in the scope.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1881
             */
16252
3bfe9b68a0fa 8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents: 16240
diff changeset
  1882
            final boolean varsInScope = function.allVarsInScope();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1883
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1884
            // 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
  1885
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1886
            final boolean hasArguments = function.needsArguments();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1887
            final List<MapTuple<Symbol>> tuples = new ArrayList<>();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1888
            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
  1889
            for (final Symbol symbol : block.getSymbols()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1890
                if (symbol.isInternal() || symbol.isThis()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1891
                    continue;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1892
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1893
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1894
                if (symbol.isVar()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1895
                    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
  1896
                    if (varsInScope || symbol.isScope()) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1897
                        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
  1898
                        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
  1899
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1900
                        //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
  1901
                        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
  1902
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1903
                        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
  1904
                    }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1905
                } else if (symbol.isParam() && (varsInScope || hasArguments || symbol.isScope())) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1906
                    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
  1907
                    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
  1908
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1909
                    final Type   paramType;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1910
                    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
  1911
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1912
                    if (hasArguments) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1913
                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already ";
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1914
                        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
  1915
                        paramType   = null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1916
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1917
                        paramSymbol = symbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1918
                        // 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
  1919
                        // 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
  1920
                        // 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
  1921
                        // 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
  1922
                        // name.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1923
                        for(;;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1924
                            final IdentNode nextParam = paramIter.next();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1925
                            if(nextParam.getName().equals(symbol.getName())) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1926
                                paramType = nextParam.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1927
                                break;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1928
                            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1929
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1930
                    }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1931
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1932
                    tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, paramType, paramSymbol) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1933
                        //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
  1934
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1935
                        public Class<?> getValueType() {
29834
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
  1936
                            if (!useDualFields() ||  value == null || paramType == null || paramType.isBoolean()) {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1937
                                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
  1938
                            }
29834
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
  1939
                            return paramType.getTypeClass();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1940
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1941
                    });
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1942
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1943
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1944
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1945
            /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1946
             * Create a new object based on the symbols and values, generate
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1947
             * bootstrap code for object
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1948
             */
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1949
            final FieldObjectCreator<Symbol> creator = new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1950
                @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1951
                protected void loadValue(final Symbol value, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1952
                    method.load(value, type);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1953
                }
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1954
            };
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1955
            creator.makeObject(method);
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1956
            if (block.providesScopeCreator()) {
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1957
                scopeObjectCreators.push(creator);
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  1958
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1959
            // program function: merge scope into global
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1960
            if (isFunctionBody && function.isProgram()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1961
                method.invoke(ScriptRuntime.MERGE_SCOPE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1962
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1963
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1964
            method.storeCompilerConstant(SCOPE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1965
            if(!isFunctionBody) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1966
                // 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
  1967
                // actually causes issues with UnwarrantedOptimismException handlers as ASM will sort this handler to
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1968
                // 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
  1969
                final Label scopeEntryLabel = new Label("scope_entry");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1970
                scopeEntryLabels.push(scopeEntryLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1971
                method.label(scopeEntryLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1972
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1973
        } else if (isFunctionBody && function.isVarArg()) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1974
            // 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
  1975
            // we need to assign them separately here.
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1976
            int nextParam = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1977
            for (final IdentNode param : function.getParameters()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1978
                param.getSymbol().setFieldIndex(nextParam++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1979
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1980
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1981
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1982
        // 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
  1983
        printSymbols(block, function, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1984
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1985
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1986
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1987
     * 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
  1988
     * @param function function for which code is being generated.
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 initializeMethodParameters(final FunctionNode function) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1991
        final Label functionStart = new Label("fn_start");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1992
        method.label(functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1993
        int nextSlot = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1994
        if(function.needsCallee()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1995
            initializeInternalFunctionParameter(CALLEE, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1996
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1997
        initializeInternalFunctionParameter(THIS, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1998
        if(function.isVarArg()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1999
            initializeInternalFunctionParameter(VARARGS, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2000
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2001
            for(final IdentNode param: function.getParameters()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2002
                final Symbol symbol = param.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2003
                if(symbol.isBytecodeLocal()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2004
                    method.initializeMethodParameter(symbol, param.getType(), functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2005
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2006
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2007
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2008
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2009
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2010
    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
  2011
        final Symbol symbol = initializeInternalFunctionOrSplitParameter(cc, fn, functionStart, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2012
        // Internal function params (:callee, this, and :varargs) are never expanded to multiple slots
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2013
        assert symbol.getFirstSlot() == slot;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2014
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2015
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2016
    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
  2017
        final Symbol symbol = fn.getBody().getExistingSymbol(cc.symbolName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2018
        final Type type = Type.typeFor(cc.type());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2019
        method.initializeMethodParameter(symbol, type, functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2020
        method.onLocalStore(type, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2021
        return symbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2022
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2023
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2024
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2025
     * 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
  2026
     * 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
  2027
     * 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
  2028
     * and we need to spread them into their new locations.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2029
     * @param function the function for which parameter-spreading code needs to be emitted
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2030
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2031
    private void expandParameterSlots(final FunctionNode function) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2032
        final List<IdentNode> parameters = function.getParameters();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2033
        // Calculate the total number of incoming parameter slots
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2034
        int currentIncomingSlot = function.needsCallee() ? 2 : 1;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2035
        for(final IdentNode parameter: parameters) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2036
            currentIncomingSlot += parameter.getType().getSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2037
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2038
        // 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
  2039
        for(int i = parameters.size(); i-- > 0;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2040
            final IdentNode parameter = parameters.get(i);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2041
            final Type parameterType = parameter.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2042
            final int typeWidth = parameterType.getSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2043
            currentIncomingSlot -= typeWidth;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2044
            final Symbol symbol = parameter.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2045
            final int slotCount = symbol.slotCount();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2046
            assert slotCount > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2047
            // Scoped parameters must not hold more than one value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2048
            assert symbol.isBytecodeLocal() || slotCount == typeWidth;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2049
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2050
            // Mark it as having its value stored into it by the method invocation.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2051
            method.onLocalStore(parameterType, currentIncomingSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2052
            if(currentIncomingSlot != symbol.getSlot(parameterType)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2053
                method.load(parameterType, currentIncomingSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2054
                method.store(symbol, parameterType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2055
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2056
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2057
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2058
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2059
    private void initArguments(final FunctionNode function) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2060
        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
  2061
        if (function.needsCallee()) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2062
            method.loadCompilerConstant(CALLEE);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2063
        } else {
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2064
            // 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
  2065
            // caller.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2066
            assert function.isStrict();
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2067
            method.loadNull();
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2068
        }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2069
        method.load(function.getParameters().size());
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2070
        globalAllocateArguments();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2071
        method.storeCompilerConstant(ARGUMENTS);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2072
    }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2073
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2074
    private boolean skipFunction(final FunctionNode functionNode) {
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2075
        final ScriptEnvironment env = compiler.getScriptEnvironment();
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2076
        final boolean lazy = env._lazy_compilation;
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2077
        final boolean onDemand = compiler.isOnDemandCompilation();
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2078
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2079
        // 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
  2080
        if((onDemand || lazy) && lc.getOutermostFunction() != functionNode) {
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2081
            return true;
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2082
        }
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2083
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2084
        // 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
  2085
        // 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
  2086
        // lingers around. Also, currently loading previously persisted optimistic types information only works if
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2087
        // 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
  2088
        // benefit of using previously persisted types.
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  2089
        //
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2090
        // 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
  2091
        // 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
  2092
        // 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
  2093
        // 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
  2094
        // 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
  2095
        // 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
  2096
        // :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
  2097
        return !onDemand && lazy && env._optimistic_types && functionNode.isProgram();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2098
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2099
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2100
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2101
    public boolean enterFunctionNode(final FunctionNode functionNode) {
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2102
        if (skipFunction(functionNode)) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2103
            // 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
  2104
            // load it on the stack here.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2105
            newFunctionObject(functionNode, false);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2106
            return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  2107
        }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  2108
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2109
        final String fnName = functionNode.getName();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2110
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2111
        // 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
  2112
        // 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
  2113
        // 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
  2114
        // 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
  2115
        // 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
  2116
        // 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
  2117
        // 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
  2118
        // worth it, and generate one method with most generic type closure.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2119
        if (!emittedMethods.contains(fnName)) {
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
  2120
            log.info("=== BEGIN ", fnName);
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2121
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2122
            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
  2123
            unit = lc.pushCompileUnit(functionNode.getCompileUnit());
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2124
            assert lc.hasCompileUnits();
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2125
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2126
            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
  2127
            pushMethodEmitter(isRestOf() ? classEmitter.restOfMethod(functionNode) : classEmitter.method(functionNode));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2128
            method.setPreventUndefinedLoad();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2129
            if(useOptimisticTypes()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2130
                lc.pushUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2131
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2132
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2133
            // new method - reset last line number
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2134
            lastLineNumber = -1;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2135
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2136
            method.begin();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2137
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2138
            if (isRestOf()) {
32316
5d7dd8dc7729 8133785: SharedScopeCall should be enabled for non-optimistic call sites in optimistic compilation
attila
parents: 32049
diff changeset
  2139
                assert continuationInfo == null;
5d7dd8dc7729 8133785: SharedScopeCall should be enabled for non-optimistic call sites in optimistic compilation
attila
parents: 32049
diff changeset
  2140
                continuationInfo = new ContinuationInfo();
5d7dd8dc7729 8133785: SharedScopeCall should be enabled for non-optimistic call sites in optimistic compilation
attila
parents: 32049
diff changeset
  2141
                method.gotoLoopStart(continuationInfo.getHandlerLabel());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2142
            }
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2143
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2144
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2145
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2146
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2147
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2148
    private void pushMethodEmitter(final MethodEmitter newMethod) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2149
        method = lc.pushMethodEmitter(newMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2150
        catchLabels.push(METHOD_BOUNDARY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2151
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2152
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2153
    private void popMethodEmitter() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2154
        method = lc.popMethodEmitter(method);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2155
        assert catchLabels.peek() == METHOD_BOUNDARY;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2156
        catchLabels.pop();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2157
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2158
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2159
    @Override
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  2160
    public Node leaveFunctionNode(final FunctionNode functionNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2161
        try {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2162
            final boolean markOptimistic;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2163
            if (emittedMethods.add(functionNode.getName())) {
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  2164
                markOptimistic = generateUnwarrantedOptimismExceptionHandlers(functionNode);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2165
                generateContinuationHandler();
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2166
                method.end(); // wrap up this method
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2167
                unit   = lc.popCompileUnit(functionNode.getCompileUnit());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2168
                popMethodEmitter();
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
  2169
                log.info("=== END ", functionNode.getName());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2170
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2171
                markOptimistic = false;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2172
            }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2173
32692
8f60bd284bf4 8055917: jdk.nashorn.internal.codegen.CompilationPhase$N should be renamed to proper classes
sundar
parents: 32534
diff changeset
  2174
            FunctionNode newFunctionNode = functionNode;
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2175
            if (markOptimistic) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2176
                newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2177
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2178
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2179
            newFunctionObject(newFunctionNode, true);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2180
            return newFunctionNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2181
        } catch (final Throwable t) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2182
            Context.printStackTrace(t);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2183
            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
  2184
            e.initCause(t);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2185
            throw e;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2186
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2187
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2188
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2189
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2190
    public boolean enterIfNode(final IfNode ifNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2191
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2192
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2193
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2194
        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
  2195
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2196
        final Expression test = ifNode.getTest();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2197
        final Block pass = ifNode.getPass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2198
        final Block fail = ifNode.getFail();
27971
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2199
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2200
        if (Expression.isAlwaysTrue(test)) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2201
            loadAndDiscard(test);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2202
            pass.accept(this);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2203
            return false;
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2204
        } else if (Expression.isAlwaysFalse(test)) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2205
            loadAndDiscard(test);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2206
            if (fail != null) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2207
                fail.accept(this);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2208
            }
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2209
            return false;
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2210
        }
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2211
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2212
        final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2213
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2214
        final Label failLabel  = new Label("if_fail");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2215
        final Label afterLabel = (fail == null && !hasFailConversion) ? null : new Label("if_done");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2216
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2217
        emitBranch(test, failLabel, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2218
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2219
        pass.accept(this);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2220
        if(method.isReachable() && afterLabel != null) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2221
            method._goto(afterLabel); //don't fallthru to fail block
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2222
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2223
        method.label(failLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2224
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2225
        if (fail != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2226
            fail.accept(this);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2227
        } else if(hasFailConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2228
            method.beforeJoinPoint(ifNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2229
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2230
27971
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2231
        if(afterLabel != null && afterLabel.isReachable()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2232
            method.label(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2233
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2234
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2235
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2236
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2237
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2238
    private void emitBranch(final Expression test, final Label label, final boolean jumpWhenTrue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2239
        new BranchOptimizer(this, method).execute(test, label, jumpWhenTrue);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2240
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2241
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2242
    private void enterStatement(final Statement statement) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2243
        lineNumber(statement);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2244
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2245
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
  2246
    private void lineNumber(final Statement statement) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2247
        lineNumber(statement.getLineNumber());
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2248
    }
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2249
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
  2250
    private void lineNumber(final int lineNumber) {
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2251
        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
  2252
            method.lineNumber(lineNumber);
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2253
            lastLineNumber = lineNumber;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2254
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2255
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2256
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2257
    int getLastLineNumber() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2258
        return lastLineNumber;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2259
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2260
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2261
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2262
     * Load a list of nodes as an array of a specific type
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2263
     * The array will contain the visited nodes.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2264
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2265
     * @param arrayLiteralNode the array of contents
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2266
     * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2267
     */
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2268
    private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  2269
        assert arrayType == Type.INT_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2270
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2271
        final Expression[]     nodes    = arrayLiteralNode.getValue();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2272
        final Object           presets  = arrayLiteralNode.getPresets();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2273
        final int[]            postsets = arrayLiteralNode.getPostsets();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2274
        final List<Splittable.SplitRange> ranges   = arrayLiteralNode.getSplitRanges();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2275
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2276
        loadConstant(presets);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2277
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2278
        final Type elementType = arrayType.getElementType();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2279
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2280
        if (ranges != null) {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2281
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2282
            loadSplitLiteral(new SplitLiteralCreator() {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2283
                @Override
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2284
                public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2285
                    for (int i = start; i < end; i++) {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2286
                        method.load(type, slot);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2287
                        storeElement(nodes, elementType, postsets[i]);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2288
                    }
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2289
                    method.load(type, slot);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2290
                }
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2291
            }, ranges, arrayType);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2292
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2293
            return;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2294
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2295
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2296
        if(postsets.length > 0) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2297
            final int arraySlot = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2298
            method.storeTemp(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2299
            for (final int postset : postsets) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2300
                method.load(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2301
                storeElement(nodes, elementType, postset);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2302
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2303
            method.load(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2304
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2305
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2306
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2307
    private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2308
        method.load(index);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2309
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2310
        final Expression element = nodes[index];
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2311
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2312
        if (element == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2313
            method.loadEmpty(elementType);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2314
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2315
            loadExpressionAsType(element, elementType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2316
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2317
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2318
        method.arraystore();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2319
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2320
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2321
    private MethodEmitter loadArgsArray(final List<Expression> args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2322
        final Object[] array = new Object[args.size()];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2323
        loadConstant(array);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2324
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2325
        for (int i = 0; i < args.size(); i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2326
            method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2327
            method.load(i);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2328
            loadExpression(args.get(i), TypeBounds.OBJECT); // variable arity methods always take objects
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2329
            method.arraystore();
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
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2333
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2334
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2335
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2336
     * 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
  2337
     * subpackage. Do not call directly.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2338
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2339
     * @param string string to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2340
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2341
    void loadConstant(final String string) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2342
        final String       unitClassName = unit.getUnitClassName();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2343
        final ClassEmitter classEmitter  = unit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2344
        final int          index         = compiler.getConstantData().add(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2345
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2346
        method.load(index);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2347
        method.invokestatic(unitClassName, GET_STRING.symbolName(), methodDescriptor(String.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2348
        classEmitter.needGetConstantMethod(String.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2349
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2350
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2351
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2352
     * 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
  2353
     * subpackage. Do not call directly.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2354
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2355
     * @param object object to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2356
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2357
    void loadConstant(final Object object) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2358
        loadConstant(object, unit, method);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2359
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2360
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2361
    private void loadConstant(final Object object, final CompileUnit compileUnit, final MethodEmitter methodEmitter) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2362
        final String       unitClassName = compileUnit.getUnitClassName();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2363
        final ClassEmitter classEmitter  = compileUnit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2364
        final int          index         = compiler.getConstantData().add(object);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2365
        final Class<?>     cls           = object.getClass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2366
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2367
        if (cls == PropertyMap.class) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2368
            methodEmitter.load(index);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2369
            methodEmitter.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2370
            classEmitter.needGetConstantMethod(PropertyMap.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2371
        } else if (cls.isArray()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2372
            methodEmitter.load(index);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2373
            final String methodName = ClassEmitter.getArrayMethodName(cls);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2374
            methodEmitter.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2375
            classEmitter.needGetConstantMethod(cls);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2376
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2377
            methodEmitter.loadConstants().load(index).arrayload();
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
  2378
            if (object instanceof ArrayData) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2379
                methodEmitter.checkcast(ArrayData.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2380
                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
  2381
            } else if (cls != Object.class) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2382
                methodEmitter.checkcast(cls);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2383
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2384
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2385
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2386
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2387
    private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2388
        methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2389
    }
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2390
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2391
    // literal values
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2392
    private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2393
        final Object value = node.getValue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2394
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2395
        if (value == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2396
            method.loadNull();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2397
        } else if (value instanceof Undefined) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2398
            method.loadUndefined(resultBounds.within(Type.OBJECT));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2399
        } else if (value instanceof String) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2400
            final String string = (String)value;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2401
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  2402
            if (string.length() > MethodEmitter.LARGE_STRING_THRESHOLD / 3) { // 3 == max bytes per encoded char
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2403
                loadConstant(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2404
            } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2405
                method.load(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2406
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2407
        } else if (value instanceof RegexToken) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2408
            loadRegex((RegexToken)value);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2409
        } else if (value instanceof Boolean) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2410
            method.load((Boolean)value);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2411
        } else if (value instanceof Integer) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2412
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2413
                method.load((Integer)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2414
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2415
            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2416
                method.load(((Integer)value).doubleValue());
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2417
            } else {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2418
                method.load((Integer)value);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2419
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2420
        } else if (value instanceof Double) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2421
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2422
                method.load((Double)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2423
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2424
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2425
                method.load((Double)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2426
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2427
        } else if (node instanceof ArrayLiteralNode) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2428
            final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2429
            final ArrayType atype = arrayLiteral.getArrayType();
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2430
            loadArray(arrayLiteral, atype);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2431
            globalAllocateArray(atype);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2432
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2433
            throw new UnsupportedOperationException("Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2434
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2435
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2436
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2437
    private MethodEmitter loadRegexToken(final RegexToken value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2438
        method.load(value.getExpression());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2439
        method.load(value.getOptions());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2440
        return globalNewRegExp();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2441
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2442
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2443
    private MethodEmitter loadRegex(final RegexToken regexToken) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2444
        if (regexFieldCount > MAX_REGEX_FIELDS) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2445
            return loadRegexToken(regexToken);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2446
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2447
        // 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
  2448
        final String       regexName    = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2449
        final ClassEmitter classEmitter = unit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2450
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2451
        classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2452
        regexFieldCount++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2453
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2454
        // get field, if null create new regex, finally clone regex object
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2455
        method.getStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2456
        method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2457
        final Label cachedLabel = new Label("cached");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2458
        method.ifnonnull(cachedLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2459
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2460
        method.pop();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2461
        loadRegexToken(regexToken);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2462
        method.dup();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2463
        method.putStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2464
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2465
        method.label(cachedLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2466
        globalRegExpCopy();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2467
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2468
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2469
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2470
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2471
    /**
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2472
     * 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
  2473
     * @param value value
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2474
     * @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
  2475
     * @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
  2476
     */
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2477
    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
  2478
        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
  2479
            boolean contains;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2480
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2481
            @Override
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2482
            public Boolean get() {
32888
24f99be3d5ab 8134502: introduce abstraction for basic NodeVisitor usage
attila
parents: 32784
diff changeset
  2483
                value.accept(new SimpleNodeVisitor() {
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2484
                    @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
  2485
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2486
                        return false;
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2487
                    }
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2488
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2489
                    @Override
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2490
                    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
  2491
                        if (contains) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2492
                            return false;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2493
                        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2494
                        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
  2495
                            contains = true;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2496
                            return false;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2497
                        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2498
                        return true;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2499
                    }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2500
                });
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2501
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2502
                return contains;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2503
            }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2504
        }.get();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2505
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2506
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2507
    private void loadObjectNode(final ObjectNode objectNode) {
17981
9b8e085aa1fe 8015955: ObjectNode.elements should be stronger typed
attila
parents: 17969
diff changeset
  2508
        final List<PropertyNode> elements = objectNode.getElements();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2509
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2510
        final List<MapTuple<Expression>> tuples = new ArrayList<>();
41145
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2511
        // List below will contain getter/setter properties and properties with computed keys (ES6)
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2512
        final List<PropertyNode> specialProperties = 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
  2513
        final int ccp = getCurrentContinuationEntryPoint();
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2514
        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2515
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2516
        Expression protoNode = null;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2517
        boolean restOfProperty = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2518
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2519
        for (final PropertyNode propertyNode : elements) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2520
            final Expression value = propertyNode.getValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2521
            final String key = propertyNode.getKeyName();
41145
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2522
            final boolean isComputedOrAccessor = propertyNode.isComputed() || value == null;
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2523
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2524
            // Just use a pseudo-symbol. We just need something non null; use the name and zero flags.
41145
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2525
            final Symbol symbol = isComputedOrAccessor ? null : new Symbol(key, 0);
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2526
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2527
            if (isComputedOrAccessor) {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2528
                // Properties with computed names or getter/setters need special handling.
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2529
                specialProperties.add(propertyNode);
24281
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2530
            } else if (propertyNode.getKey() instanceof IdentNode &&
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2531
                       key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2532
                // ES6 draft compliant __proto__ inside object literal
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2533
                // Identifier key and name is __proto__
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2534
                protoNode = value;
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2535
                continue;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2536
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2537
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2538
            restOfProperty |=
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2539
                value != null &&
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2540
                isValid(ccp) &&
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2541
                propertyValueContains(value, ccp);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2542
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2543
            //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
  2544
            //(I think)
41145
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2545
            final Class<?> valueType = (!useDualFields() || isComputedOrAccessor || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2546
            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
  2547
                @Override
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2548
                public Class<?> getValueType() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2549
                    return type.getTypeClass();
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2550
                }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2551
            });
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2552
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2553
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2554
        final ObjectCreator<?> oc;
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2555
        if (elements.size() > OBJECT_SPILL_THRESHOLD) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2556
            oc = new SpillObjectCreator(this, tuples);
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2557
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2558
            oc = new FieldObjectCreator<Expression>(this, tuples) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2559
                @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2560
                protected void loadValue(final Expression node, final Type type) {
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  2561
                    // Use generic type in order to avoid conversion between object types
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  2562
                    loadExpressionAsType(node, Type.generic(type));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2563
                }};
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2564
        }
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2565
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2566
        if (ranges != null) {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2567
            oc.createObject(method);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2568
            loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass()));
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2569
        } else {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2570
            oc.makeObject(method);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2571
        }
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2572
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2573
        //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
  2574
        //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
  2575
        //handler
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2576
        if (restOfProperty) {
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2577
            final ContinuationInfo ci = getContinuationInfo();
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  2578
            ci.setObjectLiteralMap(method.getStackSize(), oc.getMap());
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2579
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2580
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2581
        method.dup();
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2582
        if (protoNode != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2583
            loadExpressionAsObject(protoNode);
24772
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2584
            // take care of { __proto__: 34 } or some such!
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2585
            method.convert(Type.OBJECT);
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2586
            method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2587
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2588
            method.invoke(ScriptObject.SET_GLOBAL_OBJECT_PROTO);
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2589
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2590
41145
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2591
        for (final PropertyNode propertyNode : specialProperties) {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2592
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2593
            method.dup();
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2594
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2595
            if (propertyNode.isComputed()) {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2596
                assert propertyNode.getKeyName() == null;
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2597
                loadExpressionAsObject(propertyNode.getKey());
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2598
            } else {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2599
                method.loadKey(propertyNode.getKey());
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2600
            }
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2601
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2602
            if (propertyNode.getValue() != null) {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2603
                loadExpressionAsObject(propertyNode.getValue());
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2604
                method.load(0);
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2605
                method.invoke(ScriptObject.GENERIC_SET);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2606
            } else {
41145
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2607
                final FunctionNode getter = propertyNode.getGetter();
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2608
                final FunctionNode setter = propertyNode.getSetter();
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2609
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2610
                assert getter != null || setter != null;
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2611
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2612
                if (getter == null) {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2613
                    method.loadNull();
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2614
                } else {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2615
                    getter.accept(this);
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2616
                }
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2617
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2618
                if (setter == null) {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2619
                    method.loadNull();
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2620
                } else {
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2621
                    setter.accept(this);
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2622
                }
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2623
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2624
                method.invoke(ScriptObject.SET_USER_ACCESSORS);
b9a1cb9ed1d3 8164467: ES6 computed properties are implemented wrongly
hannesw
parents: 37732
diff changeset
  2625
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2626
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2627
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2628
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2629
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2630
    public boolean enterReturnNode(final ReturnNode returnNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2631
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2632
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2633
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2634
        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
  2635
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
  2636
        final Type returnType = lc.getCurrentFunction().getReturnType();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2637
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2638
        final Expression expression = returnNode.getExpression();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2639
        if (expression != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2640
            loadExpressionUnbounded(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2641
        } else {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2642
            method.loadUndefined(returnType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2643
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2644
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2645
        method._return(returnType);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2646
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2647
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2648
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2649
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2650
    private boolean undefinedCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2651
        final Request request = runtimeNode.getRequest();
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2652
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2653
        if (!Request.isUndefinedCheck(request)) {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2654
            return false;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2655
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2656
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2657
        final Expression lhs = args.get(0);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2658
        final Expression rhs = args.get(1);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2659
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2660
        final Symbol lhsSymbol = lhs instanceof IdentNode ? ((IdentNode)lhs).getSymbol() : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2661
        final Symbol rhsSymbol = rhs instanceof IdentNode ? ((IdentNode)rhs).getSymbol() : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2662
        // One must be a "undefined" identifier, otherwise we can't get here
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2663
        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
  2664
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2665
        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
  2666
        if (isUndefinedSymbol(lhsSymbol)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2667
            undefinedSymbol = lhsSymbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2668
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2669
            assert isUndefinedSymbol(rhsSymbol);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2670
            undefinedSymbol = rhsSymbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2671
        }
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2672
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2673
        assert undefinedSymbol != null; //remove warning
24781
00f645e2d28a 8044803: Unnecessary restOf check
attila
parents: 24774
diff changeset
  2674
        if (!undefinedSymbol.isScope()) {
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2675
            return false; //disallow undefined as local var or parameter
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2676
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2677
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2678
        if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2679
            //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
  2680
            return false;
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2681
        }
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2682
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2683
        if(isDeoptimizedExpression(lhs)) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2684
            // 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
  2685
            // 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
  2686
            // 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
  2687
            // "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
  2688
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2689
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2690
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2691
        //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
  2692
        //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
  2693
        if (!compiler.isGlobalSymbol(lc.getCurrentFunction(), "undefined")) {
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  2694
            return false;
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2695
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2696
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2697
        final boolean isUndefinedCheck = request == Request.IS_UNDEFINED;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2698
        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
  2699
        if (expr.getType().isPrimitive()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2700
            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
  2701
            method.load(!isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2702
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2703
            final Label checkTrue  = new Label("ud_check_true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2704
            final Label end        = new Label("end");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2705
            loadExpressionAsObject(expr);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2706
            method.loadUndefined(Type.OBJECT);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2707
            method.if_acmpeq(checkTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2708
            method.load(!isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2709
            method._goto(end);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2710
            method.label(checkTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2711
            method.load(isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2712
            method.label(end);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2713
        }
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2714
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2715
        return true;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2716
    }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2717
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2718
    private static boolean isUndefinedSymbol(final Symbol symbol) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2719
        return symbol != null && "undefined".equals(symbol.getName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2720
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2721
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2722
    private static boolean isNullLiteral(final Node node) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2723
        return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2724
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2725
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2726
    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2727
        final Request request = runtimeNode.getRequest();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2728
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2729
        if (!Request.isEQ(request) && !Request.isNE(request)) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2730
            return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2731
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2732
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2733
        assert args.size() == 2 : "EQ or NE or TYPEOF need two args";
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2734
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2735
        Expression lhs = args.get(0);
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2736
        Expression rhs = args.get(1);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2737
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2738
        if (isNullLiteral(lhs)) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2739
            final Expression tmp = lhs;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2740
            lhs = rhs;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2741
            rhs = tmp;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2742
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2743
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2744
        if (!isNullLiteral(rhs)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2745
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2746
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2747
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2748
        if (!lhs.getType().isObject()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2749
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2750
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2751
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2752
        if(isDeoptimizedExpression(lhs)) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2753
            // 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
  2754
            // 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
  2755
            // 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
  2756
            // 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
  2757
            // method and any of its (transitive) rest-ofs."
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2758
            // 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
  2759
            // 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
  2760
            // 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
  2761
            // operation.
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2762
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2763
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2764
18631
537b279999e5 8016667: Wrong bytecode when testing/setting due to null check shortcut checking against primitive too
lagergren
parents: 18628
diff changeset
  2765
        // 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
  2766
        // involved like {D}x=null, we will fail - this is very rare
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2767
        final Label trueLabel  = new Label("trueLabel");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2768
        final Label falseLabel = new Label("falseLabel");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2769
        final Label endLabel   = new Label("end");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2770
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2771
        loadExpressionUnbounded(lhs);    //lhs
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2772
        final Label popLabel;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2773
        if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2774
            method.dup(); //lhs lhs
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2775
            popLabel = new Label("pop");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2776
        } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2777
            popLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2778
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2779
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2780
        if (Request.isEQ(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2781
            method.ifnull(!Request.isStrict(request) ? popLabel : trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2782
            if (!Request.isStrict(request)) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2783
                method.loadUndefined(Type.OBJECT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2784
                method.if_acmpeq(trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2785
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2786
            method.label(falseLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2787
            method.load(false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2788
            method._goto(endLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2789
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2790
                method.label(popLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2791
                method.pop();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2792
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2793
            method.label(trueLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2794
            method.load(true);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2795
            method.label(endLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2796
        } else if (Request.isNE(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2797
            method.ifnull(!Request.isStrict(request) ? popLabel : falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2798
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2799
                method.loadUndefined(Type.OBJECT);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2800
                method.if_acmpeq(falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2801
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2802
            method.label(trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2803
            method.load(true);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2804
            method._goto(endLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2805
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2806
                method.label(popLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2807
                method.pop();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2808
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2809
            method.label(falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2810
            method.load(false);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2811
            method.label(endLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2812
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2813
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2814
        assert runtimeNode.getType().isBoolean();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2815
        method.convert(runtimeNode.getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2816
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2817
        return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2818
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2819
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2820
    /**
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2821
     * 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
  2822
     * @param rootExpr the expression being tested
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2823
     * @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
  2824
     */
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2825
    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
  2826
        if(!isRestOf()) {
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2827
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2828
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2829
        return new Supplier<Boolean>() {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2830
            boolean contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2831
            @Override
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2832
            public Boolean get() {
32888
24f99be3d5ab 8134502: introduce abstraction for basic NodeVisitor usage
attila
parents: 32784
diff changeset
  2833
                rootExpr.accept(new SimpleNodeVisitor() {
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2834
                    @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
  2835
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2836
                        return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2837
                    }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2838
                    @Override
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2839
                    public boolean enterDefault(final Node node) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2840
                        if(!contains && node instanceof Optimistic) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2841
                            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
  2842
                            contains = isValid(pp) && isContinuationEntryPoint(pp);
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2843
                        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2844
                        return !contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2845
                    }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2846
                });
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2847
                return contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2848
            }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2849
        }.get();
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  2850
    }
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  2851
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2852
    private void loadRuntimeNode(final RuntimeNode runtimeNode) {
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2853
        final List<Expression> args = new ArrayList<>(runtimeNode.getArgs());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2854
        if (nullCheck(runtimeNode, args)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2855
           return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2856
        } else if(undefinedCheck(runtimeNode, args)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2857
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2858
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2859
        // Revert a false undefined check to a strict equality check
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2860
        final RuntimeNode newRuntimeNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2861
        final Request request = runtimeNode.getRequest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2862
        if (Request.isUndefinedCheck(request)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2863
            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
  2864
        } else {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2865
            newRuntimeNode = runtimeNode;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2866
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2867
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2868
        for (final Expression arg : args) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2869
            loadExpression(arg, TypeBounds.OBJECT);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2870
        }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2871
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2872
        method.invokestatic(
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2873
                CompilerConstants.className(ScriptRuntime.class),
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2874
                newRuntimeNode.getRequest().toString(),
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2875
                new FunctionSignature(
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2876
                    false,
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2877
                    false,
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2878
                    newRuntimeNode.getType(),
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2879
                    args.size()).toString());
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2880
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2881
        method.convert(newRuntimeNode.getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2882
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2883
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2884
    private void defineCommonSplitMethodParameters() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2885
        defineSplitMethodParameter(0, CALLEE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2886
        defineSplitMethodParameter(1, THIS);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2887
        defineSplitMethodParameter(2, SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2888
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2889
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2890
    private void defineSplitMethodParameter(final int slot, final CompilerConstants cc) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2891
        defineSplitMethodParameter(slot, Type.typeFor(cc.type()));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2892
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2893
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2894
    private void defineSplitMethodParameter(final int slot, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2895
        method.defineBlockLocalVariable(slot, slot + type.getSlots());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2896
        method.onLocalStore(type, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2897
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2898
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2899
    private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2900
        assert ranges != null;
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2901
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2902
        // final Type literalType = Type.typeFor(literalClass);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2903
        final MethodEmitter savedMethod     = method;
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2904
        final FunctionNode  currentFunction = lc.getCurrentFunction();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2905
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2906
        for (final Splittable.SplitRange splitRange : ranges) {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2907
            unit = lc.pushCompileUnit(splitRange.getCompileUnit());
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2908
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2909
            assert unit != null;
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2910
            final String className = unit.getUnitClassName();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2911
            final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2912
            final Class<?> clazz   = literalType.getTypeClass();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2913
            final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2914
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2915
            pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2916
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2917
            method.setFunctionNode(currentFunction);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2918
            method.begin();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2919
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2920
            defineCommonSplitMethodParameters();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2921
            defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2922
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2923
            // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2924
            // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2925
            final int literalSlot = fixScopeSlot(currentFunction, 3);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2926
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2927
            lc.enterSplitNode();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2928
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2929
            creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh());
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2930
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2931
            method._return();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2932
            lc.exitSplitNode();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2933
            method.end();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2934
            lc.releaseSlots();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2935
            popMethodEmitter();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2936
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2937
            assert method == savedMethod;
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2938
            method.loadCompilerConstant(CALLEE).swap();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2939
            method.loadCompilerConstant(THIS).swap();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2940
            method.loadCompilerConstant(SCOPE).swap();
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2941
            method.invokestatic(className, name, signature);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2942
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2943
            unit = lc.popCompileUnit(unit);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2944
        }
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2945
    }
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  2946
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2947
    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
  2948
        // 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
  2949
        final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2950
        final int defaultScopeSlot = SCOPE.slot();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2951
        int newExtraSlot = extraSlot;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2952
        if (actualScopeSlot != defaultScopeSlot) {
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2953
            if (actualScopeSlot == extraSlot) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2954
                newExtraSlot = extraSlot + 1;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2955
                method.defineBlockLocalVariable(newExtraSlot, newExtraSlot + 1);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2956
                method.load(Type.OBJECT, extraSlot);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2957
                method.storeHidden(Type.OBJECT, newExtraSlot);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2958
            } else {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2959
                method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2960
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2961
            method.load(SCOPE_TYPE, defaultScopeSlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2962
            method.storeCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2963
        }
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2964
        return newExtraSlot;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2965
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2966
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2967
    @Override
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2968
    public boolean enterSplitReturn(final SplitReturn splitReturn) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2969
        if (method.isReachable()) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2970
            method.loadUndefined(lc.getCurrentFunction().getReturnType())._return();
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2971
        }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2972
        return false;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2973
    }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2974
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2975
    @Override
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2976
    public boolean enterSetSplitState(final SetSplitState setSplitState) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2977
        if (method.isReachable()) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2978
            method.setSplitState(setSplitState.getState());
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2979
        }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2980
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2981
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2982
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2983
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2984
    public boolean enterSwitchNode(final SwitchNode switchNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2985
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2986
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2987
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2988
        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
  2989
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2990
        final Expression     expression  = switchNode.getExpression();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2991
        final List<CaseNode> cases       = switchNode.getCases();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2992
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2993
        if (cases.isEmpty()) {
20569
2386d10eadd3 8026033: Switch should load expression even when there are no cases in it
sundar
parents: 20559
diff changeset
  2994
            // still evaluate expression for side-effects.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2995
            loadAndDiscard(expression);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2996
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2997
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2998
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2999
        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
  3000
        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
  3001
        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
  3002
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3003
        if (defaultCase != null && cases.size() == 1) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3004
            // default case only
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3005
            assert cases.get(0) == defaultCase;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3006
            loadAndDiscard(expression);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3007
            defaultCase.getBody().accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3008
            method.breakLabel(breakLabel, liveLocalsOnBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3009
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3010
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3011
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3012
        // 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
  3013
        // 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
  3014
        Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3015
        final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3016
27970
7b0048b90967 8066225: NPE in MethodEmitter with duplicate integer switch cases
attila
parents: 27969
diff changeset
  3017
        if (switchNode.isUniqueInteger()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3018
            // Tree for sorting values.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3019
            final TreeMap<Integer, Label> tree = new TreeMap<>();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3020
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3021
            // Build up sorted tree.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3022
            for (final CaseNode caseNode : cases) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3023
                final Node test = caseNode.getTest();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3024
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3025
                if (test != null) {
16235
cc200fdc3478 8008206: The allInteger case for SwitchNode generation in CodeGenerator assumes integer LITERALS only.
lagergren
parents: 16233
diff changeset
  3026
                    final Integer value = (Integer)((LiteralNode<?>)test).getValue();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3027
                    final Label   entry = caseNode.getEntry();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3028
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3029
                    // Take first duplicate.
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  3030
                    if (!tree.containsKey(value)) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3031
                        tree.put(value, entry);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3032
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3033
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3034
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3035
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3036
            // Copy values and labels to arrays.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3037
            final int       size   = tree.size();
35407
204abe4d8cbc 8147591: Revisit Collection.toArray(new T[size]) calls in nashorn and dynalink code
mhaupt
parents: 34732
diff changeset
  3038
            final Integer[] values = tree.keySet().toArray(new Integer[0]);
204abe4d8cbc 8147591: Revisit Collection.toArray(new T[size]) calls in nashorn and dynalink code
mhaupt
parents: 34732
diff changeset
  3039
            final Label[]   labels = tree.values().toArray(new Label[0]);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3040
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3041
            // Discern low, high and range.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3042
            final int lo    = values[0];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3043
            final int hi    = values[size - 1];
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3044
            final long range = (long)hi - (long)lo + 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3045
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3046
            // Find an unused value for default.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3047
            int deflt = Integer.MIN_VALUE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3048
            for (final int value : values) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3049
                if (deflt == value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3050
                    deflt++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3051
                } else if (deflt < value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3052
                    break;
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
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3056
            // Load switch expression.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3057
            loadExpressionUnbounded(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3058
            final Type type = expression.getType();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3059
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3060
            // 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
  3061
            if (!type.isInteger()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3062
                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
  3063
                final Class<?> exprClass = type.getTypeClass();
18628
012cd852f881 8019488: switch on literals result in NoSuchMethodError or VerifyError
sundar
parents: 18621
diff changeset
  3064
                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
  3065
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3066
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3067
            if(hasSkipConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3068
                assert defaultLabel == breakLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3069
                defaultLabel = new Label("switch_skip");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3070
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3071
            // 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
  3072
            // smaller representation, favor TABLESWITCH when they're equal size.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3073
            if (range + 1 <= (size * 2) && range <= Integer.MAX_VALUE) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3074
                final Label[] table = new Label[(int)range];
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3075
                Arrays.fill(table, defaultLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3076
                for (int i = 0; i < size; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3077
                    final int value = values[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3078
                    table[value - lo] = labels[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3079
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3080
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  3081
                method.tableswitch(lo, hi, defaultLabel, table);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3082
            } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3083
                final int[] ints = new int[size];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3084
                for (int i = 0; i < size; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3085
                    ints[i] = values[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3086
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3087
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  3088
                method.lookupswitch(defaultLabel, ints, labels);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3089
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3090
            // 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
  3091
            // local variable conversions if neither case is taken.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3092
            if(hasSkipConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3093
                method.label(defaultLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3094
                method.beforeJoinPoint(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3095
                method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3096
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3097
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3098
            final Symbol tagSymbol = switchNode.getTag();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3099
            // TODO: we could have non-object tag
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3100
            final int tagSlot = tagSymbol.getSlot(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3101
            loadExpressionAsObject(expression);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3102
            method.store(tagSymbol, Type.OBJECT);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3103
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3104
            for (final CaseNode caseNode : cases) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3105
                final Expression test = caseNode.getTest();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3106
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3107
                if (test != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3108
                    method.load(Type.OBJECT, tagSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3109
                    loadExpressionAsObject(test);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3110
                    method.invoke(ScriptRuntime.EQ_STRICT);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3111
                    method.ifne(caseNode.getEntry());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3112
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3113
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3114
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3115
            if (defaultCase != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3116
                method._goto(defaultLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3117
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3118
                method.beforeJoinPoint(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3119
                method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3120
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3121
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3122
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3123
        // First case is only reachable through jump
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3124
        assert !method.isReachable();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3125
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3126
        for (final CaseNode caseNode : cases) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3127
            final Label fallThroughLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3128
            if(caseNode.getLocalVariableConversion() != null && method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3129
                fallThroughLabel = new Label("fallthrough");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3130
                method._goto(fallThroughLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3131
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3132
                fallThroughLabel = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3133
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3134
            method.label(caseNode.getEntry());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3135
            method.beforeJoinPoint(caseNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3136
            if(fallThroughLabel != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3137
                method.label(fallThroughLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3138
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3139
            caseNode.getBody().accept(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3140
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3141
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3142
        method.breakLabel(breakLabel, liveLocalsOnBreak);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3143
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3144
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3145
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3146
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3147
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3148
    public boolean enterThrowNode(final ThrowNode throwNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3149
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3150
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3151
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3152
        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
  3153
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3154
        if (throwNode.isSyntheticRethrow()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3155
            method.beforeJoinPoint(throwNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3156
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3157
            //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
  3158
            final IdentNode exceptionExpr = (IdentNode)throwNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3159
            final Symbol exceptionSymbol = exceptionExpr.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3160
            method.load(exceptionSymbol, EXCEPTION_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3161
            method.checkcast(EXCEPTION_TYPE.getTypeClass());
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3162
            method.athrow();
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3163
            return false;
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3164
        }
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3165
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3166
        final Source     source     = getCurrentSource();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3167
        final Expression expression = throwNode.getExpression();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3168
        final int        position   = throwNode.position();
20559
9244eb6d195b 8025515: Performance issues with Source.getLine()
hannesw
parents: 20215
diff changeset
  3169
        final int        line       = throwNode.getLineNumber();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3170
        final int        column     = source.getColumn(position);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3171
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3172
        // 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
  3173
        // 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
  3174
        // 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
  3175
        // the not-yet-<init>ialized object on the stack from the UnwarrantedOptimismException handler, and bytecode
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3176
        // verifier forbids that.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3177
        loadExpressionAsObject(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3178
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3179
        method.load(source.getName());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3180
        method.load(line);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3181
        method.load(column);
22387
81639250d335 8031983: Error objects should capture stack at the constructor
sundar
parents: 21868
diff changeset
  3182
        method.invoke(ECMAException.CREATE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3183
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3184
        method.beforeJoinPoint(throwNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3185
        method.athrow();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3186
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3187
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3188
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3189
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3190
    private Source getCurrentSource() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3191
        return lc.getCurrentFunction().getSource();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3192
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3193
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3194
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3195
    public boolean enterTryNode(final TryNode tryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3196
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3197
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3198
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3199
        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
  3200
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3201
        final Block       body        = tryNode.getBody();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3202
        final List<Block> catchBlocks = tryNode.getCatchBlocks();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3203
        final Symbol      vmException = tryNode.getException();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3204
        final Label       entry       = new Label("try");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3205
        final Label       recovery    = new Label("catch");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3206
        final Label       exit        = new Label("end_try");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3207
        final Label       skip        = new Label("skip");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3208
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3209
        method.canThrow(recovery);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3210
        // 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
  3211
        // 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
  3212
        // 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
  3213
        // conversions of assignments within the try block.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3214
        method.beforeTry(tryNode, recovery);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3215
        method.label(entry);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3216
        catchLabels.push(recovery);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3217
        try {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3218
            body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3219
        } finally {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3220
            assert catchLabels.peek() == recovery;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3221
            catchLabels.pop();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3222
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3223
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3224
        method.label(exit);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3225
        final boolean bodyCanThrow = exit.isAfter(entry);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3226
        if(!bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3227
            // 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
  3228
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3229
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3230
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3231
        method._try(entry, exit, recovery, Throwable.class);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3232
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3233
        if (method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3234
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3235
        }
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3236
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3237
        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3238
            TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3239
            // All inlined finallies end with a jump or a return
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3240
            assert !method.isReachable();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3241
        }
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3242
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3243
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3244
        method._catch(recovery);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3245
        method.store(vmException, EXCEPTION_TYPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3246
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3247
        final int catchBlockCount = catchBlocks.size();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3248
        final Label afterCatch = new Label("after_catch");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3249
        for (int i = 0; i < catchBlockCount; i++) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3250
            assert method.isReachable();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3251
            final Block catchBlock = catchBlocks.get(i);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3252
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3253
            // 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
  3254
            // 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
  3255
            lc.push(catchBlock);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3256
            enterBlock(catchBlock);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3257
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3258
            final CatchNode  catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
41983
eb674141ab03 8156615: Catch parameter can be a BindingPattern in ES6 mode
sdama
parents: 41422
diff changeset
  3259
            final IdentNode  exception          = catchNode.getExceptionIdentifier();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3260
            final Expression exceptionCondition = catchNode.getExceptionCondition();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3261
            final Block      catchBody          = catchNode.getBody();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3262
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3263
            new Store<IdentNode>(exception) {
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3264
                @Override
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3265
                protected void storeNonDiscard() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3266
                    // 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
  3267
                    // stored, so we override storeNonDiscard to be a no-op.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3268
                }
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
  3269
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3270
                @Override
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3271
                protected void evaluate() {
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3272
                    if (catchNode.isSyntheticRethrow()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3273
                        method.load(vmException, EXCEPTION_TYPE);
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3274
                        return;
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3275
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3276
                    /*
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3277
                     * If caught object is an instance of ECMAException, then
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3278
                     * bind obj.thrown to the script catch var. Or else bind the
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3279
                     * caught object itself to the script catch var.
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3280
                     */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3281
                    final Label notEcmaException = new Label("no_ecma_exception");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3282
                    method.load(vmException, EXCEPTION_TYPE).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3283
                    method.checkcast(ECMAException.class); //TODO is this necessary?
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3284
                    method.getField(ECMAException.THROWN);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3285
                    method.label(notEcmaException);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3286
                }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3287
            }.store();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3288
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3289
            final boolean isConditionalCatch = exceptionCondition != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3290
            final Label nextCatch;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3291
            if (isConditionalCatch) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3292
                loadExpressionAsBoolean(exceptionCondition);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3293
                nextCatch = new Label("next_catch");
27823
a591041cf33c 8066232: problem with conditional catch compilation
attila
parents: 27817
diff changeset
  3294
                nextCatch.markAsBreakTarget();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3295
                method.ifeq(nextCatch);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3296
            } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3297
                nextCatch = null;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3298
            }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3299
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3300
            catchBody.accept(this);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3301
            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
  3302
            lc.pop(catchBlock);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3303
            if(nextCatch != null) {
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3304
                if(method.isReachable()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3305
                    method._goto(afterCatch);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3306
                }
27823
a591041cf33c 8066232: problem with conditional catch compilation
attila
parents: 27817
diff changeset
  3307
                method.breakLabel(nextCatch, lc.getUsedSlotCount());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3308
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3309
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3310
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3311
        // 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
  3312
        method.label(afterCatch);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3313
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3314
            method.markDeadLocalVariable(vmException);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3315
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3316
        method.label(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3317
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3318
        // 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
  3319
        assert tryNode.getFinallyBody() == null;
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3320
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3321
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3322
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3323
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3324
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3325
    public boolean enterVarNode(final VarNode varNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3326
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3327
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3328
        }
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3329
        final Expression init = varNode.getInit();
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3330
        final IdentNode identNode = varNode.getName();
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3331
        final Symbol identSymbol = identNode.getSymbol();
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3332
        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
  3333
        final boolean needsScope = identSymbol.isScope();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3334
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3335
        if (init == null) {
36691
56a7257458e7 8151811: Const declarations do not work in for..in loops
hannesw
parents: 36690
diff changeset
  3336
            // Block-scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ).
56a7257458e7 8151811: Const declarations do not work in for..in loops
hannesw
parents: 36690
diff changeset
  3337
            // However, don't do this for CONST which always has an initializer except in the special case of
56a7257458e7 8151811: Const declarations do not work in for..in loops
hannesw
parents: 36690
diff changeset
  3338
            // for-in/of loops, in which it is initialized in the loop header and should be left untouched here.
56a7257458e7 8151811: Const declarations do not work in for..in loops
hannesw
parents: 36690
diff changeset
  3339
            if (needsScope && varNode.isLet()) {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3340
                method.loadCompilerConstant(SCOPE);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3341
                method.loadUndefined(Type.OBJECT);
36696
39ff39c8e396 8151700: Add support for ES6 for-of
hannesw
parents: 36691
diff changeset
  3342
                final int flags = getScopeCallSiteFlags(identSymbol) | CALLSITE_DECLARE;
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3343
                assert isFastScope(identSymbol);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3344
                storeFastScopeVar(identSymbol, flags);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3345
            }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3346
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3347
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3348
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3349
        enterStatement(varNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3350
        assert method != null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3351
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3352
        if (needsScope) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3353
            method.loadCompilerConstant(SCOPE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3354
            loadExpressionUnbounded(init);
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3355
            // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
  3356
            final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  3357
            if (isFastScope(identSymbol)) {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  3358
                storeFastScopeVar(identSymbol, flags);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3359
            } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  3360
                method.dynamicSet(identNode.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3361
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3362
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3363
            final Type identType = identNode.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3364
            if(identType == Type.UNDEFINED) {
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3365
                // 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
  3366
                // or the left hand side is a dead variable.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3367
                assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3368
                loadAndDiscard(init);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3369
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3370
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3371
            loadExpressionAsType(init, identType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3372
            storeIdentWithCatchConversion(identNode, identType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3373
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3374
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3375
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3376
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3377
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3378
    private void storeIdentWithCatchConversion(final IdentNode identNode, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3379
        // 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
  3380
        // that will be live at the exit from the try block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3381
        final LocalVariableConversion conversion = identNode.getLocalVariableConversion();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3382
        final Symbol symbol = identNode.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3383
        if(conversion != null && conversion.isLive()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3384
            assert symbol == conversion.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3385
            assert symbol.isBytecodeLocal();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3386
            // 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
  3387
            assert conversion.getNext() == null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3388
            assert conversion.getFrom() == type;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3389
            // We must propagate potential type change to the catch block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3390
            final Label catchLabel = catchLabels.peek();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3391
            assert catchLabel != METHOD_BOUNDARY; // ident conversion only exists in try blocks
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3392
            assert catchLabel.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3393
            final Type joinType = conversion.getTo();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3394
            final Label.Stack catchStack = catchLabel.getStack();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3395
            final int joinSlot = symbol.getSlot(joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3396
            // 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
  3397
            // 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
  3398
            // 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
  3399
            // 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
  3400
            if(catchStack.getUsedSlotsWithLiveTemporaries() > joinSlot) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3401
                method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3402
                method.convert(joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3403
                method.store(symbol, joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3404
                catchLabel.getStack().onLocalStore(joinType, joinSlot, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3405
                method.canThrow(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3406
                // Store but keep the previous store live too.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3407
                method.store(symbol, type, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3408
                return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3409
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3410
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3411
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3412
        method.store(symbol, type, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3413
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3414
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3415
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3416
    public boolean enterWhileNode(final WhileNode whileNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3417
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3418
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3419
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3420
        if(whileNode.isDoWhile()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3421
            enterDoWhile(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3422
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3423
            enterStatement(whileNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3424
            enterForOrWhile(whileNode, null);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3425
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3426
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3427
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3428
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3429
    private void enterForOrWhile(final LoopNode loopNode, final JoinPredecessorExpression modify) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3430
        // 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
  3431
        // 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
  3432
        // 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
  3433
        // 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
  3434
        // 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
  3435
        // to double: var i = {valueOf: function() { return 1} }; while(--i >= 0) { ... }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3436
        // 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
  3437
        // different code shape.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3438
        final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3439
        final JoinPredecessorExpression test = loopNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3440
        if(Expression.isAlwaysFalse(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3441
            loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3442
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3443
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3444
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3445
        method.beforeJoinPoint(loopNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3446
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3447
        final Label continueLabel = loopNode.getContinueLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3448
        final Label repeatLabel = modify != null ? new Label("for_repeat") : continueLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3449
        method.label(repeatLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3450
        final int liveLocalsOnContinue = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3451
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3452
        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
  3453
        final Label   breakLabel            = loopNode.getBreakLabel();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3454
        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
  3455
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3456
        if(Expression.isAlwaysTrue(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3457
            if(test != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3458
                loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3459
                if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3460
                    method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3461
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3462
            }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3463
        } 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
  3464
            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
  3465
                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
  3466
                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
  3467
                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
  3468
            } else {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3469
                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
  3470
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3471
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3472
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3473
        body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3474
        if(repeatLabel != continueLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3475
            emitContinueLabel(continueLabel, liveLocalsOnContinue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3476
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3477
27977
42799be30dcd 8067219: NPE in ScriptObject.clone() when running with object fields
hannesw
parents: 27976
diff changeset
  3478
        if (loopNode.hasPerIterationScope() && lc.getCurrentBlock().needsScope()) {
27817
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3479
            // 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
  3480
            method.loadCompilerConstant(SCOPE);
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3481
            method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3482
            method.storeCompilerConstant(SCOPE);
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3483
        }
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3484
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3485
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3486
            if(modify != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3487
                lineNumber(loopNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3488
                loadAndDiscard(modify);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3489
                method.beforeJoinPoint(modify);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3490
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3491
            method._goto(repeatLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3492
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3493
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3494
        method.breakLabel(breakLabel, liveLocalsOnBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3495
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3496
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3497
    private void emitContinueLabel(final Label continueLabel, final int liveLocals) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3498
        final boolean reachable = method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3499
        method.breakLabel(continueLabel, liveLocals);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3500
        // 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
  3501
        // 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
  3502
        // must make sure those are thrown away.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3503
        if(!reachable) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3504
            method.undefineLocalVariables(lc.getUsedSlotCount(), false);
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3505
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3506
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3507
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3508
    private void enterDoWhile(final WhileNode whileNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3509
        final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3510
        method.beforeJoinPoint(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3511
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3512
        final Block body = whileNode.getBody();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3513
        body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3514
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3515
        emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3516
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3517
            lineNumber(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3518
            final JoinPredecessorExpression test = whileNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3519
            final Label bodyEntryLabel = body.getEntryLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3520
            final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3521
            if(Expression.isAlwaysFalse(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3522
                loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3523
                if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3524
                    method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3525
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3526
            } else if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3527
                // 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
  3528
                final Label beforeExit = new Label("do_while_preexit");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3529
                emitBranch(test.getExpression(), beforeExit, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3530
                method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3531
                method._goto(bodyEntryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3532
                method.label(beforeExit);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3533
                method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3534
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3535
                emitBranch(test.getExpression(), bodyEntryLabel, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3536
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3537
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3538
        method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3539
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3540
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3541
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3542
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3543
    public boolean enterWithNode(final WithNode withNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3544
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3545
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3546
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3547
        enterStatement(withNode);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3548
        final Expression expression = withNode.getExpression();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3549
        final Block      body       = withNode.getBody();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3550
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3551
        // 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
  3552
        // 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
  3553
        // 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
  3554
        // 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
  3555
        final boolean hasScope = method.hasScope();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3556
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
  3557
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3558
            method.loadCompilerConstant(SCOPE);
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3559
        }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3560
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3561
        loadExpressionAsObject(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3562
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3563
        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
  3564
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3565
            // Construct a WithObject if we have a scope
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3566
            method.invoke(ScriptRuntime.OPEN_WITH);
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3567
            method.storeCompilerConstant(SCOPE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3568
            tryLabel = new Label("with_try");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3569
            method.label(tryLabel);
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3570
        } else {
20215
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3571
            // 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
  3572
            // for null or undefined value.
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3573
            globalCheckObjectCoercible();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3574
            tryLabel = null;
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3575
        }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3576
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3577
        // Always process body
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3578
        body.accept(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3579
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
  3580
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3581
            // Ensure we always close the WithObject
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3582
            final Label endLabel   = new Label("with_end");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3583
            final Label catchLabel = new Label("with_catch");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3584
            final Label exitLabel  = new Label("with_exit");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3585
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3586
            method.label(endLabel);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3587
            // 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
  3588
            // 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
  3589
            final boolean bodyCanThrow = endLabel.isAfter(tryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3590
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3591
                method._try(tryLabel, endLabel, catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3592
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3593
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3594
            final boolean reachable = method.isReachable();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3595
            if(reachable) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3596
                popScope();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3597
                if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3598
                    method._goto(exitLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3599
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3600
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3601
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3602
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3603
                method._catch(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3604
                popScopeException();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3605
                method.athrow();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3606
                if(reachable) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3607
                    method.label(exitLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3608
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3609
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3610
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3611
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3612
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3613
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3614
    private void loadADD(final UnaryNode unaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3615
        loadExpression(unaryNode.getExpression(), resultBounds.booleanToInt().notWiderThan(Type.NUMBER));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3616
        if(method.peekType() == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3617
            // 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
  3618
            method.convert(Type.INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3619
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3620
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3621
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3622
    private void loadBIT_NOT(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3623
        loadExpression(unaryNode.getExpression(), TypeBounds.INT).load(-1).xor();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3624
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3625
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3626
    private void loadDECINC(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3627
        final Expression operand     = unaryNode.getExpression();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3628
        final Type       type        = unaryNode.getType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3629
        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
  3630
        final TokenType  tokenType   = unaryNode.tokenType();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3631
        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
  3632
        final boolean    isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3633
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3634
        assert !type.isObject();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3635
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3636
        new SelfModifyingStore<UnaryNode>(unaryNode, operand) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3637
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3638
            private void loadRhs() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3639
                loadExpression(operand, typeBounds, true);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3640
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3641
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3642
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3643
            protected void evaluate() {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3644
                if(isPostfix) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3645
                    loadRhs();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3646
                } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3647
                    new OptimisticOperation(unaryNode, typeBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3648
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3649
                        void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3650
                            loadRhs();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3651
                            loadMinusOne();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3652
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3653
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3654
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3655
                            doDecInc(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3656
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3657
                    }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(operand));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3658
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3659
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3660
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3661
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3662
            protected void storeNonDiscard() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3663
                super.storeNonDiscard();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3664
                if (isPostfix) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3665
                    new OptimisticOperation(unaryNode, typeBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3666
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3667
                        void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3668
                            loadMinusOne();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3669
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3670
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3671
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3672
                            doDecInc(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3673
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3674
                    }.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
  3675
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3676
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3677
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3678
            private void loadMinusOne() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3679
                if (type.isInteger()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3680
                    method.load(isIncrement ? 1 : -1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3681
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3682
                    method.load(isIncrement ? 1.0 : -1.0);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3683
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3684
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3685
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3686
            private void doDecInc(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3687
                method.add(programPoint);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3688
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3689
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3690
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3691
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3692
    private static int getOptimisticIgnoreCountForSelfModifyingExpression(final Expression target) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3693
        return target instanceof AccessNode ? 1 : target instanceof IndexNode ? 2 : 0;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3694
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3695
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3696
    private void loadAndDiscard(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3697
        // 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
  3698
        // be able to eliminate even more checks.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3699
        if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3700
            assert !lc.isCurrentDiscard(expr);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3701
            // 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
  3702
            // undefined.
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
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3705
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3706
        lc.pushDiscard(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3707
        loadExpression(expr, TypeBounds.UNBOUNDED);
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3708
        if (lc.popDiscardIfCurrent(expr)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3709
            assert !expr.isAssignment();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3710
            // 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
  3711
            method.pop();
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3712
        }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3713
    }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3714
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3715
    /**
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3716
     * Loads the expression with the specified type bounds, but if the parent expression is the current discard,
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3717
     * then instead loads and discards the expression.
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3718
     * @param parent the parent expression that's tested for being the current discard
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3719
     * @param expr the expression that's either normally loaded or discard-loaded
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3720
     * @param resultBounds result bounds for when loading the expression normally
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3721
     */
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3722
    private void loadMaybeDiscard(final Expression parent, final Expression expr, final TypeBounds resultBounds) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3723
        loadMaybeDiscard(lc.popDiscardIfCurrent(parent), expr, resultBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3724
    }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3725
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3726
    /**
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3727
     * Loads the expression with the specified type bounds, or loads and discards the expression, depending on the
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3728
     * value of the discard flag. Useful as a helper for expressions with control flow where you often can't combine
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3729
     * testing for being the current discard and loading the subexpressions.
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3730
     * @param discard if true, the expression is loaded and discarded
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3731
     * @param expr the expression that's either normally loaded or discard-loaded
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3732
     * @param resultBounds result bounds for when loading the expression normally
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3733
     */
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3734
    private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3735
        if (discard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3736
            loadAndDiscard(expr);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3737
        } else {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3738
            loadExpression(expr, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3739
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3740
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3741
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3742
    private void loadNEW(final UnaryNode unaryNode) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3743
        final CallNode callNode = (CallNode)unaryNode.getExpression();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3744
        final List<Expression> args   = callNode.getArgs();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3745
32048
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  3746
        final Expression func = callNode.getFunction();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3747
        // Load function reference.
32048
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  3748
        loadExpressionAsObject(func); // must detect type error
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  3749
32049
af8f6292d54d 8133119: Error message associated with TypeError for call and new should include stringified Node
sundar
parents: 32048
diff changeset
  3750
        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3751
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3752
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3753
    private void loadNOT(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3754
        final Expression expr = unaryNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3755
        if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3756
            // !!x is idiomatic boolean cast in JavaScript
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3757
            loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3758
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3759
            final Label trueLabel  = new Label("true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3760
            final Label afterLabel = new Label("after");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3761
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3762
            emitBranch(expr, trueLabel, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3763
            method.load(true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3764
            method._goto(afterLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3765
            method.label(trueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3766
            method.load(false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3767
            method.label(afterLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3768
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3769
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3770
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3771
    private void loadSUB(final UnaryNode unaryNode, final TypeBounds resultBounds) {
24774
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3772
        final Type type = unaryNode.getType();
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3773
        assert type.isNumeric();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3774
        final TypeBounds numericBounds = resultBounds.booleanToInt();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3775
        new OptimisticOperation(unaryNode, numericBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3776
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3777
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3778
                final Expression expr = unaryNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3779
                loadExpression(expr, numericBounds.notWiderThan(Type.NUMBER));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3780
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3781
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3782
            void consumeStack() {
24774
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3783
                // 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
  3784
                // 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
  3785
                // 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
  3786
                if(type.isNumber()) {
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3787
                    method.convert(type);
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3788
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3789
                method.neg(getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3790
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3791
        }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3792
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3793
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3794
    public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3795
        loadAndDiscard(unaryNode.getExpression());
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3796
        if (!lc.popDiscardIfCurrent(unaryNode)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3797
            method.loadUndefined(resultBounds.widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3798
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3799
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3800
48354
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3801
    public void loadDELETE(final UnaryNode unaryNode) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3802
        final Expression expression = unaryNode.getExpression();
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3803
        if (expression instanceof IdentNode) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3804
            final IdentNode ident = (IdentNode)expression;
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3805
            final Symbol symbol = ident.getSymbol();
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3806
            final String name = ident.getName();
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3807
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3808
            if (symbol.isThis()) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3809
                // Can't delete "this", ignore and return true
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3810
                if (!lc.popDiscardIfCurrent(unaryNode)) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3811
                    method.load(true);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3812
                }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3813
            } else if (lc.getCurrentFunction().isStrict()) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3814
                // All other scope identifier delete attempts fail for strict mode
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3815
                method.load(name);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3816
                method.invoke(ScriptRuntime.STRICT_FAIL_DELETE);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3817
            } else if (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel()))) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3818
                // If symbol is a function parameter, or a declared non-global variable, delete is a no-op and returns false.
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3819
                if (!lc.popDiscardIfCurrent(unaryNode)) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3820
                    method.load(false);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3821
                }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3822
            } else {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3823
                method.loadCompilerConstant(SCOPE);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3824
                method.load(name);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3825
                if ((symbol.isGlobal() && !symbol.isFunctionDeclaration()) || symbol.isProgramLevel()) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3826
                    method.invoke(ScriptRuntime.SLOW_DELETE);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3827
                } else {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3828
                    method.load(false); // never strict here; that was handled with STRICT_FAIL_DELETE above.
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3829
                    method.invoke(ScriptObject.DELETE);
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3830
                }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3831
            }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3832
        } else if (expression instanceof BaseNode) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3833
            loadExpressionAsObject(((BaseNode)expression).getBase());
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3834
            if (expression instanceof AccessNode) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3835
                final AccessNode accessNode = (AccessNode) expression;
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3836
                method.dynamicRemove(accessNode.getProperty(), getCallSiteFlags(), accessNode.isIndex());
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3837
            } else if (expression instanceof IndexNode) {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3838
                loadExpressionAsObject(((IndexNode) expression).getIndex());
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3839
                method.dynamicRemoveIndex(getCallSiteFlags());
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3840
            } else {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3841
                throw new AssertionError(expression.getClass().getName());
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3842
            }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3843
        } else {
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3844
            throw new AssertionError(expression.getClass().getName());
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3845
        }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3846
    }
c96d4c720995 8193371: Use Dynalink REMOVE operation in Nashorn
attila
parents: 48247
diff changeset
  3847
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3848
    public void loadADD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3849
        new OptimisticOperation(binaryNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3850
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3851
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3852
                final TypeBounds operandBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3853
                final boolean isOptimistic = isValid(getProgramPoint());
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3854
                boolean forceConversionSeparation = false;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3855
                if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3856
                    operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3857
                } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3858
                    // Non-optimistic, non-FP +. Allow it to overflow.
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3859
                    final Type widestOperationType = binaryNode.getWidestOperationType();
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3860
                    operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3861
                    forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3862
                }
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3863
                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3864
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3865
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3866
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3867
            void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3868
                method.add(getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3869
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3870
        }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3871
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3872
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3873
    private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3874
        final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3875
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3876
        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(binaryNode);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3877
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3878
        final Label skip = new Label("skip");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3879
        if(narrowestOperandType == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3880
            // optimize all-boolean logical expressions
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3881
            final Label onTrue = new Label("andor_true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3882
            emitBranch(binaryNode, onTrue, true);
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3883
            if (isCurrentDiscard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3884
                method.label(onTrue);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3885
            } else {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3886
                method.load(false);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3887
                method._goto(skip);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3888
                method.label(onTrue);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3889
                method.load(true);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3890
                method.label(skip);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3891
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3892
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3893
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3894
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3895
        final TypeBounds outBounds = resultBounds.notNarrowerThan(narrowestOperandType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3896
        final JoinPredecessorExpression lhs = (JoinPredecessorExpression)binaryNode.lhs();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3897
        final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3898
        final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3899
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3900
        loadExpression(lhs, outBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3901
        if (!isCurrentDiscard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3902
            method.dup();
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3903
        }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3904
        method.convert(Type.BOOLEAN);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3905
        if (isAnd) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3906
            if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3907
                method.ifne(evalRhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3908
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3909
                method.ifeq(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3910
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3911
        } else if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3912
            method.ifeq(evalRhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3913
        } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3914
            method.ifne(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3915
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3916
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3917
        if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3918
            method.beforeJoinPoint(lhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3919
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3920
            method.label(evalRhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3921
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3922
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3923
        if (!isCurrentDiscard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3924
            method.pop();
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3925
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3926
        final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3927
        loadMaybeDiscard(isCurrentDiscard, rhs, outBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3928
        method.beforeJoinPoint(rhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3929
        method.label(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3930
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3931
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3932
    private static boolean isLocalVariable(final Expression lhs) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3933
        return lhs instanceof IdentNode && isLocalVariable((IdentNode)lhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3934
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3935
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3936
    private static boolean isLocalVariable(final IdentNode lhs) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3937
        return lhs.getSymbol().isBytecodeLocal();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3938
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3939
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3940
    // 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
  3941
    private void loadASSIGN(final BinaryNode binaryNode) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3942
        final Expression lhs = binaryNode.lhs();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3943
        final Expression rhs = binaryNode.rhs();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3944
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3945
        final Type rhsType = rhs.getType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3946
        // Detect dead assignments
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3947
        if(lhs instanceof IdentNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3948
            final Symbol symbol = ((IdentNode)lhs).getSymbol();
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3949
            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.popDiscardIfCurrent(binaryNode)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3950
                loadAndDiscard(rhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3951
                method.markDeadLocalVariable(symbol);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3952
                return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3953
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3954
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3955
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3956
        new Store<BinaryNode>(binaryNode, lhs) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3957
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3958
            protected void evaluate() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3959
                // 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
  3960
                // remain optimistic, and then explicitly convert to the required type if needed.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3961
                loadExpressionAsType(rhs, rhsType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3962
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3963
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3964
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3965
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3966
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3967
     * Binary self-assignment that can be optimistic: +=, -=, *=, and /=.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3968
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3969
    private abstract class BinaryOptimisticSelfAssignment extends SelfModifyingStore<BinaryNode> {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3970
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3971
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3972
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3973
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3974
         * @param node the assign op node
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3975
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3976
        BinaryOptimisticSelfAssignment(final BinaryNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3977
            super(node, node.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3978
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3979
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3980
        protected abstract void op(OptimisticOperation oo);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3981
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3982
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3983
        protected void evaluate() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3984
            final Expression lhs = assignNode.lhs();
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3985
            final Expression rhs = assignNode.rhs();
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3986
            final Type widestOperationType = assignNode.getWidestOperationType();
27969
c03b64ccbd0f 8066227: CodeGenerator load unitialized slot
attila
parents: 27968
diff changeset
  3987
            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widestOperationType);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3988
            new OptimisticOperation(assignNode, bounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3989
                @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3990
                void loadStack() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3991
                    final boolean forceConversionSeparation;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3992
                    if (isValid(getProgramPoint()) || widestOperationType == Type.NUMBER) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3993
                        forceConversionSeparation = false;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3994
                    } else {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3995
                        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
  3996
                        forceConversionSeparation = operandType.narrowerThan(widestOperationType);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3997
                    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3998
                    loadBinaryOperands(lhs, rhs, bounds, true, forceConversionSeparation);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3999
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4000
                @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4001
                void consumeStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4002
                    op(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4003
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4004
            }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(lhs));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4005
            method.convert(assignNode.getType());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4006
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4007
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4008
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4009
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4010
     * Non-optimistic binary self-assignment operation. Basically, everything except +=, -=, *=, and /=.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4011
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4012
    private abstract class BinarySelfAssignment extends SelfModifyingStore<BinaryNode> {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4013
        BinarySelfAssignment(final BinaryNode node) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4014
            super(node, node.lhs());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4015
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4016
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4017
        protected abstract void op();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4018
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4019
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4020
        protected void evaluate() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  4021
            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4022
            op();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4023
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4024
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4025
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4026
    private void loadASSIGN_ADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4027
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4028
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4029
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4030
                assert !(binaryNode.getType().isObject() && oo.isOptimistic);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4031
                method.add(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4032
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4033
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4034
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4035
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4036
    private void loadASSIGN_BIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4037
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4038
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4039
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4040
                method.and();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4041
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4042
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4043
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4044
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4045
    private void loadASSIGN_BIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4046
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4047
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4048
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4049
                method.or();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4050
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4051
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4052
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4053
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4054
    private void loadASSIGN_BIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4055
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4056
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4057
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4058
                method.xor();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4059
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4060
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4061
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4062
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4063
    private void loadASSIGN_DIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4064
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4065
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4066
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4067
                method.div(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4068
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4069
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4070
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4071
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4072
    private void loadASSIGN_MOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4073
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4074
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4075
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4076
                method.rem(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4077
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4078
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4079
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4080
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4081
    private void loadASSIGN_MUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4082
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4083
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4084
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4085
                method.mul(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4086
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4087
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4088
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4089
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4090
    private void loadASSIGN_SAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4091
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4092
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4093
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4094
                method.sar();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4095
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4096
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4097
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4098
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4099
    private void loadASSIGN_SHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4100
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4101
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4102
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4103
                method.shl();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4104
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4105
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4106
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4107
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4108
    private void loadASSIGN_SHR(final BinaryNode binaryNode) {
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4109
        new SelfModifyingStore<BinaryNode>(binaryNode, binaryNode.lhs()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4110
            @Override
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4111
            protected void evaluate() {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4112
                new OptimisticOperation(assignNode, new TypeBounds(Type.INT, Type.NUMBER)) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4113
                    @Override
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4114
                    void loadStack() {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4115
                        assert assignNode.getWidestOperandType() == Type.INT;
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4116
                        if (isRhsZero(binaryNode)) {
42383
7c6ddb187262 8170594: >>>=0 generates invalid bytecode for BaseNode LHS
attila
parents: 41983
diff changeset
  4117
                            loadExpression(binaryNode.lhs(), TypeBounds.INT, true);
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4118
                        } else {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4119
                            loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false);
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4120
                            method.shr();
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4121
                        }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4122
                    }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4123
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4124
                    @Override
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4125
                    void consumeStack() {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4126
                        if (isOptimistic(binaryNode)) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4127
                            toUint32Optimistic(binaryNode.getProgramPoint());
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4128
                        } else {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4129
                            toUint32Double();
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4130
                        }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4131
                    }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4132
                }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(binaryNode.lhs()));
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4133
                method.convert(assignNode.getType());
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4134
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4135
        }.store();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4136
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4137
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4138
    private void doSHR(final BinaryNode binaryNode) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4139
        new OptimisticOperation(binaryNode, new TypeBounds(Type.INT, Type.NUMBER)) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4140
            @Override
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4141
            void loadStack() {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4142
                if (isRhsZero(binaryNode)) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4143
                    loadExpressionAsType(binaryNode.lhs(), Type.INT);
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4144
                } else {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4145
                    loadBinaryOperands(binaryNode);
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4146
                    method.shr();
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4147
                }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4148
            }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4149
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4150
            @Override
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4151
            void consumeStack() {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4152
                if (isOptimistic(binaryNode)) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4153
                    toUint32Optimistic(binaryNode.getProgramPoint());
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4154
                } else {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4155
                    toUint32Double();
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4156
                }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4157
            }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4158
        }.emit();
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4159
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4160
    }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4161
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4162
    private void toUint32Optimistic(final int programPoint) {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4163
        method.load(programPoint);
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4164
        JSType.TO_UINT32_OPTIMISTIC.invoke(method);
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4165
    }
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4166
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4167
    private void toUint32Double() {
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4168
        JSType.TO_UINT32_DOUBLE.invoke(method);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4169
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4170
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4171
    private void loadASSIGN_SUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4172
        new BinaryOptimisticSelfAssignment(binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4173
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4174
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4175
                method.sub(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4176
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4177
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4178
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4179
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4180
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4181
     * Helper class for binary arithmetic ops
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4182
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4183
    private abstract class BinaryArith {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4184
        protected abstract void op(int programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4185
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4186
        protected void evaluate(final BinaryNode node, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4187
            final TypeBounds numericBounds = resultBounds.booleanToInt().objectToNumber();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4188
            new OptimisticOperation(node, numericBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4189
                @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4190
                void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4191
                    final TypeBounds operandBounds;
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  4192
                    boolean forceConversionSeparation = false;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4193
                    if(numericBounds.narrowest == Type.NUMBER) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4194
                        // 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
  4195
                        // and L2D after operand evaluation.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4196
                        assert numericBounds.widest == Type.NUMBER;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4197
                        operandBounds = numericBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4198
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4199
                        final boolean isOptimistic = isValid(getProgramPoint());
27358
8898e06e68c1 8061957: Some arithmetic operations have unnecessary widening
attila
parents: 27212
diff changeset
  4200
                        if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4201
                            operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4202
                        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4203
                            // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4204
                            operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4205
                                    numericBounds.widest), Type.NUMBER);
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4206
                            forceConversionSeparation = true;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4207
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4208
                    }
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  4209
                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4210
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4211
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4212
                @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4213
                void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4214
                    op(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4215
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4216
            }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4217
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4218
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4219
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4220
    private void loadBIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4221
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4222
        method.and();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4223
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4224
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4225
    private void loadBIT_OR(final BinaryNode binaryNode) {
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4226
        // Optimize x|0 to (int)x
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4227
        if (isRhsZero(binaryNode)) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4228
            loadExpressionAsType(binaryNode.lhs(), Type.INT);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4229
        } else {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4230
            loadBinaryOperands(binaryNode);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4231
            method.or();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4232
        }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4233
    }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4234
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4235
    private static boolean isRhsZero(final BinaryNode binaryNode) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4236
        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
  4237
        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4238
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4239
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4240
    private void loadBIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4241
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4242
        method.xor();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4243
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4244
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4245
    private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4246
        loadAndDiscard(binaryNode.lhs());
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4247
        loadMaybeDiscard(binaryNode, binaryNode.rhs(), resultBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4248
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4249
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4250
    private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4251
        loadMaybeDiscard(binaryNode, binaryNode.lhs(), resultBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4252
        loadAndDiscard(binaryNode.rhs());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4253
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4254
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4255
    private void loadDIV(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4256
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4257
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4258
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4259
                method.div(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4260
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4261
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4262
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4263
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4264
    private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  4265
        loadComparisonOperands(binaryNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4266
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4267
        final Label trueLabel  = new Label("trueLabel");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4268
        final Label afterLabel = new Label("skip");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4269
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4270
        method.conditionalJump(cond, trueLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4271
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4272
        method.load(Boolean.FALSE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4273
        method._goto(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4274
        method.label(trueLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4275
        method.load(Boolean.TRUE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4276
        method.label(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4277
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4278
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4279
    private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4280
        new BinaryArith() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4281
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4282
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4283
                method.rem(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4284
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4285
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4286
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4287
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4288
    private void loadMUL(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4289
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4290
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4291
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4292
                method.mul(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4293
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4294
        }.evaluate(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4295
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4296
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4297
    private void loadSAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4298
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4299
        method.sar();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4300
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4301
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4302
    private void loadSHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4303
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4304
        method.shl();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4305
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4306
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4307
    private void loadSHR(final BinaryNode binaryNode) {
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4308
        doSHR(binaryNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4309
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4310
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4311
    private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4312
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4313
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4314
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4315
                method.sub(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4316
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4317
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4318
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4319
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4320
    @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
  4321
    public boolean enterLabelNode(final LabelNode labelNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4322
        labeledBlockBreakLiveLocals.push(lc.getUsedSlotCount());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4323
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4324
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4325
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4326
    @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
  4327
    protected boolean enterDefault(final Node node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4328
        throw new AssertionError("Code generator entered node of type " + node.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4329
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4330
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4331
    private void loadTernaryNode(final TernaryNode ternaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4332
        final Expression test = ternaryNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4333
        final JoinPredecessorExpression trueExpr  = ternaryNode.getTrueExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4334
        final JoinPredecessorExpression falseExpr = ternaryNode.getFalseExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4335
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4336
        final Label falseLabel = new Label("ternary_false");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4337
        final Label exitLabel  = new Label("ternary_exit");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4338
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4339
        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
  4340
        final TypeBounds outBounds = resultBounds.notNarrowerThan(outNarrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4341
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4342
        emitBranch(test, falseLabel, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4343
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4344
        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(ternaryNode);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4345
        loadMaybeDiscard(isCurrentDiscard, trueExpr.getExpression(), outBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4346
        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4347
        method.beforeJoinPoint(trueExpr);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4348
        method._goto(exitLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4349
        method.label(falseLabel);
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4350
        loadMaybeDiscard(isCurrentDiscard, falseExpr.getExpression(), outBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4351
        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4352
        method.beforeJoinPoint(falseExpr);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4353
        method.label(exitLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4354
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4355
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4356
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4357
     * Generate all shared scope calls generated during codegen.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4358
     */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4359
    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
  4360
        for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4361
            scopeAccess.generateScopeCall();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4362
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4363
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4364
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4365
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4366
     * Debug code used to print symbols
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4367
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4368
     * @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
  4369
     * @param function the function we are in
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4370
     * @param ident identifier for block or function where applicable
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4371
     */
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4372
    private void printSymbols(final Block block, final FunctionNode function, final String ident) {
37732
3673fec68d16 8134503: support ES6 parsing in Nashorn
hannesw
parents: 36696
diff changeset
  4373
        if (compiler.getScriptEnvironment()._print_symbols || function.getDebugFlag(FunctionNode.DEBUG_PRINT_SYMBOLS)) {
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4374
            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
  4375
            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
  4376
            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
  4377
                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
  4378
            }
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4379
            out.println();
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4380
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4381
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4382
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4383
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4384
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4385
     * The difference between a store and a self modifying store is that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4386
     * the latter may load part of the target on the stack, e.g. the base
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4387
     * of an AccessNode or the base and index of an IndexNode. These are used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4388
     * both as target and as an extra source. Previously it was problematic
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4389
     * for self modifying stores if the target/lhs didn't belong to one
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4390
     * of three trivial categories: IdentNode, AcessNodes, IndexNodes. In that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4391
     * case it was evaluated and tagged as "resolved", which meant at the second
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4392
     * 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
  4393
     * it would be evaluated to a nop in the scope and cause stack underflow
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4394
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4395
     * see NASHORN-703
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4396
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4397
     * @param <T>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4398
     */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4399
    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
  4400
        protected SelfModifyingStore(final T assignNode, final Expression target) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4401
            super(assignNode, target);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4402
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4403
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4404
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4405
        protected boolean isSelfModifying() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4406
            return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4407
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4408
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4409
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4410
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4411
     * Helper class to generate stores
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4412
     */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4413
    private abstract class Store<T extends Expression> {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4414
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4415
        /** An assignment node, e.g. x += y */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4416
        protected final T assignNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4417
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4418
        /** 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
  4419
        private final Expression target;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4420
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4421
        /** How deep on the stack do the arguments go if this generates an indy call */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4422
        private int depth;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4423
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4424
        /** 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
  4425
        private IdentNode quick;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4426
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4427
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4428
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4429
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4430
         * @param assignNode the node representing the whole assignment
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4431
         * @param target     the target node of the assignment (destination)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4432
         */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4433
        protected Store(final T assignNode, final Expression target) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4434
            this.assignNode = assignNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4435
            this.target = target;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4436
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4437
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4438
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4439
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4440
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4441
         * @param assignNode the node representing the whole assignment
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4442
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4443
        protected Store(final T assignNode) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4444
            this(assignNode, assignNode);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4445
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4446
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4447
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4448
         * Is this a self modifying store operation, e.g. *= or ++
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4449
         * @return true if self modifying store
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4450
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4451
        protected boolean isSelfModifying() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4452
            return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4453
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4454
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4455
        private void prologue() {
32534
b3ec7f3b3c2a 8136349: Typos patch for nashorn sources submitted on Sep 10, 2015
sundar
parents: 32527
diff changeset
  4456
            /*
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4457
             * This loads the parts of the target, e.g base and index. they are kept
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4458
             * on the stack throughout the store and used at the end to execute it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4459
             */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4460
32888
24f99be3d5ab 8134502: introduce abstraction for basic NodeVisitor usage
attila
parents: 32784
diff changeset
  4461
            target.accept(new SimpleNodeVisitor() {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4462
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4463
                public boolean enterIdentNode(final IdentNode node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4464
                    if (node.getSymbol().isScope()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4465
                        method.loadCompilerConstant(SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4466
                        depth += Type.SCOPE.getSlots();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4467
                        assert depth == 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4468
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4469
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4470
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4471
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4472
                private void enterBaseNode() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4473
                    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
  4474
                    final BaseNode   baseNode = (BaseNode)target;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4475
                    final Expression base     = baseNode.getBase();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4476
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4477
                    loadExpressionAsObject(base);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4478
                    depth += Type.OBJECT.getSlots();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4479
                    assert depth == 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4480
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4481
                    if (isSelfModifying()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4482
                        method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4483
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4484
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4485
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4486
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4487
                public boolean enterAccessNode(final AccessNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4488
                    enterBaseNode();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4489
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4490
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4491
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4492
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4493
                public boolean enterIndexNode(final IndexNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4494
                    enterBaseNode();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4495
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4496
                    final Expression index = node.getIndex();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4497
                    if (!index.getType().isNumeric()) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  4498
                        // could be boolean here as well
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4499
                        loadExpressionAsObject(index);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  4500
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4501
                        loadExpressionUnbounded(index);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4502
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4503
                    depth += index.getType().getSlots();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4504
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4505
                    if (isSelfModifying()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4506
                        //convert "base base index" to "base index base index"
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4507
                        method.dup(1);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4508
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4509
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4510
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4511
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4512
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4513
            });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4514
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4515
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4516
        /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4517
         * 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
  4518
         * frame.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4519
         *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4520
         * @param type the type of the variable
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4521
         *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4522
         * @return the quick variable
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4523
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4524
        private IdentNode quickLocalVariable(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4525
            final String name = lc.getCurrentFunction().uniqueName(QUICK_PREFIX.symbolName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4526
            final Symbol symbol = new Symbol(name, IS_INTERNAL | HAS_SLOT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4527
            symbol.setHasSlotFor(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4528
            symbol.setFirstSlot(lc.quickSlot(type));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4529
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4530
            final IdentNode quickIdent = IdentNode.createInternalIdentifier(symbol).setType(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4531
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4532
            return quickIdent;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4533
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4534
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4535
        // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4536
        protected void storeNonDiscard() {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4537
            if (lc.popDiscardIfCurrent(assignNode)) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4538
                assert assignNode.isAssignment();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4539
                return;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4540
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4541
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4542
            if (method.dup(depth) == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4543
                method.dup();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4544
                final Type quickType = method.peekType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4545
                this.quick = quickLocalVariable(quickType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4546
                final Symbol quickSymbol = quick.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4547
                method.storeTemp(quickType, quickSymbol.getFirstSlot());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4548
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4549
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4550
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4551
        private void epilogue() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4552
            /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4553
             * Take the original target args from the stack and use them
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4554
             * 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
  4555
             *
889ddb179cdf 8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents: 16190
diff changeset
  4556
             * 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
  4557
             * 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
  4558
             * very rare. See for example test/script/basic/access-specializer.js
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4559
             */
32888
24f99be3d5ab 8134502: introduce abstraction for basic NodeVisitor usage
attila
parents: 32784
diff changeset
  4560
            target.accept(new SimpleNodeVisitor() {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4561
                @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
  4562
                protected boolean enterDefault(final Node node) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4563
                    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
  4564
                }
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4565
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4566
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4567
                public boolean enterIdentNode(final IdentNode node) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4568
                    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
  4569
                    assert symbol != null;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4570
                    if (symbol.isScope()) {
36690
06b714373aa4 8151810: for-in iteration does not provide per-iteration scope
hannesw
parents: 35407
diff changeset
  4571
                        final int flags = getScopeCallSiteFlags(symbol) | (node.isDeclaredHere() ? CALLSITE_DECLARE : 0);
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  4572
                        if (isFastScope(symbol)) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4573
                            storeFastScopeVar(symbol, flags);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4574
                        } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4575
                            method.dynamicSet(node.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4576
                        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4577
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4578
                        final Type storeType = assignNode.getType();
34732
6605efbe8447 8144020: Remove long as an internal numeric type
hannesw
parents: 33890
diff changeset
  4579
                        assert storeType != Type.LONG;
26241
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4580
                        if (symbol.hasSlotFor(storeType)) {
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4581
                            // 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
  4582
                            // give us an unnecessary ClassCastException.
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4583
                            method.convert(storeType);
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4584
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4585
                        storeIdentWithCatchConversion(node, storeType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4586
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4587
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4588
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4589
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4590
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4591
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4592
                public boolean enterAccessNode(final AccessNode node) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4593
                    method.dynamicSet(node.getProperty(), getCallSiteFlags(), node.isIndex());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4594
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4595
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4596
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4597
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4598
                public boolean enterIndexNode(final IndexNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4599
                    method.dynamicSetIndex(getCallSiteFlags());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4600
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4601
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4602
            });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4603
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4604
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4605
            // whatever is on the stack now is the final answer
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4606
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4607
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4608
        protected abstract void evaluate();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4609
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4610
        void store() {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4611
            if (target instanceof IdentNode) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4612
                checkTemporalDeadZone((IdentNode)target);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4613
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4614
            prologue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4615
            evaluate(); // leaves an operation of whatever the operationType was on the stack
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4616
            storeNonDiscard();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4617
            epilogue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4618
            if (quick != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4619
                method.load(quick);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4620
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4621
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4622
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4623
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4624
    private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4625
        assert lc.peek() == functionNode;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4626
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  4627
        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
  4628
24784
ed11bdcc878a 8044816: On-demand compiled top-level program doesn't need :createProgramFunction
attila
parents: 24781
diff changeset
  4629
        if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4630
            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
  4631
                    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
  4632
                    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
  4633
            createFunction.begin();
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4634
            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
  4635
            createFunction.load(SCOPE_TYPE, 0);
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4636
            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
  4637
            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
  4638
            createFunction.end();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4639
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4640
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  4641
        if (addInitializer && !compiler.isOnDemandCompilation()) {
30056
06d201382b55 8053905: Eager code generation fails for earley boyer with split threshold set to 1000
hannesw
parents: 29941
diff changeset
  4642
            functionNode.getCompileUnit().addFunctionInitializer(data, functionNode);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4643
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4644
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4645
        // 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
  4646
        // generated in its outer context that'd need it as a callee).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4647
        if (lc.getOutermostFunction() == functionNode) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4648
            return;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4649
        }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4650
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4651
        loadConstantsAndIndex(data, method);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4652
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4653
        if (functionNode.needsParentScope()) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  4654
            method.loadCompilerConstant(SCOPE);
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4655
            method.invoke(CREATE_FUNCTION_OBJECT);
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  4656
        } else {
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4657
            method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4658
        }
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  4659
    }
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  4660
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
  4661
    // calls on Global class.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4662
    private MethodEmitter globalInstance() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4663
        return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';');
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4664
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4665
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4666
    private MethodEmitter globalAllocateArguments() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4667
        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
  4668
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4669
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4670
    private MethodEmitter globalNewRegExp() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4671
        return method.invokestatic(GLOBAL_OBJECT, "newRegExp", methodDescriptor(Object.class, String.class, String.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4672
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4673
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4674
    private MethodEmitter globalRegExpCopy() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4675
        return method.invokestatic(GLOBAL_OBJECT, "regExpCopy", methodDescriptor(Object.class, Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4676
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4677
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4678
    private MethodEmitter globalAllocateArray(final ArrayType type) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4679
        //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
  4680
        return method.invokestatic(GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4681
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4682
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4683
    private MethodEmitter globalIsEval() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4684
        return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4685
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4686
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4687
    private MethodEmitter globalReplaceLocationPropertyPlaceholder() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4688
        return method.invokestatic(GLOBAL_OBJECT, "replaceLocationPropertyPlaceholder", methodDescriptor(Object.class, Object.class, Object.class));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4689
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4690
20215
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4691
    private MethodEmitter globalCheckObjectCoercible() {
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4692
        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
  4693
    }
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4694
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4695
    private MethodEmitter globalDirectEval() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4696
        return method.invokestatic(GLOBAL_OBJECT, "directEval",
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  4697
                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4698
    }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4699
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4700
    private abstract class OptimisticOperation {
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  4701
        final boolean isOptimistic;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4702
        // expression and optimistic are the same reference
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4703
        private final Expression expression;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4704
        private final Optimistic optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4705
        private final TypeBounds resultBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4706
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4707
        OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4708
            this.optimistic = optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4709
            this.expression = (Expression)optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4710
            this.resultBounds = resultBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4711
            this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() &&
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4712
                    // 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
  4713
                    // is narrower than the upper bound.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4714
                    resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4715
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4716
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4717
        MethodEmitter emit() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4718
            return emit(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4719
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4720
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4721
        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
  4722
            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
  4723
            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
  4724
            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
  4725
            final int     stackSizeOnEntry              = method.getStackSize() - ignoredArgCount;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4726
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4727
            // First store the values on the stack opportunistically into local variables. Doing it before loadStack()
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4728
            // 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
  4729
            // storeStack().
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4730
            storeStack(ignoredArgCount, optimisticOrContinuation);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4731
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4732
            // Now, load the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4733
            loadStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4734
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4735
            // 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
  4736
            // (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
  4737
            // 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
  4738
            // 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
  4739
            // unfortunate cases this second storeStack() will restore the invariant that everything on the stack is
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4740
            // 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
  4741
            final int liveLocalsCount = storeStack(method.getStackSize() - stackSizeOnEntry, optimisticOrContinuation);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4742
            assert optimisticOrContinuation == (liveLocalsCount != -1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4743
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4744
            final Label beginTry;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4745
            final Label catchLabel;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4746
            final Label afterConsumeStack = isOptimistic || currentContinuationEntryPoint ? new Label("after_consume_stack") : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4747
            if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4748
                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
  4749
                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
  4750
                catchLabel = new Label(catchLabelName);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4751
                method.label(beginTry);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4752
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4753
                beginTry = catchLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4754
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4755
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4756
            consumeStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4757
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4758
            if(isOptimistic) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4759
                method._try(beginTry, afterConsumeStack, catchLabel, UnwarrantedOptimismException.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4760
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4761
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4762
            if(isOptimistic || currentContinuationEntryPoint) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4763
                method.label(afterConsumeStack);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4764
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4765
                final int[] localLoads = method.getLocalLoadsOnStack(0, stackSizeOnEntry);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4766
                assert everyStackValueIsLocalLoad(localLoads) : Arrays.toString(localLoads) + ", " + stackSizeOnEntry + ", " + ignoredArgCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4767
                final List<Type> localTypesList = method.getLocalVariableTypes();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4768
                final int usedLocals = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4769
                final List<Type> localTypes = method.getWidestLiveLocals(localTypesList.subList(0, usedLocals));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4770
                assert everyLocalLoadIsValid(localLoads, usedLocals) : Arrays.toString(localLoads) + " ~ " + localTypes;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4771
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4772
                if(isOptimistic) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4773
                    addUnwarrantedOptimismHandlerLabel(localTypes, catchLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4774
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4775
                if(currentContinuationEntryPoint) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4776
                    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
  4777
                    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
  4778
                    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
  4779
                    ci.setTargetLabel(afterConsumeStack);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4780
                    ci.getHandlerLabel().markAsOptimisticContinuationHandlerFor(afterConsumeStack);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4781
                    // 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
  4782
                    // dead local variables.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4783
                    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
  4784
                    ci.setStackStoreSpec(localLoads);
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4785
                    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
  4786
                    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
  4787
                    ci.setReturnValueType(method.peekType());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4788
                    ci.lineNumber = getLastLineNumber();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4789
                    ci.catchLabel = catchLabels.peek();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4790
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4791
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4792
            return method;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4793
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4794
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4795
        /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4796
         * 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
  4797
         * can result in an {@code UnwarantedOptimizationException}.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4798
         * @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
  4799
         * 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
  4800
         * (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
  4801
         * 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
  4802
         * into fixing it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4803
         * @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
  4804
         * for temporary storage of ignored arguments are not returned).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4805
         * @param optimisticOrContinuation if false, this method should not execute
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4806
         * a label for a catch block for the {@code UnwarantedOptimizationException}, suitable for capturing the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4807
         * currently live local variables, tailored to their types.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4808
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4809
        private int storeStack(final int ignoreArgCount, final boolean optimisticOrContinuation) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4810
            if(!optimisticOrContinuation) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4811
                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
  4812
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4813
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4814
            final int stackSize = method.getStackSize();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4815
            final Type[] stackTypes = method.getTypesFromStack(stackSize);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4816
            final int[] localLoadsOnStack = method.getLocalLoadsOnStack(0, stackSize);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4817
            final int usedSlots = method.getUsedSlotsWithLiveTemporaries();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4818
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4819
            final int firstIgnored = stackSize - ignoreArgCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4820
            // 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
  4821
            int firstNonLoad = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4822
            while(firstNonLoad < firstIgnored && localLoadsOnStack[firstNonLoad] != Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4823
                firstNonLoad++;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4824
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4825
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4826
            // 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
  4827
            // the number of used slots as the number of live local variables.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4828
            if(firstNonLoad >= firstIgnored) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4829
                return usedSlots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4830
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4831
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4832
            // 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
  4833
            // are not direct loads of existing local variables.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4834
            int tempSlotsNeeded = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4835
            for(int i = firstNonLoad; i < stackSize; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4836
                if(localLoadsOnStack[i] == Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4837
                    tempSlotsNeeded += stackTypes[i].getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4838
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4839
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4840
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4841
            // 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
  4842
            // 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
  4843
            // ones end up at the end of the local variable table.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4844
            int lastTempSlot = usedSlots + tempSlotsNeeded;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4845
            int ignoreSlotCount = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4846
            for(int i = stackSize; i -- > firstNonLoad;) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4847
                final int loadSlot = localLoadsOnStack[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4848
                if(loadSlot == Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4849
                    final Type type = stackTypes[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4850
                    final int slots = type.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4851
                    lastTempSlot -= slots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4852
                    if(i >= firstIgnored) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4853
                        ignoreSlotCount += slots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4854
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4855
                    method.storeTemp(type, lastTempSlot);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4856
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4857
                    method.pop();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4858
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4859
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4860
            assert lastTempSlot == usedSlots; // used all temporary locals
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4861
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4862
            final List<Type> localTypesList = method.getLocalVariableTypes();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4863
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4864
            // Load values back on stack.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4865
            for(int i = firstNonLoad; i < stackSize; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4866
                final int loadSlot = localLoadsOnStack[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4867
                final Type stackType = stackTypes[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4868
                final boolean isLoad = loadSlot != Label.Stack.NON_LOAD;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4869
                final int lvarSlot = isLoad ? loadSlot : lastTempSlot;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4870
                final Type lvarType = localTypesList.get(lvarSlot);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4871
                method.load(lvarType, lvarSlot);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4872
                if(isLoad) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4873
                    // 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
  4874
                    // 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
  4875
                    // on-stack conversion operators is necessary to accommodate for differences in local variable types
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4876
                    // after deoptimization; having a conversion operator throw away "load"-ness would create different
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4877
                    // local variable table shapes between optimism-failed code and its deoptimized rest-of method).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4878
                    // 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
  4879
                    // different.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4880
                    // 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
  4881
                    // 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
  4882
                    // in a deoptimized method, as their original input argument got widened. Maybe experiment with
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4883
                    // throwing away "load"-ness for narrowing conversions in MethodEmitter.convert()?
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4884
                    method.convert(stackType);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4885
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4886
                    // 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
  4887
                    assert lvarType == stackType;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4888
                    lastTempSlot += lvarType.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4889
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4890
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4891
            // used all temporaries
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4892
            assert lastTempSlot == usedSlots + tempSlotsNeeded;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4893
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4894
            return lastTempSlot - ignoreSlotCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4895
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4896
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4897
        private void addUnwarrantedOptimismHandlerLabel(final List<Type> localTypes, final Label label) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4898
            final String lvarTypesDescriptor = getLvarTypesDescriptor(localTypes);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4899
            final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.getUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4900
            Collection<Label> labels = unwarrantedOptimismHandlers.get(lvarTypesDescriptor);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4901
            if(labels == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4902
                labels = new LinkedList<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4903
                unwarrantedOptimismHandlers.put(lvarTypesDescriptor, labels);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4904
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4905
            method.markLabelAsOptimisticCatchHandler(label, localTypes.size());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4906
            labels.add(label);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4907
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4908
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4909
        abstract void loadStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4910
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4911
        // 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
  4912
        // 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
  4913
        // to use OptimisticExpression for emitting it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4914
        abstract void consumeStack();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4915
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4916
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4917
         * 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
  4918
         * 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
  4919
         * 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
  4920
         * 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
  4921
         * 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
  4922
         * conversion has no side effects.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4923
         * @param name the name of the property being get
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4924
         * @param flags call site flags
32534
b3ec7f3b3c2a 8136349: Typos patch for nashorn sources submitted on Sep 10, 2015
sundar
parents: 32527
diff changeset
  4925
         * @param isMethod whether we're preferably retrieving a function
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4926
         * @return the current method emitter
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4927
         */
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4928
        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
  4929
            if(isOptimistic) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4930
                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
  4931
            }
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4932
            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod, isIndex);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4933
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4934
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4935
        MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4936
            if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4937
                return method.dynamicGetIndex(getOptimisticCoercedType(), getOptimisticFlags(flags), isMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4938
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4939
            return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4940
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4941
32048
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  4942
        MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4943
            if (isOptimistic) {
32048
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  4944
                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg);
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  4945
            }
8023426b93ab 8073733: TypeError messages with "call" and "new" could be improved
sundar
parents: 31549
diff changeset
  4946
            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4947
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4948
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4949
        int getOptimisticFlags(final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4950
            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
  4951
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4952
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4953
        int getProgramPoint() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4954
            return isOptimistic ? optimistic.getProgramPoint() : INVALID_PROGRAM_POINT;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4955
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4956
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4957
        void convertOptimisticReturnValue() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4958
            if (isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4959
                final Type optimisticType = getOptimisticCoercedType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4960
                if(!optimisticType.isObject()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4961
                    method.load(optimistic.getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4962
                    if(optimisticType.isInteger()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4963
                        method.invoke(ENSURE_INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4964
                    } else if(optimisticType.isNumber()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4965
                        method.invoke(ENSURE_NUMBER);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4966
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4967
                        throw new AssertionError(optimisticType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4968
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4969
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4970
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4971
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4972
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4973
        void replaceCompileTimeProperty() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4974
            final IdentNode identNode = (IdentNode)expression;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4975
            final String name = identNode.getSymbol().getName();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4976
            if (CompilerConstants.__FILE__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4977
                replaceCompileTimeProperty(getCurrentSource().getName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4978
            } else if (CompilerConstants.__DIR__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4979
                replaceCompileTimeProperty(getCurrentSource().getBase());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4980
            } else if (CompilerConstants.__LINE__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4981
                replaceCompileTimeProperty(getCurrentSource().getLine(identNode.position()));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4982
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4983
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4984
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4985
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4986
         * 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
  4987
         * 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
  4988
         * 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
  4989
         * 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
  4990
         * 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
  4991
         * 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
  4992
         * @param propertyValue the actual value of the property
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4993
         */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4994
        private void replaceCompileTimeProperty(final Object propertyValue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4995
            assert method.peekType().isObject();
25826
3d2dd01a3a4a 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval()
sundar
parents: 25821
diff changeset
  4996
            if(propertyValue instanceof String || propertyValue == null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4997
                method.load((String)propertyValue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4998
            } else if(propertyValue instanceof Integer) {
31549
b627094c5649 8130734: Apply transformations found by netbeans Refactor->Inspect and transform menu
sundar
parents: 30697
diff changeset
  4999
                method.load(((Integer)propertyValue));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5000
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5001
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5002
                throw new AssertionError();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5003
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5004
            globalReplaceLocationPropertyPlaceholder();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5005
            convertOptimisticReturnValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5006
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5007
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5008
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5009
         * 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
  5010
         * 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
  5011
         * 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
  5012
         * 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
  5013
         * 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
  5014
         * affect it.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5015
         * @return
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5016
         */
48247
fa5a47cad0c9 8069338: Implement sharedScopeCall for optimistic types
hannesw
parents: 47216
diff changeset
  5017
        Type getOptimisticCoercedType() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5018
            final Type optimisticType = expression.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5019
            assert resultBounds.widest.widerThan(optimisticType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5020
            final Type narrowest = resultBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5021
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5022
            if(narrowest.isBoolean() || narrowest.narrowerThan(optimisticType)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5023
                assert !optimisticType.isObject();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5024
                return optimisticType;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5025
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5026
            assert !narrowest.isObject();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5027
            return narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5028
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5029
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5030
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5031
    private static boolean isOptimistic(final Optimistic optimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5032
        if(!optimistic.canBeOptimistic()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5033
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5034
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5035
        final Expression expr = (Expression)optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5036
        return expr.getType().narrowerThan(expr.getWidestOperationType());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5037
    }
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
    private static boolean everyLocalLoadIsValid(final int[] loads, final int localCount) {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5040
        for (final int load : loads) {
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5041
            if(load < 0 || load >= localCount) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5042
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5043
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5044
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5045
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5046
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5047
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5048
    private static boolean everyStackValueIsLocalLoad(final int[] loads) {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5049
        for (final int load : loads) {
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5050
            if(load == Label.Stack.NON_LOAD) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5051
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5052
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5053
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5054
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5055
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5056
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5057
    private String getLvarTypesDescriptor(final List<Type> localVarTypes) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5058
        final int count = localVarTypes.size();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5059
        final StringBuilder desc = new StringBuilder(count);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5060
        for(int i = 0; i < count;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5061
            i += appendType(desc, localVarTypes.get(i));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5062
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5063
        return method.markSymbolBoundariesInLvarTypesDescriptor(desc.toString());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5064
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5065
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5066
    private static int appendType(final StringBuilder b, final Type t) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5067
        b.append(t.getBytecodeStackType());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5068
        return t.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5069
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5070
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5071
    private static int countSymbolsInLvarTypeDescriptor(final String lvarTypeDescriptor) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5072
        int count = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5073
        for(int i = 0; i < lvarTypeDescriptor.length(); ++i) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5074
            if(Character.isUpperCase(lvarTypeDescriptor.charAt(i))) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5075
                ++count;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5076
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5077
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5078
        return count;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5079
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5080
    }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5081
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5082
     * Generates all the required {@code UnwarrantedOptimismException} handlers for the current function. The employed
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5083
     * 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
  5084
     * 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
  5085
     * 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
  5086
     * 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
  5087
     * 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
  5088
     * entry to its immediately preceding one for longest matching prefix.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5089
     * @return true if there is at least one exception handler
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5090
     */
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5091
    private boolean generateUnwarrantedOptimismExceptionHandlers(final FunctionNode fn) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5092
        if(!useOptimisticTypes()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5093
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5094
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5095
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5096
        // 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
  5097
        // handler specifications.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5098
        final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.popUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5099
        if(unwarrantedOptimismHandlers.isEmpty()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5100
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5101
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5102
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5103
        method.lineNumber(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5104
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5105
        final List<OptimismExceptionHandlerSpec> handlerSpecs = new ArrayList<>(unwarrantedOptimismHandlers.size() * 4/3);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5106
        for(final String spec: unwarrantedOptimismHandlers.keySet()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5107
            handlerSpecs.add(new OptimismExceptionHandlerSpec(spec, true));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5108
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5109
        Collections.sort(handlerSpecs, Collections.reverseOrder());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5110
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5111
        // 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
  5112
        final Map<String, Label> delegationLabels = new HashMap<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5113
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5114
        // 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
  5115
        // 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
  5116
        for(int handlerIndex = 0; handlerIndex < handlerSpecs.size(); ++handlerIndex) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5117
            final OptimismExceptionHandlerSpec spec = handlerSpecs.get(handlerIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5118
            final String lvarSpec = spec.lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5119
            if(spec.catchTarget) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5120
                assert !method.isReachable();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5121
                // Start a catch block and assign the labels for this lvarSpec with it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5122
                method._catch(unwarrantedOptimismHandlers.get(lvarSpec));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5123
                // 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
  5124
                // symbols - the number of uppercase characters.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5125
                method.load(countSymbolsInLvarTypeDescriptor(lvarSpec));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5126
                method.newarray(Type.OBJECT_ARRAY);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5127
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5128
            if(spec.delegationTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5129
                // 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
  5130
                // shared code (after the array creation code, which is never shared).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5131
                method.label(delegationLabels.get(lvarSpec)); // label must exist
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5132
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5133
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5134
            final boolean lastHandler = handlerIndex == handlerSpecs.size() - 1;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5135
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5136
            int lvarIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5137
            final int firstArrayIndex;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5138
            final int firstLvarIndex;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5139
            Label delegationLabel;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5140
            final String commonLvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5141
            if(lastHandler) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5142
                // Last handler block, doesn't delegate to anything.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5143
                lvarIndex = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5144
                firstLvarIndex = 0;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5145
                firstArrayIndex = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5146
                delegationLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5147
                commonLvarSpec = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5148
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5149
                // 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
  5150
                // 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
  5151
                // prefix handler.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5152
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5153
                // 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
  5154
                // this handler and the next handler on the list.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5155
                final int nextHandlerIndex = handlerIndex + 1;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5156
                final String nextLvarSpec = handlerSpecs.get(nextHandlerIndex).lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5157
                commonLvarSpec = commonPrefix(lvarSpec, nextLvarSpec);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5158
                // We don't chop symbols in half
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5159
                assert Character.isUpperCase(commonLvarSpec.charAt(commonLvarSpec.length() - 1));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5160
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5161
                // 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
  5162
                {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5163
                    boolean addNewHandler = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5164
                    int commonHandlerIndex = nextHandlerIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5165
                    for(; commonHandlerIndex < handlerSpecs.size(); ++commonHandlerIndex) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5166
                        final OptimismExceptionHandlerSpec forwardHandlerSpec = handlerSpecs.get(commonHandlerIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5167
                        final String forwardLvarSpec = forwardHandlerSpec.lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5168
                        if(forwardLvarSpec.equals(commonLvarSpec)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5169
                            // We already have a handler for the common prefix.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5170
                            addNewHandler = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5171
                            // Make sure we mark it as a delegation target.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5172
                            forwardHandlerSpec.delegationTarget = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5173
                            break;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5174
                        } else if(!forwardLvarSpec.startsWith(commonLvarSpec)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5175
                            break;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5176
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5177
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5178
                    if(addNewHandler) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5179
                        // We need to insert a common prefix handler. Note handlers created with catchTarget == false
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5180
                        // will automatically have delegationTarget == true (because that's the only reason for their
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5181
                        // existence).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5182
                        handlerSpecs.add(commonHandlerIndex, new OptimismExceptionHandlerSpec(commonLvarSpec, false));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5183
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5184
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5185
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5186
                firstArrayIndex = countSymbolsInLvarTypeDescriptor(commonLvarSpec);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5187
                lvarIndex = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5188
                for(int j = 0; j < commonLvarSpec.length(); ++j) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5189
                    lvarIndex += CodeGeneratorLexicalContext.getTypeForSlotDescriptor(commonLvarSpec.charAt(j)).getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5190
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5191
                firstLvarIndex = lvarIndex;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5192
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5193
                // Create a delegation label if not already present
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5194
                delegationLabel = delegationLabels.get(commonLvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5195
                if(delegationLabel == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5196
                    // uo_pa == "unwarranted optimism, populate array"
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5197
                    delegationLabel = new Label("uo_pa_" + commonLvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5198
                    delegationLabels.put(commonLvarSpec, delegationLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5199
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5200
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5201
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5202
            // Load local variables handled by this handler on stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5203
            int args = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5204
            boolean symbolHadValue = false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5205
            for(int typeIndex = commonLvarSpec == null ? 0 : commonLvarSpec.length(); typeIndex < lvarSpec.length(); ++typeIndex) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5206
                final char typeDesc = lvarSpec.charAt(typeIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5207
                final Type lvarType = CodeGeneratorLexicalContext.getTypeForSlotDescriptor(typeDesc);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5208
                if (!lvarType.isUnknown()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5209
                    method.load(lvarType, lvarIndex);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5210
                    symbolHadValue = true;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5211
                    args++;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5212
                } else if(typeDesc == 'U' && !symbolHadValue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5213
                    // 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
  5214
                    // 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
  5215
                    // 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
  5216
                    // 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
  5217
                    // 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
  5218
                    // 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
  5219
                    // 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
  5220
                    // 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
  5221
                    // 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
  5222
                    // 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
  5223
                    // 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
  5224
                    if(method.peekType() == Type.UNDEFINED) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5225
                        method.dup();
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.loadUndefined(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5228
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5229
                    args++;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5230
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5231
                if(Character.isUpperCase(typeDesc)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5232
                    // Reached symbol boundary; reset flag for the next symbol.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5233
                    symbolHadValue = false;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5234
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5235
                lvarIndex += lvarType.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5236
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5237
            assert args > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5238
            // Delegate actual storing into array to an array populator utility method.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5239
            //on the stack:
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5240
            // object array to be populated
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5241
            // start index
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5242
            // a lot of types
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5243
            method.dynamicArrayPopulatorCall(args + 1, firstArrayIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5244
            if(delegationLabel != null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5245
                // 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
  5246
                // RewriteException.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5247
                assert !lastHandler;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5248
                assert commonLvarSpec != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5249
                // 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
  5250
                // delegate label
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5251
                method.undefineLocalVariables(firstLvarIndex, true);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5252
                final OptimismExceptionHandlerSpec nextSpec = handlerSpecs.get(handlerIndex + 1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5253
                // 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
  5254
                // 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
  5255
                if(!nextSpec.lvarSpec.equals(commonLvarSpec) || nextSpec.catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5256
                    method._goto(delegationLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5257
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5258
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5259
                assert lastHandler;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5260
                // Nothing to delegate to, so this handler must create and throw the RewriteException.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5261
                // At this point we have the UnwarrantedOptimismException and the Object[] with local variables on
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5262
                // stack. We need to create a RewriteException, push two references to it below the constructor
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5263
                // arguments, invoke the constructor, and throw the exception.
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5264
                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
  5265
                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
  5266
                    loadConstant(getContinuationEntryPoints());
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
  5267
                    method.invoke(CREATE_REWRITE_EXCEPTION_REST_OF);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5268
                } else {
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
  5269
                    method.invoke(CREATE_REWRITE_EXCEPTION);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5270
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5271
                method.athrow();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5272
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5273
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5274
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5275
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5276
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5277
    private static String[] getByteCodeSymbolNames(final FunctionNode fn) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5278
        // 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
  5279
        // 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
  5280
        // 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
  5281
        // here.
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5282
        final List<String> names = new ArrayList<>();
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5283
        for (final Symbol symbol: fn.getBody().getSymbols()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5284
            if (symbol.hasSlot()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5285
                if (symbol.isScope()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5286
                    // slot + scope can only be true for parameters
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5287
                    assert symbol.isParam();
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5288
                    names.add(null);
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5289
                } else {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5290
                    names.add(symbol.getName());
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5291
                }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5292
            }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5293
        }
35407
204abe4d8cbc 8147591: Revisit Collection.toArray(new T[size]) calls in nashorn and dynalink code
mhaupt
parents: 34732
diff changeset
  5294
        return names.toArray(new String[0]);
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5295
    }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5296
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
  5297
    private static String commonPrefix(final String s1, final String s2) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5298
        final int l1 = s1.length();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5299
        final int l = Math.min(l1, s2.length());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5300
        int lms = -1; // last matching symbol
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5301
        for(int i = 0; i < l; ++i) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5302
            final char c1 = s1.charAt(i);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5303
            if(c1 != s2.charAt(i)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5304
                return s1.substring(0, lms + 1);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5305
            } else if(Character.isUpperCase(c1)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5306
                lms = i;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5307
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5308
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5309
        return l == l1 ? s1 : s2;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5310
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5311
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5312
    private static class OptimismExceptionHandlerSpec implements Comparable<OptimismExceptionHandlerSpec> {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5313
        private final String lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5314
        private final boolean catchTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5315
        private boolean delegationTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5316
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
  5317
        OptimismExceptionHandlerSpec(final String lvarSpec, final boolean catchTarget) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5318
            this.lvarSpec = lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5319
            this.catchTarget = catchTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5320
            if(!catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5321
                delegationTarget = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5322
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5323
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5324
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5325
        @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
  5326
        public int compareTo(final OptimismExceptionHandlerSpec o) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5327
            return lvarSpec.compareTo(o.lvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5328
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5329
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5330
        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5331
        public String toString() {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5332
            final StringBuilder b = new StringBuilder(64).append("[HandlerSpec ").append(lvarSpec);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5333
            if(catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5334
                b.append(", catchTarget");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5335
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5336
            if(delegationTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5337
                b.append(", delegationTarget");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5338
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5339
            return b.append("]").toString();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5340
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5341
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5342
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5343
    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
  5344
        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
  5345
        private Label targetLabel; // Label for the target instruction.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5346
        int lvarCount;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5347
        // 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
  5348
        private int[] stackStoreSpec;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5349
        // 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
  5350
        private Type[] stackTypes;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5351
        // 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
  5352
        private Type returnValueType;
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5353
        // If we are in the middle of an object literal initialization, we need to update the property maps
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5354
        private Map<Integer, PropertyMap> objectLiteralMaps;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5355
        // The line number at the continuation point
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5356
        private int lineNumber;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5357
        // 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
  5358
        private Label catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5359
        // 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
  5360
        private int exceptionScopePops;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5361
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5362
        ContinuationInfo() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5363
            this.handlerLabel = new Label("continuation_handler");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5364
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5365
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5366
        Label getHandlerLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5367
            return handlerLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5368
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5369
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5370
        boolean hasTargetLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5371
            return targetLabel != null;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5372
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5373
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5374
        Label getTargetLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5375
            return targetLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5376
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5377
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5378
        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
  5379
            this.targetLabel = targetLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5380
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5381
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5382
        int[] getStackStoreSpec() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5383
            return stackStoreSpec.clone();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5384
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5385
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5386
        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
  5387
            this.stackStoreSpec = stackStoreSpec;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5388
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5389
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5390
        Type[] getStackTypes() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5391
            return stackTypes.clone();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5392
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5393
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5394
        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
  5395
            this.stackTypes = stackTypes;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5396
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5397
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5398
        Type getReturnValueType() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5399
            return returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5400
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5401
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5402
        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
  5403
            this.returnValueType = returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5404
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5405
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5406
        void setObjectLiteralMap(final int objectLiteralStackDepth, final PropertyMap objectLiteralMap) {
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5407
            if (objectLiteralMaps == null) {
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5408
                objectLiteralMaps = new HashMap<>();
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5409
            }
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5410
            objectLiteralMaps.put(objectLiteralStackDepth, objectLiteralMap);
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5411
        }
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5412
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5413
        PropertyMap getObjectLiteralMap(final int stackDepth) {
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5414
            return objectLiteralMaps == null ? null : objectLiteralMaps.get(stackDepth);
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5415
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5416
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5417
        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5418
        public String toString() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5419
             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
  5420
                     Arrays.toString(stackStoreSpec) + ", returnValueType=" + returnValueType + "]";
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5421
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5422
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5423
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5424
    private ContinuationInfo getContinuationInfo() {
32316
5d7dd8dc7729 8133785: SharedScopeCall should be enabled for non-optimistic call sites in optimistic compilation
attila
parents: 32049
diff changeset
  5425
        return continuationInfo;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5426
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5427
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5428
    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
  5429
        if (!isRestOf()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5430
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5431
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5432
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5433
        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
  5434
        method.label(ci.getHandlerLabel());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5435
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5436
        // 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
  5437
        // 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
  5438
        method.lineNumber(0);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5439
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5440
        final Label.Stack stack = ci.getTargetLabel().getStack();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5441
        final List<Type> lvarTypes = stack.getLocalVariableTypesCopy();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5442
        final BitSet symbolBoundary = stack.getSymbolBoundaryCopy();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5443
        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
  5444
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
  5445
        final Type rewriteExceptionType = Type.typeFor(RewriteException.class);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5446
        // 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
  5447
        method.load(rewriteExceptionType, 0);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5448
        method.storeTemp(rewriteExceptionType, lvarCount);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5449
        // Get local variable array
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5450
        method.load(rewriteExceptionType, 0);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5451
        method.invoke(RewriteException.GET_BYTECODE_SLOTS);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5452
        // 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
  5453
        // 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
  5454
        // 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
  5455
        // 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
  5456
        // was undefined, there will be an explicit Undefined value in the array.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5457
        int arrayIndex = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5458
        for(int lvarIndex = 0; lvarIndex < lvarCount;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5459
            final Type lvarType = lvarTypes.get(lvarIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5460
            if(!lvarType.isUnknown()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5461
                method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5462
                method.load(arrayIndex).arrayload();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5463
                final Class<?> typeClass = lvarType.getTypeClass();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5464
                // Deoptimization in array initializers can cause arrays to undergo component type widening
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5465
                if(typeClass == long[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5466
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5467
                    method.invoke(RewriteException.TO_LONG_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5468
                } else if(typeClass == double[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5469
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5470
                    method.invoke(RewriteException.TO_DOUBLE_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5471
                } else if(typeClass == Object[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5472
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5473
                    method.invoke(RewriteException.TO_OBJECT_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5474
                } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5475
                    if(!(typeClass.isPrimitive() || typeClass == Object.class)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5476
                        // 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
  5477
                        // 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
  5478
                        // 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
  5479
                        // "{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
  5480
                        // Undefined, however NativeArray can't hold Undefined instance.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5481
                        method.loadType(Type.getInternalName(typeClass));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5482
                        method.invoke(RewriteException.INSTANCE_OR_NULL);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5483
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5484
                    method.convert(lvarType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5485
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5486
                method.storeHidden(lvarType, lvarIndex, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5487
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5488
            final int nextLvarIndex = lvarIndex + lvarType.getSlots();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5489
            if(symbolBoundary.get(nextLvarIndex - 1)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5490
                ++arrayIndex;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5491
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5492
            lvarIndex = nextLvarIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5493
        }
26250
84bbd0e8b2b2 8056025: CompilationPhase.setStates() is hot in class installation phase
attila
parents: 26241
diff changeset
  5494
        if (AssertsEnabled.assertsEnabled()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5495
            method.load(arrayIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5496
            method.invoke(RewriteException.ASSERT_ARRAY_LENGTH);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5497
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5498
            method.pop();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5499
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5500
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5501
        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
  5502
        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
  5503
        final boolean isStackEmpty   = stackStoreSpec.length == 0;
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5504
        int replacedObjectLiteralMaps = 0;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5505
        if(!isStackEmpty) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5506
            // Load arguments on the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5507
            for(int i = 0; i < stackStoreSpec.length; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5508
                final int slot = stackStoreSpec[i];
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5509
                method.load(lvarTypes.get(slot), slot);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5510
                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
  5511
                // stack: s0=object literal being initialized
32534
b3ec7f3b3c2a 8136349: Typos patch for nashorn sources submitted on Sep 10, 2015
sundar
parents: 32527
diff changeset
  5512
                // change map of s0 so that the property we are initializing when we failed
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5513
                // is now ci.returnValueType
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5514
                final PropertyMap map = ci.getObjectLiteralMap(i);
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5515
                if (map != null) {
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5516
                    method.dup();
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5517
                    assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object";
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5518
                    loadConstant(map);
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5519
                    method.invoke(ScriptObject.SET_MAP);
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5520
                    replacedObjectLiteralMaps++;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5521
                }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5522
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5523
        }
41238
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5524
        // Must have emitted the code for replacing all object literal maps
a3c1a712c67e 8166902: Nested object literal property maps not reset in optimistic recompilation
hannesw
parents: 41145
diff changeset
  5525
        assert ci.objectLiteralMaps == null || ci.objectLiteralMaps.size() == replacedObjectLiteralMaps;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5526
        // Load RewriteException back.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5527
        method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5528
        // Get rid of the stored reference
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5529
        method.loadNull();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5530
        method.storeHidden(Type.OBJECT, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5531
        // Mark it dead
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5532
        method.markDeadSlots(lvarCount, Type.OBJECT.getSlots());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5533
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5534
        // Load return value on the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5535
        method.invoke(RewriteException.GET_RETURN_VALUE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5536
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5537
        final Type returnValueType = ci.getReturnValueType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5538
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5539
        // 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
  5540
        boolean needsCatch = false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5541
        final Label targetCatchLabel = ci.catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5542
        Label _try = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5543
        if(returnValueType.isPrimitive()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5544
            // 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
  5545
            method.lineNumber(ci.lineNumber);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5546
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5547
            if(targetCatchLabel != METHOD_BOUNDARY) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5548
                _try = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5549
                method.label(_try);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5550
                needsCatch = true;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5551
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5552
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5553
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5554
        // Convert return value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5555
        method.convert(returnValueType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5556
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5557
        final int scopePopCount = needsCatch ? ci.exceptionScopePops : 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5558
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5559
        // 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
  5560
        // 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
  5561
        final Label catchLabel = scopePopCount > 0 ? new Label("") : targetCatchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5562
        if(needsCatch) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5563
            final Label _end_try = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5564
            method.label(_end_try);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5565
            method._try(_try, _end_try, catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5566
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5567
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5568
        // 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
  5569
        method._goto(ci.getTargetLabel());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5570
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5571
        // Make a scope-popping exception delegate if needed
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5572
        if(catchLabel != targetCatchLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5573
            method.lineNumber(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5574
            assert scopePopCount > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5575
            method._catch(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5576
            popScopes(scopePopCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5577
            method.uncheckedGoto(targetCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5578
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5579
    }
32781
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5580
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5581
    /**
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5582
     * Interface implemented by object creators that support splitting over multiple methods.
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5583
     */
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5584
    interface SplitLiteralCreator {
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5585
        /**
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5586
         * Generate code to populate a range of the literal object. A reference to the object
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5587
         * should be left on the stack when the method terminates.
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5588
         *
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5589
         * @param method the method emitter
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5590
         * @param type the type of the literal object
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5591
         * @param slot the local slot containing the literal object
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5592
         * @param start the start index (inclusive)
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5593
         * @param end the end index (exclusive)
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5594
         */
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5595
        void populateRange(MethodEmitter method, Type type, int slot, int start, int end);
d8f34ffbbc7a 8135190: Method code too large in Babel browser.js script
hannesw
parents: 32692
diff changeset
  5596
    }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  5597
}