nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/CodeGenerator.java
author attila
Fri, 15 May 2015 10:19:37 +0200
changeset 30697 85feee7acc91
parent 30391 62dcad329b26
child 31549 b627094c5649
permissions -rw-r--r--
8079424: code generator for discarded boolean logical operation has an extra pop Reviewed-by: lagergren, sundar
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     1
/*
16151
97c1e756ae1e 8005663: Update copyright year to 2013
jlaskey
parents: 16147
diff changeset
     2
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     4
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Oracle designates this
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
     9
 * by Oracle in the LICENSE file that accompanied this code.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    10
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    15
 * accompanied this code).
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    16
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    20
 *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    21
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    22
 * or visit www.oracle.com if you need additional information or have any
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    23
 * questions.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    24
 */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    25
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    26
package jdk.nashorn.internal.codegen;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    27
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    28
import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.PRIVATE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    29
import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    30
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    31
import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
    32
import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    33
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    34
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    35
import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    36
import static jdk.nashorn.internal.codegen.CompilerConstants.REGEX_PREFIX;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    37
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    38
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    39
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
    40
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    41
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    42
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    43
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    44
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
    45
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
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;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
    96
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
    97
import jdk.nashorn.internal.ir.GetSplitState;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    98
import jdk.nashorn.internal.ir.IdentNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
    99
import jdk.nashorn.internal.ir.IfNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   100
import jdk.nashorn.internal.ir.IndexNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   101
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
   102
import jdk.nashorn.internal.ir.JumpStatement;
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
   103
import jdk.nashorn.internal.ir.JumpToInlinedFinally;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   104
import jdk.nashorn.internal.ir.LabelNode;
17968
108ba976aa02 8015684: FieldObjectCreator.putField ignores getValueType
attila
parents: 17778
diff changeset
   105
import jdk.nashorn.internal.ir.LexicalContext;
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   106
import jdk.nashorn.internal.ir.LexicalContextNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   107
import jdk.nashorn.internal.ir.LiteralNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   108
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   109
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   110
import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   111
import jdk.nashorn.internal.ir.LocalVariableConversion;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   112
import jdk.nashorn.internal.ir.LoopNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   113
import jdk.nashorn.internal.ir.Node;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   114
import jdk.nashorn.internal.ir.ObjectNode;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   115
import jdk.nashorn.internal.ir.Optimistic;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   116
import jdk.nashorn.internal.ir.PropertyNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   117
import jdk.nashorn.internal.ir.ReturnNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   118
import jdk.nashorn.internal.ir.RuntimeNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   119
import jdk.nashorn.internal.ir.RuntimeNode.Request;
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   120
import jdk.nashorn.internal.ir.SetSplitState;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   121
import jdk.nashorn.internal.ir.SplitReturn;
17524
703643aeb0d6 8013914: Removed explicit LineNumberNodes that were too brittle when code moves around, and also introduced unnecessary footprint. Introduced the Statement node and fixed dead code elimination issues that were discovered by the absense of labels for LineNumberNodes.
lagergren
parents: 17523
diff changeset
   122
import jdk.nashorn.internal.ir.Statement;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   123
import jdk.nashorn.internal.ir.SwitchNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   124
import jdk.nashorn.internal.ir.Symbol;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   125
import jdk.nashorn.internal.ir.TernaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   126
import jdk.nashorn.internal.ir.ThrowNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   127
import jdk.nashorn.internal.ir.TryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   128
import jdk.nashorn.internal.ir.UnaryNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   129
import jdk.nashorn.internal.ir.VarNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   130
import jdk.nashorn.internal.ir.WhileNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   131
import jdk.nashorn.internal.ir.WithNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   132
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   133
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   134
import jdk.nashorn.internal.objects.Global;
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   135
import jdk.nashorn.internal.objects.ScriptFunctionImpl;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   136
import jdk.nashorn.internal.parser.Lexer.RegexToken;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   137
import jdk.nashorn.internal.parser.TokenType;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   138
import jdk.nashorn.internal.runtime.Context;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   139
import jdk.nashorn.internal.runtime.Debug;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   140
import jdk.nashorn.internal.runtime.ECMAException;
17241
c337fefb8c84 8012334: ToUint32, ToInt32, and ToUint16 don't conform to spec
hannesw
parents: 17239
diff changeset
   141
import jdk.nashorn.internal.runtime.JSType;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   142
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   143
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
   144
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   145
import jdk.nashorn.internal.runtime.RewriteException;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   146
import jdk.nashorn.internal.runtime.Scope;
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
   147
import jdk.nashorn.internal.runtime.ScriptEnvironment;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   148
import jdk.nashorn.internal.runtime.ScriptFunction;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   149
import jdk.nashorn.internal.runtime.ScriptObject;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   150
import jdk.nashorn.internal.runtime.ScriptRuntime;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   151
import jdk.nashorn.internal.runtime.Source;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   152
import jdk.nashorn.internal.runtime.Undefined;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   153
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
   154
import jdk.nashorn.internal.runtime.arrays.ArrayData;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   155
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   156
import jdk.nashorn.internal.runtime.logging.DebugLogger;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   157
import jdk.nashorn.internal.runtime.logging.Loggable;
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   158
import jdk.nashorn.internal.runtime.logging.Logger;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   159
import jdk.nashorn.internal.runtime.options.Options;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   160
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   161
/**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   162
 * This is the lowest tier of the code generator. It takes lowered ASTs emitted
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   163
 * from Lower and emits Java byte code. The byte code emission logic is broken
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   164
 * out into MethodEmitter. MethodEmitter works internally with a type stack, and
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   165
 * 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
   166
 * number of special cases on the form
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   167
 * <pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   168
 * if (type == INT) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   169
 *     visitInsn(ILOAD, slot);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   170
 * } else if (type == DOUBLE) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   171
 *     visitInsn(DOUBLE, slot);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   172
 * }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   173
 * </pre>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   174
 * This quickly became apparent when the code generator was generalized to work
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   175
 * with all types, and not just numbers or objects.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   176
 * <p>
30391
62dcad329b26 8079349: Eliminate dead code around Nashorn code generator
attila
parents: 30390
diff changeset
   177
 * The CodeGenerator visits nodes only once and emits bytecode for them.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   178
 */
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   179
@Logger(name="codegen")
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   180
final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   181
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   182
    private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   183
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
   184
    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
   185
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   186
    private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   187
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
   188
    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
   189
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   190
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   191
    private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   192
            "ensureInt", int.class, Object.class, int.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   193
    private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   194
            "ensureLong", long.class, Object.class, int.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   195
    private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   196
            "ensureNumber", double.class, Object.class, int.class);
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   197
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   198
    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   199
            "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   200
    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunctionImpl.class,
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   201
            "create", ScriptFunction.class, Object[].class, int.class);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
   202
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   203
    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
   204
            "toNumberForEq", double.class, Object.class);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   205
    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
   206
            "toNumberForStrictEq", double.class, Object.class);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   207
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   208
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   209
    private static final Class<?> ITERATOR_CLASS = Iterator.class;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   210
    static {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   211
        assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   212
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   213
    private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   214
    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
   215
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
   216
    private static final Integer INT_ZERO = Integer.valueOf(0);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
   217
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
   218
    /** 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
   219
     *  by reflection in class installation */
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   220
    private final Compiler compiler;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   221
25240
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   222
    /** 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
   223
    private final boolean evalCode;
f92c14b1ca11 8047959: bindings created for declarations in eval code are not mutable
sundar
parents: 25236
diff changeset
   224
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   225
    /** 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
   226
    private final int callSiteFlags;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   227
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   228
    /** How many regexp fields have been emitted */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   229
    private int regexFieldCount;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   230
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
   231
    /** 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
   232
     *  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
   233
    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
   234
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
   235
    /** 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
   236
    private static final int MAX_REGEX_FIELDS = 2 * 1024;
17233
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 method emitter */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   239
    private MethodEmitter method;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   240
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   241
    /** Current compile unit */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   242
    private CompileUnit unit;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   243
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
   244
    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
   245
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
   246
    /** From what size should we use spill instead of fields for JavaScript objects? */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   247
    private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
   248
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
   249
    private final Set<String> emittedMethods = new HashSet<>();
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
   250
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   251
    // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   252
    private final Map<Integer, ContinuationInfo> fnIdToContinuationInfo = new HashMap<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   253
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   254
    private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   255
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   256
    private static final Label METHOD_BOUNDARY = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   257
    private final Deque<Label> catchLabels = new ArrayDeque<>();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   258
    // 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
   259
    private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   260
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   261
    //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
   262
    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
   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);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   350
        if (isFastScope(symbol)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   351
            // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   352
            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   353
                method.loadCompilerConstant(SCOPE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   354
                // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   355
                // just a single definitive type, resultBounds.widest.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   356
                loadSharedScopeVar(resultBounds.widest, symbol, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   357
            } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   358
                new LoadFastScopeVar(identNode, resultBounds, flags).emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   359
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   360
        } else {
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   361
            //slow scope load, we have no proto depth
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   362
            new LoadScopeVar(identNode, resultBounds, flags).emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   363
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   364
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   365
        return method;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   366
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   367
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   368
    // 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
   369
    // 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
   370
    private void checkTemporalDeadZone(final IdentNode identNode) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   371
        if (identNode.isDead()) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   372
            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
   373
        }
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   374
    }
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   375
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   376
    // Runtime check for assignment to ES6 const
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   377
    private void checkAssignTarget(final Expression expression) {
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   378
        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
   379
            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
   380
        }
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   381
    }
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
   382
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   383
    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
   384
        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
   385
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   386
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   387
    private boolean isOptimisticOrRestOf() {
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   388
        return useOptimisticTypes() || isRestOf();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   389
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   390
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   391
    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
   392
        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
   393
    }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   394
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   395
    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
   396
        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
   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
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   399
    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
   400
        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
   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
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   403
    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
   404
        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
   405
            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
   406
            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
   407
                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
   408
                    return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   409
                }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   410
            }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   411
        }
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
   412
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   413
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   414
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   415
    /**
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   416
     * 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
   417
     *
18618
136279c4cbe6 8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents: 17981
diff changeset
   418
     * @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
   419
     * @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
   420
     */
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   421
    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
   422
        if (!symbol.isScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   423
            return false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   424
        }
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
   425
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
   426
        if (!lc.inDynamicScope()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   427
            // 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
   428
            // 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
   429
            assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   430
            return true;
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 (symbol.isGlobal()) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   434
            // 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
   435
            return false;
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   436
        }
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
   437
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   438
        // 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
   439
        final String name = symbol.getName();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   440
        boolean previousWasBlock = false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   441
        for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   442
            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
   443
            if (node instanceof Block) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   444
                // 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
   445
                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
   446
                if (block.getExistingSymbol(name) == symbol) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   447
                    assert block.needsScope();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   448
                    return true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   449
                }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   450
                previousWasBlock = true;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   451
            } 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
   452
                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
   453
                    // 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
   454
                    // 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
   455
                    // 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
   456
                    // obviously not subjected to introducing new symbols.
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   457
                    return false;
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   458
                }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   459
                previousWasBlock = false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   460
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   461
        }
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   462
        // Should've found the symbol defined in a block
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
   463
        throw new AssertionError();
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   464
    }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   465
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   466
    private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   467
        assert !isOptimisticOrRestOf();
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   468
        if (isFastScope(symbol)) {
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   469
            method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   470
        } 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
   471
            method.load(-1);
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
   472
        }
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   473
        return lc.getScopeGet(unit, symbol, valueType, flags).generateInvoke(method);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   474
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   475
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   476
    private class LoadScopeVar extends OptimisticOperation {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   477
        final IdentNode identNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   478
        private final int flags;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   479
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   480
        LoadScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   481
            super(identNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   482
            this.identNode = identNode;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   483
            this.flags = flags;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   484
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   485
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   486
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   487
        void loadStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   488
            method.loadCompilerConstant(SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   489
            getProto();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   490
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   491
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   492
        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
   493
            //empty
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   494
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   495
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   496
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   497
        void consumeStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   498
            // 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
   499
            // it anyway for replaceLocationPropertyPlaceholder.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   500
            if(identNode.isCompileTimePropertyName()) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   501
                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   502
                replaceCompileTimeProperty();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   503
            } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   504
                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   505
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   506
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   507
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   508
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   509
    private class LoadFastScopeVar extends LoadScopeVar {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   510
        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
   511
            super(identNode, resultBounds, flags);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   512
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   513
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   514
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   515
        void getProto() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   516
            loadFastScopeProto(identNode.getSymbol(), false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   517
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   518
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   519
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   520
    private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   521
        loadFastScopeProto(symbol, true);
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
   522
        method.dynamicSet(symbol.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   523
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   524
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   525
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   526
    private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   527
        //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
   528
        //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
   529
        final FunctionNode fn   = lc.getCurrentFunction();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
   530
        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
   531
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
        //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
   533
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
        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
   535
        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
   536
        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
   537
        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
   538
            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
   539
        } 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
   540
            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
   541
            depth = internalDepth;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   542
        }
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
   543
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
   544
        return depth;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   545
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   546
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   547
    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
   548
        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
   549
        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
   550
        if (depth > 0) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   551
            if (swap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   552
                method.swap();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   553
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   554
            for (int i = 0; i < depth; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   555
                method.invoke(ScriptObject.GET_PROTO);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   556
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   557
            if (swap) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   558
                method.swap();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   559
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   560
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   561
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   562
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   563
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   564
     * Generate code that loads this node to the stack, not constraining its type
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   565
     *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   566
     * @param expr node to load
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   567
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   568
     * @return the method emitter used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   569
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   570
    private MethodEmitter loadExpressionUnbounded(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   571
        return loadExpression(expr, TypeBounds.UNBOUNDED);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   572
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   573
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   574
    private MethodEmitter loadExpressionAsObject(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   575
        return loadExpression(expr, TypeBounds.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   576
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   577
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   578
    MethodEmitter loadExpressionAsBoolean(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   579
        return loadExpression(expr, TypeBounds.BOOLEAN);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   580
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   581
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   582
    // 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
   583
    // with possible side effects from calling an object's toString or valueOf methods.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   584
    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
   585
        // Object to boolean conversion does not cause ToPrimitive call
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   586
        return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean();
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   587
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   588
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   589
    MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   590
        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   591
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   592
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   593
    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
   594
        // 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
   595
        // 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
   596
        // 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
   597
        // 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
   598
        // 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
   599
        // 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
   600
        // 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
   601
        // 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
   602
        // 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
   603
        // separate operations to preserve specification semantics.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   604
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   605
        // 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
   606
        // 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
   607
        final Type lhsType = undefinedToNumber(lhs.getType());
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   608
        final Type rhsType = undefinedToNumber(rhs.getType());
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   609
        final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   610
        final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   611
        if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   612
            // 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
   613
            if (forceConversionSeparation) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   614
                // 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
   615
                // 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
   616
                // 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
   617
                // concrete cases where this could happen.
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   618
                final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   619
                loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   620
                method.convert(operandBounds.within(method.peekType()));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   621
                loadExpression(rhs, safeConvertBounds, false);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   622
                method.convert(operandBounds.within(method.peekType()));
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   623
            } else {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   624
                // 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
   625
                loadExpression(lhs, operandBounds, baseAlreadyOnStack);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   626
                loadExpression(rhs, operandBounds, false);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   627
            }
21457
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   628
        } else {
381acbd07fe5 8027042: Evaluation order for binary operators can be improved
hannesw
parents: 21449
diff changeset
   629
            // Can't reorder. Load and convert separately.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   630
            final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   631
            loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   632
            final Type lhsLoadedType = method.peekType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   633
            loadExpression(rhs, safeConvertBounds, false);
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   634
            final Type convertedLhsType = operandBounds.within(method.peekType());
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   635
            if (convertedLhsType != lhsLoadedType) {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   636
                // 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
   637
                method.swap().convert(convertedLhsType).swap();
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   638
            }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   639
            method.convert(operandBounds.within(method.peekType()));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   640
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   641
        assert Type.generic(method.peekType()) == operandBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   642
        assert Type.generic(method.peekType(1)) == operandBounds.narrowest;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   643
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   644
        return method;
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   645
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   646
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   647
    /**
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   648
     * 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
   649
     * 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
   650
     * 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
   651
     * 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
   652
     * 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
   653
     * 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
   654
     * 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
   655
     * 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
   656
     * 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
   657
     * 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
   658
     * 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
   659
     * {@link #loadBinaryOperands(BinaryNode)}.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   660
     *
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   661
     * @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
   662
     * @return the current method emitter.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   663
     */
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   664
    MethodEmitter loadComparisonOperands(final BinaryNode cmp) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   665
        final Expression lhs = cmp.lhs();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   666
        final Expression rhs = cmp.rhs();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   667
        final Type lhsType = lhs.getType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   668
        final Type rhsType = rhs.getType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   669
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   670
        // 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
   671
        assert !(lhsType.isObject() && rhsType.isObject());
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   672
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   673
        if (lhsType.isObject() || rhsType.isObject()) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   674
            // 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
   675
            // 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
   676
            // 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
   677
            // 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
   678
            // "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
   679
            // 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
   680
            final boolean canReorder = lhsType.isPrimitive() || rhs.isLocal();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   681
            // 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
   682
            // (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
   683
            // This is because relational operators' semantics prescribes vanilla ToNumber() conversion, while
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   684
            // (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
   685
            // "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
   686
            // to compile as:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   687
            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)D
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   688
            // instead of the more costly:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   689
            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)Object
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   690
            //   invokestatic JSType.toNumber(Object)D
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   691
            // 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
   692
            // 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
   693
            // into a freely coercible one, which would be wrong.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   694
            final boolean canCombineLoadAndConvert = canReorder && cmp.isRelational();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   695
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   696
            // LOAD LEFT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   697
            loadExpression(lhs, canCombineLoadAndConvert && !lhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   698
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   699
            final Type lhsLoadedType = method.peekType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   700
            final TokenType tt = cmp.tokenType();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   701
            if (canReorder) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   702
                // Can reorder CONVERT LEFT and LOAD RIGHT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   703
                emitObjectToNumberComparisonConversion(method, tt);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   704
                loadExpression(rhs, canCombineLoadAndConvert && !rhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   705
            } else {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   706
                // Can't reorder CONVERT LEFT and LOAD RIGHT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   707
                loadExpression(rhs, TypeBounds.UNBOUNDED);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   708
                if (lhsLoadedType != Type.NUMBER) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   709
                    method.swap();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   710
                    emitObjectToNumberComparisonConversion(method, tt);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   711
                    method.swap();
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   712
                }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   713
            }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   714
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   715
            // CONVERT RIGHT
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   716
            emitObjectToNumberComparisonConversion(method, tt);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   717
            return method;
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
        // For primitive operands, just don't do anything special.
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   720
        return loadBinaryOperands(cmp);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   721
    }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   722
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   723
    private static void emitObjectToNumberComparisonConversion(final MethodEmitter method, final TokenType tt) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   724
        switch(tt) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   725
        case EQ:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   726
        case NE:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   727
            if (method.peekType().isObject()) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   728
                TO_NUMBER_FOR_EQ.invoke(method);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   729
                return;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   730
            }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   731
            break;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   732
        case EQ_STRICT:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   733
        case NE_STRICT:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   734
            if (method.peekType().isObject()) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   735
                TO_NUMBER_FOR_STRICT_EQ.invoke(method);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   736
                return;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   737
            }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   738
            break;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   739
        default:
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   740
            break;
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   741
        }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   742
        method.convert(Type.NUMBER);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   743
    }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   744
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   745
    private static final Type undefinedToNumber(final Type type) {
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   746
        return type == Type.UNDEFINED ? Type.NUMBER : type;
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   747
    }
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
   748
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   749
    private static final class TypeBounds {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   750
        final Type narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   751
        final Type widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   752
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   753
        static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   754
        static final TypeBounds INT = exact(Type.INT);
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
   755
        static final TypeBounds NUMBER = exact(Type.NUMBER);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   756
        static final TypeBounds OBJECT = exact(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   757
        static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   758
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   759
        static TypeBounds exact(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   760
            return new TypeBounds(type, type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   761
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   762
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   763
        TypeBounds(final Type narrowest, final Type widest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   764
            assert widest    != null && widest    != Type.UNDEFINED && widest != Type.UNKNOWN : widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   765
            assert narrowest != null && narrowest != Type.UNDEFINED : narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   766
            assert !narrowest.widerThan(widest) : narrowest + " wider than " + widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   767
            assert !widest.narrowerThan(narrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   768
            this.narrowest = Type.generic(narrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   769
            this.widest = Type.generic(widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   770
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   771
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   772
        TypeBounds notNarrowerThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   773
            return maybeNew(Type.narrowest(Type.widest(narrowest, type), widest), widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   774
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   775
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   776
        TypeBounds notWiderThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   777
            return maybeNew(Type.narrowest(narrowest, type), Type.narrowest(widest, type));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   778
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   779
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   780
        boolean canBeNarrowerThan(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   781
            return narrowest.narrowerThan(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   782
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   783
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   784
        TypeBounds maybeNew(final Type newNarrowest, final Type newWidest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   785
            if(newNarrowest == narrowest && newWidest == widest) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   786
                return this;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   787
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   788
            return new TypeBounds(newNarrowest, newWidest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   789
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   790
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   791
        TypeBounds booleanToInt() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   792
            return maybeNew(CodeGenerator.booleanToInt(narrowest), CodeGenerator.booleanToInt(widest));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   793
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   794
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   795
        TypeBounds objectToNumber() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   796
            return maybeNew(CodeGenerator.objectToNumber(narrowest), CodeGenerator.objectToNumber(widest));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   797
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   798
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   799
        Type within(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   800
            if(type.narrowerThan(narrowest)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   801
                return narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   802
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   803
            if(type.widerThan(widest)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   804
                return widest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   805
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   806
            return type;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   807
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   808
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   809
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   810
        public String toString() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   811
            return "[" + narrowest + ", " + widest + "]";
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   812
        }
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   813
    }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
   814
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   815
    private static Type booleanToInt(final Type t) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   816
        return t == Type.BOOLEAN ? Type.INT : t;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   817
    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   818
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   819
    private static Type objectToNumber(final Type t) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   820
        return t.isObject() ? Type.NUMBER : t;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   821
    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
   822
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   823
    MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   824
        if(type == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   825
            return loadExpressionAsBoolean(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   826
        } else if(type == Type.UNDEFINED) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   827
            assert expr.getType() == Type.UNDEFINED;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   828
            return loadExpressionAsObject(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   829
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   830
        // 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
   831
        // converted early) and then applies explicit conversion afterwards.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   832
        return loadExpression(expr, TypeBounds.UNBOUNDED.notNarrowerThan(type)).convert(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   833
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   834
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   835
    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   836
        return loadExpression(expr, resultBounds, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   837
    }
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
     * 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
   841
     * necessary.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   842
     * @param expr the expression to load
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   843
     * @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
   844
     * 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
   845
     * @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
   846
     * 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
   847
     * to indicate the widest possible type.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   848
     * @return the method emitter
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   849
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   850
    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
   851
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   852
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   853
         * The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y"
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   854
         * or IndexNode e.g. "x[y]". Both AccessNodes and IndexNodes are
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   855
         * BaseNodes and the logic for loading the base object is reused
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   856
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   857
        final CodeGenerator codegen = this;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   858
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
   859
        final boolean isCurrentDiscard = codegen.lc.isCurrentDiscard(expr);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   860
        expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   861
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   862
            public boolean enterIdentNode(final IdentNode identNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   863
                loadIdent(identNode, resultBounds);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   864
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   865
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   866
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   867
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   868
            public boolean enterAccessNode(final AccessNode accessNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   869
                new OptimisticOperation(accessNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   870
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   871
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   872
                        if (!baseAlreadyOnStack) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   873
                            loadExpressionAsObject(accessNode.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   874
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   875
                        assert method.peekType().isObject();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   876
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   877
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   878
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   879
                        final int flags = getCallSiteFlags();
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
   880
                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction(), accessNode.isIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   881
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   882
                }.emit(baseAlreadyOnStack ? 1 : 0);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   883
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   884
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   885
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   886
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   887
            public boolean enterIndexNode(final IndexNode indexNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   888
                new OptimisticOperation(indexNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   889
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   890
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   891
                        if (!baseAlreadyOnStack) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   892
                            loadExpressionAsObject(indexNode.getBase());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   893
                            loadExpressionUnbounded(indexNode.getIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   894
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   895
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   896
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   897
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   898
                        final int flags = getCallSiteFlags();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   899
                        dynamicGetIndex(flags, indexNode.isFunction());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
   900
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   901
                }.emit(baseAlreadyOnStack ? 2 : 0);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
   902
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   903
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   904
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
   905
            @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
   906
            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
   907
                // 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
   908
                // 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
   909
                lc.pop(functionNode);
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
   910
                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
   911
                // 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
   912
                // 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
   913
                // 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
   914
                // 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
   915
                lc.push(functionNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   916
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   917
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   918
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   919
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   920
            public boolean enterASSIGN(final BinaryNode binaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
   921
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   922
                loadASSIGN(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   923
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   924
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   925
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   926
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   927
            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
   928
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   929
                loadASSIGN_ADD(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   930
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   931
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   932
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   933
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   934
            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
   935
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   936
                loadASSIGN_BIT_AND(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   937
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   938
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   939
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   940
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   941
            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
   942
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   943
                loadASSIGN_BIT_OR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   944
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   945
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   946
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   947
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   948
            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
   949
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   950
                loadASSIGN_BIT_XOR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   951
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   952
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   953
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   954
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   955
            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
   956
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   957
                loadASSIGN_DIV(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   958
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   959
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   960
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   961
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   962
            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
   963
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   964
                loadASSIGN_MOD(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   965
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   966
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   967
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   968
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   969
            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
   970
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   971
                loadASSIGN_MUL(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   972
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   973
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   974
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   975
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   976
            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
   977
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   978
                loadASSIGN_SAR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   979
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   980
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   981
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   982
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   983
            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
   984
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   985
                loadASSIGN_SHL(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   986
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   987
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   988
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   989
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   990
            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
   991
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   992
                loadASSIGN_SHR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   993
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   994
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   995
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   996
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   997
            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
   998
                checkAssignTarget(binaryNode.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
   999
                loadASSIGN_SUB(binaryNode);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1000
                return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1001
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1002
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1003
            @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
  1004
            public boolean enterCallNode(final CallNode callNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1005
                return loadCallNode(callNode, resultBounds);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1006
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1007
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
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 enterLiteralNode(final LiteralNode<?> literalNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1010
                loadLiteral(literalNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1011
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1012
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1013
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1014
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1015
            public boolean enterTernaryNode(final TernaryNode ternaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1016
                loadTernaryNode(ternaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1017
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1018
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1019
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1020
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1021
            public boolean enterADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1022
                loadADD(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1023
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1024
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1025
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1026
            @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
  1027
            public boolean enterSUB(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1028
                loadSUB(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1029
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1030
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1031
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1032
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1033
            public boolean enterSUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1034
                loadSUB(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1035
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1036
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1037
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1038
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1039
            public boolean enterMUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1040
                loadMUL(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1041
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1042
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1043
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1044
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1045
            public boolean enterDIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1046
                loadDIV(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1047
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1048
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1049
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1050
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1051
            public boolean enterMOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1052
                loadMOD(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1053
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1054
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1055
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1056
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1057
            public boolean enterSAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1058
                loadSAR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1059
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1060
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1061
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1062
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1063
            public boolean enterSHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1064
                loadSHL(binaryNode);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1065
                return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1066
            }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1067
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1068
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1069
            public boolean enterSHR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1070
                loadSHR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1071
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1072
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1073
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1074
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1075
            public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1076
                loadCOMMALEFT(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1077
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1078
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1079
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1080
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1081
            public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1082
                loadCOMMARIGHT(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1083
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1084
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1085
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1086
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1087
            public boolean enterAND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1088
                loadAND_OR(binaryNode, resultBounds, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1089
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1090
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1091
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1092
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1093
            public boolean enterOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1094
                loadAND_OR(binaryNode, resultBounds, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1095
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1096
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1097
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1098
            @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
  1099
            public boolean enterNOT(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1100
                loadNOT(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1101
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1102
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1103
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1104
            @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
  1105
            public boolean enterADD(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1106
                loadADD(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1107
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1108
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1109
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1110
            @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
  1111
            public boolean enterBIT_NOT(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1112
                loadBIT_NOT(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1113
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1114
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1115
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1116
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1117
            public boolean enterBIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1118
                loadBIT_AND(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1119
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1120
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1121
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1122
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1123
            public boolean enterBIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1124
                loadBIT_OR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1125
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1126
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1127
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1128
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1129
            public boolean enterBIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1130
                loadBIT_XOR(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1131
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1132
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1133
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1134
            @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
  1135
            public boolean enterVOID(final UnaryNode unaryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1136
                loadVOID(unaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1137
                return false;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1138
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1139
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1140
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1141
            public boolean enterEQ(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1142
                loadCmp(binaryNode, Condition.EQ);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1143
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1144
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1145
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1146
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1147
            public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1148
                loadCmp(binaryNode, Condition.EQ);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1149
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1150
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1151
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1152
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1153
            public boolean enterGE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1154
                loadCmp(binaryNode, Condition.GE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1155
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1156
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1157
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1158
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1159
            public boolean enterGT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1160
                loadCmp(binaryNode, Condition.GT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1161
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1162
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1163
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1164
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1165
            public boolean enterLE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1166
                loadCmp(binaryNode, Condition.LE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1167
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1168
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1169
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1170
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1171
            public boolean enterLT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1172
                loadCmp(binaryNode, Condition.LT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1173
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1174
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1175
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1176
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1177
            public boolean enterNE(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1178
                loadCmp(binaryNode, Condition.NE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1179
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1180
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1181
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1182
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1183
            public boolean enterNE_STRICT(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1184
                loadCmp(binaryNode, Condition.NE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1185
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1186
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1187
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1188
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1189
            public boolean enterObjectNode(final ObjectNode objectNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1190
                loadObjectNode(objectNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1191
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1192
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1193
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1194
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1195
            public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1196
                loadRuntimeNode(runtimeNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1197
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1198
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1199
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1200
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1201
            public boolean enterNEW(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1202
                loadNEW(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1203
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1204
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1205
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1206
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1207
            public boolean enterDECINC(final UnaryNode unaryNode) {
29281
8cc2618a07aa 8073707: const re-assignment should not reported as a early error
hannesw
parents: 28690
diff changeset
  1208
                checkAssignTarget(unaryNode.getExpression());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1209
                loadDECINC(unaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1210
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1211
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1212
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1213
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1214
            public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  1215
                loadMaybeDiscard(joinExpr, joinExpr.getExpression(), resultBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1216
                return false;
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1217
            }
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1218
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  1219
            @Override
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1220
            public boolean enterGetSplitState(final GetSplitState getSplitState) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1221
                method.loadScope();
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1222
                method.invoke(Scope.GET_SPLIT_STATE);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1223
                return false;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1224
            }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1225
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1226
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1227
            public boolean enterDefault(final Node otherNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1228
                // Must have handled all expressions that can legally be encountered.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1229
                throw new AssertionError(otherNode.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1230
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1231
        });
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  1232
        if(!isCurrentDiscard) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1233
            coerceStackTop(resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1234
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1235
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1236
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1237
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1238
    private MethodEmitter coerceStackTop(final TypeBounds typeBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1239
        return method.convert(typeBounds.within(method.peekType()));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1240
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1241
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1242
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1243
     * 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
  1244
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1245
     * @param block block containing symbols.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1246
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1247
    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
  1248
        for (final Symbol symbol : block.getSymbols()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1249
            if (symbol.isBytecodeLocal()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1250
                method.closeLocalVariable(symbol, block.getBreakLabel());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1251
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1252
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1253
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1254
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1255
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1256
    public boolean enterBlock(final Block block) {
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1257
        final Label entryLabel = block.getEntryLabel();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1258
        if (entryLabel.isBreakTarget()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1259
            // Entry label is a break target only for an inlined finally block.
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1260
            assert !method.isReachable();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1261
            method.breakLabel(entryLabel, lc.getUsedSlotCount());
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1262
        } else {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1263
            method.label(entryLabel);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1264
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1265
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1266
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1267
        }
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1268
        if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1269
            return false;
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  1270
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1271
        initLocals(block);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1272
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1273
        assert lc.getUsedSlotCount() == method.getFirstTemp();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1274
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1275
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1276
30390
357f9a3f9394 8079269: Optimistic rewrite in object literal causes ArrayIndexOutOfBoundsException
attila
parents: 30056
diff changeset
  1277
    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
  1278
        return !lc.inSplitNode() && compiler.useOptimisticTypes();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1279
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1280
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1281
    @Override
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  1282
    public Node leaveBlock(final Block block) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1283
        popBlockScope(block);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1284
        method.beforeJoinPoint(block);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1285
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1286
        closeBlockVariables(block);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1287
        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
  1288
        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
  1289
            "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
  1290
            " 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
  1291
            " 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
  1292
            " firstTemp=" + method.getFirstTemp();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1293
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1294
        return block;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1295
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1296
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1297
    private void popBlockScope(final Block block) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1298
        final Label breakLabel = block.getBreakLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1299
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1300
        if(!block.needsScope() || lc.isFunctionBody()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1301
            emitBlockBreakLabel(breakLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1302
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1303
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1304
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1305
        final Label beginTryLabel = scopeEntryLabels.pop();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1306
        final Label recoveryLabel = new Label("block_popscope_catch");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1307
        emitBlockBreakLabel(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1308
        final boolean bodyCanThrow = breakLabel.isAfter(beginTryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1309
        if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1310
            method._try(beginTryLabel, breakLabel, recoveryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1311
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1312
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1313
        Label afterCatchLabel = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1314
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1315
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1316
            popScope();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1317
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1318
                afterCatchLabel = new Label("block_after_catch");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1319
                method._goto(afterCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1320
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1321
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1322
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
            assert !method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1325
            method._catch(recoveryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1326
            popScopeException();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1327
            method.athrow();
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(afterCatchLabel != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1330
            method.label(afterCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1331
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1332
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1333
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1334
    private void emitBlockBreakLabel(final Label breakLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1335
        // 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
  1336
        final LabelNode labelNode = lc.getCurrentBlockLabelNode();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1337
        if(labelNode != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1338
            // Only have conversions if we're reachable
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1339
            assert labelNode.getLocalVariableConversion() == null || method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1340
            method.beforeJoinPoint(labelNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1341
            method.breakLabel(breakLabel, labeledBlockBreakLiveLocals.pop());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1342
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1343
            method.label(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1344
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1345
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1346
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1347
    private void popScope() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1348
        popScopes(1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1349
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1350
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1351
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1352
     * 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
  1353
     * 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
  1354
     * performing a ToPrimitive conversion.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1355
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1356
    private void popScopeException() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1357
        popScope();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1358
        final ContinuationInfo ci = getContinuationInfo();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1359
        if(ci != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1360
            final Label catchLabel = ci.catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1361
            if(catchLabel != METHOD_BOUNDARY && catchLabel == catchLabels.peek()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1362
                ++ci.exceptionScopePops;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1363
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1364
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1365
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1366
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1367
    private void popScopesUntil(final LexicalContextNode until) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1368
        popScopes(lc.getScopeNestingLevelTo(until));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1369
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1370
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1371
    private void popScopes(final int count) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1372
        if(count == 0) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1373
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1374
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1375
        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
  1376
        if (!method.hasScope()) {
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1377
            // 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
  1378
            // 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
  1379
            // 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
  1380
            return;
90ab6e5bb5dd 8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
attila
parents: 25244
diff changeset
  1381
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1382
        method.loadCompilerConstant(SCOPE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1383
        for(int i = 0; i < count; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1384
            method.invoke(ScriptObject.GET_PROTO);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1385
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1386
        method.storeCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1387
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1388
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1389
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1390
    public boolean enterBreakNode(final BreakNode breakNode) {
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1391
        return enterJumpStatement(breakNode);
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1392
    }
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1393
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1394
    @Override
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1395
    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1396
        return enterJumpStatement(jumpToInlinedFinally);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1397
    }
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1398
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1399
    private boolean enterJumpStatement(final JumpStatement jump) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1400
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1401
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1402
        }
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1403
        enterStatement(jump);
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
        method.beforeJoinPoint(jump);
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1406
        popScopesUntil(jump.getPopScopeLimit(lc));
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  1407
        final Label targetLabel = jump.getTargetLabel(lc);
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1408
        targetLabel.markAsBreakTarget();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  1409
        method._goto(targetLabel);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1410
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1411
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1412
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1413
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1414
    private int loadArgs(final List<Expression> args) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1415
        final int argCount = args.size();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1416
        // arg have already been converted to objects here.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1417
        if (argCount > LinkerCallSite.ARGLIMIT) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1418
            loadArgsArray(args);
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  1419
            return 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1420
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1421
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1422
        for (final Expression arg : args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1423
            assert arg != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1424
            loadExpressionUnbounded(arg);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1425
        }
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  1426
        return argCount;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1427
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1428
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1429
    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
  1430
        lineNumber(callNode.getLineNumber());
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1431
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1432
        final List<Expression> args = callNode.getArgs();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1433
        final Expression function = callNode.getFunction();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1434
        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
  1435
        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
  1436
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
  1437
        function.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1438
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
  1439
            private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1440
                final Symbol symbol = identNode.getSymbol();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1441
                final boolean isFastScope = isFastScope(symbol);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1442
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1443
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1444
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1445
                        method.loadCompilerConstant(SCOPE);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1446
                        if (isFastScope) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1447
                            method.load(getScopeProtoDepth(currentBlock, symbol));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1448
                        } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1449
                            method.load(-1); // Bypass fast-scope code in shared callsite
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1450
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1451
                        loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1452
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1453
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1454
                    void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1455
                        final Type[] paramTypes = method.getTypesFromStack(args.size());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1456
                        // 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
  1457
                        // loader, so we need to weaken reference signatures to Object.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1458
                        for(int i = 0; i < paramTypes.length; ++i) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1459
                            paramTypes[i] = Type.generic(paramTypes[i]);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1460
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1461
                        // As shared scope calls are only used in non-optimistic compilation, we switch from using
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1462
                        // TypeBounds to just a single definitive type, resultBounds.widest.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1463
                        final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol,
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
  1464
                                identNode.getType(), resultBounds.widest, paramTypes, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1465
                        scopeCall.generateInvoke(method);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1466
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1467
                }.emit();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1468
                return method;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1469
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1470
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1471
            private void scopeCall(final IdentNode ident, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1472
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1473
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1474
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1475
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1476
                        loadExpressionAsObject(ident); // foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1477
                        // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
24727
attila
parents: 24725 23372
diff changeset
  1478
                        method.loadUndefined(Type.OBJECT); //the 'this'
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1479
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1480
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1481
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1482
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1483
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1484
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1485
                }.emit();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1486
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1487
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1488
            private void evalCall(final IdentNode ident, final int flags) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1489
                final Label invoke_direct_eval  = new Label("invoke_direct_eval");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1490
                final Label is_not_eval  = new Label("is_not_eval");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1491
                final Label eval_done = new Label("eval_done");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1492
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1493
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1494
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1495
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1496
                    void loadStack() {
25242
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1497
                        /**
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
  1498
                         * We want to load 'eval' to check if it is indeed global builtin eval.
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1499
                         * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1500
                         * 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
  1501
                         * 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
  1502
                         * won't be detected as builtin eval. So, we make ident as "not a function" which
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1503
                         * results in "dyn:getProp|getElem|getMethod" being generated and so WithObject
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1504
                         * 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
  1505
                         *
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
  1506
                         * 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
  1507
                         *
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
  1508
                         *  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
  1509
                         *  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
  1510
                         *      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
  1511
                         *  }
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
                         */
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
  1513
                        loadExpressionAsObject(ident.setIsNotFunction()); // Type.OBJECT as foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1514
                        globalIsEval();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1515
                        method.ifeq(is_not_eval);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1516
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1517
                        // Load up self (scope).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1518
                        method.loadCompilerConstant(SCOPE);
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1519
                        final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1520
                        // load evaluated code
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1521
                        loadExpressionAsObject(evalArgs.get(0));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1522
                        // 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
  1523
                        final int numArgs = evalArgs.size();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1524
                        for (int i = 1; i < numArgs; i++) {
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1525
                            loadAndDiscard(evalArgs.get(i));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1526
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1527
                        method._goto(invoke_direct_eval);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1528
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1529
                        method.label(is_not_eval);
25242
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1530
                        // load this time but with dyn:getMethod|getProp|getElem
ac1d21c4d61d 8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
sundar
parents: 25240
diff changeset
  1531
                        loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1532
                        // This is some scope 'eval' or global eval replaced by user
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1533
                        // but not the built-in ECMAScript 'eval' function call
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1534
                        method.loadNull();
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1535
                        argsCount = loadArgs(callNode.getArgs());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1536
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1537
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1538
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1539
                    void consumeStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1540
                        // Ordinary call
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1541
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1542
                        method._goto(eval_done);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1543
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1544
                        method.label(invoke_direct_eval);
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1545
                        // 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
  1546
                        // them can ever be optimistic.
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1547
                        method.loadCompilerConstant(THIS);
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1548
                        method.load(callNode.getEvalArgs().getLocation());
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  1549
                        method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1550
                        // direct call to Global.directEval
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1551
                        globalDirectEval();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1552
                        convertOptimisticReturnValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1553
                        coerceStackTop(resultBounds);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1554
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1555
                }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1556
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1557
                method.label(eval_done);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1558
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1559
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1560
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1561
            public boolean enterIdentNode(final IdentNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1562
                final Symbol symbol = node.getSymbol();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1563
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1564
                if (symbol.isScope()) {
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
  1565
                    final int flags = getScopeCallSiteFlags(symbol);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1566
                    final int useCount = symbol.getUseCount();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1567
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1568
                    // Threshold for generating shared scope callsite is lower for fast scope symbols because we know
17239
6dd68632cdcd 8011065: Problems when script implements an interface with variadic methods
attila
parents: 17233
diff changeset
  1569
                    // we can dial in the correct scope. However, we also need to enable it for non-fast scopes to
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1570
                    // support huge scripts like mandreel.js.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1571
                    if (callNode.isEval()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1572
                        evalCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1573
                    } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  1574
                            || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1575
                            || CodeGenerator.this.lc.inDynamicScope()
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1576
                            || isOptimisticOrRestOf()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1577
                        scopeCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1578
                    } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1579
                        sharedScopeCall(node, flags);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1580
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1581
                    assert method.peekType().equals(resultBounds.within(callNode.getType())) : method.peekType() + " != " + resultBounds + "(" + callNode.getType() + ")";
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1582
                } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1583
                    enterDefault(node);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1584
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1585
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1586
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1587
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1588
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1589
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1590
            public boolean enterAccessNode(final AccessNode node) {
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1591
                //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
  1592
                //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
  1593
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1594
                //call nodes have program points.
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  1595
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1596
                final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1597
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1598
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1599
                    int argCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1600
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1601
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1602
                        loadExpressionAsObject(node.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1603
                        method.dup();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1604
                        // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1605
                        // a callable object. Nobody in their right mind would optimistically type this call site.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1606
                        assert !node.isOptimistic();
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  1607
                        method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1608
                        method.swap();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1609
                        argCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1610
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1611
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1612
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1613
                        dynamicCall(2 + argCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1614
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1615
                }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1616
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1617
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1618
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1619
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1620
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1621
            public boolean enterFunctionNode(final FunctionNode origCallee) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1622
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1623
                    FunctionNode callee;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1624
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1625
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1626
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1627
                        callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1628
                        if (callee.isStrict()) { // "this" is undefined
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1629
                            method.loadUndefined(Type.OBJECT);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1630
                        } else { // get global from scope (which is the self)
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1631
                            globalInstance();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1632
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1633
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1634
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1635
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1636
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1637
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1638
                        final int flags = getCallSiteFlags();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1639
                        //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1640
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1641
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1642
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1643
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1644
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1645
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1646
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1647
            public boolean enterIndexNode(final IndexNode node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1648
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1649
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1650
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1651
                    void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1652
                        loadExpressionAsObject(node.getBase());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1653
                        method.dup();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1654
                        final Type indexType = node.getIndex().getType();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1655
                        if (indexType.isObject() || indexType.isBoolean()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1656
                            loadExpressionAsObject(node.getIndex()); //TODO boolean
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1657
                        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1658
                            loadExpressionUnbounded(node.getIndex());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1659
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1660
                        // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1661
                        // back a callable object. Nobody in their right mind would optimistically type this call site.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1662
                        assert !node.isOptimistic();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1663
                        method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1664
                        method.swap();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1665
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1666
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1667
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1668
                    void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1669
                        final int flags = getCallSiteFlags();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1670
                        dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1671
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1672
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1673
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1674
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1675
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1676
            @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1677
            protected boolean enterDefault(final Node node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1678
                new OptimisticOperation(callNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1679
                    int argsCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1680
                    @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1681
                    void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1682
                        // Load up function.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1683
                        loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
24727
attila
parents: 24725 23372
diff changeset
  1684
                        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
  1685
                        argsCount = loadArgs(args);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1686
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1687
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1688
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1689
                            final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1690
                            dynamicCall(2 + argsCount, flags);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1691
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1692
                }.emit();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1693
                return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1694
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1695
        });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1696
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1697
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1698
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1699
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1700
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1701
     * Returns the flags with optimistic flag and program point removed.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1702
     * @param flags the flags that need optimism stripped from them.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1703
     * @return flags without optimism
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1704
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1705
    static int nonOptimisticFlags(final int flags) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1706
        return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1707
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1708
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1709
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1710
    public boolean enterContinueNode(final ContinueNode continueNode) {
26889
dba314d7a634 8059371: Code duplication in handling of break and continue
attila
parents: 26507
diff changeset
  1711
        return enterJumpStatement(continueNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1712
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1713
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1714
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1715
    public boolean enterEmptyNode(final EmptyNode emptyNode) {
30391
62dcad329b26 8079349: Eliminate dead code around Nashorn code generator
attila
parents: 30390
diff changeset
  1716
        // 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
  1717
        return false;
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
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1721
    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1722
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1723
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1724
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1725
        enterStatement(expressionStatement);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1726
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1727
        loadAndDiscard(expressionStatement.getExpression());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1728
        assert method.getStackSize() == 0;
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1729
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1730
        return false;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1731
    }
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1732
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1733
    @Override
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1734
    public boolean enterBlockStatement(final BlockStatement blockStatement) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1735
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1736
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1737
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1738
        enterStatement(blockStatement);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1739
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  1740
        blockStatement.getBlock().accept(this);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1741
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1742
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1743
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1744
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1745
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1746
    public boolean enterForNode(final ForNode forNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1747
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1748
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1749
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1750
        enterStatement(forNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1751
        if (forNode.isForIn()) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  1752
            enterForIn(forNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1753
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1754
            final Expression init = forNode.getInit();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1755
            if (init != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1756
                loadAndDiscard(init);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1757
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1758
            enterForOrWhile(forNode, forNode.getModify());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1759
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1760
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1761
        return false;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1762
    }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1763
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1764
    private void enterForIn(final ForNode forNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1765
        loadExpression(forNode.getModify(), TypeBounds.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1766
        method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1767
        final Symbol iterSymbol = forNode.getIterator();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1768
        final int iterSlot = iterSymbol.getSlot(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1769
        method.store(iterSymbol, ITERATOR_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1770
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1771
        method.beforeJoinPoint(forNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1772
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1773
        final Label continueLabel = forNode.getContinueLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1774
        final Label breakLabel    = forNode.getBreakLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1775
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1776
        method.label(continueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1777
        method.load(ITERATOR_TYPE, iterSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1778
        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "hasNext", boolean.class));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1779
        final JoinPredecessorExpression test = forNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1780
        final Block body = forNode.getBody();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1781
        if(LocalVariableConversion.hasLiveConversion(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1782
            final Label afterConversion = new Label("for_in_after_test_conv");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1783
            method.ifne(afterConversion);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1784
            method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1785
            method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1786
            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
  1787
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1788
            method.ifeq(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1789
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1790
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1791
        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
  1792
            @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
  1793
            protected void storeNonDiscard() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1794
                // 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
  1795
                // stored, so we override storeNonDiscard to be a no-op.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1796
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1797
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
  1798
            @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
  1799
            protected void evaluate() {
26507
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1800
                new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1801
                    @Override
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1802
                    void loadStack() {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1803
                        method.load(ITERATOR_TYPE, iterSlot);
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1804
                    }
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1805
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1806
                    @Override
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1807
                    void consumeStack() {
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1808
                        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1809
                        convertOptimisticReturnValue();
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1810
                    }
9d6e3ec59878 8034954: Optimistic iteration in for-in and for-each
attila
parents: 26377
diff changeset
  1811
                }.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
  1812
            }
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
        }.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
  1814
        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
  1815
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1816
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1817
            method._goto(continueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1818
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1819
        method.label(breakLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1820
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1821
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1822
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1823
     * Initialize the slots in a frame to undefined.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1824
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1825
     * @param block block with local vars.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1826
     */
16168
f0c208287983 8005976: Break out AccessSpecializer into one pass before CodeGenerator instead of iterative applications from CodeGenerator
lagergren
parents: 16152
diff changeset
  1827
    private void initLocals(final Block block) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1828
        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
  1829
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
  1830
        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
  1831
        final FunctionNode function = lc.getCurrentFunction();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1832
        if (isFunctionBody) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1833
            initializeMethodParameters(function);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1834
            if(!function.isVarArg()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1835
                expandParameterSlots(function);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1836
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1837
            if (method.hasScope()) {
18853
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1838
                if (function.needsParentScope()) {
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1839
                    method.loadCompilerConstant(CALLEE);
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1840
                    method.invoke(ScriptFunction.GET_SCOPE);
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1841
                } else {
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1842
                    assert function.hasScopeBlock();
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1843
                    method.loadNull();
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1844
                }
25ba8264b427 8019819: scope symbol didn't get a slot in certain cases
attila
parents: 18852
diff changeset
  1845
                method.storeCompilerConstant(SCOPE);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1846
            }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1847
            if (function.needsArguments()) {
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1848
                initArguments(function);
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1849
            }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1850
        }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1851
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1852
        /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1853
         * Determine if block needs scope, if not, just do initSymbols for this block.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1854
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1855
        if (block.needsScope()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1856
            /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1857
             * Determine if function is varargs and consequently variables have to
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1858
             * be in the scope.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1859
             */
16252
3bfe9b68a0fa 8008648: Lazy JIT scope and callee semantics bugfixes. Broke out wallclock timer.
lagergren
parents: 16240
diff changeset
  1860
            final boolean varsInScope = function.allVarsInScope();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1861
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1862
            // 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
  1863
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1864
            final boolean hasArguments = function.needsArguments();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1865
            final List<MapTuple<Symbol>> tuples = new ArrayList<>();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1866
            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
  1867
            for (final Symbol symbol : block.getSymbols()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1868
                if (symbol.isInternal() || symbol.isThis()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1869
                    continue;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1870
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1871
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1872
                if (symbol.isVar()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1873
                    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
  1874
                    if (varsInScope || symbol.isScope()) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1875
                        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
  1876
                        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
  1877
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1878
                        //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
  1879
                        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
  1880
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1881
                        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
  1882
                    }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1883
                } else if (symbol.isParam() && (varsInScope || hasArguments || symbol.isScope())) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1884
                    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
  1885
                    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
  1886
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1887
                    final Type   paramType;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1888
                    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
  1889
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1890
                    if (hasArguments) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1891
                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already ";
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1892
                        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
  1893
                        paramType   = null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1894
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1895
                        paramSymbol = symbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1896
                        // 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
  1897
                        // 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
  1898
                        // 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
  1899
                        // 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
  1900
                        // name.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1901
                        for(;;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1902
                            final IdentNode nextParam = paramIter.next();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1903
                            if(nextParam.getName().equals(symbol.getName())) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1904
                                paramType = nextParam.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1905
                                break;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1906
                            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1907
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1908
                    }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1909
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1910
                    tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, paramType, paramSymbol) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1911
                        //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
  1912
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1913
                        public Class<?> getValueType() {
29834
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
  1914
                            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
  1915
                                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
  1916
                            }
29834
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
  1917
                            return paramType.getTypeClass();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1918
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1919
                    });
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1920
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1921
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1922
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1923
            /*
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1924
             * Create a new object based on the symbols and values, generate
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1925
             * bootstrap code for object
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1926
             */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1927
            new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1928
                @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1929
                protected void loadValue(final Symbol value, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1930
                    method.load(value, type);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1931
                }
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  1932
            }.makeObject(method);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1933
            // program function: merge scope into global
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1934
            if (isFunctionBody && function.isProgram()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1935
                method.invoke(ScriptRuntime.MERGE_SCOPE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1936
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1937
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  1938
            method.storeCompilerConstant(SCOPE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1939
            if(!isFunctionBody) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1940
                // 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
  1941
                // actually causes issues with UnwarrantedOptimismException handlers as ASM will sort this handler to
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1942
                // 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
  1943
                final Label scopeEntryLabel = new Label("scope_entry");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1944
                scopeEntryLabels.push(scopeEntryLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1945
                method.label(scopeEntryLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  1946
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1947
        } else if (isFunctionBody && function.isVarArg()) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1948
            // 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
  1949
            // we need to assign them separately here.
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  1950
            int nextParam = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1951
            for (final IdentNode param : function.getParameters()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1952
                param.getSymbol().setFieldIndex(nextParam++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1953
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1954
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1955
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1956
        // 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
  1957
        printSymbols(block, function, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1958
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  1959
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1960
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1961
     * 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
  1962
     * @param function function for which code is being generated.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1963
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1964
    private void initializeMethodParameters(final FunctionNode function) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1965
        final Label functionStart = new Label("fn_start");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1966
        method.label(functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1967
        int nextSlot = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1968
        if(function.needsCallee()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1969
            initializeInternalFunctionParameter(CALLEE, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1970
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1971
        initializeInternalFunctionParameter(THIS, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1972
        if(function.isVarArg()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1973
            initializeInternalFunctionParameter(VARARGS, function, functionStart, nextSlot++);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1974
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1975
            for(final IdentNode param: function.getParameters()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1976
                final Symbol symbol = param.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1977
                if(symbol.isBytecodeLocal()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1978
                    method.initializeMethodParameter(symbol, param.getType(), functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1979
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1980
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1981
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1982
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1983
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1984
    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
  1985
        final Symbol symbol = initializeInternalFunctionOrSplitParameter(cc, fn, functionStart, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1986
        // Internal function params (:callee, this, and :varargs) are never expanded to multiple slots
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1987
        assert symbol.getFirstSlot() == slot;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1988
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1989
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  1990
    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
  1991
        final Symbol symbol = fn.getBody().getExistingSymbol(cc.symbolName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1992
        final Type type = Type.typeFor(cc.type());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1993
        method.initializeMethodParameter(symbol, type, functionStart);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1994
        method.onLocalStore(type, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1995
        return symbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1996
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1997
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1998
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  1999
     * 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
  2000
     * 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
  2001
     * 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
  2002
     * and we need to spread them into their new locations.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2003
     * @param function the function for which parameter-spreading code needs to be emitted
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2004
     */
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2005
    private void expandParameterSlots(final FunctionNode function) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2006
        final List<IdentNode> parameters = function.getParameters();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2007
        // Calculate the total number of incoming parameter slots
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2008
        int currentIncomingSlot = function.needsCallee() ? 2 : 1;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2009
        for(final IdentNode parameter: parameters) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2010
            currentIncomingSlot += parameter.getType().getSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2011
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2012
        // 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
  2013
        for(int i = parameters.size(); i-- > 0;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2014
            final IdentNode parameter = parameters.get(i);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2015
            final Type parameterType = parameter.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2016
            final int typeWidth = parameterType.getSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2017
            currentIncomingSlot -= typeWidth;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2018
            final Symbol symbol = parameter.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2019
            final int slotCount = symbol.slotCount();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2020
            assert slotCount > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2021
            // Scoped parameters must not hold more than one value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2022
            assert symbol.isBytecodeLocal() || slotCount == typeWidth;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2023
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2024
            // Mark it as having its value stored into it by the method invocation.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2025
            method.onLocalStore(parameterType, currentIncomingSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2026
            if(currentIncomingSlot != symbol.getSlot(parameterType)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2027
                method.load(parameterType, currentIncomingSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2028
                method.store(symbol, parameterType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2029
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2030
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2031
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2032
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2033
    private void initArguments(final FunctionNode function) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2034
        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
  2035
        if (function.needsCallee()) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2036
            method.loadCompilerConstant(CALLEE);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2037
        } else {
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2038
            // 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
  2039
            // caller.
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2040
            assert function.isStrict();
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2041
            method.loadNull();
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2042
        }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2043
        method.load(function.getParameters().size());
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2044
        globalAllocateArguments();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2045
        method.storeCompilerConstant(ARGUMENTS);
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2046
    }
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  2047
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2048
    private boolean skipFunction(final FunctionNode functionNode) {
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2049
        final ScriptEnvironment env = compiler.getScriptEnvironment();
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2050
        final boolean lazy = env._lazy_compilation;
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2051
        final boolean onDemand = compiler.isOnDemandCompilation();
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2052
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2053
        // 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
  2054
        if((onDemand || lazy) && lc.getOutermostFunction() != functionNode) {
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2055
            return true;
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2056
        }
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2057
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2058
        // 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
  2059
        // 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
  2060
        // lingers around. Also, currently loading previously persisted optimistic types information only works if
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2061
        // 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
  2062
        // benefit of using previously persisted types.
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  2063
        //
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2064
        // 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
  2065
        // 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
  2066
        // 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
  2067
        // 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
  2068
        // 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
  2069
        // 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
  2070
        // :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
  2071
        return !onDemand && lazy && env._optimistic_types && functionNode.isProgram();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2072
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2073
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2074
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2075
    public boolean enterFunctionNode(final FunctionNode functionNode) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2076
        final int fnId = functionNode.getId();
24725
7bb1f687a852 8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents: 24721
diff changeset
  2077
25236
fac419f1e889 8046921: Deoptimization type information peristence
attila
parents: 24784
diff changeset
  2078
        if (skipFunction(functionNode)) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2079
            // 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
  2080
            // load it on the stack here.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2081
            newFunctionObject(functionNode, false);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2082
            return false;
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  2083
        }
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  2084
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2085
        final String fnName = functionNode.getName();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2086
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2087
        // 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
  2088
        // 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
  2089
        // 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
  2090
        // 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
  2091
        // 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
  2092
        // 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
  2093
        // 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
  2094
        // worth it, and generate one method with most generic type closure.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2095
        if (!emittedMethods.contains(fnName)) {
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
  2096
            log.info("=== BEGIN ", fnName);
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2097
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2098
            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
  2099
            unit = lc.pushCompileUnit(functionNode.getCompileUnit());
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2100
            assert lc.hasCompileUnits();
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2101
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2102
            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
  2103
            pushMethodEmitter(isRestOf() ? classEmitter.restOfMethod(functionNode) : classEmitter.method(functionNode));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2104
            method.setPreventUndefinedLoad();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2105
            if(useOptimisticTypes()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2106
                lc.pushUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2107
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2108
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2109
            // new method - reset last line number
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2110
            lastLineNumber = -1;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2111
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2112
            method.begin();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2113
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2114
            if (isRestOf()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2115
                final ContinuationInfo ci = new ContinuationInfo();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2116
                fnIdToContinuationInfo.put(fnId, ci);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2117
                method.gotoLoopStart(ci.getHandlerLabel());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2118
            }
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2119
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2120
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2121
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2122
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2123
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2124
    private void pushMethodEmitter(final MethodEmitter newMethod) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2125
        method = lc.pushMethodEmitter(newMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2126
        catchLabels.push(METHOD_BOUNDARY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2127
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2128
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2129
    private void popMethodEmitter() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2130
        method = lc.popMethodEmitter(method);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2131
        assert catchLabels.peek() == METHOD_BOUNDARY;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2132
        catchLabels.pop();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2133
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2134
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2135
    @Override
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  2136
    public Node leaveFunctionNode(final FunctionNode functionNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2137
        try {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2138
            final boolean markOptimistic;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2139
            if (emittedMethods.add(functionNode.getName())) {
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  2140
                markOptimistic = generateUnwarrantedOptimismExceptionHandlers(functionNode);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2141
                generateContinuationHandler();
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2142
                method.end(); // wrap up this method
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2143
                unit   = lc.popCompileUnit(functionNode.getCompileUnit());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2144
                popMethodEmitter();
24744
5290da85fc3d 8038426: Move all loggers from process wide scope into Global scope
lagergren
parents: 24740
diff changeset
  2145
                log.info("=== END ", functionNode.getName());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2146
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2147
                markOptimistic = false;
18872
bfb736c5aa43 8019822: Duplicate name and signature in finally block
attila
parents: 18867
diff changeset
  2148
            }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2149
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2150
            FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED);
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2151
            if (markOptimistic) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2152
                newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2153
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2154
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2155
            newFunctionObject(newFunctionNode, true);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2156
            return newFunctionNode;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2157
        } catch (final Throwable t) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2158
            Context.printStackTrace(t);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2159
            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
  2160
            e.initCause(t);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2161
            throw e;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2162
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2163
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2164
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2165
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2166
    public boolean enterIfNode(final IfNode ifNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2167
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2168
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2169
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2170
        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
  2171
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2172
        final Expression test = ifNode.getTest();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2173
        final Block pass = ifNode.getPass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2174
        final Block fail = ifNode.getFail();
27971
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2175
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2176
        if (Expression.isAlwaysTrue(test)) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2177
            loadAndDiscard(test);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2178
            pass.accept(this);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2179
            return false;
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2180
        } else if (Expression.isAlwaysFalse(test)) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2181
            loadAndDiscard(test);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2182
            if (fail != null) {
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2183
                fail.accept(this);
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2184
            }
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2185
            return false;
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2186
        }
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2187
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2188
        final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2189
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2190
        final Label failLabel  = new Label("if_fail");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2191
        final Label afterLabel = (fail == null && !hasFailConversion) ? null : new Label("if_done");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2192
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2193
        emitBranch(test, failLabel, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2194
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2195
        pass.accept(this);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2196
        if(method.isReachable() && afterLabel != null) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2197
            method._goto(afterLabel); //don't fallthru to fail block
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2198
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2199
        method.label(failLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2200
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2201
        if (fail != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2202
            fail.accept(this);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2203
        } else if(hasFailConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2204
            method.beforeJoinPoint(ifNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2205
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2206
27971
bff4872beee5 8066224: fixes for folding a constant-test ternary operator
attila
parents: 27970
diff changeset
  2207
        if(afterLabel != null && afterLabel.isReachable()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2208
            method.label(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2209
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2210
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2211
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2212
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2213
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2214
    private void emitBranch(final Expression test, final Label label, final boolean jumpWhenTrue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2215
        new BranchOptimizer(this, method).execute(test, label, jumpWhenTrue);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2216
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2217
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2218
    private void enterStatement(final Statement statement) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2219
        lineNumber(statement);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2220
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2221
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
  2222
    private void lineNumber(final Statement statement) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2223
        lineNumber(statement.getLineNumber());
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2224
    }
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2225
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
  2226
    private void lineNumber(final int lineNumber) {
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2227
        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
  2228
            method.lineNumber(lineNumber);
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2229
            lastLineNumber = lineNumber;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2230
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2231
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2232
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2233
    int getLastLineNumber() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2234
        return lastLineNumber;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2235
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2236
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2237
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2238
     * Load a list of nodes as an array of a specific type
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2239
     * The array will contain the visited nodes.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2240
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2241
     * @param arrayLiteralNode the array of contents
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2242
     * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2243
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2244
     * @return the method generator that was used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2245
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2246
    private MethodEmitter loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
18633
c2138d47b2c6 8017082: Long array literals were slightly broken
lagergren
parents: 18631
diff changeset
  2247
        assert arrayType == Type.INT_ARRAY || arrayType == Type.LONG_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2248
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2249
        final Expression[]    nodes    = arrayLiteralNode.getValue();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2250
        final Object          presets  = arrayLiteralNode.getPresets();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2251
        final int[]           postsets = arrayLiteralNode.getPostsets();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2252
        final Class<?>        type     = arrayType.getTypeClass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2253
        final List<ArrayUnit> units    = arrayLiteralNode.getUnits();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2254
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2255
        loadConstant(presets);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2256
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2257
        final Type elementType = arrayType.getElementType();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2258
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2259
        if (units != null) {
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2260
            final MethodEmitter savedMethod     = method;
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2261
            final FunctionNode  currentFunction = lc.getCurrentFunction();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2262
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2263
            for (final ArrayUnit arrayUnit : units) {
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2264
                unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2265
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2266
                final String className = unit.getUnitClassName();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2267
                assert unit != null;
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2268
                final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2269
                final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2270
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2271
                pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
17769
14ea7feaf658 8012522: Clean up lexical contexts - split out stack based functionality in CodeGenerator and generify NodeVisitors based on their LexicalContext type to avoid casts
lagergren
parents: 17766
diff changeset
  2272
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2273
                method.setFunctionNode(currentFunction);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2274
                method.begin();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2275
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2276
                defineCommonSplitMethodParameters();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2277
                defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), arrayType);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2278
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2279
                // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2280
                // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2281
                final int arraySlot = fixScopeSlot(currentFunction, 3);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2282
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2283
                lc.enterSplitNode();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2284
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2285
                for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2286
                    method.load(arrayType, arraySlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2287
                    storeElement(nodes, elementType, postsets[i]);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2288
                }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2289
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2290
                method.load(arrayType, arraySlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2291
                method._return();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2292
                lc.exitSplitNode();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2293
                method.end();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2294
                lc.releaseSlots();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2295
                popMethodEmitter();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2296
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2297
                assert method == savedMethod;
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2298
                method.loadCompilerConstant(CALLEE);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2299
                method.swap();
19084
daddbeee0058 8020356: ClassCastException Undefined->Scope on spiltter class generated for a large switch statement
hannesw
parents: 18872
diff changeset
  2300
                method.loadCompilerConstant(THIS);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2301
                method.swap();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2302
                method.loadCompilerConstant(SCOPE);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2303
                method.swap();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2304
                method.invokestatic(className, name, signature);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2305
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
  2306
                unit = lc.popCompileUnit(unit);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2307
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2308
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2309
            return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2310
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2311
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2312
        if(postsets.length > 0) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2313
            final int arraySlot = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2314
            method.storeTemp(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2315
            for (final int postset : postsets) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2316
                method.load(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2317
                storeElement(nodes, elementType, postset);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2318
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2319
            method.load(arrayType, arraySlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2320
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2321
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2322
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2323
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2324
    private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2325
        method.load(index);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2326
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2327
        final Expression element = nodes[index];
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2328
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2329
        if (element == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2330
            method.loadEmpty(elementType);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2331
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2332
            loadExpressionAsType(element, elementType);
16147
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
        method.arraystore();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2336
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2337
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2338
    private MethodEmitter loadArgsArray(final List<Expression> args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2339
        final Object[] array = new Object[args.size()];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2340
        loadConstant(array);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2341
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2342
        for (int i = 0; i < args.size(); i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2343
            method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2344
            method.load(i);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2345
            loadExpression(args.get(i), TypeBounds.OBJECT); // variable arity methods always take objects
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2346
            method.arraystore();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2347
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2348
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2349
        return method;
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
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2353
     * 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
  2354
     * subpackage. Do not call directly.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2355
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2356
     * @param string string to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2357
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2358
    void loadConstant(final String string) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2359
        final String       unitClassName = unit.getUnitClassName();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2360
        final ClassEmitter classEmitter  = unit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2361
        final int          index         = compiler.getConstantData().add(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2362
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2363
        method.load(index);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2364
        method.invokestatic(unitClassName, GET_STRING.symbolName(), methodDescriptor(String.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2365
        classEmitter.needGetConstantMethod(String.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2366
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2367
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2368
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2369
     * 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
  2370
     * subpackage. Do not call directly.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2371
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2372
     * @param object object to load
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2373
     */
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  2374
    void loadConstant(final Object object) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2375
        loadConstant(object, unit, method);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2376
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2377
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2378
    private void loadConstant(final Object object, final CompileUnit compileUnit, final MethodEmitter methodEmitter) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2379
        final String       unitClassName = compileUnit.getUnitClassName();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2380
        final ClassEmitter classEmitter  = compileUnit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2381
        final int          index         = compiler.getConstantData().add(object);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2382
        final Class<?>     cls           = object.getClass();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2383
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2384
        if (cls == PropertyMap.class) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2385
            methodEmitter.load(index);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2386
            methodEmitter.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2387
            classEmitter.needGetConstantMethod(PropertyMap.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2388
        } else if (cls.isArray()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2389
            methodEmitter.load(index);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2390
            final String methodName = ClassEmitter.getArrayMethodName(cls);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2391
            methodEmitter.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2392
            classEmitter.needGetConstantMethod(cls);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2393
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2394
            methodEmitter.loadConstants().load(index).arrayload();
19236
73d242d205f9 8020132: Big object literal with numerical keys exceeds method size
hannesw
parents: 19095
diff changeset
  2395
            if (object instanceof ArrayData) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2396
                methodEmitter.checkcast(ArrayData.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2397
                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
  2398
            } else if (cls != Object.class) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2399
                methodEmitter.checkcast(cls);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2400
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2401
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2402
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2403
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2404
    private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2405
        methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2406
    }
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  2407
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2408
    // literal values
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2409
    private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2410
        final Object value = node.getValue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2411
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2412
        if (value == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2413
            method.loadNull();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2414
        } else if (value instanceof Undefined) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2415
            method.loadUndefined(resultBounds.within(Type.OBJECT));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2416
        } else if (value instanceof String) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2417
            final String string = (String)value;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2418
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  2419
            if (string.length() > MethodEmitter.LARGE_STRING_THRESHOLD / 3) { // 3 == max bytes per encoded char
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2420
                loadConstant(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2421
            } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2422
                method.load(string);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2423
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2424
        } else if (value instanceof RegexToken) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2425
            loadRegex((RegexToken)value);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2426
        } else if (value instanceof Boolean) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2427
            method.load((Boolean)value);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2428
        } else if (value instanceof Integer) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2429
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2430
                method.load((Integer)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2431
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2432
            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2433
                method.load(((Integer)value).doubleValue());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2434
            } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2435
                method.load(((Integer)value).longValue());
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2436
            } else {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2437
                method.load((Integer)value);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2438
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2439
        } else if (value instanceof Long) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2440
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2441
                method.load((Long)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2442
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2443
            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2444
                method.load(((Long)value).doubleValue());
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2445
            } else {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2446
                method.load((Long)value);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2447
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2448
        } else if (value instanceof Double) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2449
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2450
                method.load((Double)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2451
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2452
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2453
                method.load((Double)value);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2454
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2455
        } else if (node instanceof ArrayLiteralNode) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2456
            final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2457
            final ArrayType atype = arrayLiteral.getArrayType();
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2458
            loadArray(arrayLiteral, atype);
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  2459
            globalAllocateArray(atype);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2460
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2461
            throw new UnsupportedOperationException("Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2462
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2463
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2464
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2465
    private MethodEmitter loadRegexToken(final RegexToken value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2466
        method.load(value.getExpression());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2467
        method.load(value.getOptions());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2468
        return globalNewRegExp();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2469
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2470
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2471
    private MethodEmitter loadRegex(final RegexToken regexToken) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2472
        if (regexFieldCount > MAX_REGEX_FIELDS) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2473
            return loadRegexToken(regexToken);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2474
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2475
        // 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
  2476
        final String       regexName    = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2477
        final ClassEmitter classEmitter = unit.getClassEmitter();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2478
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2479
        classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2480
        regexFieldCount++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2481
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2482
        // get field, if null create new regex, finally clone regex object
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2483
        method.getStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2484
        method.dup();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2485
        final Label cachedLabel = new Label("cached");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2486
        method.ifnonnull(cachedLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2487
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2488
        method.pop();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2489
        loadRegexToken(regexToken);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2490
        method.dup();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2491
        method.putStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2492
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2493
        method.label(cachedLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2494
        globalRegExpCopy();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2495
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2496
        return method;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2497
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2498
24747
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
     * 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
  2501
     * @param value value
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2502
     * @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
  2503
     * @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
  2504
     */
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2505
    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
  2506
        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
  2507
            boolean contains;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2508
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2509
            @Override
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2510
            public Boolean get() {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2511
                value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2512
                    @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
  2513
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2514
                        return false;
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2515
                    }
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2516
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2517
                    @Override
24764
722a9603b237 8043633: In order to remove global state outside of contexts, make sure Timing class is an instance and not a static global collection of data. Move into Context. Move -Dnashorn.timing to an official logging option.
lagergren
parents: 24760
diff changeset
  2518
                    public boolean enterObjectNode(final ObjectNode objectNode) {
24760
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2519
                        return false;
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2520
                    }
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2521
183f11df79ee 8043431: Fix yet another corner case of JDK-8041995
attila
parents: 24759
diff changeset
  2522
                    @Override
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2523
                    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
  2524
                        if (contains) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2525
                            return false;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2526
                        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2527
                        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
  2528
                            contains = true;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2529
                            return false;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2530
                        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2531
                        return true;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2532
                    }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2533
                });
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2534
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2535
                return contains;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2536
            }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2537
        }.get();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2538
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2539
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2540
    private void loadObjectNode(final ObjectNode objectNode) {
17981
9b8e085aa1fe 8015955: ObjectNode.elements should be stronger typed
attila
parents: 17969
diff changeset
  2541
        final List<PropertyNode> elements = objectNode.getElements();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2542
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2543
        final List<MapTuple<Expression>> tuples = new ArrayList<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2544
        final List<PropertyNode> gettersSetters = new ArrayList<>();
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2545
        final int ccp = getCurrentContinuationEntryPoint();
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2546
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2547
        Expression protoNode = null;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2548
        boolean restOfProperty = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2549
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2550
        for (final PropertyNode propertyNode : elements) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2551
            final Expression value = propertyNode.getValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2552
            final String key = propertyNode.getKeyName();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2553
            // Just use a pseudo-symbol. We just need something non null; use the name and zero flags.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2554
            final Symbol symbol = value == null ? null : new Symbol(key, 0);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2555
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2556
            if (value == null) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2557
                gettersSetters.add(propertyNode);
24281
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2558
            } else if (propertyNode.getKey() instanceof IdentNode &&
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2559
                       key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2560
                // ES6 draft compliant __proto__ inside object literal
58ed42a1ebc6 8042364: Make __proto__ ES6 draft compliant
sundar
parents: 23767
diff changeset
  2561
                // Identifier key and name is __proto__
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2562
                protoNode = value;
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2563
                continue;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2564
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2565
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2566
            restOfProperty |=
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2567
                value != null &&
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2568
                isValid(ccp) &&
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2569
                propertyValueContains(value, ccp);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2570
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2571
            //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
  2572
            //(I think)
29834
f678f348c947 8067215: Disable dual fields when not using optimistic types
hannesw
parents: 29410
diff changeset
  2573
            final Class<?> valueType = (!useDualFields() || value == null || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2574
            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
  2575
                @Override
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2576
                public Class<?> getValueType() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2577
                    return type.getTypeClass();
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2578
                }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2579
            });
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2580
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2581
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2582
        final ObjectCreator<?> oc;
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2583
        if (elements.size() > OBJECT_SPILL_THRESHOLD) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2584
            oc = new SpillObjectCreator(this, tuples);
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2585
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2586
            oc = new FieldObjectCreator<Expression>(this, tuples) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2587
                @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2588
                protected void loadValue(final Expression node, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2589
                    loadExpressionAsType(node, type);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2590
                }};
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2591
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2592
        oc.makeObject(method);
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2593
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2594
        //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
  2595
        //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
  2596
        //handler
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2597
        if (restOfProperty) {
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2598
            final ContinuationInfo ci = getContinuationInfo();
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2599
            // Can be set at most once for a single rest-of method
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  2600
            assert ci.getObjectLiteralMap() == null;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2601
            ci.setObjectLiteralMap(oc.getMap());
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  2602
            ci.setObjectLiteralStackDepth(method.getStackSize());
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  2603
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2604
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2605
        method.dup();
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2606
        if (protoNode != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2607
            loadExpressionAsObject(protoNode);
24772
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2608
            // take care of { __proto__: 34 } or some such!
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2609
            method.convert(Type.OBJECT);
0fc1013a1785 8044520: Nashorn cannot execute node.js's express module
sundar
parents: 24769
diff changeset
  2610
            method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2611
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2612
            method.invoke(ScriptObject.SET_GLOBAL_OBJECT_PROTO);
19881
d92851923f86 8024174: Setting __proto__ property in Object literal should be supported
sundar
parents: 19236
diff changeset
  2613
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2614
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2615
        for (final PropertyNode propertyNode : gettersSetters) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2616
            final FunctionNode getter = propertyNode.getGetter();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2617
            final FunctionNode setter = propertyNode.getSetter();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2618
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2619
            assert getter != null || setter != null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2620
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2621
            method.dup().loadKey(propertyNode.getKey());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2622
            if (getter == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2623
                method.loadNull();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2624
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2625
                getter.accept(this);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2626
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2627
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2628
            if (setter == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2629
                method.loadNull();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2630
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2631
                setter.accept(this);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2632
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2633
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2634
            method.invoke(ScriptObject.SET_USER_ACCESSORS);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2635
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2636
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2637
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2638
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2639
    public boolean enterReturnNode(final ReturnNode returnNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2640
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2641
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2642
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2643
        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
  2644
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
  2645
        final Type returnType = lc.getCurrentFunction().getReturnType();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2646
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2647
        final Expression expression = returnNode.getExpression();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2648
        if (expression != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2649
            loadExpressionUnbounded(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2650
        } else {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2651
            method.loadUndefined(returnType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2652
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2653
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2654
        method._return(returnType);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2655
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2656
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2657
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2658
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2659
    private boolean undefinedCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2660
        final Request request = runtimeNode.getRequest();
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2661
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2662
        if (!Request.isUndefinedCheck(request)) {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2663
            return false;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2664
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2665
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2666
        final Expression lhs = args.get(0);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2667
        final Expression rhs = args.get(1);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2668
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2669
        final Symbol lhsSymbol = lhs instanceof IdentNode ? ((IdentNode)lhs).getSymbol() : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2670
        final Symbol rhsSymbol = rhs instanceof IdentNode ? ((IdentNode)rhs).getSymbol() : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2671
        // One must be a "undefined" identifier, otherwise we can't get here
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2672
        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
  2673
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2674
        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
  2675
        if (isUndefinedSymbol(lhsSymbol)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2676
            undefinedSymbol = lhsSymbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2677
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2678
            assert isUndefinedSymbol(rhsSymbol);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2679
            undefinedSymbol = rhsSymbol;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2680
        }
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2681
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2682
        assert undefinedSymbol != null; //remove warning
24781
00f645e2d28a 8044803: Unnecessary restOf check
attila
parents: 24774
diff changeset
  2683
        if (!undefinedSymbol.isScope()) {
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2684
            return false; //disallow undefined as local var or parameter
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2685
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2686
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2687
        if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2688
            //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
  2689
            return false;
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2690
        }
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2691
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2692
        if(isDeoptimizedExpression(lhs)) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2693
            // 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
  2694
            // 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
  2695
            // 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
  2696
            // "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
  2697
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2698
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2699
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2700
        //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
  2701
        //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
  2702
        if (!compiler.isGlobalSymbol(lc.getCurrentFunction(), "undefined")) {
24738
be2026c9717c 8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents: 24736
diff changeset
  2703
            return false;
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2704
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2705
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2706
        final boolean isUndefinedCheck = request == Request.IS_UNDEFINED;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2707
        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
  2708
        if (expr.getType().isPrimitive()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2709
            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
  2710
            method.load(!isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2711
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2712
            final Label checkTrue  = new Label("ud_check_true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2713
            final Label end        = new Label("end");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2714
            loadExpressionAsObject(expr);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2715
            method.loadUndefined(Type.OBJECT);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2716
            method.if_acmpeq(checkTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2717
            method.load(!isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2718
            method._goto(end);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2719
            method.label(checkTrue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2720
            method.load(isUndefinedCheck);
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2721
            method.label(end);
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2722
        }
24736
4e7eba3d014b 8039044: Expand undefined intrinsics for all commutative combinators of scrict undefined checks
lagergren
parents: 24735
diff changeset
  2723
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2724
        return true;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2725
    }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2726
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2727
    private static boolean isUndefinedSymbol(final Symbol symbol) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2728
        return symbol != null && "undefined".equals(symbol.getName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2729
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2730
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2731
    private static boolean isNullLiteral(final Node node) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2732
        return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2733
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2734
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2735
    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2736
        final Request request = runtimeNode.getRequest();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2737
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2738
        if (!Request.isEQ(request) && !Request.isNE(request)) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2739
            return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2740
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2741
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2742
        assert args.size() == 2 : "EQ or NE or TYPEOF need two args";
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2743
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2744
        Expression lhs = args.get(0);
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2745
        Expression rhs = args.get(1);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2746
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2747
        if (isNullLiteral(lhs)) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2748
            final Expression tmp = lhs;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2749
            lhs = rhs;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2750
            rhs = tmp;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2751
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2752
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2753
        if (!isNullLiteral(rhs)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2754
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2755
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2756
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2757
        if (!lhs.getType().isObject()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2758
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2759
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2760
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2761
        if(isDeoptimizedExpression(lhs)) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2762
            // 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
  2763
            // 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
  2764
            // 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
  2765
            // 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
  2766
            // method and any of its (transitive) rest-ofs."
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2767
            // 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
  2768
            // 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
  2769
            // 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
  2770
            // operation.
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2771
            return false;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2772
        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2773
18631
537b279999e5 8016667: Wrong bytecode when testing/setting due to null check shortcut checking against primitive too
lagergren
parents: 18628
diff changeset
  2774
        // 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
  2775
        // involved like {D}x=null, we will fail - this is very rare
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2776
        final Label trueLabel  = new Label("trueLabel");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2777
        final Label falseLabel = new Label("falseLabel");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2778
        final Label endLabel   = new Label("end");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2779
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2780
        loadExpressionUnbounded(lhs);    //lhs
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2781
        final Label popLabel;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2782
        if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2783
            method.dup(); //lhs lhs
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2784
            popLabel = new Label("pop");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2785
        } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2786
            popLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2787
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2788
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2789
        if (Request.isEQ(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2790
            method.ifnull(!Request.isStrict(request) ? popLabel : trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2791
            if (!Request.isStrict(request)) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2792
                method.loadUndefined(Type.OBJECT);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2793
                method.if_acmpeq(trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2794
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2795
            method.label(falseLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2796
            method.load(false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2797
            method._goto(endLabel);
24719
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.label(popLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2800
                method.pop();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2801
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2802
            method.label(trueLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2803
            method.load(true);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2804
            method.label(endLabel);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2805
        } else if (Request.isNE(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2806
            method.ifnull(!Request.isStrict(request) ? popLabel : falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2807
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2808
                method.loadUndefined(Type.OBJECT);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2809
                method.if_acmpeq(falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2810
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2811
            method.label(trueLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2812
            method.load(true);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2813
            method._goto(endLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2814
            if (!Request.isStrict(request)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2815
                method.label(popLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2816
                method.pop();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2817
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2818
            method.label(falseLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2819
            method.load(false);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2820
            method.label(endLabel);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2821
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2822
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2823
        assert runtimeNode.getType().isBoolean();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2824
        method.convert(runtimeNode.getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2825
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2826
        return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2827
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2828
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2829
    /**
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2830
     * 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
  2831
     * @param rootExpr the expression being tested
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2832
     * @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
  2833
     */
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2834
    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
  2835
        if(!isRestOf()) {
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
        return new Supplier<Boolean>() {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2839
            boolean contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2840
            @Override
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2841
            public Boolean get() {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2842
                rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2843
                    @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
  2844
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2845
                        return false;
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
                    @Override
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2848
                    public boolean enterDefault(final Node node) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2849
                        if(!contains && node instanceof Optimistic) {
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2850
                            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
  2851
                            contains = isValid(pp) && isContinuationEntryPoint(pp);
24758
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2852
                        }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2853
                        return !contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2854
                    }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2855
                });
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2856
                return contains;
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2857
            }
eb9658fa0120 8043235: Type-based optimizations interfere with continuation methods
attila
parents: 24757
diff changeset
  2858
        }.get();
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  2859
    }
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  2860
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2861
    private void loadRuntimeNode(final RuntimeNode runtimeNode) {
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2862
        final List<Expression> args = new ArrayList<>(runtimeNode.getArgs());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2863
        if (nullCheck(runtimeNode, args)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2864
           return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2865
        } else if(undefinedCheck(runtimeNode, args)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2866
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2867
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2868
        // Revert a false undefined check to a strict equality check
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2869
        final RuntimeNode newRuntimeNode;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2870
        final Request request = runtimeNode.getRequest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2871
        if (Request.isUndefinedCheck(request)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2872
            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
  2873
        } else {
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2874
            newRuntimeNode = runtimeNode;
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2875
        }
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2876
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2877
        for (final Expression arg : args) {
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2878
            loadExpression(arg, TypeBounds.OBJECT);
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2879
        }
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2880
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2881
        method.invokestatic(
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2882
                CompilerConstants.className(ScriptRuntime.class),
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2883
                newRuntimeNode.getRequest().toString(),
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2884
                new FunctionSignature(
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2885
                    false,
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2886
                    false,
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2887
                    newRuntimeNode.getType(),
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  2888
                    args.size()).toString());
24735
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2889
9833d3ceed5b 8038945: Simplify strict undefined checks
lagergren
parents: 24731
diff changeset
  2890
        method.convert(newRuntimeNode.getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2891
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2892
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2893
    private void defineCommonSplitMethodParameters() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2894
        defineSplitMethodParameter(0, CALLEE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2895
        defineSplitMethodParameter(1, THIS);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2896
        defineSplitMethodParameter(2, SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2897
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2898
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2899
    private void defineSplitMethodParameter(final int slot, final CompilerConstants cc) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2900
        defineSplitMethodParameter(slot, Type.typeFor(cc.type()));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2901
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2902
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2903
    private void defineSplitMethodParameter(final int slot, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2904
        method.defineBlockLocalVariable(slot, slot + type.getSlots());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2905
        method.onLocalStore(type, slot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2906
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2907
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2908
    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
  2909
        // 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
  2910
        final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2911
        final int defaultScopeSlot = SCOPE.slot();
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2912
        int newExtraSlot = extraSlot;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2913
        if (actualScopeSlot != defaultScopeSlot) {
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2914
            if (actualScopeSlot == extraSlot) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2915
                newExtraSlot = extraSlot + 1;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2916
                method.defineBlockLocalVariable(newExtraSlot, newExtraSlot + 1);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2917
                method.load(Type.OBJECT, extraSlot);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2918
                method.storeHidden(Type.OBJECT, newExtraSlot);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2919
            } else {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2920
                method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2921
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2922
            method.load(SCOPE_TYPE, defaultScopeSlot);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2923
            method.storeCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2924
        }
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2925
        return newExtraSlot;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2926
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2927
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2928
    @Override
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2929
    public boolean enterSplitReturn(final SplitReturn splitReturn) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2930
        if (method.isReachable()) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2931
            method.loadUndefined(lc.getCurrentFunction().getReturnType())._return();
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2932
        }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2933
        return false;
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2934
    }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2935
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2936
    @Override
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2937
    public boolean enterSetSplitState(final SetSplitState setSplitState) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2938
        if (method.isReachable()) {
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2939
            method.setSplitState(setSplitState.getState());
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2940
        }
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  2941
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2942
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2943
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2944
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2945
    public boolean enterSwitchNode(final SwitchNode switchNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2946
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2947
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2948
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  2949
        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
  2950
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  2951
        final Expression     expression  = switchNode.getExpression();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2952
        final List<CaseNode> cases       = switchNode.getCases();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2953
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2954
        if (cases.isEmpty()) {
20569
2386d10eadd3 8026033: Switch should load expression even when there are no cases in it
sundar
parents: 20559
diff changeset
  2955
            // still evaluate expression for side-effects.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2956
            loadAndDiscard(expression);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  2957
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2958
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2959
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2960
        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
  2961
        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
  2962
        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
  2963
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  2964
        if (defaultCase != null && cases.size() == 1) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2965
            // default case only
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2966
            assert cases.get(0) == defaultCase;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2967
            loadAndDiscard(expression);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2968
            defaultCase.getBody().accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2969
            method.breakLabel(breakLabel, liveLocalsOnBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2970
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2971
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2972
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2973
        // 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
  2974
        // 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
  2975
        Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2976
        final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  2977
27970
7b0048b90967 8066225: NPE in MethodEmitter with duplicate integer switch cases
attila
parents: 27969
diff changeset
  2978
        if (switchNode.isUniqueInteger()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2979
            // Tree for sorting values.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2980
            final TreeMap<Integer, Label> tree = new TreeMap<>();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2981
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2982
            // Build up sorted tree.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2983
            for (final CaseNode caseNode : cases) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2984
                final Node test = caseNode.getTest();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2985
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2986
                if (test != null) {
16235
cc200fdc3478 8008206: The allInteger case for SwitchNode generation in CodeGenerator assumes integer LITERALS only.
lagergren
parents: 16233
diff changeset
  2987
                    final Integer value = (Integer)((LiteralNode<?>)test).getValue();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2988
                    final Label   entry = caseNode.getEntry();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2989
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2990
                    // Take first duplicate.
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  2991
                    if (!tree.containsKey(value)) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2992
                        tree.put(value, entry);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2993
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2994
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2995
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2996
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2997
            // Copy values and labels to arrays.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2998
            final int       size   = tree.size();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  2999
            final Integer[] values = tree.keySet().toArray(new Integer[size]);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3000
            final Label[]   labels = tree.values().toArray(new Label[size]);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3001
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3002
            // Discern low, high and range.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3003
            final int lo    = values[0];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3004
            final int hi    = values[size - 1];
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3005
            final long range = (long)hi - (long)lo + 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3006
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3007
            // Find an unused value for default.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3008
            int deflt = Integer.MIN_VALUE;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3009
            for (final int value : values) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3010
                if (deflt == value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3011
                    deflt++;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3012
                } else if (deflt < value) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3013
                    break;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3014
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3015
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3016
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3017
            // Load switch expression.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3018
            loadExpressionUnbounded(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3019
            final Type type = expression.getType();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3020
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3021
            // 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
  3022
            if (!type.isInteger()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3023
                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
  3024
                final Class<?> exprClass = type.getTypeClass();
18628
012cd852f881 8019488: switch on literals result in NoSuchMethodError or VerifyError
sundar
parents: 18621
diff changeset
  3025
                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
  3026
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3027
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3028
            if(hasSkipConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3029
                assert defaultLabel == breakLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3030
                defaultLabel = new Label("switch_skip");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3031
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3032
            // 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
  3033
            // smaller representation, favor TABLESWITCH when they're equal size.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3034
            if (range + 1 <= (size * 2) && range <= Integer.MAX_VALUE) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3035
                final Label[] table = new Label[(int)range];
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3036
                Arrays.fill(table, defaultLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3037
                for (int i = 0; i < size; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3038
                    final int value = values[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3039
                    table[value - lo] = labels[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3040
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3041
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  3042
                method.tableswitch(lo, hi, defaultLabel, table);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3043
            } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3044
                final int[] ints = new int[size];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3045
                for (int i = 0; i < size; i++) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3046
                    ints[i] = values[i];
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3047
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3048
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  3049
                method.lookupswitch(defaultLabel, ints, labels);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3050
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3051
            // 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
  3052
            // local variable conversions if neither case is taken.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3053
            if(hasSkipConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3054
                method.label(defaultLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3055
                method.beforeJoinPoint(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3056
                method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3057
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3058
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3059
            final Symbol tagSymbol = switchNode.getTag();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3060
            // TODO: we could have non-object tag
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3061
            final int tagSlot = tagSymbol.getSlot(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3062
            loadExpressionAsObject(expression);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3063
            method.store(tagSymbol, Type.OBJECT);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3064
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3065
            for (final CaseNode caseNode : cases) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3066
                final Expression test = caseNode.getTest();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3067
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3068
                if (test != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3069
                    method.load(Type.OBJECT, tagSlot);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3070
                    loadExpressionAsObject(test);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3071
                    method.invoke(ScriptRuntime.EQ_STRICT);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3072
                    method.ifne(caseNode.getEntry());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3073
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3074
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3075
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3076
            if (defaultCase != null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3077
                method._goto(defaultLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3078
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3079
                method.beforeJoinPoint(switchNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3080
                method._goto(breakLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3081
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3082
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3083
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3084
        // First case is only reachable through jump
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3085
        assert !method.isReachable();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3086
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3087
        for (final CaseNode caseNode : cases) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3088
            final Label fallThroughLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3089
            if(caseNode.getLocalVariableConversion() != null && method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3090
                fallThroughLabel = new Label("fallthrough");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3091
                method._goto(fallThroughLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3092
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3093
                fallThroughLabel = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3094
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3095
            method.label(caseNode.getEntry());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3096
            method.beforeJoinPoint(caseNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3097
            if(fallThroughLabel != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3098
                method.label(fallThroughLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3099
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3100
            caseNode.getBody().accept(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3101
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3102
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3103
        method.breakLabel(breakLabel, liveLocalsOnBreak);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3104
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3105
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3106
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3107
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3108
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3109
    public boolean enterThrowNode(final ThrowNode throwNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3110
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3111
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3112
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3113
        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
  3114
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3115
        if (throwNode.isSyntheticRethrow()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3116
            method.beforeJoinPoint(throwNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3117
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3118
            //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
  3119
            final IdentNode exceptionExpr = (IdentNode)throwNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3120
            final Symbol exceptionSymbol = exceptionExpr.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3121
            method.load(exceptionSymbol, EXCEPTION_TYPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3122
            method.checkcast(EXCEPTION_TYPE.getTypeClass());
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3123
            method.athrow();
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3124
            return false;
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3125
        }
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3126
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3127
        final Source     source     = getCurrentSource();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3128
        final Expression expression = throwNode.getExpression();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3129
        final int        position   = throwNode.position();
20559
9244eb6d195b 8025515: Performance issues with Source.getLine()
hannesw
parents: 20215
diff changeset
  3130
        final int        line       = throwNode.getLineNumber();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3131
        final int        column     = source.getColumn(position);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3132
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3133
        // 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
  3134
        // 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
  3135
        // 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
  3136
        // the not-yet-<init>ialized object on the stack from the UnwarrantedOptimismException handler, and bytecode
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3137
        // verifier forbids that.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3138
        loadExpressionAsObject(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3139
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3140
        method.load(source.getName());
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3141
        method.load(line);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3142
        method.load(column);
22387
81639250d335 8031983: Error objects should capture stack at the constructor
sundar
parents: 21868
diff changeset
  3143
        method.invoke(ECMAException.CREATE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3144
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3145
        method.beforeJoinPoint(throwNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3146
        method.athrow();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3147
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3148
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3149
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3150
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3151
    private Source getCurrentSource() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3152
        return lc.getCurrentFunction().getSource();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3153
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3154
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3155
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3156
    public boolean enterTryNode(final TryNode tryNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3157
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3158
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3159
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3160
        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
  3161
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3162
        final Block       body        = tryNode.getBody();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3163
        final List<Block> catchBlocks = tryNode.getCatchBlocks();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3164
        final Symbol      vmException = tryNode.getException();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3165
        final Label       entry       = new Label("try");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3166
        final Label       recovery    = new Label("catch");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3167
        final Label       exit        = new Label("end_try");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3168
        final Label       skip        = new Label("skip");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3169
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3170
        method.canThrow(recovery);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3171
        // 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
  3172
        // 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
  3173
        // 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
  3174
        // conversions of assignments within the try block.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3175
        method.beforeTry(tryNode, recovery);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3176
        method.label(entry);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3177
        catchLabels.push(recovery);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3178
        try {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3179
            body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3180
        } finally {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3181
            assert catchLabels.peek() == recovery;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3182
            catchLabels.pop();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3183
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3184
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3185
        method.label(exit);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3186
        final boolean bodyCanThrow = exit.isAfter(entry);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3187
        if(!bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3188
            // 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
  3189
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3190
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3191
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3192
        method._try(entry, exit, recovery, Throwable.class);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3193
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3194
        if (method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3195
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3196
        }
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3197
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3198
        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3199
            TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3200
            // All inlined finallies end with a jump or a return
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3201
            assert !method.isReachable();
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3202
        }
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3203
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3204
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3205
        method._catch(recovery);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3206
        method.store(vmException, EXCEPTION_TYPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3207
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3208
        final int catchBlockCount = catchBlocks.size();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3209
        final Label afterCatch = new Label("after_catch");
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3210
        for (int i = 0; i < catchBlockCount; i++) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3211
            assert method.isReachable();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3212
            final Block catchBlock = catchBlocks.get(i);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3213
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3214
            // 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
  3215
            // 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
  3216
            lc.push(catchBlock);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3217
            enterBlock(catchBlock);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3218
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3219
            final CatchNode  catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3220
            final IdentNode  exception          = catchNode.getException();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3221
            final Expression exceptionCondition = catchNode.getExceptionCondition();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3222
            final Block      catchBody          = catchNode.getBody();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3223
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3224
            new Store<IdentNode>(exception) {
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3225
                @Override
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3226
                protected void storeNonDiscard() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3227
                    // 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
  3228
                    // stored, so we override storeNonDiscard to be a no-op.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3229
                }
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
  3230
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3231
                @Override
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3232
                protected void evaluate() {
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3233
                    if (catchNode.isSyntheticRethrow()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3234
                        method.load(vmException, EXCEPTION_TYPE);
17745
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3235
                        return;
86e5a15b3b20 8014426: Original exception no longer thrown away when a finally rethrows
lagergren
parents: 17524
diff changeset
  3236
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3237
                    /*
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3238
                     * If caught object is an instance of ECMAException, then
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3239
                     * bind obj.thrown to the script catch var. Or else bind the
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3240
                     * caught object itself to the script catch var.
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3241
                     */
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3242
                    final Label notEcmaException = new Label("no_ecma_exception");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3243
                    method.load(vmException, EXCEPTION_TYPE).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3244
                    method.checkcast(ECMAException.class); //TODO is this necessary?
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3245
                    method.getField(ECMAException.THROWN);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3246
                    method.label(notEcmaException);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3247
                }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3248
            }.store();
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3249
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3250
            final boolean isConditionalCatch = exceptionCondition != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3251
            final Label nextCatch;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3252
            if (isConditionalCatch) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3253
                loadExpressionAsBoolean(exceptionCondition);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3254
                nextCatch = new Label("next_catch");
27823
a591041cf33c 8066232: problem with conditional catch compilation
attila
parents: 27817
diff changeset
  3255
                nextCatch.markAsBreakTarget();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3256
                method.ifeq(nextCatch);
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3257
            } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3258
                nextCatch = null;
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3259
            }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3260
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3261
            catchBody.accept(this);
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3262
            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
  3263
            lc.pop(catchBlock);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3264
            if(nextCatch != null) {
28690
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3265
                if(method.isReachable()) {
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3266
                    method._goto(afterCatch);
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3267
                }
27823
a591041cf33c 8066232: problem with conditional catch compilation
attila
parents: 27817
diff changeset
  3268
                method.breakLabel(nextCatch, lc.getUsedSlotCount());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3269
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3270
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3271
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3272
        // 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
  3273
        method.label(afterCatch);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3274
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3275
            method.markDeadLocalVariable(vmException);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3276
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3277
        method.label(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3278
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3279
        // 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
  3280
        assert tryNode.getFinallyBody() == null;
78317797ab62 8067139: Finally blocks inlined incorrectly
attila
parents: 28320
diff changeset
  3281
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3282
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3283
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3284
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3285
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3286
    public boolean enterVarNode(final VarNode varNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3287
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3288
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3289
        }
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3290
        final Expression init = varNode.getInit();
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3291
        final IdentNode identNode = varNode.getName();
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3292
        final Symbol identSymbol = identNode.getSymbol();
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3293
        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
  3294
        final boolean needsScope = identSymbol.isScope();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3295
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3296
        if (init == null) {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3297
            if (needsScope && varNode.isBlockScoped()) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3298
                // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3299
                method.loadCompilerConstant(SCOPE);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3300
                method.loadUndefined(Type.OBJECT);
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
  3301
                final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3302
                assert isFastScope(identSymbol);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3303
                storeFastScopeVar(identSymbol, flags);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3304
            }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3305
            return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3306
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3307
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3308
        enterStatement(varNode);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3309
        assert method != null;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3310
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3311
        if (needsScope) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3312
            method.loadCompilerConstant(SCOPE);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3313
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3314
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3315
        if (needsScope) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3316
            loadExpressionUnbounded(init);
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  3317
            // 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
  3318
            final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  3319
            if (isFastScope(identSymbol)) {
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  3320
                storeFastScopeVar(identSymbol, flags);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3321
            } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  3322
                method.dynamicSet(identNode.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3323
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3324
        } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3325
            final Type identType = identNode.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3326
            if(identType == Type.UNDEFINED) {
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3327
                // 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
  3328
                // or the left hand side is a dead variable.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3329
                assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3330
                loadAndDiscard(init);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3331
                return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3332
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3333
            loadExpressionAsType(init, identType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3334
            storeIdentWithCatchConversion(identNode, identType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3335
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3336
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3337
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3338
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3339
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3340
    private void storeIdentWithCatchConversion(final IdentNode identNode, final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3341
        // 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
  3342
        // that will be live at the exit from the try block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3343
        final LocalVariableConversion conversion = identNode.getLocalVariableConversion();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3344
        final Symbol symbol = identNode.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3345
        if(conversion != null && conversion.isLive()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3346
            assert symbol == conversion.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3347
            assert symbol.isBytecodeLocal();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3348
            // 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
  3349
            assert conversion.getNext() == null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3350
            assert conversion.getFrom() == type;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3351
            // We must propagate potential type change to the catch block
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3352
            final Label catchLabel = catchLabels.peek();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3353
            assert catchLabel != METHOD_BOUNDARY; // ident conversion only exists in try blocks
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3354
            assert catchLabel.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3355
            final Type joinType = conversion.getTo();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3356
            final Label.Stack catchStack = catchLabel.getStack();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3357
            final int joinSlot = symbol.getSlot(joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3358
            // 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
  3359
            // 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
  3360
            // 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
  3361
            // 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
  3362
            if(catchStack.getUsedSlotsWithLiveTemporaries() > joinSlot) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3363
                method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3364
                method.convert(joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3365
                method.store(symbol, joinType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3366
                catchLabel.getStack().onLocalStore(joinType, joinSlot, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3367
                method.canThrow(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3368
                // Store but keep the previous store live too.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3369
                method.store(symbol, type, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3370
                return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3371
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3372
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3373
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3374
        method.store(symbol, type, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3375
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3376
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3377
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3378
    public boolean enterWhileNode(final WhileNode whileNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3379
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3380
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3381
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3382
        if(whileNode.isDoWhile()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3383
            enterDoWhile(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3384
        } else {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3385
            enterStatement(whileNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3386
            enterForOrWhile(whileNode, null);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3387
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3388
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3389
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3390
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3391
    private void enterForOrWhile(final LoopNode loopNode, final JoinPredecessorExpression modify) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3392
        // 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
  3393
        // 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
  3394
        // 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
  3395
        // 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
  3396
        // 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
  3397
        // to double: var i = {valueOf: function() { return 1} }; while(--i >= 0) { ... }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3398
        // 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
  3399
        // different code shape.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3400
        final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3401
        final JoinPredecessorExpression test = loopNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3402
        if(Expression.isAlwaysFalse(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3403
            loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3404
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3405
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3406
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3407
        method.beforeJoinPoint(loopNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3408
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3409
        final Label continueLabel = loopNode.getContinueLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3410
        final Label repeatLabel = modify != null ? new Label("for_repeat") : continueLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3411
        method.label(repeatLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3412
        final int liveLocalsOnContinue = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3413
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3414
        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
  3415
        final Label   breakLabel            = loopNode.getBreakLabel();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3416
        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
  3417
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3418
        if(Expression.isAlwaysTrue(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3419
            if(test != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3420
                loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3421
                if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3422
                    method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3423
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3424
            }
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3425
        } 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
  3426
            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
  3427
                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
  3428
                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
  3429
                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
  3430
            } else {
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3431
                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
  3432
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3433
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3434
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3435
        body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3436
        if(repeatLabel != continueLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3437
            emitContinueLabel(continueLabel, liveLocalsOnContinue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3438
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3439
27977
42799be30dcd 8067219: NPE in ScriptObject.clone() when running with object fields
hannesw
parents: 27976
diff changeset
  3440
        if (loopNode.hasPerIterationScope() && lc.getCurrentBlock().needsScope()) {
27817
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3441
            // 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
  3442
            method.loadCompilerConstant(SCOPE);
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3443
            method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3444
            method.storeCompilerConstant(SCOPE);
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3445
        }
56f6161c3e55 8057980: let & const: remaining issues with lexical scoping
hannesw
parents: 27365
diff changeset
  3446
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3447
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3448
            if(modify != null) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3449
                lineNumber(loopNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3450
                loadAndDiscard(modify);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3451
                method.beforeJoinPoint(modify);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3452
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3453
            method._goto(repeatLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3454
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3455
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3456
        method.breakLabel(breakLabel, liveLocalsOnBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3457
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3458
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3459
    private void emitContinueLabel(final Label continueLabel, final int liveLocals) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3460
        final boolean reachable = method.isReachable();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3461
        method.breakLabel(continueLabel, liveLocals);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3462
        // 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
  3463
        // 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
  3464
        // must make sure those are thrown away.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3465
        if(!reachable) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3466
            method.undefineLocalVariables(lc.getUsedSlotCount(), false);
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3467
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3468
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3469
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3470
    private void enterDoWhile(final WhileNode whileNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3471
        final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3472
        method.beforeJoinPoint(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3473
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3474
        final Block body = whileNode.getBody();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3475
        body.accept(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3476
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3477
        emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3478
        if(method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3479
            lineNumber(whileNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3480
            final JoinPredecessorExpression test = whileNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3481
            final Label bodyEntryLabel = body.getEntryLabel();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3482
            final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3483
            if(Expression.isAlwaysFalse(test)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3484
                loadAndDiscard(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3485
                if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3486
                    method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3487
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3488
            } else if(testHasLiveConversion) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3489
                // 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
  3490
                final Label beforeExit = new Label("do_while_preexit");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3491
                emitBranch(test.getExpression(), beforeExit, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3492
                method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3493
                method._goto(bodyEntryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3494
                method.label(beforeExit);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3495
                method.beforeJoinPoint(test);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3496
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3497
                emitBranch(test.getExpression(), bodyEntryLabel, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3498
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3499
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3500
        method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3501
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3502
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3503
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3504
    @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3505
    public boolean enterWithNode(final WithNode withNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3506
        if(!method.isReachable()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3507
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3508
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3509
        enterStatement(withNode);
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3510
        final Expression expression = withNode.getExpression();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3511
        final Block      body       = withNode.getBody();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3512
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3513
        // 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
  3514
        // 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
  3515
        // 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
  3516
        // 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
  3517
        final boolean hasScope = method.hasScope();
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3518
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
  3519
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3520
            method.loadCompilerConstant(SCOPE);
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3521
        }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3522
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3523
        loadExpressionAsObject(expression);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3524
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3525
        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
  3526
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3527
            // Construct a WithObject if we have a scope
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3528
            method.invoke(ScriptRuntime.OPEN_WITH);
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3529
            method.storeCompilerConstant(SCOPE);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3530
            tryLabel = new Label("with_try");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3531
            method.label(tryLabel);
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3532
        } else {
20215
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3533
            // 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
  3534
            // for null or undefined value.
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  3535
            globalCheckObjectCoercible();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3536
            tryLabel = null;
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3537
        }
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3538
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3539
        // Always process body
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3540
        body.accept(this);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3541
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
  3542
        if (hasScope) {
17255
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3543
            // Ensure we always close the WithObject
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3544
            final Label endLabel   = new Label("with_end");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3545
            final Label catchLabel = new Label("with_catch");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3546
            final Label exitLabel  = new Label("with_exit");
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3547
aa61d23e36e5 8013419: Streamline handling of with and eval
attila
parents: 17246
diff changeset
  3548
            method.label(endLabel);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3549
            // 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
  3550
            // 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
  3551
            final boolean bodyCanThrow = endLabel.isAfter(tryLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3552
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3553
                method._try(tryLabel, endLabel, catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3554
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3555
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  3556
            final boolean reachable = method.isReachable();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3557
            if(reachable) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3558
                popScope();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3559
                if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3560
                    method._goto(exitLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3561
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3562
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3563
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3564
            if(bodyCanThrow) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3565
                method._catch(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3566
                popScopeException();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3567
                method.athrow();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3568
                if(reachable) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3569
                    method.label(exitLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3570
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3571
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3572
        }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  3573
        return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3574
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3575
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3576
    private void loadADD(final UnaryNode unaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3577
        loadExpression(unaryNode.getExpression(), resultBounds.booleanToInt().notWiderThan(Type.NUMBER));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3578
        if(method.peekType() == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3579
            // 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
  3580
            method.convert(Type.INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3581
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3582
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3583
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3584
    private void loadBIT_NOT(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3585
        loadExpression(unaryNode.getExpression(), TypeBounds.INT).load(-1).xor();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3586
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3587
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3588
    private void loadDECINC(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3589
        final Expression operand     = unaryNode.getExpression();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3590
        final Type       type        = unaryNode.getType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3591
        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
  3592
        final TokenType  tokenType   = unaryNode.tokenType();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3593
        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
  3594
        final boolean    isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3595
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3596
        assert !type.isObject();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3597
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3598
        new SelfModifyingStore<UnaryNode>(unaryNode, operand) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3599
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3600
            private void loadRhs() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3601
                loadExpression(operand, typeBounds, true);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3602
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3603
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3604
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3605
            protected void evaluate() {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3606
                if(isPostfix) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3607
                    loadRhs();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3608
                } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3609
                    new OptimisticOperation(unaryNode, typeBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3610
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3611
                        void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3612
                            loadRhs();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3613
                            loadMinusOne();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3614
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3615
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3616
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3617
                            doDecInc(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3618
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3619
                    }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(operand));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3620
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3621
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3622
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3623
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3624
            protected void storeNonDiscard() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3625
                super.storeNonDiscard();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3626
                if (isPostfix) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3627
                    new OptimisticOperation(unaryNode, typeBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3628
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3629
                        void loadStack() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3630
                            loadMinusOne();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3631
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3632
                        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3633
                        void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3634
                            doDecInc(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3635
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3636
                    }.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
  3637
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3638
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3639
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3640
            private void loadMinusOne() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3641
                if (type.isInteger()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3642
                    method.load(isIncrement ? 1 : -1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3643
                } else if (type.isLong()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3644
                    method.load(isIncrement ? 1L : -1L);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3645
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3646
                    method.load(isIncrement ? 1.0 : -1.0);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3647
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3648
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3649
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3650
            private void doDecInc(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3651
                method.add(programPoint);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3652
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3653
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3654
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3655
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3656
    private static int getOptimisticIgnoreCountForSelfModifyingExpression(final Expression target) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3657
        return target instanceof AccessNode ? 1 : target instanceof IndexNode ? 2 : 0;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3658
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3659
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3660
    private void loadAndDiscard(final Expression expr) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3661
        // 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
  3662
        // be able to eliminate even more checks.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3663
        if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3664
            assert !lc.isCurrentDiscard(expr);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3665
            // 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
  3666
            // undefined.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3667
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3668
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3669
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3670
        lc.pushDiscard(expr);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3671
        loadExpression(expr, TypeBounds.UNBOUNDED);
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3672
        if (lc.popDiscardIfCurrent(expr)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3673
            assert !expr.isAssignment();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3674
            // 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
  3675
            method.pop();
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3676
        }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3677
    }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3678
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3679
    /**
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3680
     * 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
  3681
     * then instead loads and discards the expression.
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3682
     * @param parent the parent expression that's tested for being the current discard
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3683
     * @param expr the expression that's either normally loaded or discard-loaded
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3684
     * @param resultBounds result bounds for when loading the expression normally
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3685
     */
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3686
    private void loadMaybeDiscard(final Expression parent, final Expression expr, final TypeBounds resultBounds) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3687
        loadMaybeDiscard(lc.popDiscardIfCurrent(parent), expr, resultBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3688
    }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3689
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3690
    /**
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3691
     * 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
  3692
     * 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
  3693
     * testing for being the current discard and loading the subexpressions.
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3694
     * @param discard if true, the expression is loaded and discarded
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3695
     * @param expr the expression that's either normally loaded or discard-loaded
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3696
     * @param resultBounds result bounds for when loading the expression normally
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3697
     */
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3698
    private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3699
        if (discard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3700
            loadAndDiscard(expr);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3701
        } else {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3702
            loadExpression(expr, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3703
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3704
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3705
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3706
    private void loadNEW(final UnaryNode unaryNode) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3707
        final CallNode callNode = (CallNode)unaryNode.getExpression();
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3708
        final List<Expression> args   = callNode.getArgs();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3709
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3710
        // Load function reference.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3711
        loadExpressionAsObject(callNode.getFunction()); // must detect type error
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3712
16210
8ad1381b69d0 8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents: 16209
diff changeset
  3713
        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3714
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3715
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3716
    private void loadNOT(final UnaryNode unaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3717
        final Expression expr = unaryNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3718
        if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3719
            // !!x is idiomatic boolean cast in JavaScript
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3720
            loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3721
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3722
            final Label trueLabel  = new Label("true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3723
            final Label afterLabel = new Label("after");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3724
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3725
            emitBranch(expr, trueLabel, true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3726
            method.load(true);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3727
            method._goto(afterLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3728
            method.label(trueLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3729
            method.load(false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3730
            method.label(afterLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3731
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3732
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3733
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3734
    private void loadSUB(final UnaryNode unaryNode, final TypeBounds resultBounds) {
24774
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3735
        final Type type = unaryNode.getType();
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3736
        assert type.isNumeric();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3737
        final TypeBounds numericBounds = resultBounds.booleanToInt();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3738
        new OptimisticOperation(unaryNode, numericBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3739
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3740
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3741
                final Expression expr = unaryNode.getExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3742
                loadExpression(expr, numericBounds.notWiderThan(Type.NUMBER));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3743
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3744
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3745
            void consumeStack() {
24774
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3746
                // 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
  3747
                // 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
  3748
                // 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
  3749
                if(type.isNumber()) {
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3750
                    method.convert(type);
da5a0201be9d 8044533: Deoptimizing negation produces wrong result for zero
attila
parents: 24773
diff changeset
  3751
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3752
                method.neg(getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3753
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3754
        }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3755
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3756
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3757
    public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3758
        loadAndDiscard(unaryNode.getExpression());
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3759
        if (!lc.popDiscardIfCurrent(unaryNode)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3760
            method.loadUndefined(resultBounds.widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3761
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3762
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3763
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3764
    public void loadADD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3765
        new OptimisticOperation(binaryNode, resultBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3766
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3767
            void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3768
                final TypeBounds operandBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3769
                final boolean isOptimistic = isValid(getProgramPoint());
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3770
                boolean forceConversionSeparation = false;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3771
                if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3772
                    operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3773
                } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3774
                    // Non-optimistic, non-FP +. Allow it to overflow.
27968
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3775
                    final Type widestOperationType = binaryNode.getWidestOperationType();
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3776
                    operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
52e31251a179 8066230: Undefined object type assertion when computing TypeBounds
attila
parents: 27823
diff changeset
  3777
                    forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3778
                }
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3779
                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3780
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3781
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3782
            @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  3783
            void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3784
                method.add(getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3785
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3786
        }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3787
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3788
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3789
    private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3790
        final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3791
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3792
        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(binaryNode);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3793
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3794
        final Label skip = new Label("skip");
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3795
        if(narrowestOperandType == Type.BOOLEAN) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3796
            // optimize all-boolean logical expressions
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3797
            final Label onTrue = new Label("andor_true");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3798
            emitBranch(binaryNode, onTrue, true);
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3799
            if (isCurrentDiscard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3800
                method.label(onTrue);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3801
            } else {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3802
                method.load(false);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3803
                method._goto(skip);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3804
                method.label(onTrue);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3805
                method.load(true);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3806
                method.label(skip);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3807
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3808
            return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3809
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3810
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3811
        final TypeBounds outBounds = resultBounds.notNarrowerThan(narrowestOperandType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3812
        final JoinPredecessorExpression lhs = (JoinPredecessorExpression)binaryNode.lhs();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3813
        final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3814
        final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3815
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3816
        loadExpression(lhs, outBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3817
        if (!isCurrentDiscard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3818
            method.dup();
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3819
        }
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3820
        method.convert(Type.BOOLEAN);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3821
        if (isAnd) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3822
            if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3823
                method.ifne(evalRhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3824
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3825
                method.ifeq(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3826
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3827
        } else if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3828
            method.ifeq(evalRhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3829
        } else {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3830
            method.ifne(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3831
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3832
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3833
        if(lhsConvert) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3834
            method.beforeJoinPoint(lhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3835
            method._goto(skip);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3836
            method.label(evalRhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3837
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3838
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3839
        if (!isCurrentDiscard) {
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3840
            method.pop();
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3841
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3842
        final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3843
        loadMaybeDiscard(isCurrentDiscard, rhs, outBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3844
        method.beforeJoinPoint(rhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3845
        method.label(skip);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3846
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3847
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3848
    private static boolean isLocalVariable(final Expression lhs) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3849
        return lhs instanceof IdentNode && isLocalVariable((IdentNode)lhs);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3850
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3851
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3852
    private static boolean isLocalVariable(final IdentNode lhs) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3853
        return lhs.getSymbol().isBytecodeLocal();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3854
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3855
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3856
    // 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
  3857
    private void loadASSIGN(final BinaryNode binaryNode) {
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3858
        final Expression lhs = binaryNode.lhs();
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  3859
        final Expression rhs = binaryNode.rhs();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3860
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3861
        final Type rhsType = rhs.getType();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3862
        // Detect dead assignments
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3863
        if(lhs instanceof IdentNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3864
            final Symbol symbol = ((IdentNode)lhs).getSymbol();
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  3865
            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.popDiscardIfCurrent(binaryNode)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3866
                loadAndDiscard(rhs);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3867
                method.markDeadLocalVariable(symbol);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3868
                return;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3869
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3870
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3871
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3872
        new Store<BinaryNode>(binaryNode, lhs) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3873
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3874
            protected void evaluate() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3875
                // 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
  3876
                // remain optimistic, and then explicitly convert to the required type if needed.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3877
                loadExpressionAsType(rhs, rhsType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3878
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3879
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3880
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3881
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3882
    /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3883
     * Binary self-assignment that can be optimistic: +=, -=, *=, and /=.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3884
     */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3885
    private abstract class BinaryOptimisticSelfAssignment extends SelfModifyingStore<BinaryNode> {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3886
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3887
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3888
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3889
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3890
         * @param node the assign op node
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3891
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3892
        BinaryOptimisticSelfAssignment(final BinaryNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3893
            super(node, node.lhs());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3894
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3895
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3896
        protected abstract void op(OptimisticOperation oo);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3897
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3898
        @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3899
        protected void evaluate() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3900
            final Expression lhs = assignNode.lhs();
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3901
            final Expression rhs = assignNode.rhs();
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3902
            final Type widestOperationType = assignNode.getWidestOperationType();
27969
c03b64ccbd0f 8066227: CodeGenerator load unitialized slot
attila
parents: 27968
diff changeset
  3903
            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widestOperationType);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3904
            new OptimisticOperation(assignNode, bounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3905
                @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3906
                void loadStack() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3907
                    final boolean forceConversionSeparation;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3908
                    if (isValid(getProgramPoint()) || widestOperationType == Type.NUMBER) {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3909
                        forceConversionSeparation = false;
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3910
                    } else {
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3911
                        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
  3912
                        forceConversionSeparation = operandType.narrowerThan(widestOperationType);
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3913
                    }
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3914
                    loadBinaryOperands(lhs, rhs, bounds, true, forceConversionSeparation);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3915
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3916
                @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3917
                void consumeStack() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3918
                    op(this);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3919
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3920
            }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(lhs));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3921
            method.convert(assignNode.getType());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3922
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3923
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3924
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3925
    /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3926
     * Non-optimistic binary self-assignment operation. Basically, everything except +=, -=, *=, and /=.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3927
     */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3928
    private abstract class BinarySelfAssignment extends SelfModifyingStore<BinaryNode> {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3929
        BinarySelfAssignment(final BinaryNode node) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3930
            super(node, node.lhs());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3931
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3932
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3933
        protected abstract void op();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3934
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3935
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3936
        protected void evaluate() {
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  3937
            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3938
            op();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3939
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3940
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3941
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3942
    private void loadASSIGN_ADD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3943
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3944
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3945
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3946
                assert !(binaryNode.getType().isObject() && oo.isOptimistic);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3947
                method.add(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3948
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3949
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3950
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3951
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3952
    private void loadASSIGN_BIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3953
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3954
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3955
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3956
                method.and();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3957
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3958
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3959
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3960
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3961
    private void loadASSIGN_BIT_OR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3962
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3963
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3964
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3965
                method.or();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3966
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3967
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3968
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3969
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3970
    private void loadASSIGN_BIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3971
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3972
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3973
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3974
                method.xor();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3975
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3976
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3977
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3978
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3979
    private void loadASSIGN_DIV(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3980
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3981
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3982
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3983
                method.div(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3984
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3985
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3986
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3987
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3988
    private void loadASSIGN_MOD(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3989
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3990
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3991
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3992
                method.rem(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3993
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3994
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3995
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3996
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3997
    private void loadASSIGN_MUL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  3998
        new BinaryOptimisticSelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  3999
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4000
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4001
                method.mul(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4002
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4003
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4004
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4005
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4006
    private void loadASSIGN_SAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4007
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4008
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4009
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4010
                method.sar();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4011
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4012
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4013
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4014
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4015
    private void loadASSIGN_SHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4016
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4017
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4018
            protected void op() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4019
                method.shl();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4020
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4021
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4022
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4023
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4024
    private void loadASSIGN_SHR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4025
        new BinarySelfAssignment(binaryNode) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4026
            @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4027
            protected void op() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4028
                doSHR();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4029
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4030
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4031
        }.store();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4032
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4033
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4034
    private void doSHR() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4035
        // TODO: make SHR optimistic
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4036
        method.shr();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4037
        toUint();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4038
    }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4039
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4040
    private void toUint() {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4041
        JSType.TO_UINT32_I.invoke(method);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4042
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4043
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4044
    private void loadASSIGN_SUB(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4045
        new BinaryOptimisticSelfAssignment(binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4046
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4047
            protected void op(final OptimisticOperation oo) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4048
                method.sub(oo.getProgramPoint());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4049
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4050
        }.store();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4051
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4052
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4053
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4054
     * Helper class for binary arithmetic ops
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4055
     */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4056
    private abstract class BinaryArith {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4057
        protected abstract void op(int programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4058
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4059
        protected void evaluate(final BinaryNode node, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4060
            final TypeBounds numericBounds = resultBounds.booleanToInt().objectToNumber();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4061
            new OptimisticOperation(node, numericBounds) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4062
                @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4063
                void loadStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4064
                    final TypeBounds operandBounds;
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  4065
                    boolean forceConversionSeparation = false;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4066
                    if(numericBounds.narrowest == Type.NUMBER) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4067
                        // 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
  4068
                        // and L2D after operand evaluation.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4069
                        assert numericBounds.widest == Type.NUMBER;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4070
                        operandBounds = numericBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4071
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4072
                        final boolean isOptimistic = isValid(getProgramPoint());
27358
8898e06e68c1 8061957: Some arithmetic operations have unnecessary widening
attila
parents: 27212
diff changeset
  4073
                        if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4074
                            operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4075
                        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4076
                            // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4077
                            operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4078
                                    numericBounds.widest), Type.NUMBER);
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  4079
                            forceConversionSeparation = node.getWidestOperationType().narrowerThan(numericBounds.widest);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4080
                        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4081
                    }
27208
e8a33eadb339 8058610: must not let long operations overflow
attila
parents: 27206
diff changeset
  4082
                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4083
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4084
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4085
                @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4086
                void consumeStack() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4087
                    op(getProgramPoint());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4088
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4089
            }.emit();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4090
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4091
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4092
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4093
    private void loadBIT_AND(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4094
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4095
        method.and();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4096
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4097
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4098
    private void loadBIT_OR(final BinaryNode binaryNode) {
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4099
        // Optimize x|0 to (int)x
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4100
        if (isRhsZero(binaryNode)) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4101
            loadExpressionAsType(binaryNode.lhs(), Type.INT);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4102
        } else {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4103
            loadBinaryOperands(binaryNode);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4104
            method.or();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4105
        }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4106
    }
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4107
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4108
    private static boolean isRhsZero(final BinaryNode binaryNode) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4109
        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
  4110
        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4111
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4112
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4113
    private void loadBIT_XOR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4114
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4115
        method.xor();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4116
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4117
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4118
    private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4119
        loadAndDiscard(binaryNode.lhs());
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4120
        loadMaybeDiscard(binaryNode, binaryNode.rhs(), resultBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4121
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4122
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4123
    private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4124
        loadMaybeDiscard(binaryNode, binaryNode.lhs(), resultBounds);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4125
        loadAndDiscard(binaryNode.rhs());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4126
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4127
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4128
    private void loadDIV(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4129
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4130
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4131
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4132
                method.div(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4133
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4134
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4135
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4136
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4137
    private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
29283
fb47e4d25a9f 8035712: Restore some of the RuntimeCallSite specializations
attila
parents: 29281
diff changeset
  4138
        loadComparisonOperands(binaryNode);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4139
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4140
        final Label trueLabel  = new Label("trueLabel");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4141
        final Label afterLabel = new Label("skip");
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4142
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4143
        method.conditionalJump(cond, trueLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4144
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4145
        method.load(Boolean.FALSE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4146
        method._goto(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4147
        method.label(trueLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4148
        method.load(Boolean.TRUE);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4149
        method.label(afterLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4150
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4151
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4152
    private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4153
        new BinaryArith() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4154
            @Override
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4155
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4156
                method.rem(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4157
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4158
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4159
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4160
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4161
    private void loadMUL(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4162
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4163
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4164
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4165
                method.mul(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4166
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4167
        }.evaluate(binaryNode, resultBounds);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4168
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4169
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4170
    private void loadSAR(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4171
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4172
        method.sar();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4173
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4174
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4175
    private void loadSHL(final BinaryNode binaryNode) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4176
        loadBinaryOperands(binaryNode);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4177
        method.shl();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4178
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4179
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4180
    private void loadSHR(final BinaryNode binaryNode) {
27212
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4181
        // Optimize x >>> 0 to (uint)x
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4182
        if (isRhsZero(binaryNode)) {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4183
            loadExpressionAsType(binaryNode.lhs(), Type.INT);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4184
            toUint();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4185
        } else {
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4186
            loadBinaryOperands(binaryNode);
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4187
            doSHR();
3361766097cd 8061955: asm.js idioms result in unnecessarily code emission
attila
parents: 27208
diff changeset
  4188
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4189
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4190
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4191
    private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4192
        new BinaryArith() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4193
            @Override
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4194
            protected void op(final int programPoint) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4195
                method.sub(programPoint);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4196
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4197
        }.evaluate(binaryNode, resultBounds);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4198
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4199
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4200
    @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
  4201
    public boolean enterLabelNode(final LabelNode labelNode) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4202
        labeledBlockBreakLiveLocals.push(lc.getUsedSlotCount());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4203
        return true;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4204
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4205
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4206
    @Override
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4207
    protected boolean enterDefault(final Node node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4208
        throw new AssertionError("Code generator entered node of type " + node.getClass().getName());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4209
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4210
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4211
    private void loadTernaryNode(final TernaryNode ternaryNode, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4212
        final Expression test = ternaryNode.getTest();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4213
        final JoinPredecessorExpression trueExpr  = ternaryNode.getTrueExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4214
        final JoinPredecessorExpression falseExpr = ternaryNode.getFalseExpression();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4215
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4216
        final Label falseLabel = new Label("ternary_false");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4217
        final Label exitLabel  = new Label("ternary_exit");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4218
24759
31aed7d9c02a 8034206: Make parts of code pipeline reusable in order to facilitate faster warmup and faster lazy compilation.
lagergren
parents: 24758
diff changeset
  4219
        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
  4220
        final TypeBounds outBounds = resultBounds.notNarrowerThan(outNarrowest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4221
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4222
        emitBranch(test, falseLabel, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4223
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4224
        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(ternaryNode);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4225
        loadMaybeDiscard(isCurrentDiscard, trueExpr.getExpression(), outBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4226
        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4227
        method.beforeJoinPoint(trueExpr);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4228
        method._goto(exitLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4229
        method.label(falseLabel);
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4230
        loadMaybeDiscard(isCurrentDiscard, falseExpr.getExpression(), outBounds);
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4231
        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4232
        method.beforeJoinPoint(falseExpr);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4233
        method.label(exitLabel);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4234
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4235
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4236
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4237
     * Generate all shared scope calls generated during codegen.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4238
     */
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4239
    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
  4240
        for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4241
            scopeAccess.generateScopeCall();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4242
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4243
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4244
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4245
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4246
     * Debug code used to print symbols
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4247
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4248
     * @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
  4249
     * @param function the function we are in
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4250
     * @param ident identifier for block or function where applicable
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4251
     */
26065
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4252
    private void printSymbols(final Block block, final FunctionNode function, final String ident) {
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4253
        if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4254
            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
  4255
            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
  4256
            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
  4257
                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
  4258
            }
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4259
            out.println();
d15adb218527 8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
sundar
parents: 26055
diff changeset
  4260
        }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4261
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4262
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4263
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4264
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4265
     * The difference between a store and a self modifying store is that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4266
     * the latter may load part of the target on the stack, e.g. the base
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4267
     * of an AccessNode or the base and index of an IndexNode. These are used
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4268
     * both as target and as an extra source. Previously it was problematic
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4269
     * for self modifying stores if the target/lhs didn't belong to one
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4270
     * of three trivial categories: IdentNode, AcessNodes, IndexNodes. In that
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4271
     * case it was evaluated and tagged as "resolved", which meant at the second
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4272
     * 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
  4273
     * it would be evaluated to a nop in the scope and cause stack underflow
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4274
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4275
     * see NASHORN-703
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4276
     *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4277
     * @param <T>
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4278
     */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4279
    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
  4280
        protected SelfModifyingStore(final T assignNode, final Expression target) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4281
            super(assignNode, target);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4282
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4283
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4284
        @Override
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4285
        protected boolean isSelfModifying() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4286
            return true;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4287
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4288
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4289
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4290
    /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4291
     * Helper class to generate stores
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4292
     */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4293
    private abstract class Store<T extends Expression> {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4294
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4295
        /** An assignment node, e.g. x += y */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4296
        protected final T assignNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4297
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4298
        /** 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
  4299
        private final Expression target;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4300
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4301
        /** How deep on the stack do the arguments go if this generates an indy call */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4302
        private int depth;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4303
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4304
        /** 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
  4305
        private IdentNode quick;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4306
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4307
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4308
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4309
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4310
         * @param assignNode the node representing the whole assignment
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4311
         * @param target     the target node of the assignment (destination)
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4312
         */
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4313
        protected Store(final T assignNode, final Expression target) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4314
            this.assignNode = assignNode;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4315
            this.target = target;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4316
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4317
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4318
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4319
         * Constructor
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4320
         *
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4321
         * @param assignNode the node representing the whole assignment
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4322
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4323
        protected Store(final T assignNode) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4324
            this(assignNode, assignNode);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4325
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4326
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4327
        /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4328
         * Is this a self modifying store operation, e.g. *= or ++
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4329
         * @return true if self modifying store
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4330
         */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4331
        protected boolean isSelfModifying() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4332
            return false;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4333
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4334
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4335
        private void prologue() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4336
            /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4337
             * This loads the parts of the target, e.g base and index. they are kept
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4338
             * on the stack throughout the store and used at the end to execute it
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4339
             */
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4340
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
  4341
            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4342
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4343
                public boolean enterIdentNode(final IdentNode node) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4344
                    if (node.getSymbol().isScope()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4345
                        method.loadCompilerConstant(SCOPE);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4346
                        depth += Type.SCOPE.getSlots();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4347
                        assert depth == 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4348
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4349
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4350
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4351
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4352
                private void enterBaseNode() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4353
                    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
  4354
                    final BaseNode   baseNode = (BaseNode)target;
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4355
                    final Expression base     = baseNode.getBase();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4356
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4357
                    loadExpressionAsObject(base);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4358
                    depth += Type.OBJECT.getSlots();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4359
                    assert depth == 1;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4360
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4361
                    if (isSelfModifying()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4362
                        method.dup();
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
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4367
                public boolean enterAccessNode(final AccessNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4368
                    enterBaseNode();
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4369
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4370
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4371
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4372
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4373
                public boolean enterIndexNode(final IndexNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4374
                    enterBaseNode();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4375
18867
bc91e3fcc5ba 8013925: Remove symbol fields from nodes that don't need them
attila
parents: 18865
diff changeset
  4376
                    final Expression index = node.getIndex();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4377
                    if (!index.getType().isNumeric()) {
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  4378
                        // could be boolean here as well
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4379
                        loadExpressionAsObject(index);
20928
3ff39d5c8c08 8026137: Fix Issues with Binary Evaluation Order
lagergren
parents: 20925
diff changeset
  4380
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4381
                        loadExpressionUnbounded(index);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4382
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4383
                    depth += index.getType().getSlots();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4384
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4385
                    if (isSelfModifying()) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4386
                        //convert "base base index" to "base index base index"
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4387
                        method.dup(1);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4388
                    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4389
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4390
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4391
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4392
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4393
            });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4394
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4395
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4396
        /**
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4397
         * 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
  4398
         * frame.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4399
         *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4400
         * @param type the type of the variable
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4401
         *
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4402
         * @return the quick variable
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4403
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4404
        private IdentNode quickLocalVariable(final Type type) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4405
            final String name = lc.getCurrentFunction().uniqueName(QUICK_PREFIX.symbolName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4406
            final Symbol symbol = new Symbol(name, IS_INTERNAL | HAS_SLOT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4407
            symbol.setHasSlotFor(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4408
            symbol.setFirstSlot(lc.quickSlot(type));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4409
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4410
            final IdentNode quickIdent = IdentNode.createInternalIdentifier(symbol).setType(type);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4411
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4412
            return quickIdent;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4413
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4414
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4415
        // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4416
        protected void storeNonDiscard() {
29410
cdfd8fbb2b1d 8074484: More agressive value discarding
attila
parents: 29283
diff changeset
  4417
            if (lc.popDiscardIfCurrent(assignNode)) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4418
                assert assignNode.isAssignment();
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4419
                return;
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4420
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4421
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4422
            if (method.dup(depth) == null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4423
                method.dup();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4424
                final Type quickType = method.peekType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4425
                this.quick = quickLocalVariable(quickType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4426
                final Symbol quickSymbol = quick.getSymbol();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4427
                method.storeTemp(quickType, quickSymbol.getFirstSlot());
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4428
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4429
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4430
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4431
        private void epilogue() {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4432
            /**
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4433
             * Take the original target args from the stack and use them
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4434
             * 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
  4435
             *
889ddb179cdf 8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents: 16190
diff changeset
  4436
             * 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
  4437
             * 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
  4438
             * very rare. See for example test/script/basic/access-specializer.js
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4439
             */
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
  4440
            target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4441
                @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
  4442
                protected boolean enterDefault(final Node node) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4443
                    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
  4444
                }
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4445
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4446
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4447
                public boolean enterIdentNode(final IdentNode node) {
16206
83069fa0935b 8006529: Methods always get callee - it should be conditional
attila
parents: 16201
diff changeset
  4448
                    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
  4449
                    assert symbol != null;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4450
                    if (symbol.isScope()) {
29941
4da7ab19348e 8077955: Undeclared globals in eval code should not be handled as fast scope
hannesw
parents: 29834
diff changeset
  4451
                        final int flags = getScopeCallSiteFlags(symbol);
16530
201d682e75f4 8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents: 16525
diff changeset
  4452
                        if (isFastScope(symbol)) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4453
                            storeFastScopeVar(symbol, flags);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4454
                        } else {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4455
                            method.dynamicSet(node.getName(), flags, false);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4456
                        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4457
                    } else {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4458
                        final Type storeType = assignNode.getType();
26241
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4459
                        if (symbol.hasSlotFor(storeType)) {
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4460
                            // 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
  4461
                            // give us an unnecessary ClassCastException.
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4462
                            method.convert(storeType);
fb1db04b455f 8055870: iteration fails if index var is not used
attila
parents: 26068
diff changeset
  4463
                        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4464
                        storeIdentWithCatchConversion(node, storeType);
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4465
                    }
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4466
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4467
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4468
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4469
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4470
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4471
                public boolean enterAccessNode(final AccessNode node) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4472
                    method.dynamicSet(node.getProperty(), getCallSiteFlags(), node.isIndex());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4473
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4474
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4475
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4476
                @Override
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4477
                public boolean enterIndexNode(final IndexNode node) {
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4478
                    method.dynamicSetIndex(getCallSiteFlags());
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4479
                    return false;
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4480
                }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4481
            });
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4482
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4483
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4484
            // whatever is on the stack now is the final answer
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4485
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4486
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4487
        protected abstract void evaluate();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4488
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4489
        void store() {
26377
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4490
            if (target instanceof IdentNode) {
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4491
                checkTemporalDeadZone((IdentNode)target);
028dad61662f 8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents: 26250
diff changeset
  4492
            }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4493
            prologue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4494
            evaluate(); // leaves an operation of whatever the operationType was on the stack
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4495
            storeNonDiscard();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4496
            epilogue();
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4497
            if (quick != null) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4498
                method.load(quick);
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4499
            }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4500
        }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4501
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4502
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4503
    private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4504
        assert lc.peek() == functionNode;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4505
27206
d4a707c9db5a 8059844: Implement optimistic splitter
attila
parents: 26890
diff changeset
  4506
        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
  4507
24784
ed11bdcc878a 8044816: On-demand compiled top-level program doesn't need :createProgramFunction
attila
parents: 24781
diff changeset
  4508
        if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4509
            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
  4510
                    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
  4511
                    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
  4512
            createFunction.begin();
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4513
            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
  4514
            createFunction.load(SCOPE_TYPE, 0);
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4515
            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
  4516
            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
  4517
            createFunction.end();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4518
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4519
26055
fe8be844ba50 8043956: Make code caching work with optimistic typing and lazy compilation
hannesw
parents: 25829
diff changeset
  4520
        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
  4521
            functionNode.getCompileUnit().addFunctionInitializer(data, functionNode);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4522
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4523
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4524
        // 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
  4525
        // generated in its outer context that'd need it as a callee).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4526
        if (lc.getOutermostFunction() == functionNode) {
17233
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4527
            return;
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4528
        }
72ccf78a8216 8010701: Immutable nodes - final iteration
lagergren
parents: 16530
diff changeset
  4529
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4530
        loadConstantsAndIndex(data, method);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4531
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4532
        if (functionNode.needsParentScope()) {
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  4533
            method.loadCompilerConstant(SCOPE);
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4534
            method.invoke(CREATE_FUNCTION_OBJECT);
18852
604c1d681b6f 8017084: Use spill properties for large object literals
hannesw
parents: 18851
diff changeset
  4535
        } else {
28320
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4536
            method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
bbf9cfde97f6 8068784: Halve the function object creation code size
attila
parents: 27977
diff changeset
  4537
        }
16233
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  4538
    }
95d3e01c04c3 8008199: Lazy compilation and trampoline implementation
lagergren
parents: 16226
diff changeset
  4539
18851
bdb92c95f886 8019947: inherited property invalidation does not work with two globals in same context
sundar
parents: 18844
diff changeset
  4540
    // calls on Global class.
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4541
    private MethodEmitter globalInstance() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4542
        return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';');
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4543
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4544
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4545
    private MethodEmitter globalAllocateArguments() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4546
        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
  4547
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4548
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4549
    private MethodEmitter globalNewRegExp() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4550
        return method.invokestatic(GLOBAL_OBJECT, "newRegExp", methodDescriptor(Object.class, String.class, String.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4551
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4552
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4553
    private MethodEmitter globalRegExpCopy() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4554
        return method.invokestatic(GLOBAL_OBJECT, "regExpCopy", methodDescriptor(Object.class, Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4555
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4556
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4557
    private MethodEmitter globalAllocateArray(final ArrayType type) {
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4558
        //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
  4559
        return method.invokestatic(GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;");
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4560
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4561
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4562
    private MethodEmitter globalIsEval() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4563
        return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4564
    }
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4565
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4566
    private MethodEmitter globalReplaceLocationPropertyPlaceholder() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4567
        return method.invokestatic(GLOBAL_OBJECT, "replaceLocationPropertyPlaceholder", methodDescriptor(Object.class, Object.class, Object.class));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4568
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4569
20215
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4570
    private MethodEmitter globalCheckObjectCoercible() {
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4571
        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
  4572
    }
984244201382 8025111: undefined or null 'with' expression in empty with block should throw TypeError
sundar
parents: 20209
diff changeset
  4573
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4574
    private MethodEmitter globalDirectEval() {
16240
e1468b33e201 8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents: 16235
diff changeset
  4575
        return method.invokestatic(GLOBAL_OBJECT, "directEval",
25423
ca63828cf996 8047067: all eval arguments need to be copied in Lower
attila
parents: 25256
diff changeset
  4576
                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  4577
    }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4578
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4579
    private abstract class OptimisticOperation {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4580
        private final boolean isOptimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4581
        // expression and optimistic are the same reference
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4582
        private final Expression expression;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4583
        private final Optimistic optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4584
        private final TypeBounds resultBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4585
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4586
        OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4587
            this.optimistic = optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4588
            this.expression = (Expression)optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4589
            this.resultBounds = resultBounds;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4590
            this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() &&
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4591
                    // 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
  4592
                    // is narrower than the upper bound.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4593
                    resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4594
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4595
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4596
        MethodEmitter emit() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4597
            return emit(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4598
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4599
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4600
        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
  4601
            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
  4602
            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
  4603
            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
  4604
            final int     stackSizeOnEntry              = method.getStackSize() - ignoredArgCount;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4605
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4606
            // First store the values on the stack opportunistically into local variables. Doing it before loadStack()
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4607
            // 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
  4608
            // storeStack().
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4609
            storeStack(ignoredArgCount, optimisticOrContinuation);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4610
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4611
            // Now, load the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4612
            loadStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4613
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4614
            // 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
  4615
            // (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
  4616
            // 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
  4617
            // 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
  4618
            // unfortunate cases this second storeStack() will restore the invariant that everything on the stack is
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4619
            // 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
  4620
            final int liveLocalsCount = storeStack(method.getStackSize() - stackSizeOnEntry, optimisticOrContinuation);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4621
            assert optimisticOrContinuation == (liveLocalsCount != -1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4622
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4623
            final Label beginTry;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4624
            final Label catchLabel;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4625
            final Label afterConsumeStack = isOptimistic || currentContinuationEntryPoint ? new Label("after_consume_stack") : null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4626
            if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4627
                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
  4628
                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
  4629
                catchLabel = new Label(catchLabelName);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4630
                method.label(beginTry);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4631
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4632
                beginTry = catchLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4633
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4634
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4635
            consumeStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4636
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4637
            if(isOptimistic) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4638
                method._try(beginTry, afterConsumeStack, catchLabel, UnwarrantedOptimismException.class);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4639
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4640
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4641
            if(isOptimistic || currentContinuationEntryPoint) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4642
                method.label(afterConsumeStack);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4643
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4644
                final int[] localLoads = method.getLocalLoadsOnStack(0, stackSizeOnEntry);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4645
                assert everyStackValueIsLocalLoad(localLoads) : Arrays.toString(localLoads) + ", " + stackSizeOnEntry + ", " + ignoredArgCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4646
                final List<Type> localTypesList = method.getLocalVariableTypes();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4647
                final int usedLocals = method.getUsedSlotsWithLiveTemporaries();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4648
                final List<Type> localTypes = method.getWidestLiveLocals(localTypesList.subList(0, usedLocals));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4649
                assert everyLocalLoadIsValid(localLoads, usedLocals) : Arrays.toString(localLoads) + " ~ " + localTypes;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4650
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4651
                if(isOptimistic) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4652
                    addUnwarrantedOptimismHandlerLabel(localTypes, catchLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4653
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4654
                if(currentContinuationEntryPoint) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4655
                    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
  4656
                    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
  4657
                    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
  4658
                    ci.setTargetLabel(afterConsumeStack);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4659
                    ci.getHandlerLabel().markAsOptimisticContinuationHandlerFor(afterConsumeStack);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4660
                    // 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
  4661
                    // dead local variables.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4662
                    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
  4663
                    ci.setStackStoreSpec(localLoads);
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  4664
                    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
  4665
                    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
  4666
                    ci.setReturnValueType(method.peekType());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4667
                    ci.lineNumber = getLastLineNumber();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4668
                    ci.catchLabel = catchLabels.peek();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4669
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4670
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4671
            return method;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4672
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4673
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4674
        /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4675
         * 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
  4676
         * can result in an {@code UnwarantedOptimizationException}.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4677
         * @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
  4678
         * 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
  4679
         * (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
  4680
         * 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
  4681
         * into fixing it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4682
         * @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
  4683
         * for temporary storage of ignored arguments are not returned).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4684
         * @param optimisticOrContinuation if false, this method should not execute
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4685
         * a label for a catch block for the {@code UnwarantedOptimizationException}, suitable for capturing the
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4686
         * currently live local variables, tailored to their types.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4687
         */
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4688
        private int storeStack(final int ignoreArgCount, final boolean optimisticOrContinuation) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4689
            if(!optimisticOrContinuation) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4690
                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
  4691
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4692
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4693
            final int stackSize = method.getStackSize();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4694
            final Type[] stackTypes = method.getTypesFromStack(stackSize);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4695
            final int[] localLoadsOnStack = method.getLocalLoadsOnStack(0, stackSize);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4696
            final int usedSlots = method.getUsedSlotsWithLiveTemporaries();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4697
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4698
            final int firstIgnored = stackSize - ignoreArgCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4699
            // 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
  4700
            int firstNonLoad = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4701
            while(firstNonLoad < firstIgnored && localLoadsOnStack[firstNonLoad] != Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4702
                firstNonLoad++;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4703
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4704
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4705
            // 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
  4706
            // the number of used slots as the number of live local variables.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4707
            if(firstNonLoad >= firstIgnored) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4708
                return usedSlots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4709
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4710
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4711
            // 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
  4712
            // are not direct loads of existing local variables.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4713
            int tempSlotsNeeded = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4714
            for(int i = firstNonLoad; i < stackSize; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4715
                if(localLoadsOnStack[i] == Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4716
                    tempSlotsNeeded += stackTypes[i].getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4717
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4718
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4720
            // 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
  4721
            // 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
  4722
            // ones end up at the end of the local variable table.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4723
            int lastTempSlot = usedSlots + tempSlotsNeeded;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4724
            int ignoreSlotCount = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4725
            for(int i = stackSize; i -- > firstNonLoad;) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4726
                final int loadSlot = localLoadsOnStack[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4727
                if(loadSlot == Label.Stack.NON_LOAD) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4728
                    final Type type = stackTypes[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4729
                    final int slots = type.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4730
                    lastTempSlot -= slots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4731
                    if(i >= firstIgnored) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4732
                        ignoreSlotCount += slots;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4733
                    }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4734
                    method.storeTemp(type, lastTempSlot);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4735
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4736
                    method.pop();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4737
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4738
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4739
            assert lastTempSlot == usedSlots; // used all temporary locals
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4740
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4741
            final List<Type> localTypesList = method.getLocalVariableTypes();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4742
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4743
            // Load values back on stack.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4744
            for(int i = firstNonLoad; i < stackSize; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4745
                final int loadSlot = localLoadsOnStack[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4746
                final Type stackType = stackTypes[i];
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4747
                final boolean isLoad = loadSlot != Label.Stack.NON_LOAD;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4748
                final int lvarSlot = isLoad ? loadSlot : lastTempSlot;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4749
                final Type lvarType = localTypesList.get(lvarSlot);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4750
                method.load(lvarType, lvarSlot);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4751
                if(isLoad) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4752
                    // 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
  4753
                    // 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
  4754
                    // on-stack conversion operators is necessary to accommodate for differences in local variable types
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4755
                    // after deoptimization; having a conversion operator throw away "load"-ness would create different
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4756
                    // local variable table shapes between optimism-failed code and its deoptimized rest-of method).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4757
                    // 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
  4758
                    // different.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4759
                    // 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
  4760
                    // 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
  4761
                    // in a deoptimized method, as their original input argument got widened. Maybe experiment with
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4762
                    // throwing away "load"-ness for narrowing conversions in MethodEmitter.convert()?
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4763
                    method.convert(stackType);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4764
                } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4765
                    // 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
  4766
                    assert lvarType == stackType;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4767
                    lastTempSlot += lvarType.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4768
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4769
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4770
            // used all temporaries
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4771
            assert lastTempSlot == usedSlots + tempSlotsNeeded;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4772
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4773
            return lastTempSlot - ignoreSlotCount;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4774
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4775
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4776
        private void addUnwarrantedOptimismHandlerLabel(final List<Type> localTypes, final Label label) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4777
            final String lvarTypesDescriptor = getLvarTypesDescriptor(localTypes);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4778
            final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.getUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4779
            Collection<Label> labels = unwarrantedOptimismHandlers.get(lvarTypesDescriptor);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4780
            if(labels == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4781
                labels = new LinkedList<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4782
                unwarrantedOptimismHandlers.put(lvarTypesDescriptor, labels);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4783
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4784
            method.markLabelAsOptimisticCatchHandler(label, localTypes.size());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4785
            labels.add(label);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4786
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4787
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4788
        abstract void loadStack();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4789
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4790
        // 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
  4791
        // 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
  4792
        // to use OptimisticExpression for emitting it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4793
        abstract void consumeStack();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4794
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4795
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4796
         * 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
  4797
         * 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
  4798
         * 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
  4799
         * 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
  4800
         * 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
  4801
         * conversion has no side effects.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4802
         * @param name the name of the property being get
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4803
         * @param flags call site flags
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4804
         * @param isMethod whether we're preferrably retrieving a function
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4805
         * @return the current method emitter
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4806
         */
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4807
        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
  4808
            if(isOptimistic) {
27976
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4809
                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
  4810
            }
ef54dfb4fc7d 8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents: 27971
diff changeset
  4811
            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod, isIndex);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4812
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4813
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4814
        MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4815
            if(isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4816
                return method.dynamicGetIndex(getOptimisticCoercedType(), getOptimisticFlags(flags), isMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4817
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4818
            return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4819
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4820
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4821
        MethodEmitter dynamicCall(final int argCount, final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4822
            if (isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4823
                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4824
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4825
            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4826
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4827
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4828
        int getOptimisticFlags(final int flags) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4829
            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
  4830
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4831
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4832
        int getProgramPoint() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4833
            return isOptimistic ? optimistic.getProgramPoint() : INVALID_PROGRAM_POINT;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4834
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4835
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4836
        void convertOptimisticReturnValue() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4837
            if (isOptimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4838
                final Type optimisticType = getOptimisticCoercedType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4839
                if(!optimisticType.isObject()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4840
                    method.load(optimistic.getProgramPoint());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4841
                    if(optimisticType.isInteger()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4842
                        method.invoke(ENSURE_INT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4843
                    } else if(optimisticType.isLong()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4844
                        method.invoke(ENSURE_LONG);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4845
                    } else if(optimisticType.isNumber()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4846
                        method.invoke(ENSURE_NUMBER);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4847
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4848
                        throw new AssertionError(optimisticType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4849
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4850
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4851
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4852
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4853
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4854
        void replaceCompileTimeProperty() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4855
            final IdentNode identNode = (IdentNode)expression;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4856
            final String name = identNode.getSymbol().getName();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4857
            if (CompilerConstants.__FILE__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4858
                replaceCompileTimeProperty(getCurrentSource().getName());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4859
            } else if (CompilerConstants.__DIR__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4860
                replaceCompileTimeProperty(getCurrentSource().getBase());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4861
            } else if (CompilerConstants.__LINE__.name().equals(name)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4862
                replaceCompileTimeProperty(getCurrentSource().getLine(identNode.position()));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4863
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4864
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4865
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4866
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4867
         * 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
  4868
         * 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
  4869
         * 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
  4870
         * 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
  4871
         * 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
  4872
         * 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
  4873
         * @param propertyValue the actual value of the property
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4874
         */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4875
        private void replaceCompileTimeProperty(final Object propertyValue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4876
            assert method.peekType().isObject();
25826
3d2dd01a3a4a 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval()
sundar
parents: 25821
diff changeset
  4877
            if(propertyValue instanceof String || propertyValue == null) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4878
                method.load((String)propertyValue);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4879
            } else if(propertyValue instanceof Integer) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4880
                method.load(((Integer)propertyValue).intValue());
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4881
                method.convert(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4882
            } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4883
                throw new AssertionError();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4884
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4885
            globalReplaceLocationPropertyPlaceholder();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4886
            convertOptimisticReturnValue();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4887
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4888
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4889
        /**
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4890
         * 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
  4891
         * 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
  4892
         * 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
  4893
         * 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
  4894
         * 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
  4895
         * affect it.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4896
         * @return
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4897
         */
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4898
        private Type getOptimisticCoercedType() {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4899
            final Type optimisticType = expression.getType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4900
            assert resultBounds.widest.widerThan(optimisticType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4901
            final Type narrowest = resultBounds.narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4902
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4903
            if(narrowest.isBoolean() || narrowest.narrowerThan(optimisticType)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4904
                assert !optimisticType.isObject();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4905
                return optimisticType;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4906
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4907
            assert !narrowest.isObject();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4908
            return narrowest;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4909
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4910
    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4911
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4912
    private static boolean isOptimistic(final Optimistic optimistic) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4913
        if(!optimistic.canBeOptimistic()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4914
            return false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4915
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4916
        final Expression expr = (Expression)optimistic;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4917
        return expr.getType().narrowerThan(expr.getWidestOperationType());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4918
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4919
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
  4920
    private static boolean everyLocalLoadIsValid(final int[] loads, final int localCount) {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4921
        for (final int load : loads) {
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4922
            if(load < 0 || load >= localCount) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4923
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4924
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4925
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4926
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4927
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4928
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4929
    private static boolean everyStackValueIsLocalLoad(final int[] loads) {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4930
        for (final int load : loads) {
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  4931
            if(load == Label.Stack.NON_LOAD) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4932
                return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4933
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4934
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4935
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4936
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4937
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4938
    private String getLvarTypesDescriptor(final List<Type> localVarTypes) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4939
        final int count = localVarTypes.size();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4940
        final StringBuilder desc = new StringBuilder(count);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4941
        for(int i = 0; i < count;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4942
            i += appendType(desc, localVarTypes.get(i));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4943
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4944
        return method.markSymbolBoundariesInLvarTypesDescriptor(desc.toString());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4945
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4946
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4947
    private static int appendType(final StringBuilder b, final Type t) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4948
        b.append(t.getBytecodeStackType());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4949
        return t.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4950
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4951
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4952
    private static int countSymbolsInLvarTypeDescriptor(final String lvarTypeDescriptor) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4953
        int count = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4954
        for(int i = 0; i < lvarTypeDescriptor.length(); ++i) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4955
            if(Character.isUpperCase(lvarTypeDescriptor.charAt(i))) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4956
                ++count;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4957
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4958
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4959
        return count;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4960
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4961
    }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4962
    /**
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4963
     * Generates all the required {@code UnwarrantedOptimismException} handlers for the current function. The employed
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4964
     * 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
  4965
     * 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
  4966
     * 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
  4967
     * 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
  4968
     * 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
  4969
     * entry to its immediately preceding one for longest matching prefix.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4970
     * @return true if there is at least one exception handler
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4971
     */
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  4972
    private boolean generateUnwarrantedOptimismExceptionHandlers(final FunctionNode fn) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4973
        if(!useOptimisticTypes()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4974
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4975
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4976
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4977
        // 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
  4978
        // handler specifications.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4979
        final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.popUnwarrantedOptimismHandlers();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4980
        if(unwarrantedOptimismHandlers.isEmpty()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4981
            return false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4982
        }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4983
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4984
        method.lineNumber(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  4985
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4986
        final List<OptimismExceptionHandlerSpec> handlerSpecs = new ArrayList<>(unwarrantedOptimismHandlers.size() * 4/3);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4987
        for(final String spec: unwarrantedOptimismHandlers.keySet()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4988
            handlerSpecs.add(new OptimismExceptionHandlerSpec(spec, true));
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4989
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4990
        Collections.sort(handlerSpecs, Collections.reverseOrder());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4991
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4992
        // 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
  4993
        final Map<String, Label> delegationLabels = new HashMap<>();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4994
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4995
        // 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
  4996
        // 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
  4997
        for(int handlerIndex = 0; handlerIndex < handlerSpecs.size(); ++handlerIndex) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4998
            final OptimismExceptionHandlerSpec spec = handlerSpecs.get(handlerIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  4999
            final String lvarSpec = spec.lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5000
            if(spec.catchTarget) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5001
                assert !method.isReachable();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5002
                // Start a catch block and assign the labels for this lvarSpec with it.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5003
                method._catch(unwarrantedOptimismHandlers.get(lvarSpec));
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5004
                // 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
  5005
                // symbols - the number of uppercase characters.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5006
                method.load(countSymbolsInLvarTypeDescriptor(lvarSpec));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5007
                method.newarray(Type.OBJECT_ARRAY);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5008
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5009
            if(spec.delegationTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5010
                // 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
  5011
                // shared code (after the array creation code, which is never shared).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5012
                method.label(delegationLabels.get(lvarSpec)); // label must exist
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5013
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5014
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5015
            final boolean lastHandler = handlerIndex == handlerSpecs.size() - 1;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5016
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5017
            int lvarIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5018
            final int firstArrayIndex;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5019
            final int firstLvarIndex;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5020
            Label delegationLabel;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5021
            final String commonLvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5022
            if(lastHandler) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5023
                // Last handler block, doesn't delegate to anything.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5024
                lvarIndex = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5025
                firstLvarIndex = 0;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5026
                firstArrayIndex = 0;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5027
                delegationLabel = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5028
                commonLvarSpec = null;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5029
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5030
                // 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
  5031
                // 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
  5032
                // prefix handler.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5033
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5034
                // 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
  5035
                // this handler and the next handler on the list.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5036
                final int nextHandlerIndex = handlerIndex + 1;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5037
                final String nextLvarSpec = handlerSpecs.get(nextHandlerIndex).lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5038
                commonLvarSpec = commonPrefix(lvarSpec, nextLvarSpec);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5039
                // We don't chop symbols in half
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5040
                assert Character.isUpperCase(commonLvarSpec.charAt(commonLvarSpec.length() - 1));
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5041
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5042
                // 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
  5043
                {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5044
                    boolean addNewHandler = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5045
                    int commonHandlerIndex = nextHandlerIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5046
                    for(; commonHandlerIndex < handlerSpecs.size(); ++commonHandlerIndex) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5047
                        final OptimismExceptionHandlerSpec forwardHandlerSpec = handlerSpecs.get(commonHandlerIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5048
                        final String forwardLvarSpec = forwardHandlerSpec.lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5049
                        if(forwardLvarSpec.equals(commonLvarSpec)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5050
                            // We already have a handler for the common prefix.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5051
                            addNewHandler = false;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5052
                            // Make sure we mark it as a delegation target.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5053
                            forwardHandlerSpec.delegationTarget = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5054
                            break;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5055
                        } else if(!forwardLvarSpec.startsWith(commonLvarSpec)) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5056
                            break;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5057
                        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5058
                    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5059
                    if(addNewHandler) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5060
                        // We need to insert a common prefix handler. Note handlers created with catchTarget == false
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5061
                        // will automatically have delegationTarget == true (because that's the only reason for their
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5062
                        // existence).
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5063
                        handlerSpecs.add(commonHandlerIndex, new OptimismExceptionHandlerSpec(commonLvarSpec, false));
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
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5067
                firstArrayIndex = countSymbolsInLvarTypeDescriptor(commonLvarSpec);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5068
                lvarIndex = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5069
                for(int j = 0; j < commonLvarSpec.length(); ++j) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5070
                    lvarIndex += CodeGeneratorLexicalContext.getTypeForSlotDescriptor(commonLvarSpec.charAt(j)).getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5071
                }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5072
                firstLvarIndex = lvarIndex;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5073
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5074
                // Create a delegation label if not already present
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5075
                delegationLabel = delegationLabels.get(commonLvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5076
                if(delegationLabel == null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5077
                    // uo_pa == "unwarranted optimism, populate array"
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5078
                    delegationLabel = new Label("uo_pa_" + commonLvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5079
                    delegationLabels.put(commonLvarSpec, delegationLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5080
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5081
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5082
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5083
            // Load local variables handled by this handler on stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5084
            int args = 0;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5085
            boolean symbolHadValue = false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5086
            for(int typeIndex = commonLvarSpec == null ? 0 : commonLvarSpec.length(); typeIndex < lvarSpec.length(); ++typeIndex) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5087
                final char typeDesc = lvarSpec.charAt(typeIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5088
                final Type lvarType = CodeGeneratorLexicalContext.getTypeForSlotDescriptor(typeDesc);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5089
                if (!lvarType.isUnknown()) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5090
                    method.load(lvarType, lvarIndex);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5091
                    symbolHadValue = true;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5092
                    args++;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5093
                } else if(typeDesc == 'U' && !symbolHadValue) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5094
                    // 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
  5095
                    // 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
  5096
                    // 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
  5097
                    // 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
  5098
                    // 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
  5099
                    // 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
  5100
                    // 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
  5101
                    // 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
  5102
                    // 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
  5103
                    // 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
  5104
                    // 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
  5105
                    if(method.peekType() == Type.UNDEFINED) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5106
                        method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5107
                    } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5108
                        method.loadUndefined(Type.OBJECT);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5109
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5110
                    args++;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5111
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5112
                if(Character.isUpperCase(typeDesc)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5113
                    // Reached symbol boundary; reset flag for the next symbol.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5114
                    symbolHadValue = false;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5115
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5116
                lvarIndex += lvarType.getSlots();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5117
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5118
            assert args > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5119
            // Delegate actual storing into array to an array populator utility method.
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5120
            //on the stack:
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5121
            // object array to be populated
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5122
            // start index
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5123
            // a lot of types
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5124
            method.dynamicArrayPopulatorCall(args + 1, firstArrayIndex);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5125
            if(delegationLabel != null) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5126
                // 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
  5127
                // RewriteException.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5128
                assert !lastHandler;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5129
                assert commonLvarSpec != null;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5130
                // 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
  5131
                // delegate label
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5132
                method.undefineLocalVariables(firstLvarIndex, true);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5133
                final OptimismExceptionHandlerSpec nextSpec = handlerSpecs.get(handlerIndex + 1);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5134
                // 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
  5135
                // 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
  5136
                if(!nextSpec.lvarSpec.equals(commonLvarSpec) || nextSpec.catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5137
                    method._goto(delegationLabel);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5138
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5139
            } else {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5140
                assert lastHandler;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5141
                // Nothing to delegate to, so this handler must create and throw the RewriteException.
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5142
                // At this point we have the UnwarrantedOptimismException and the Object[] with local variables on
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5143
                // stack. We need to create a RewriteException, push two references to it below the constructor
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5144
                // arguments, invoke the constructor, and throw the exception.
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5145
                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
  5146
                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
  5147
                    loadConstant(getContinuationEntryPoints());
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
  5148
                    method.invoke(CREATE_REWRITE_EXCEPTION_REST_OF);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5149
                } else {
24773
34c21f8464c5 8044171: Make optimistic exception handlers smaller
attila
parents: 24772
diff changeset
  5150
                    method.invoke(CREATE_REWRITE_EXCEPTION);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5151
                }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5152
                method.athrow();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5153
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5154
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5155
        return true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5156
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5157
24729
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5158
    private static String[] getByteCodeSymbolNames(final FunctionNode fn) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5159
        // 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
  5160
        // 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
  5161
        // 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
  5162
        // here.
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5163
        final List<String> names = new ArrayList<>();
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5164
        for (final Symbol symbol: fn.getBody().getSymbols()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5165
            if (symbol.hasSlot()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5166
                if (symbol.isScope()) {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5167
                    // slot + scope can only be true for parameters
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5168
                    assert symbol.isParam();
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5169
                    names.add(null);
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5170
                } else {
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5171
                    names.add(symbol.getName());
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5172
                }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5173
            }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5174
        }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5175
        return names.toArray(new String[names.size()]);
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5176
    }
2b13051f2122 8037534: Use scope types to determine optimistic types
attila
parents: 24727
diff changeset
  5177
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
  5178
    private static String commonPrefix(final String s1, final String s2) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5179
        final int l1 = s1.length();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5180
        final int l = Math.min(l1, s2.length());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5181
        int lms = -1; // last matching symbol
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5182
        for(int i = 0; i < l; ++i) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5183
            final char c1 = s1.charAt(i);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5184
            if(c1 != s2.charAt(i)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5185
                return s1.substring(0, lms + 1);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5186
            } else if(Character.isUpperCase(c1)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5187
                lms = i;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5188
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5189
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5190
        return l == l1 ? s1 : s2;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5191
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5192
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5193
    private static class OptimismExceptionHandlerSpec implements Comparable<OptimismExceptionHandlerSpec> {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5194
        private final String lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5195
        private final boolean catchTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5196
        private boolean delegationTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5197
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
  5198
        OptimismExceptionHandlerSpec(final String lvarSpec, final boolean catchTarget) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5199
            this.lvarSpec = lvarSpec;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5200
            this.catchTarget = catchTarget;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5201
            if(!catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5202
                delegationTarget = true;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5203
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5204
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5205
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5206
        @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
  5207
        public int compareTo(final OptimismExceptionHandlerSpec o) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5208
            return lvarSpec.compareTo(o.lvarSpec);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5209
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5210
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5211
        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5212
        public String toString() {
24720
75f8388b79df 8035836: Array performance improvements
lagergren
parents: 24719
diff changeset
  5213
            final StringBuilder b = new StringBuilder(64).append("[HandlerSpec ").append(lvarSpec);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5214
            if(catchTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5215
                b.append(", catchTarget");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5216
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5217
            if(delegationTarget) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5218
                b.append(", delegationTarget");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5219
            }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5220
            return b.append("]").toString();
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5221
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5222
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5223
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5224
    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
  5225
        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
  5226
        private Label targetLabel; // Label for the target instruction.
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5227
        int lvarCount;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5228
        // 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
  5229
        private int[] stackStoreSpec;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5230
        // 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
  5231
        private Type[] stackTypes;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5232
        // 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
  5233
        private Type returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5234
        // If we are in the middle of an object literal initialization, we need to update the map
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5235
        private PropertyMap objectLiteralMap;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5236
        // Object literal stack depth for object literal - not necessarly top if property is a tree
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5237
        private int objectLiteralStackDepth = -1;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5238
        // The line number at the continuation point
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5239
        private int lineNumber;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5240
        // 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
  5241
        private Label catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5242
        // 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
  5243
        private int exceptionScopePops;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5244
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5245
        ContinuationInfo() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5246
            this.handlerLabel = new Label("continuation_handler");
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5247
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5248
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5249
        Label getHandlerLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5250
            return handlerLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5251
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5252
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5253
        boolean hasTargetLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5254
            return targetLabel != null;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5255
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5256
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5257
        Label getTargetLabel() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5258
            return targetLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5259
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5260
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5261
        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
  5262
            this.targetLabel = targetLabel;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5263
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5264
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5265
        int[] getStackStoreSpec() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5266
            return stackStoreSpec.clone();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5267
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5268
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5269
        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
  5270
            this.stackStoreSpec = stackStoreSpec;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5271
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5272
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5273
        Type[] getStackTypes() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5274
            return stackTypes.clone();
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5275
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5276
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5277
        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
  5278
            this.stackTypes = stackTypes;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5279
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5280
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5281
        Type getReturnValueType() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5282
            return returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5283
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5284
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5285
        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
  5286
            this.returnValueType = returnValueType;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5287
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5288
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5289
        int getObjectLiteralStackDepth() {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5290
            return objectLiteralStackDepth;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5291
        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5292
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5293
        void setObjectLiteralStackDepth(final int objectLiteralStackDepth) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5294
            this.objectLiteralStackDepth = objectLiteralStackDepth;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5295
        }
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5296
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5297
        PropertyMap getObjectLiteralMap() {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5298
            return objectLiteralMap;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5299
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5300
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5301
        void setObjectLiteralMap(final PropertyMap objectLiteralMap) {
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5302
            this.objectLiteralMap = objectLiteralMap;
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5303
        }
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5304
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5305
        @Override
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5306
        public String toString() {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5307
             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
  5308
                     Arrays.toString(stackStoreSpec) + ", returnValueType=" + returnValueType + "]";
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5309
        }
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 ContinuationInfo getContinuationInfo() {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5313
        return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId());
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5314
    }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5315
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5316
    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
  5317
        if (!isRestOf()) {
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5318
            return;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5319
        }
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5320
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5321
        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
  5322
        method.label(ci.getHandlerLabel());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5323
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5324
        // 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
  5325
        // 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
  5326
        method.lineNumber(0);
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5327
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5328
        final Label.Stack stack = ci.getTargetLabel().getStack();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5329
        final List<Type> lvarTypes = stack.getLocalVariableTypesCopy();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5330
        final BitSet symbolBoundary = stack.getSymbolBoundaryCopy();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5331
        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
  5332
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
  5333
        final Type rewriteExceptionType = Type.typeFor(RewriteException.class);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5334
        // 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
  5335
        method.load(rewriteExceptionType, 0);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5336
        method.storeTemp(rewriteExceptionType, lvarCount);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5337
        // Get local variable array
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5338
        method.load(rewriteExceptionType, 0);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5339
        method.invoke(RewriteException.GET_BYTECODE_SLOTS);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5340
        // 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
  5341
        // 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
  5342
        // 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
  5343
        // 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
  5344
        // was undefined, there will be an explicit Undefined value in the array.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5345
        int arrayIndex = 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5346
        for(int lvarIndex = 0; lvarIndex < lvarCount;) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5347
            final Type lvarType = lvarTypes.get(lvarIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5348
            if(!lvarType.isUnknown()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5349
                method.dup();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5350
                method.load(arrayIndex).arrayload();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5351
                final Class<?> typeClass = lvarType.getTypeClass();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5352
                // Deoptimization in array initializers can cause arrays to undergo component type widening
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5353
                if(typeClass == long[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5354
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5355
                    method.invoke(RewriteException.TO_LONG_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5356
                } else if(typeClass == double[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5357
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5358
                    method.invoke(RewriteException.TO_DOUBLE_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5359
                } else if(typeClass == Object[].class) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5360
                    method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5361
                    method.invoke(RewriteException.TO_OBJECT_ARRAY);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5362
                } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5363
                    if(!(typeClass.isPrimitive() || typeClass == Object.class)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5364
                        // 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
  5365
                        // 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
  5366
                        // 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
  5367
                        // "{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
  5368
                        // Undefined, however NativeArray can't hold Undefined instance.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5369
                        method.loadType(Type.getInternalName(typeClass));
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5370
                        method.invoke(RewriteException.INSTANCE_OR_NULL);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5371
                    }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5372
                    method.convert(lvarType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5373
                }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5374
                method.storeHidden(lvarType, lvarIndex, false);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5375
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5376
            final int nextLvarIndex = lvarIndex + lvarType.getSlots();
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5377
            if(symbolBoundary.get(nextLvarIndex - 1)) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5378
                ++arrayIndex;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5379
            }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5380
            lvarIndex = nextLvarIndex;
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5381
        }
26250
84bbd0e8b2b2 8056025: CompilationPhase.setStates() is hot in class installation phase
attila
parents: 26241
diff changeset
  5382
        if (AssertsEnabled.assertsEnabled()) {
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5383
            method.load(arrayIndex);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5384
            method.invoke(RewriteException.ASSERT_ARRAY_LENGTH);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5385
        } else {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5386
            method.pop();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5387
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5388
24740
26791be09688 8040089: Apply to call transform was incomplete. Now passes all tests and performance is back
lagergren
parents: 24738
diff changeset
  5389
        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
  5390
        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
  5391
        final boolean isStackEmpty   = stackStoreSpec.length == 0;
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5392
        boolean replacedObjectLiteralMap = false;
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5393
        if(!isStackEmpty) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5394
            // Load arguments on the stack
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5395
            final int objectLiteralStackDepth = ci.getObjectLiteralStackDepth();
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5396
            for(int i = 0; i < stackStoreSpec.length; ++i) {
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5397
                final int slot = stackStoreSpec[i];
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5398
                method.load(lvarTypes.get(slot), slot);
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5399
                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
  5400
                // stack: s0=object literal being initialized
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5401
                // change map of s0 so that the property we are initilizing when we failed
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5402
                // is now ci.returnValueType
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5403
                if (i == objectLiteralStackDepth) {
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5404
                    method.dup();
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5405
                    assert ci.getObjectLiteralMap() != null;
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5406
                    assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object";
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5407
                    loadConstant(ci.getObjectLiteralMap());
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5408
                    method.invoke(ScriptObject.SET_MAP);
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5409
                    replacedObjectLiteralMap = true;
24747
c7485e5d6cf4 8041995: Problems when loading tree expressions with several optimistic program points when optimistically initializing ObjectNodes
lagergren
parents: 24745
diff changeset
  5410
                }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5411
            }
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5412
        }
24757
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5413
        // Must have emitted the code for replacing the map of an object literal if we have a set object literal stack depth
f5e65b565230 8043133: Fix corner cases of JDK-8041995
attila
parents: 24751
diff changeset
  5414
        assert ci.getObjectLiteralStackDepth() == -1 || replacedObjectLiteralMap;
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5415
        // Load RewriteException back.
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5416
        method.load(rewriteExceptionType, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5417
        // Get rid of the stored reference
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5418
        method.loadNull();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5419
        method.storeHidden(Type.OBJECT, lvarCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5420
        // Mark it dead
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5421
        method.markDeadSlots(lvarCount, Type.OBJECT.getSlots());
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5422
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5423
        // Load return value on the stack
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5424
        method.invoke(RewriteException.GET_RETURN_VALUE);
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5425
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5426
        final Type returnValueType = ci.getReturnValueType();
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5427
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5428
        // 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
  5429
        boolean needsCatch = false;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5430
        final Label targetCatchLabel = ci.catchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5431
        Label _try = null;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5432
        if(returnValueType.isPrimitive()) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5433
            // 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
  5434
            method.lineNumber(ci.lineNumber);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5435
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5436
            if(targetCatchLabel != METHOD_BOUNDARY) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5437
                _try = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5438
                method.label(_try);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5439
                needsCatch = true;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5440
            }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5441
        }
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5442
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5443
        // Convert return value
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5444
        method.convert(returnValueType);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5445
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5446
        final int scopePopCount = needsCatch ? ci.exceptionScopePops : 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5447
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5448
        // 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
  5449
        // 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
  5450
        final Label catchLabel = scopePopCount > 0 ? new Label("") : targetCatchLabel;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5451
        if(needsCatch) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5452
            final Label _end_try = new Label("");
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5453
            method.label(_end_try);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5454
            method._try(_try, _end_try, catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5455
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5456
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5457
        // 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
  5458
        method._goto(ci.getTargetLabel());
24751
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5459
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5460
        // Make a scope-popping exception delegate if needed
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5461
        if(catchLabel != targetCatchLabel) {
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5462
            method.lineNumber(0);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5463
            assert scopePopCount > 0;
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5464
            method._catch(catchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5465
            popScopes(scopePopCount);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5466
            method.uncheckedGoto(targetCatchLabel);
ccbd9cd3f720 8042118: Separate types from symbols
attila
parents: 24749
diff changeset
  5467
        }
24719
f726e9d67629 8035820: Optimistic recompilation
attila
parents: 22387
diff changeset
  5468
    }
16147
e63b63819133 8005403: Open-source Nashorn
jlaskey
parents:
diff changeset
  5469
}