author | erikj |
Tue, 12 Sep 2017 19:03:39 +0200 | |
changeset 47216 | 71c04702a3d5 |
parent 39165 | nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/MethodEmitter.java@f0000753cecd |
child 48247 | fa5a47cad0c9 |
permissions | -rw-r--r-- |
16147 | 1 |
/* |
16151 | 2 |
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. |
16147 | 3 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 |
* |
|
5 |
* This code is free software; you can redistribute it and/or modify it |
|
6 |
* under the terms of the GNU General Public License version 2 only, as |
|
7 |
* published by the Free Software Foundation. Oracle designates this |
|
8 |
* particular file as subject to the "Classpath" exception as provided |
|
9 |
* by Oracle in the LICENSE file that accompanied this code. |
|
10 |
* |
|
11 |
* This code is distributed in the hope that it will be useful, but WITHOUT |
|
12 |
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
13 |
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
14 |
* version 2 for more details (a copy is included in the LICENSE file that |
|
15 |
* accompanied this code). |
|
16 |
* |
|
17 |
* You should have received a copy of the GNU General Public License version |
|
18 |
* 2 along with this work; if not, write to the Free Software Foundation, |
|
19 |
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
20 |
* |
|
21 |
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
22 |
* or visit www.oracle.com if you need additional information or have any |
|
23 |
* questions. |
|
24 |
*/ |
|
25 |
||
26 |
package jdk.nashorn.internal.codegen; |
|
27 |
||
28 |
import static jdk.internal.org.objectweb.asm.Opcodes.ATHROW; |
|
29 |
import static jdk.internal.org.objectweb.asm.Opcodes.CHECKCAST; |
|
30 |
import static jdk.internal.org.objectweb.asm.Opcodes.DUP2; |
|
31 |
import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD; |
|
32 |
import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC; |
|
33 |
import static jdk.internal.org.objectweb.asm.Opcodes.GOTO; |
|
34 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; |
|
39165
f0000753cecd
8160141: removed deprecated method calls in nashorn code
sundar
parents:
38485
diff
changeset
|
35 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEINTERFACE; |
16147 | 36 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFEQ; |
37 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFGE; |
|
38 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFGT; |
|
39 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFLE; |
|
40 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFLT; |
|
41 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFNE; |
|
42 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFNONNULL; |
|
43 |
import static jdk.internal.org.objectweb.asm.Opcodes.IFNULL; |
|
44 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPEQ; |
|
45 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPNE; |
|
46 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPEQ; |
|
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:
24719
diff
changeset
|
47 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE; |
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:
24719
diff
changeset
|
48 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGT; |
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:
24719
diff
changeset
|
49 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLE; |
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:
24719
diff
changeset
|
50 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLT; |
24751 | 51 |
import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPNE; |
16147 | 52 |
import static jdk.internal.org.objectweb.asm.Opcodes.INSTANCEOF; |
53 |
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE; |
|
54 |
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL; |
|
55 |
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC; |
|
56 |
import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL; |
|
57 |
import static jdk.internal.org.objectweb.asm.Opcodes.NEW; |
|
58 |
import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD; |
|
59 |
import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC; |
|
60 |
import static jdk.internal.org.objectweb.asm.Opcodes.RETURN; |
|
17233 | 61 |
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; |
16147 | 62 |
import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS; |
17233 | 63 |
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE; |
16147 | 64 |
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS; |
65 |
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS_DEBUGGER; |
|
17233 | 66 |
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS; |
16147 | 67 |
import static jdk.nashorn.internal.codegen.CompilerConstants.className; |
68 |
import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup; |
|
69 |
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; |
|
70 |
import static jdk.nashorn.internal.codegen.CompilerConstants.staticField; |
|
71 |
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; |
|
24719 | 72 |
import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE; |
33533
43400f0f2b47
8141144: Move NameCodec to jdk.nashorn.internal space
attila
parents:
33343
diff
changeset
|
73 |
import static jdk.nashorn.internal.runtime.linker.NameCodec.EMPTY_NAME; |
24719 | 74 |
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC; |
75 |
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT; |
|
27206 | 76 |
|
16147 | 77 |
import java.io.PrintStream; |
78 |
import java.lang.reflect.Array; |
|
24719 | 79 |
import java.util.Collection; |
16147 | 80 |
import java.util.EnumSet; |
24751 | 81 |
import java.util.IdentityHashMap; |
17233 | 82 |
import java.util.List; |
24751 | 83 |
import java.util.Map; |
16147 | 84 |
import jdk.internal.org.objectweb.asm.Handle; |
85 |
import jdk.internal.org.objectweb.asm.MethodVisitor; |
|
86 |
import jdk.nashorn.internal.codegen.ClassEmitter.Flag; |
|
87 |
import jdk.nashorn.internal.codegen.CompilerConstants.Call; |
|
88 |
import jdk.nashorn.internal.codegen.CompilerConstants.FieldAccess; |
|
89 |
import jdk.nashorn.internal.codegen.types.ArrayType; |
|
90 |
import jdk.nashorn.internal.codegen.types.BitwiseType; |
|
91 |
import jdk.nashorn.internal.codegen.types.NumericType; |
|
92 |
import jdk.nashorn.internal.codegen.types.Type; |
|
93 |
import jdk.nashorn.internal.ir.FunctionNode; |
|
94 |
import jdk.nashorn.internal.ir.IdentNode; |
|
24751 | 95 |
import jdk.nashorn.internal.ir.JoinPredecessor; |
16147 | 96 |
import jdk.nashorn.internal.ir.LiteralNode; |
24751 | 97 |
import jdk.nashorn.internal.ir.LocalVariableConversion; |
16147 | 98 |
import jdk.nashorn.internal.ir.Symbol; |
24751 | 99 |
import jdk.nashorn.internal.ir.TryNode; |
27099
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
100 |
import jdk.nashorn.internal.objects.NativeArray; |
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
101 |
import jdk.nashorn.internal.runtime.ArgumentSetter; |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
102 |
import jdk.nashorn.internal.runtime.Context; |
17233 | 103 |
import jdk.nashorn.internal.runtime.Debug; |
16147 | 104 |
import jdk.nashorn.internal.runtime.JSType; |
24719 | 105 |
import jdk.nashorn.internal.runtime.RewriteException; |
26890 | 106 |
import jdk.nashorn.internal.runtime.Scope; |
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
107 |
import jdk.nashorn.internal.runtime.ScriptObject; |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
108 |
import jdk.nashorn.internal.runtime.ScriptRuntime; |
24751 | 109 |
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException; |
16147 | 110 |
import jdk.nashorn.internal.runtime.linker.Bootstrap; |
33533
43400f0f2b47
8141144: Move NameCodec to jdk.nashorn.internal space
attila
parents:
33343
diff
changeset
|
111 |
import jdk.nashorn.internal.runtime.linker.NameCodec; |
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
112 |
import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
113 |
import jdk.nashorn.internal.runtime.logging.DebugLogger; |
16147 | 114 |
import jdk.nashorn.internal.runtime.options.Options; |
115 |
||
116 |
/** |
|
117 |
* This is the main function responsible for emitting method code |
|
118 |
* in a class. It maintains a type stack and keeps track of control |
|
119 |
* flow to make sure that the registered instructions don't violate |
|
120 |
* byte code verification. |
|
121 |
* |
|
122 |
* Running Nashorn with -ea will assert as soon as a type stack |
|
123 |
* becomes corrupt, for easier debugging |
|
124 |
* |
|
125 |
* Running Nashorn with -Dnashorn.codegen.debug=true will print |
|
126 |
* all generated bytecode and labels to stderr, for easier debugging, |
|
127 |
* including bytecode stack contents |
|
128 |
*/ |
|
30391
62dcad329b26
8079349: Eliminate dead code around Nashorn code generator
attila
parents:
29283
diff
changeset
|
129 |
public class MethodEmitter { |
16147 | 130 |
/** The ASM MethodVisitor we are plugged into */ |
131 |
private final MethodVisitor method; |
|
132 |
||
133 |
/** Parent classEmitter representing the class of this method */ |
|
134 |
private final ClassEmitter classEmitter; |
|
135 |
||
136 |
/** FunctionNode representing this method, or null if none exists */ |
|
17233 | 137 |
protected FunctionNode functionNode; |
16147 | 138 |
|
24751 | 139 |
/** Current type stack for current evaluation */ |
140 |
private Label.Stack stack; |
|
141 |
||
142 |
private boolean preventUndefinedLoad; |
|
143 |
||
144 |
/** |
|
145 |
* Map of live local variable definitions. |
|
146 |
*/ |
|
147 |
private final Map<Symbol, LocalVariableDef> localVariableDefs = new IdentityHashMap<>(); |
|
148 |
||
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
149 |
/** The context */ |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
150 |
private final Context context; |
16147 | 151 |
|
152 |
/** Threshold in chars for when string constants should be split */ |
|
153 |
static final int LARGE_STRING_THRESHOLD = 32 * 1024; |
|
154 |
||
155 |
/** Debug flag, should we dump all generated bytecode along with stacks? */ |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
156 |
private final DebugLogger log; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
157 |
private final boolean debug; |
16147 | 158 |
|
159 |
/** dump stack on a particular line, or -1 if disabled */ |
|
160 |
private static final int DEBUG_TRACE_LINE; |
|
161 |
||
162 |
static { |
|
163 |
final String tl = Options.getStringProperty("nashorn.codegen.debug.trace", "-1"); |
|
164 |
int line = -1; |
|
165 |
try { |
|
166 |
line = Integer.parseInt(tl); |
|
167 |
} catch (final NumberFormatException e) { |
|
168 |
//fallthru |
|
169 |
} |
|
170 |
DEBUG_TRACE_LINE = line; |
|
171 |
} |
|
172 |
||
173 |
/** Bootstrap for normal indy:s */ |
|
39165
f0000753cecd
8160141: removed deprecated method calls in nashorn code
sundar
parents:
38485
diff
changeset
|
174 |
private static final Handle LINKERBOOTSTRAP = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor(), false); |
16147 | 175 |
|
24719 | 176 |
/** Bootstrap for array populators */ |
39165
f0000753cecd
8160141: removed deprecated method calls in nashorn code
sundar
parents:
38485
diff
changeset
|
177 |
private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor(), false); |
24719 | 178 |
|
16147 | 179 |
/** |
180 |
* Constructor - internal use from ClassEmitter only |
|
16154
de44634fa4ec
8005782: get rid of javadoc errors, warnings in nashorn build
sundar
parents:
16151
diff
changeset
|
181 |
* @see ClassEmitter#method |
16147 | 182 |
* |
183 |
* @param classEmitter the class emitter weaving the class this method is in |
|
184 |
* @param method a method visitor |
|
185 |
*/ |
|
186 |
MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method) { |
|
187 |
this(classEmitter, method, null); |
|
188 |
} |
|
189 |
||
190 |
/** |
|
191 |
* Constructor - internal use from ClassEmitter only |
|
16154
de44634fa4ec
8005782: get rid of javadoc errors, warnings in nashorn build
sundar
parents:
16151
diff
changeset
|
192 |
* @see ClassEmitter#method |
16147 | 193 |
* |
194 |
* @param classEmitter the class emitter weaving the class this method is in |
|
195 |
* @param method a method visitor |
|
196 |
* @param functionNode a function node representing this method |
|
197 |
*/ |
|
198 |
MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method, final FunctionNode functionNode) { |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
199 |
this.context = classEmitter.getContext(); |
16147 | 200 |
this.classEmitter = classEmitter; |
201 |
this.method = method; |
|
202 |
this.functionNode = functionNode; |
|
203 |
this.stack = null; |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
204 |
this.log = context.getLogger(CodeGenerator.class); |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
205 |
this.debug = log.isEnabled(); |
16147 | 206 |
} |
207 |
||
208 |
/** |
|
209 |
* Begin a method |
|
210 |
*/ |
|
211 |
public void begin() { |
|
212 |
classEmitter.beginMethod(this); |
|
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:
17255
diff
changeset
|
213 |
newStack(); |
16147 | 214 |
method.visitCode(); |
215 |
} |
|
216 |
||
217 |
/** |
|
218 |
* End a method |
|
219 |
*/ |
|
220 |
public void end() { |
|
221 |
method.visitMaxs(0, 0); |
|
222 |
method.visitEnd(); |
|
223 |
||
224 |
classEmitter.endMethod(this); |
|
225 |
} |
|
226 |
||
24751 | 227 |
boolean isReachable() { |
228 |
return stack != null; |
|
229 |
} |
|
230 |
||
231 |
private void doesNotContinueSequentially() { |
|
232 |
stack = null; |
|
24719 | 233 |
} |
234 |
||
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:
17255
diff
changeset
|
235 |
private void newStack() { |
17527
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
236 |
stack = new Label.Stack(); |
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:
17255
diff
changeset
|
237 |
} |
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:
17255
diff
changeset
|
238 |
|
16147 | 239 |
@Override |
240 |
public String toString() { |
|
17233 | 241 |
return "methodEmitter: " + (functionNode == null ? method : functionNode.getName()).toString() + ' ' + Debug.id(this); |
16147 | 242 |
} |
243 |
||
244 |
/** |
|
245 |
* Push a type to the existing stack |
|
246 |
* @param type the type |
|
247 |
*/ |
|
24719 | 248 |
void pushType(final Type type) { |
16147 | 249 |
if (type != null) { |
250 |
stack.push(type); |
|
251 |
} |
|
252 |
} |
|
253 |
||
254 |
/** |
|
255 |
* Pop a type from the existing stack |
|
256 |
* |
|
257 |
* @param expected expected type - will assert if wrong |
|
258 |
* |
|
259 |
* @return the type that was retrieved |
|
260 |
*/ |
|
261 |
private Type popType(final Type expected) { |
|
24719 | 262 |
final Type type = popType(); |
32781
d8f34ffbbc7a
8135190: Method code too large in Babel browser.js script
hannesw
parents:
32534
diff
changeset
|
263 |
assert type.isEquivalentTo(expected) : type + " is not compatible with " + expected; |
16147 | 264 |
return type; |
265 |
} |
|
266 |
||
267 |
/** |
|
268 |
* Pop a type from the existing stack, no matter what it is. |
|
269 |
* |
|
270 |
* @return the type |
|
271 |
*/ |
|
272 |
private Type popType() { |
|
273 |
return stack.pop(); |
|
274 |
} |
|
275 |
||
276 |
/** |
|
24751 | 277 |
* Pop a type from the existing stack, ensuring that it is numeric. Boolean type is popped as int type. |
16147 | 278 |
* |
279 |
* @return the type |
|
280 |
*/ |
|
281 |
private NumericType popNumeric() { |
|
24719 | 282 |
final Type type = popType(); |
24751 | 283 |
if(type.isBoolean()) { |
284 |
// Booleans are treated as int for purposes of arithmetic operations |
|
285 |
return Type.INT; |
|
286 |
} |
|
287 |
assert type.isNumeric(); |
|
16147 | 288 |
return (NumericType)type; |
289 |
} |
|
290 |
||
291 |
/** |
|
292 |
* Pop a type from the existing stack, ensuring that it is an integer type |
|
24751 | 293 |
* (integer or long). Boolean type is popped as int type. |
16147 | 294 |
* |
295 |
* @return the type |
|
296 |
*/ |
|
24751 | 297 |
private BitwiseType popBitwise() { |
298 |
final Type type = popType(); |
|
299 |
if(type == Type.BOOLEAN) { |
|
300 |
return Type.INT; |
|
301 |
} |
|
302 |
return (BitwiseType)type; |
|
303 |
} |
|
304 |
||
16147 | 305 |
private BitwiseType popInteger() { |
24719 | 306 |
final Type type = popType(); |
24751 | 307 |
if(type == Type.BOOLEAN) { |
308 |
return Type.INT; |
|
309 |
} |
|
310 |
assert type == Type.INT; |
|
16147 | 311 |
return (BitwiseType)type; |
312 |
} |
|
313 |
||
314 |
/** |
|
315 |
* Pop a type from the existing stack, ensuring that it is an array type, |
|
316 |
* assert if not |
|
317 |
* |
|
318 |
* @return the type |
|
319 |
*/ |
|
320 |
private ArrayType popArray() { |
|
24719 | 321 |
final Type type = popType(); |
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
322 |
assert type.isArray() : type; |
16147 | 323 |
return (ArrayType)type; |
324 |
} |
|
325 |
||
326 |
/** |
|
327 |
* Peek a given number of slots from the top of the stack and return the |
|
328 |
* type in that slot |
|
329 |
* |
|
330 |
* @param pos the number of positions from the top, 0 is the top element |
|
331 |
* |
|
332 |
* @return the type at position "pos" on the stack |
|
333 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
334 |
final Type peekType(final int pos) { |
17527
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
335 |
return stack.peek(pos); |
16147 | 336 |
} |
337 |
||
338 |
/** |
|
339 |
* Peek at the type at the top of the stack |
|
340 |
* |
|
341 |
* @return the type at the top of the stack |
|
342 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
343 |
final Type peekType() { |
16147 | 344 |
return stack.peek(); |
345 |
} |
|
346 |
||
347 |
/** |
|
348 |
* Generate code a for instantiating a new object and push the |
|
349 |
* object type on the stack |
|
350 |
* |
|
351 |
* @param classDescriptor class descriptor for the object type |
|
24719 | 352 |
* @param type the type of the new object |
16147 | 353 |
* |
354 |
* @return the method emitter |
|
355 |
*/ |
|
24719 | 356 |
MethodEmitter _new(final String classDescriptor, final Type type) { |
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
357 |
debug("new", classDescriptor); |
16147 | 358 |
method.visitTypeInsn(NEW, classDescriptor); |
24719 | 359 |
pushType(type); |
16147 | 360 |
return this; |
361 |
} |
|
362 |
||
363 |
/** |
|
364 |
* Generate code a for instantiating a new object and push the |
|
365 |
* object type on the stack |
|
366 |
* |
|
367 |
* @param clazz class type to instatiate |
|
368 |
* |
|
369 |
* @return the method emitter |
|
370 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
371 |
MethodEmitter _new(final Class<?> clazz) { |
24719 | 372 |
return _new(className(clazz), Type.typeFor(clazz)); |
16147 | 373 |
} |
374 |
||
375 |
/** |
|
376 |
* Generate code to call the empty constructor for a class |
|
377 |
* |
|
378 |
* @param clazz class type to instatiate |
|
379 |
* |
|
380 |
* @return the method emitter |
|
381 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
382 |
MethodEmitter newInstance(final Class<?> clazz) { |
16147 | 383 |
return invoke(constructorNoLookup(clazz)); |
384 |
} |
|
385 |
||
386 |
/** |
|
387 |
* Perform a dup, that is, duplicate the top element and |
|
388 |
* push the duplicate down a given number of positions |
|
389 |
* on the stack. This is totally type agnostic. |
|
390 |
* |
|
391 |
* @param depth the depth on which to put the copy |
|
392 |
* |
|
393 |
* @return the method emitter, or null if depth is illegal and |
|
394 |
* has no instruction equivalent. |
|
395 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
396 |
MethodEmitter dup(final int depth) { |
16147 | 397 |
if (peekType().dup(method, depth) == null) { |
398 |
return null; |
|
399 |
} |
|
400 |
||
401 |
debug("dup", depth); |
|
402 |
||
403 |
switch (depth) { |
|
24719 | 404 |
case 0: { |
405 |
final int l0 = stack.getTopLocalLoad(); |
|
16147 | 406 |
pushType(peekType()); |
24719 | 407 |
stack.markLocalLoad(l0); |
16147 | 408 |
break; |
24719 | 409 |
} |
16147 | 410 |
case 1: { |
24719 | 411 |
final int l0 = stack.getTopLocalLoad(); |
16147 | 412 |
final Type p0 = popType(); |
24719 | 413 |
final int l1 = stack.getTopLocalLoad(); |
16147 | 414 |
final Type p1 = popType(); |
415 |
pushType(p0); |
|
24719 | 416 |
stack.markLocalLoad(l0); |
16147 | 417 |
pushType(p1); |
24719 | 418 |
stack.markLocalLoad(l1); |
16147 | 419 |
pushType(p0); |
24719 | 420 |
stack.markLocalLoad(l0); |
16147 | 421 |
break; |
422 |
} |
|
423 |
case 2: { |
|
24719 | 424 |
final int l0 = stack.getTopLocalLoad(); |
16147 | 425 |
final Type p0 = popType(); |
24719 | 426 |
final int l1 = stack.getTopLocalLoad(); |
16147 | 427 |
final Type p1 = popType(); |
24719 | 428 |
final int l2 = stack.getTopLocalLoad(); |
16147 | 429 |
final Type p2 = popType(); |
430 |
pushType(p0); |
|
24719 | 431 |
stack.markLocalLoad(l0); |
16147 | 432 |
pushType(p2); |
24719 | 433 |
stack.markLocalLoad(l2); |
16147 | 434 |
pushType(p1); |
24719 | 435 |
stack.markLocalLoad(l1); |
16147 | 436 |
pushType(p0); |
24719 | 437 |
stack.markLocalLoad(l0); |
16147 | 438 |
break; |
439 |
} |
|
440 |
default: |
|
441 |
assert false : "illegal dup depth = " + depth; |
|
442 |
return null; |
|
443 |
} |
|
444 |
||
445 |
return this; |
|
446 |
} |
|
447 |
||
448 |
/** |
|
449 |
* Perform a dup2, that is, duplicate the top element if it |
|
450 |
* is a category 2 type, or two top elements if they are category |
|
451 |
* 1 types, and push them on top of the stack |
|
452 |
* |
|
453 |
* @return the method emitter |
|
454 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
455 |
MethodEmitter dup2() { |
16147 | 456 |
debug("dup2"); |
457 |
||
458 |
if (peekType().isCategory2()) { |
|
24719 | 459 |
final int l0 = stack.getTopLocalLoad(); |
16147 | 460 |
pushType(peekType()); |
24719 | 461 |
stack.markLocalLoad(l0); |
16147 | 462 |
} else { |
24719 | 463 |
final int l0 = stack.getTopLocalLoad(); |
464 |
final Type p0 = popType(); |
|
465 |
final int l1 = stack.getTopLocalLoad(); |
|
466 |
final Type p1 = popType(); |
|
467 |
pushType(p0); |
|
468 |
stack.markLocalLoad(l0); |
|
469 |
pushType(p1); |
|
470 |
stack.markLocalLoad(l1); |
|
471 |
pushType(p0); |
|
472 |
stack.markLocalLoad(l0); |
|
473 |
pushType(p1); |
|
474 |
stack.markLocalLoad(l1); |
|
16147 | 475 |
} |
476 |
method.visitInsn(DUP2); |
|
477 |
return this; |
|
478 |
} |
|
479 |
||
480 |
/** |
|
481 |
* Duplicate the top element on the stack and push it |
|
482 |
* |
|
483 |
* @return the method emitter |
|
484 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
485 |
MethodEmitter dup() { |
16147 | 486 |
return dup(0); |
487 |
} |
|
488 |
||
489 |
/** |
|
490 |
* Pop the top element of the stack and throw it away |
|
491 |
* |
|
492 |
* @return the method emitter |
|
493 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
494 |
MethodEmitter pop() { |
16147 | 495 |
debug("pop", peekType()); |
496 |
popType().pop(method); |
|
497 |
return this; |
|
498 |
} |
|
499 |
||
500 |
/** |
|
501 |
* Pop the top element of the stack if category 2 type, or the two |
|
502 |
* top elements of the stack if category 1 types |
|
503 |
* |
|
504 |
* @return the method emitter |
|
505 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
506 |
MethodEmitter pop2() { |
16147 | 507 |
if (peekType().isCategory2()) { |
508 |
popType(); |
|
509 |
} else { |
|
510 |
get2n(); |
|
511 |
} |
|
512 |
return this; |
|
513 |
} |
|
514 |
||
515 |
/** |
|
516 |
* Swap the top two elements of the stack. This is totally |
|
517 |
* type agnostic and works for all types |
|
518 |
* |
|
519 |
* @return the method emitter |
|
520 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
521 |
MethodEmitter swap() { |
16147 | 522 |
debug("swap"); |
523 |
||
24719 | 524 |
final int l0 = stack.getTopLocalLoad(); |
16147 | 525 |
final Type p0 = popType(); |
24719 | 526 |
final int l1 = stack.getTopLocalLoad(); |
16147 | 527 |
final Type p1 = popType(); |
528 |
p0.swap(method, p1); |
|
529 |
||
530 |
pushType(p0); |
|
24719 | 531 |
stack.markLocalLoad(l0); |
16147 | 532 |
pushType(p1); |
24719 | 533 |
stack.markLocalLoad(l1); |
16147 | 534 |
return this; |
535 |
} |
|
536 |
||
24719 | 537 |
void pack() { |
538 |
final Type type = peekType(); |
|
539 |
if (type.isInteger()) { |
|
540 |
convert(PRIMITIVE_FIELD_TYPE); |
|
541 |
} else if (type.isLong()) { |
|
542 |
//nop |
|
543 |
} else if (type.isNumber()) { |
|
544 |
invokestatic("java/lang/Double", "doubleToRawLongBits", "(D)J"); |
|
545 |
} else { |
|
546 |
assert false : type + " cannot be packed!"; |
|
547 |
} |
|
548 |
} |
|
549 |
||
16147 | 550 |
/** |
24751 | 551 |
* Initializes a bytecode method parameter |
552 |
* @param symbol the symbol for the parameter |
|
553 |
* @param type the type of the parameter |
|
554 |
* @param start the label for the start of the method |
|
16147 | 555 |
*/ |
24751 | 556 |
void initializeMethodParameter(final Symbol symbol, final Type type, final Label start) { |
557 |
assert symbol.isBytecodeLocal(); |
|
558 |
localVariableDefs.put(symbol, new LocalVariableDef(start.getLabel(), type)); |
|
16147 | 559 |
} |
560 |
||
561 |
/** |
|
562 |
* Create a new string builder, call the constructor and push the instance to the stack. |
|
563 |
* |
|
564 |
* @return the method emitter |
|
565 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
566 |
MethodEmitter newStringBuilder() { |
16147 | 567 |
return invoke(constructorNoLookup(StringBuilder.class)).dup(); |
568 |
} |
|
569 |
||
570 |
/** |
|
571 |
* Pop a string and a StringBuilder from the top of the stack and call the append |
|
572 |
* function of the StringBuilder, appending the string. Pushes the StringBuilder to |
|
573 |
* the stack when finished. |
|
574 |
* |
|
575 |
* @return the method emitter |
|
576 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
577 |
MethodEmitter stringBuilderAppend() { |
16147 | 578 |
convert(Type.STRING); |
579 |
return invoke(virtualCallNoLookup(StringBuilder.class, "append", StringBuilder.class, String.class)); |
|
580 |
} |
|
581 |
||
582 |
/** |
|
583 |
* Pops two integer types from the stack, performs a bitwise and and pushes |
|
584 |
* the result |
|
585 |
* |
|
586 |
* @return the method emitter |
|
587 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
588 |
MethodEmitter and() { |
16147 | 589 |
debug("and"); |
590 |
pushType(get2i().and(method)); |
|
591 |
return this; |
|
592 |
} |
|
593 |
||
594 |
/** |
|
595 |
* Pops two integer types from the stack, performs a bitwise or and pushes |
|
596 |
* the result |
|
597 |
* |
|
598 |
* @return the method emitter |
|
599 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
600 |
MethodEmitter or() { |
16147 | 601 |
debug("or"); |
602 |
pushType(get2i().or(method)); |
|
603 |
return this; |
|
604 |
} |
|
605 |
||
606 |
/** |
|
607 |
* Pops two integer types from the stack, performs a bitwise xor and pushes |
|
608 |
* the result |
|
609 |
* |
|
610 |
* @return the method emitter |
|
611 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
612 |
MethodEmitter xor() { |
16147 | 613 |
debug("xor"); |
614 |
pushType(get2i().xor(method)); |
|
615 |
return this; |
|
616 |
} |
|
617 |
||
618 |
/** |
|
619 |
* Pops two integer types from the stack, performs a bitwise logic shift right and pushes |
|
620 |
* the result. The shift count, the first element, must be INT. |
|
621 |
* |
|
622 |
* @return the method emitter |
|
623 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
624 |
MethodEmitter shr() { |
16147 | 625 |
debug("shr"); |
24751 | 626 |
popInteger(); |
627 |
pushType(popBitwise().shr(method)); |
|
16147 | 628 |
return this; |
629 |
} |
|
630 |
||
631 |
/** |
|
632 |
* Pops two integer types from the stack, performs a bitwise shift left and and pushes |
|
633 |
* the result. The shift count, the first element, must be INT. |
|
634 |
* |
|
635 |
* @return the method emitter |
|
636 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
637 |
MethodEmitter shl() { |
16147 | 638 |
debug("shl"); |
24751 | 639 |
popInteger(); |
640 |
pushType(popBitwise().shl(method)); |
|
16147 | 641 |
return this; |
642 |
} |
|
643 |
||
644 |
/** |
|
24751 | 645 |
* Pops two integer types from the stack, performs a bitwise arithmetic shift right and pushes |
16147 | 646 |
* the result. The shift count, the first element, must be INT. |
647 |
* |
|
648 |
* @return the method emitter |
|
649 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
650 |
MethodEmitter sar() { |
16147 | 651 |
debug("sar"); |
24751 | 652 |
popInteger(); |
653 |
pushType(popBitwise().sar(method)); |
|
16147 | 654 |
return this; |
655 |
} |
|
656 |
||
657 |
/** |
|
658 |
* Pops a numeric type from the stack, negates it and pushes the result |
|
659 |
* |
|
660 |
* @return the method emitter |
|
661 |
*/ |
|
24719 | 662 |
MethodEmitter neg(final int programPoint) { |
16147 | 663 |
debug("neg"); |
24719 | 664 |
pushType(popNumeric().neg(method, programPoint)); |
16147 | 665 |
return this; |
666 |
} |
|
667 |
||
668 |
/** |
|
669 |
* Add label for the start of a catch block and push the exception to the |
|
670 |
* stack |
|
671 |
* |
|
672 |
* @param recovery label pointing to start of catch block |
|
673 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
674 |
void _catch(final Label recovery) { |
24751 | 675 |
// While in JVM a catch block can be reached through normal control flow, our code generator never does this, |
676 |
// so we might as well presume there's no stack on entry. |
|
677 |
assert stack == null; |
|
678 |
recovery.onCatch(); |
|
24719 | 679 |
label(recovery); |
24751 | 680 |
beginCatchBlock(); |
24719 | 681 |
} |
682 |
||
683 |
/** |
|
684 |
* Add any number of labels for the start of a catch block and push the exception to the |
|
685 |
* stack |
|
686 |
* |
|
687 |
* @param recoveries labels pointing to start of catch block |
|
688 |
*/ |
|
689 |
void _catch(final Collection<Label> recoveries) { |
|
24751 | 690 |
assert stack == null; |
24719 | 691 |
for(final Label l: recoveries) { |
692 |
label(l); |
|
693 |
} |
|
24751 | 694 |
beginCatchBlock(); |
16147 | 695 |
} |
696 |
||
24751 | 697 |
private void beginCatchBlock() { |
698 |
// It can happen that the catch label wasn't marked as reachable. They are marked as reachable if there's an |
|
699 |
// assignment in the try block, but it's possible that there was none. |
|
700 |
if(!isReachable()) { |
|
701 |
newStack(); |
|
702 |
} |
|
703 |
pushType(Type.typeFor(Throwable.class)); |
|
704 |
} |
|
16147 | 705 |
/** |
706 |
* Start a try/catch block. |
|
707 |
* |
|
708 |
* @param entry start label for try |
|
709 |
* @param exit end label for try |
|
710 |
* @param recovery start label for catch |
|
711 |
* @param typeDescriptor type descriptor for exception |
|
24751 | 712 |
* @param isOptimismHandler true if this is a hander for {@code UnwarrantedOptimismException}. Normally joining on a |
713 |
* catch handler kills temporary variables, but optimism handlers are an exception, as they need to capture |
|
714 |
* temporaries as well, so they must remain live. |
|
16147 | 715 |
*/ |
24751 | 716 |
private void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor, final boolean isOptimismHandler) { |
717 |
recovery.joinFromTry(entry.getStack(), isOptimismHandler); |
|
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:
17255
diff
changeset
|
718 |
method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), typeDescriptor); |
16147 | 719 |
} |
720 |
||
721 |
/** |
|
722 |
* Start a try/catch block. |
|
723 |
* |
|
724 |
* @param entry start label for try |
|
725 |
* @param exit end label for try |
|
726 |
* @param recovery start label for catch |
|
727 |
* @param clazz exception class |
|
728 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
729 |
void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) { |
24751 | 730 |
_try(entry, exit, recovery, CompilerConstants.className(clazz), clazz == UnwarrantedOptimismException.class); |
16147 | 731 |
} |
732 |
||
733 |
/** |
|
734 |
* Start a try/catch block. The catch is "Throwable" - i.e. catch-all |
|
735 |
* |
|
736 |
* @param entry start label for try |
|
737 |
* @param exit end label for try |
|
738 |
* @param recovery start label for catch |
|
739 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
740 |
void _try(final Label entry, final Label exit, final Label recovery) { |
33690 | 741 |
_try(entry, exit, recovery, null, false); |
16147 | 742 |
} |
743 |
||
24751 | 744 |
void markLabelAsOptimisticCatchHandler(final Label label, final int liveLocalCount) { |
745 |
label.markAsOptimisticCatchHandler(stack, liveLocalCount); |
|
746 |
} |
|
16147 | 747 |
|
748 |
/** |
|
749 |
* Load the constants array |
|
750 |
* @return this method emitter |
|
751 |
*/ |
|
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16262
diff
changeset
|
752 |
MethodEmitter loadConstants() { |
17233 | 753 |
getStatic(classEmitter.getUnitClassName(), CONSTANTS.symbolName(), CONSTANTS.descriptor()); |
16147 | 754 |
assert peekType().isArray() : peekType(); |
755 |
return this; |
|
756 |
} |
|
757 |
||
758 |
/** |
|
759 |
* Push the undefined value for the given type, i.e. |
|
760 |
* UNDEFINED or UNDEFINEDNUMBER. Currently we have no way of |
|
761 |
* representing UNDEFINED for INTs and LONGs, so they are not |
|
762 |
* allowed to be local variables (yet) |
|
763 |
* |
|
764 |
* @param type the type for which to push UNDEFINED |
|
765 |
* @return the method emitter |
|
766 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
767 |
MethodEmitter loadUndefined(final Type type) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
768 |
debug("load undefined ", type); |
16147 | 769 |
pushType(type.loadUndefined(method)); |
770 |
return this; |
|
771 |
} |
|
772 |
||
24719 | 773 |
MethodEmitter loadForcedInitializer(final Type type) { |
774 |
debug("load forced initializer ", type); |
|
775 |
pushType(type.loadForcedInitializer(method)); |
|
776 |
return this; |
|
777 |
} |
|
778 |
||
16147 | 779 |
/** |
780 |
* Push the empty value for the given type, i.e. EMPTY. |
|
781 |
* |
|
782 |
* @param type the type |
|
783 |
* @return the method emitter |
|
784 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
785 |
MethodEmitter loadEmpty(final Type type) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
786 |
debug("load empty ", type); |
16147 | 787 |
pushType(type.loadEmpty(method)); |
788 |
return this; |
|
789 |
} |
|
790 |
||
791 |
/** |
|
792 |
* Push null to stack |
|
793 |
* |
|
794 |
* @return the method emitter |
|
795 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
796 |
MethodEmitter loadNull() { |
16147 | 797 |
debug("aconst_null"); |
798 |
pushType(Type.OBJECT.ldc(method, null)); |
|
799 |
return this; |
|
800 |
} |
|
801 |
||
802 |
/** |
|
803 |
* Push a handle representing this class top stack |
|
804 |
* |
|
805 |
* @param className name of the class |
|
806 |
* |
|
807 |
* @return the method emitter |
|
808 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
809 |
MethodEmitter loadType(final String className) { |
16147 | 810 |
debug("load type", className); |
811 |
method.visitLdcInsn(jdk.internal.org.objectweb.asm.Type.getObjectType(className)); |
|
812 |
pushType(Type.OBJECT); |
|
813 |
return this; |
|
814 |
} |
|
815 |
||
816 |
/** |
|
817 |
* Push a boolean constant to the stack. |
|
818 |
* |
|
819 |
* @param b value of boolean |
|
820 |
* |
|
821 |
* @return the method emitter |
|
822 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
823 |
MethodEmitter load(final boolean b) { |
16147 | 824 |
debug("load boolean", b); |
825 |
pushType(Type.BOOLEAN.ldc(method, b)); |
|
826 |
return this; |
|
827 |
} |
|
828 |
||
829 |
/** |
|
830 |
* Push an int constant to the stack |
|
831 |
* |
|
832 |
* @param i value of the int |
|
833 |
* |
|
834 |
* @return the method emitter |
|
835 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
836 |
MethodEmitter load(final int i) { |
16147 | 837 |
debug("load int", i); |
838 |
pushType(Type.INT.ldc(method, i)); |
|
839 |
return this; |
|
840 |
} |
|
841 |
||
842 |
/** |
|
843 |
* Push a double constant to the stack |
|
844 |
* |
|
845 |
* @param d value of the double |
|
846 |
* |
|
847 |
* @return the method emitter |
|
848 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
849 |
MethodEmitter load(final double d) { |
16147 | 850 |
debug("load double", d); |
851 |
pushType(Type.NUMBER.ldc(method, d)); |
|
852 |
return this; |
|
853 |
} |
|
854 |
||
855 |
/** |
|
856 |
* Push an long constant to the stack |
|
857 |
* |
|
858 |
* @param l value of the long |
|
859 |
* |
|
860 |
* @return the method emitter |
|
861 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
862 |
MethodEmitter load(final long l) { |
16147 | 863 |
debug("load long", l); |
864 |
pushType(Type.LONG.ldc(method, l)); |
|
865 |
return this; |
|
866 |
} |
|
867 |
||
868 |
/** |
|
869 |
* Fetch the length of an array. |
|
870 |
* @return Array length. |
|
871 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
872 |
MethodEmitter arraylength() { |
16147 | 873 |
debug("arraylength"); |
874 |
popType(Type.OBJECT); |
|
875 |
pushType(Type.OBJECT_ARRAY.arraylength(method)); |
|
876 |
return this; |
|
877 |
} |
|
878 |
||
879 |
/** |
|
880 |
* Push a String constant to the stack |
|
881 |
* |
|
882 |
* @param s value of the String |
|
883 |
* |
|
884 |
* @return the method emitter |
|
885 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
886 |
MethodEmitter load(final String s) { |
16147 | 887 |
debug("load string", s); |
888 |
||
889 |
if (s == null) { |
|
890 |
loadNull(); |
|
891 |
return this; |
|
892 |
} |
|
893 |
||
894 |
//NASHORN-142 - split too large string |
|
895 |
final int length = s.length(); |
|
896 |
if (length > LARGE_STRING_THRESHOLD) { |
|
897 |
||
898 |
_new(StringBuilder.class); |
|
899 |
dup(); |
|
900 |
load(length); |
|
901 |
invoke(constructorNoLookup(StringBuilder.class, int.class)); |
|
902 |
||
903 |
for (int n = 0; n < length; n += LARGE_STRING_THRESHOLD) { |
|
904 |
final String part = s.substring(n, Math.min(n + LARGE_STRING_THRESHOLD, length)); |
|
905 |
load(part); |
|
906 |
stringBuilderAppend(); |
|
907 |
} |
|
908 |
||
909 |
invoke(virtualCallNoLookup(StringBuilder.class, "toString", String.class)); |
|
910 |
||
911 |
return this; |
|
912 |
} |
|
913 |
||
914 |
pushType(Type.OBJECT.ldc(method, s)); |
|
915 |
return this; |
|
916 |
} |
|
917 |
||
918 |
/** |
|
24751 | 919 |
* Pushes the value of an identifier to the stack. If the identifier does not represent a local variable or a |
920 |
* parameter, this will be a no-op. |
|
16147 | 921 |
* |
24751 | 922 |
* @param ident the identifier for the variable being loaded. |
16147 | 923 |
* |
924 |
* @return the method emitter |
|
925 |
*/ |
|
24751 | 926 |
MethodEmitter load(final IdentNode ident) { |
927 |
return load(ident.getSymbol(), ident.getType()); |
|
928 |
} |
|
929 |
||
930 |
/** |
|
931 |
* Pushes the value of the symbol to the stack with the specified type. No type conversion is being performed, and |
|
932 |
* the type is only being used if the symbol addresses a local variable slot. The value of the symbol is loaded if |
|
933 |
* it addresses a local variable slot, or it is a parameter (in which case it can also be loaded from a vararg array |
|
934 |
* or the arguments object). If it is neither, the operation is a no-op. |
|
935 |
* |
|
936 |
* @param symbol the symbol addressing the value being loaded |
|
937 |
* @param type the presumed type of the value when it is loaded from a local variable slot |
|
938 |
* @return the method emitter |
|
939 |
*/ |
|
940 |
MethodEmitter load(final Symbol symbol, final Type type) { |
|
16147 | 941 |
assert symbol != null; |
942 |
if (symbol.hasSlot()) { |
|
24751 | 943 |
final int slot = symbol.getSlot(type); |
944 |
debug("load symbol", symbol.getName(), " slot=", slot, "type=", type); |
|
945 |
load(type, slot); |
|
24719 | 946 |
// _try(new Label("dummy"), new Label("dummy2"), recovery); |
947 |
// method.visitTryCatchBlock(new Label(), arg1, arg2, arg3); |
|
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
948 |
} else if (symbol.isParam()) { |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
949 |
assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters"; |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
950 |
final int index = symbol.getFieldIndex(); |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
951 |
if (functionNode.needsArguments()) { |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
952 |
// ScriptObject.getArgument(int) on arguments |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
953 |
debug("load symbol", symbol.getName(), " arguments index=", index); |
17233 | 954 |
loadCompilerConstant(ARGUMENTS); |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
955 |
load(index); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
956 |
ScriptObject.GET_ARGUMENT.invoke(this); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
957 |
} else { |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
958 |
// array load from __varargs__ |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
959 |
debug("load symbol", symbol.getName(), " array index=", index); |
17233 | 960 |
loadCompilerConstant(VARARGS); |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
961 |
load(symbol.getFieldIndex()); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
962 |
arrayload(); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
963 |
} |
16206
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
964 |
} |
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
965 |
return this; |
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
966 |
} |
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
967 |
|
83069fa0935b
8006529: Methods always get callee - it should be conditional
attila
parents:
16201
diff
changeset
|
968 |
/** |
24751 | 969 |
* Push a local variable to the stack, given an explicit bytecode slot. |
16147 | 970 |
* This is used e.g. for stub generation where we know where items like |
971 |
* "this" and "scope" reside. |
|
972 |
* |
|
973 |
* @param type the type of the variable |
|
974 |
* @param slot the slot the variable is in |
|
975 |
* |
|
976 |
* @return the method emitter |
|
977 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
978 |
MethodEmitter load(final Type type, final int slot) { |
16147 | 979 |
debug("explicit load", type, slot); |
16225
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
980 |
final Type loadType = type.load(method, slot); |
24719 | 981 |
assert loadType != null; |
16225
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
982 |
pushType(loadType == Type.OBJECT && isThisSlot(slot) ? Type.THIS : loadType); |
24751 | 983 |
assert !preventUndefinedLoad || (slot < stack.localVariableTypes.size() && stack.localVariableTypes.get(slot) != Type.UNKNOWN) |
984 |
: "Attempted load of uninitialized slot " + slot + " (as type " + type + ")"; |
|
24719 | 985 |
stack.markLocalLoad(slot); |
16147 | 986 |
return this; |
987 |
} |
|
988 |
||
16225
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
989 |
private boolean isThisSlot(final int slot) { |
17527
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
990 |
if (functionNode == null) { |
16225
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
991 |
return slot == CompilerConstants.JAVA_THIS.slot(); |
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
992 |
} |
24751 | 993 |
final int thisSlot = getCompilerConstantSymbol(THIS).getSlot(Type.OBJECT); |
16225
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
994 |
assert !functionNode.needsCallee() || thisSlot == 1; // needsCallee -> thisSlot == 1 |
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
995 |
assert functionNode.needsCallee() || thisSlot == 0; // !needsCallee -> thisSlot == 0 |
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
996 |
return slot == thisSlot; |
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
997 |
} |
81d58c2b9fcf
8006943: Fix order of function method arguments to be (callee, thisObject)
attila
parents:
16210
diff
changeset
|
998 |
|
16147 | 999 |
/** |
1000 |
* Push a method handle to the stack |
|
1001 |
* |
|
1002 |
* @param className class name |
|
1003 |
* @param methodName method name |
|
1004 |
* @param descName descriptor |
|
1005 |
* @param flags flags that describe this handle, e.g. invokespecial new, or invoke virtual |
|
1006 |
* |
|
1007 |
* @return the method emitter |
|
1008 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1009 |
MethodEmitter loadHandle(final String className, final String methodName, final String descName, final EnumSet<Flag> flags) { |
39165
f0000753cecd
8160141: removed deprecated method calls in nashorn code
sundar
parents:
38485
diff
changeset
|
1010 |
final int flag = Flag.getValue(flags); |
16147 | 1011 |
debug("load handle "); |
39165
f0000753cecd
8160141: removed deprecated method calls in nashorn code
sundar
parents:
38485
diff
changeset
|
1012 |
pushType(Type.OBJECT.ldc(method, new Handle(flag, className, methodName, descName, flag == H_INVOKEINTERFACE))); |
16147 | 1013 |
return this; |
1014 |
} |
|
1015 |
||
24751 | 1016 |
private Symbol getCompilerConstantSymbol(final CompilerConstants cc) { |
17233 | 1017 |
return functionNode.getBody().getExistingSymbol(cc.symbolName()); |
16147 | 1018 |
} |
1019 |
||
17255 | 1020 |
/** |
1021 |
* True if this method has a slot allocated for the scope variable (meaning, something in the method actually needs |
|
1022 |
* the scope). |
|
1023 |
* @return if this method has a slot allocated for the scope variable. |
|
1024 |
*/ |
|
1025 |
boolean hasScope() { |
|
24751 | 1026 |
return getCompilerConstantSymbol(SCOPE).hasSlot(); |
17255 | 1027 |
} |
1028 |
||
17233 | 1029 |
MethodEmitter loadCompilerConstant(final CompilerConstants cc) { |
24751 | 1030 |
return loadCompilerConstant(cc, null); |
1031 |
} |
|
1032 |
||
1033 |
MethodEmitter loadCompilerConstant(final CompilerConstants cc, final Type type) { |
|
17233 | 1034 |
if (cc == SCOPE && peekType() == Type.SCOPE) { |
1035 |
dup(); |
|
1036 |
return this; |
|
1037 |
} |
|
24751 | 1038 |
return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc)); |
16147 | 1039 |
} |
1040 |
||
26890 | 1041 |
MethodEmitter loadScope() { |
1042 |
return loadCompilerConstant(SCOPE).checkcast(Scope.class); |
|
1043 |
} |
|
1044 |
||
1045 |
MethodEmitter setSplitState(final int state) { |
|
1046 |
return loadScope().load(state).invoke(Scope.SET_SPLIT_STATE); |
|
1047 |
} |
|
1048 |
||
17233 | 1049 |
void storeCompilerConstant(final CompilerConstants cc) { |
24751 | 1050 |
storeCompilerConstant(cc, null); |
1051 |
} |
|
1052 |
||
1053 |
void storeCompilerConstant(final CompilerConstants cc, final Type type) { |
|
1054 |
final Symbol symbol = getCompilerConstantSymbol(cc); |
|
1055 |
if(!symbol.hasSlot()) { |
|
1056 |
return; |
|
1057 |
} |
|
17233 | 1058 |
debug("store compiler constant ", symbol); |
24751 | 1059 |
store(symbol, type != null ? type : getCompilerConstantType(cc)); |
1060 |
} |
|
1061 |
||
1062 |
private static Type getCompilerConstantType(final CompilerConstants cc) { |
|
1063 |
final Class<?> constantType = cc.type(); |
|
1064 |
assert constantType != null; |
|
1065 |
return Type.typeFor(constantType); |
|
16147 | 1066 |
} |
1067 |
||
1068 |
/** |
|
1069 |
* Load an element from an array, determining type automatically |
|
1070 |
* @return the method emitter |
|
1071 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1072 |
MethodEmitter arrayload() { |
16147 | 1073 |
debug("Xaload"); |
1074 |
popType(Type.INT); |
|
1075 |
pushType(popArray().aload(method)); |
|
1076 |
return this; |
|
1077 |
} |
|
1078 |
||
1079 |
/** |
|
1080 |
* Pop a value, an index and an array from the stack and store |
|
1081 |
* the value at the given index in the array. |
|
1082 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1083 |
void arraystore() { |
16147 | 1084 |
debug("Xastore"); |
1085 |
final Type value = popType(); |
|
1086 |
final Type index = popType(Type.INT); |
|
1087 |
assert index.isInteger() : "array index is not integer, but " + index; |
|
1088 |
final ArrayType array = popArray(); |
|
1089 |
||
1090 |
assert value.isEquivalentTo(array.getElementType()) : "Storing "+value+" into "+array; |
|
1091 |
assert array.isObject(); |
|
1092 |
array.astore(method); |
|
1093 |
} |
|
1094 |
||
1095 |
/** |
|
1096 |
* Pop a value from the stack and store it in a local variable represented |
|
24751 | 1097 |
* by the given identifier. If the symbol has no slot, this is a NOP |
16147 | 1098 |
* |
24751 | 1099 |
* @param ident identifier to store stack to |
1100 |
*/ |
|
1101 |
void store(final IdentNode ident) { |
|
1102 |
final Type type = ident.getType(); |
|
1103 |
final Symbol symbol = ident.getSymbol(); |
|
1104 |
if(type == Type.UNDEFINED) { |
|
1105 |
assert peekType() == Type.UNDEFINED; |
|
1106 |
store(symbol, Type.OBJECT); |
|
1107 |
} else { |
|
1108 |
store(symbol, type); |
|
1109 |
} |
|
1110 |
} |
|
1111 |
||
1112 |
/** |
|
1113 |
* Represents a definition of a local variable with a type. Used for local variable table building. |
|
16147 | 1114 |
*/ |
24751 | 1115 |
private static class LocalVariableDef { |
1116 |
// The start label from where this definition lives. |
|
1117 |
private final jdk.internal.org.objectweb.asm.Label label; |
|
1118 |
// The currently live type of the local variable. |
|
1119 |
private final Type type; |
|
1120 |
||
1121 |
LocalVariableDef(final jdk.internal.org.objectweb.asm.Label label, final Type type) { |
|
1122 |
this.label = label; |
|
1123 |
this.type = type; |
|
1124 |
} |
|
1125 |
||
1126 |
} |
|
1127 |
||
1128 |
void closeLocalVariable(final Symbol symbol, final Label label) { |
|
1129 |
final LocalVariableDef def = localVariableDefs.get(symbol); |
|
1130 |
if(def != null) { |
|
1131 |
endLocalValueDef(symbol, def, label.getLabel()); |
|
1132 |
} |
|
1133 |
if(isReachable()) { |
|
1134 |
markDeadLocalVariable(symbol); |
|
1135 |
} |
|
1136 |
} |
|
1137 |
||
1138 |
void markDeadLocalVariable(final Symbol symbol) { |
|
1139 |
if(!symbol.isDead()) { |
|
1140 |
markDeadSlots(symbol.getFirstSlot(), symbol.slotCount()); |
|
1141 |
} |
|
1142 |
} |
|
1143 |
||
1144 |
void markDeadSlots(final int firstSlot, final int slotCount) { |
|
1145 |
stack.markDeadLocalVariables(firstSlot, slotCount); |
|
1146 |
} |
|
1147 |
||
1148 |
private void endLocalValueDef(final Symbol symbol, final LocalVariableDef def, final jdk.internal.org.objectweb.asm.Label label) { |
|
1149 |
String name = symbol.getName(); |
|
1150 |
if (name.equals(THIS.symbolName())) { |
|
1151 |
name = THIS_DEBUGGER.symbolName(); |
|
1152 |
} |
|
1153 |
method.visitLocalVariable(name, def.type.getDescriptor(), null, def.label, label, symbol.getSlot(def.type)); |
|
1154 |
} |
|
1155 |
||
1156 |
void store(final Symbol symbol, final Type type) { |
|
1157 |
store(symbol, type, true); |
|
1158 |
} |
|
1159 |
||
1160 |
/** |
|
1161 |
* Pop a value from the stack and store it in a variable denoted by the given symbol. The variable should be either |
|
1162 |
* a local variable, or a function parameter (and not a scoped variable). For local variables, this method will also |
|
32534
b3ec7f3b3c2a
8136349: Typos patch for nashorn sources submitted on Sep 10, 2015
sundar
parents:
32048
diff
changeset
|
1163 |
* do the bookkeeping of the local variable table as well as mark values in all alternative slots for the symbol as |
24751 | 1164 |
* dead. In this regard it differs from {@link #storeHidden(Type, int)}. |
1165 |
* |
|
1166 |
* @param symbol the symbol to store into. |
|
1167 |
* @param type the type to store |
|
1168 |
* @param onlySymbolLiveValue if true, this is the sole live value for the symbol. If false, currently live values should |
|
1169 |
* be kept live. |
|
1170 |
*/ |
|
1171 |
void store(final Symbol symbol, final Type type, final boolean onlySymbolLiveValue) { |
|
16201
889ddb179cdf
8007062: Split Lower up into Lower/Attr/FinalizeTypes. Integrate AccessSpecalizer into FinalizeTypes.
lagergren
parents:
16154
diff
changeset
|
1172 |
assert symbol != null : "No symbol to store"; |
16147 | 1173 |
if (symbol.hasSlot()) { |
24751 | 1174 |
final boolean isLiveType = symbol.hasSlotFor(type); |
1175 |
final LocalVariableDef existingDef = localVariableDefs.get(symbol); |
|
1176 |
if(existingDef == null || existingDef.type != type) { |
|
1177 |
final jdk.internal.org.objectweb.asm.Label here = new jdk.internal.org.objectweb.asm.Label(); |
|
1178 |
if(isLiveType) { |
|
1179 |
final LocalVariableDef newDef = new LocalVariableDef(here, type); |
|
1180 |
localVariableDefs.put(symbol, newDef); |
|
1181 |
} |
|
1182 |
method.visitLabel(here); |
|
1183 |
if(existingDef != null) { |
|
1184 |
endLocalValueDef(symbol, existingDef, here); |
|
1185 |
} |
|
1186 |
} |
|
1187 |
if(isLiveType) { |
|
1188 |
final int slot = symbol.getSlot(type); |
|
1189 |
debug("store symbol", symbol.getName(), " type=", type, " slot=", slot); |
|
1190 |
storeHidden(type, slot, onlySymbolLiveValue); |
|
1191 |
} else { |
|
1192 |
if(onlySymbolLiveValue) { |
|
1193 |
markDeadLocalVariable(symbol); |
|
1194 |
} |
|
1195 |
debug("dead store symbol ", symbol.getName(), " type=", type); |
|
1196 |
pop(); |
|
1197 |
} |
|
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1198 |
} else if (symbol.isParam()) { |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1199 |
assert !symbol.isScope(); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1200 |
assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters"; |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1201 |
final int index = symbol.getFieldIndex(); |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1202 |
if (functionNode.needsArguments()) { |
24751 | 1203 |
convert(Type.OBJECT); |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1204 |
debug("store symbol", symbol.getName(), " arguments index=", index); |
17233 | 1205 |
loadCompilerConstant(ARGUMENTS); |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1206 |
load(index); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1207 |
ArgumentSetter.SET_ARGUMENT.invoke(this); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1208 |
} else { |
24751 | 1209 |
convert(Type.OBJECT); |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1210 |
// varargs without arguments object - just do array store to __varargs__ |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1211 |
debug("store symbol", symbol.getName(), " array index=", index); |
17233 | 1212 |
loadCompilerConstant(VARARGS); |
16209
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1213 |
load(index); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1214 |
ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this); |
18e55b352d56
8007460: var assignment to a parameter in a varargs method causes compilation error
attila
parents:
16206
diff
changeset
|
1215 |
} |
24751 | 1216 |
} else { |
1217 |
debug("dead store symbol ", symbol.getName(), " type=", type); |
|
1218 |
pop(); |
|
16147 | 1219 |
} |
1220 |
} |
|
1221 |
||
1222 |
/** |
|
24751 | 1223 |
* Pop a value from the stack and store it in a local variable slot. Note that in contrast with |
1224 |
* {@link #store(Symbol, Type)}, this method does not adjust the local variable table, nor marks slots for |
|
1225 |
* alternative value types for the symbol as being dead. For that reason, this method is usually not called |
|
1226 |
* directly. Notable exceptions are temporary internal locals (e.g. quick store, last-catch-condition, etc.) that |
|
1227 |
* are not desired to show up in the local variable table. |
|
16147 | 1228 |
* |
1229 |
* @param type the type to pop |
|
1230 |
* @param slot the slot |
|
1231 |
*/ |
|
24751 | 1232 |
void storeHidden(final Type type, final int slot) { |
1233 |
storeHidden(type, slot, true); |
|
1234 |
} |
|
1235 |
||
1236 |
void storeHidden(final Type type, final int slot, final boolean onlyLiveSymbolValue) { |
|
1237 |
explicitStore(type, slot); |
|
1238 |
stack.onLocalStore(type, slot, onlyLiveSymbolValue); |
|
1239 |
} |
|
1240 |
||
1241 |
void storeTemp(final Type type, final int slot) { |
|
1242 |
explicitStore(type, slot); |
|
1243 |
defineTemporaryLocalVariable(slot, slot + type.getSlots()); |
|
1244 |
onLocalStore(type, slot); |
|
1245 |
} |
|
1246 |
||
1247 |
void onLocalStore(final Type type, final int slot) { |
|
1248 |
stack.onLocalStore(type, slot, true); |
|
1249 |
} |
|
1250 |
||
1251 |
private void explicitStore(final Type type, final int slot) { |
|
1252 |
assert slot != -1; |
|
24719 | 1253 |
debug("explicit store", type, slot); |
16147 | 1254 |
popType(type); |
1255 |
type.store(method, slot); |
|
24751 | 1256 |
} |
1257 |
||
1258 |
/** |
|
1259 |
* Marks a range of slots as belonging to a defined local variable. The slots will start out with no live value |
|
1260 |
* in them. |
|
1261 |
* @param fromSlot first slot, inclusive. |
|
1262 |
* @param toSlot last slot, exclusive. |
|
1263 |
*/ |
|
1264 |
void defineBlockLocalVariable(final int fromSlot, final int toSlot) { |
|
1265 |
stack.defineBlockLocalVariable(fromSlot, toSlot); |
|
24719 | 1266 |
} |
1267 |
||
24751 | 1268 |
/** |
1269 |
* Marks a range of slots as belonging to a defined temporary local variable. The slots will start out with no |
|
1270 |
* live value in them. |
|
1271 |
* @param fromSlot first slot, inclusive. |
|
1272 |
* @param toSlot last slot, exclusive. |
|
1273 |
*/ |
|
1274 |
void defineTemporaryLocalVariable(final int fromSlot, final int toSlot) { |
|
1275 |
stack.defineTemporaryLocalVariable(fromSlot, toSlot); |
|
1276 |
} |
|
1277 |
||
1278 |
/** |
|
1279 |
* Defines a new temporary local variable and returns its allocated index. |
|
1280 |
* @param width the required width (in slots) for the new variable. |
|
1281 |
* @return the bytecode slot index where the newly allocated local begins. |
|
1282 |
*/ |
|
1283 |
int defineTemporaryLocalVariable(final int width) { |
|
1284 |
return stack.defineTemporaryLocalVariable(width); |
|
1285 |
} |
|
1286 |
||
1287 |
void undefineLocalVariables(final int fromSlot, final boolean canTruncateSymbol) { |
|
1288 |
if(isReachable()) { |
|
1289 |
stack.undefineLocalVariables(fromSlot, canTruncateSymbol); |
|
24719 | 1290 |
} |
1291 |
} |
|
1292 |
||
1293 |
List<Type> getLocalVariableTypes() { |
|
24751 | 1294 |
return stack.localVariableTypes; |
24719 | 1295 |
} |
1296 |
||
24751 | 1297 |
List<Type> getWidestLiveLocals(final List<Type> localTypes) { |
1298 |
return stack.getWidestLiveLocals(localTypes); |
|
1299 |
} |
|
1300 |
||
1301 |
String markSymbolBoundariesInLvarTypesDescriptor(final String lvarDescriptor) { |
|
1302 |
return stack.markSymbolBoundariesInLvarTypesDescriptor(lvarDescriptor); |
|
16147 | 1303 |
} |
1304 |
||
1305 |
/** |
|
1306 |
* Increment/Decrement a local integer by the given value. |
|
1307 |
* |
|
1308 |
* @param slot the int slot |
|
1309 |
* @param increment the amount to increment |
|
1310 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1311 |
void iinc(final int slot, final int increment) { |
16147 | 1312 |
debug("iinc"); |
1313 |
method.visitIincInsn(slot, increment); |
|
1314 |
} |
|
1315 |
||
1316 |
/** |
|
1317 |
* Pop an exception object from the stack and generate code |
|
1318 |
* for throwing it |
|
1319 |
*/ |
|
1320 |
public void athrow() { |
|
1321 |
debug("athrow"); |
|
1322 |
final Type receiver = popType(Type.OBJECT); |
|
24719 | 1323 |
assert Throwable.class.isAssignableFrom(receiver.getTypeClass()) : receiver.getTypeClass(); |
16147 | 1324 |
method.visitInsn(ATHROW); |
24751 | 1325 |
doesNotContinueSequentially(); |
16147 | 1326 |
} |
1327 |
||
1328 |
/** |
|
1329 |
* Pop an object from the stack and perform an instanceof |
|
1330 |
* operation, given a classDescriptor to compare it to. |
|
1331 |
* Push the boolean result 1/0 as an int to the stack |
|
1332 |
* |
|
1333 |
* @param classDescriptor descriptor of the class to type check against |
|
1334 |
* |
|
1335 |
* @return the method emitter |
|
1336 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1337 |
MethodEmitter _instanceof(final String classDescriptor) { |
16147 | 1338 |
debug("instanceof", classDescriptor); |
1339 |
popType(Type.OBJECT); |
|
1340 |
method.visitTypeInsn(INSTANCEOF, classDescriptor); |
|
1341 |
pushType(Type.INT); |
|
1342 |
return this; |
|
1343 |
} |
|
1344 |
||
1345 |
/** |
|
1346 |
* Pop an object from the stack and perform an instanceof |
|
1347 |
* operation, given a classDescriptor to compare it to. |
|
1348 |
* Push the boolean result 1/0 as an int to the stack |
|
1349 |
* |
|
1350 |
* @param clazz the type to check instanceof against |
|
1351 |
* |
|
1352 |
* @return the method emitter |
|
1353 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1354 |
MethodEmitter _instanceof(final Class<?> clazz) { |
16147 | 1355 |
return _instanceof(CompilerConstants.className(clazz)); |
1356 |
} |
|
1357 |
||
1358 |
/** |
|
1359 |
* Perform a checkcast operation on the object at the top of the |
|
1360 |
* stack. |
|
1361 |
* |
|
1362 |
* @param classDescriptor descriptor of the class to type check against |
|
1363 |
* |
|
1364 |
* @return the method emitter |
|
1365 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1366 |
MethodEmitter checkcast(final String classDescriptor) { |
16147 | 1367 |
debug("checkcast", classDescriptor); |
1368 |
assert peekType().isObject(); |
|
1369 |
method.visitTypeInsn(CHECKCAST, classDescriptor); |
|
1370 |
return this; |
|
1371 |
} |
|
1372 |
||
1373 |
/** |
|
1374 |
* Perform a checkcast operation on the object at the top of the |
|
1375 |
* stack. |
|
1376 |
* |
|
1377 |
* @param clazz class to checkcast against |
|
1378 |
* |
|
1379 |
* @return the method emitter |
|
1380 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1381 |
MethodEmitter checkcast(final Class<?> clazz) { |
16147 | 1382 |
return checkcast(CompilerConstants.className(clazz)); |
1383 |
} |
|
1384 |
||
1385 |
/** |
|
1386 |
* Instantiate a new array given a length that is popped |
|
1387 |
* from the stack and the array type |
|
1388 |
* |
|
1389 |
* @param arrayType the type of the array |
|
1390 |
* |
|
1391 |
* @return the method emitter |
|
1392 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1393 |
MethodEmitter newarray(final ArrayType arrayType) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1394 |
debug("newarray ", "arrayType=", arrayType); |
16147 | 1395 |
popType(Type.INT); //LENGTH |
1396 |
pushType(arrayType.newarray(method)); |
|
1397 |
return this; |
|
1398 |
} |
|
1399 |
||
1400 |
/** |
|
1401 |
* Instantiate a multidimensional array with a given number of dimensions. |
|
1402 |
* On the stack are dim lengths of the sub arrays. |
|
1403 |
* |
|
1404 |
* @param arrayType type of the array |
|
1405 |
* @param dims number of dimensions |
|
1406 |
* |
|
1407 |
* @return the method emitter |
|
1408 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1409 |
MethodEmitter multinewarray(final ArrayType arrayType, final int dims) { |
16147 | 1410 |
debug("multianewarray ", arrayType, dims); |
1411 |
for (int i = 0; i < dims; i++) { |
|
1412 |
popType(Type.INT); //LENGTH |
|
1413 |
} |
|
1414 |
pushType(arrayType.newarray(method, dims)); |
|
1415 |
return this; |
|
1416 |
} |
|
1417 |
||
1418 |
/** |
|
1419 |
* Helper function to pop and type check the appropriate arguments |
|
1420 |
* from the stack given a method signature |
|
1421 |
* |
|
1422 |
* @param signature method signature |
|
1423 |
* |
|
1424 |
* @return return type of method |
|
1425 |
*/ |
|
1426 |
private Type fixParamStack(final String signature) { |
|
1427 |
final Type[] params = Type.getMethodArguments(signature); |
|
1428 |
for (int i = params.length - 1; i >= 0; i--) { |
|
1429 |
popType(params[i]); |
|
1430 |
} |
|
1431 |
final Type returnType = Type.getMethodReturnType(signature); |
|
1432 |
return returnType; |
|
1433 |
} |
|
1434 |
||
1435 |
/** |
|
1436 |
* Generate an invocation to a Call structure |
|
1437 |
* @see CompilerConstants |
|
1438 |
* |
|
1439 |
* @param call the call object |
|
1440 |
* |
|
1441 |
* @return the method emitter |
|
1442 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1443 |
MethodEmitter invoke(final Call call) { |
16147 | 1444 |
return call.invoke(this); |
1445 |
} |
|
1446 |
||
1447 |
private MethodEmitter invoke(final int opcode, final String className, final String methodName, final String methodDescriptor, final boolean hasReceiver) { |
|
1448 |
final Type returnType = fixParamStack(methodDescriptor); |
|
1449 |
||
1450 |
if (hasReceiver) { |
|
1451 |
popType(Type.OBJECT); |
|
1452 |
} |
|
1453 |
||
24719 | 1454 |
method.visitMethodInsn(opcode, className, methodName, methodDescriptor, opcode == INVOKEINTERFACE); |
16147 | 1455 |
|
1456 |
if (returnType != null) { |
|
1457 |
pushType(returnType); |
|
1458 |
} |
|
1459 |
||
1460 |
return this; |
|
1461 |
} |
|
1462 |
||
1463 |
/** |
|
1464 |
* Pop receiver from stack, perform an invoke special |
|
1465 |
* |
|
1466 |
* @param className class name |
|
1467 |
* @param methodName method name |
|
1468 |
* @param methodDescriptor descriptor |
|
1469 |
* |
|
1470 |
* @return the method emitter |
|
1471 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1472 |
MethodEmitter invokespecial(final String className, final String methodName, final String methodDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1473 |
debug("invokespecial", className, ".", methodName, methodDescriptor); |
16147 | 1474 |
return invoke(INVOKESPECIAL, className, methodName, methodDescriptor, true); |
1475 |
} |
|
1476 |
||
1477 |
/** |
|
1478 |
* Pop receiver from stack, perform an invoke virtual, push return value if any |
|
1479 |
* |
|
1480 |
* @param className class name |
|
1481 |
* @param methodName method name |
|
1482 |
* @param methodDescriptor descriptor |
|
1483 |
* |
|
1484 |
* @return the method emitter |
|
1485 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1486 |
MethodEmitter invokevirtual(final String className, final String methodName, final String methodDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1487 |
debug("invokevirtual", className, ".", methodName, methodDescriptor, " ", stack); |
16147 | 1488 |
return invoke(INVOKEVIRTUAL, className, methodName, methodDescriptor, true); |
1489 |
} |
|
1490 |
||
1491 |
/** |
|
1492 |
* Perform an invoke static and push the return value if any |
|
1493 |
* |
|
1494 |
* @param className class name |
|
1495 |
* @param methodName method name |
|
1496 |
* @param methodDescriptor descriptor |
|
1497 |
* |
|
1498 |
* @return the method emitter |
|
1499 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1500 |
MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1501 |
debug("invokestatic", className, ".", methodName, methodDescriptor); |
16147 | 1502 |
invoke(INVOKESTATIC, className, methodName, methodDescriptor, false); |
1503 |
return this; |
|
1504 |
} |
|
1505 |
||
1506 |
/** |
|
1507 |
* Perform an invoke static and replace the return type if we know better, e.g. Global.allocate |
|
1508 |
* that allocates an array should return an ObjectArray type as a NativeArray counts as that |
|
1509 |
* |
|
1510 |
* @param className class name |
|
1511 |
* @param methodName method name |
|
1512 |
* @param methodDescriptor descriptor |
|
1513 |
* @param returnType return type override |
|
1514 |
* |
|
1515 |
* @return the method emitter |
|
1516 |
*/ |
|
24719 | 1517 |
MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) { |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1518 |
invokestatic(className, methodName, methodDescriptor); |
16147 | 1519 |
popType(); |
1520 |
pushType(returnType); |
|
1521 |
return this; |
|
1522 |
} |
|
1523 |
||
1524 |
/** |
|
1525 |
* Pop receiver from stack, perform an invoke interface and push return value if any |
|
1526 |
* |
|
1527 |
* @param className class name |
|
1528 |
* @param methodName method name |
|
1529 |
* @param methodDescriptor descriptor |
|
1530 |
* |
|
1531 |
* @return the method emitter |
|
1532 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1533 |
MethodEmitter invokeinterface(final String className, final String methodName, final String methodDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1534 |
debug("invokeinterface", className, ".", methodName, methodDescriptor); |
16147 | 1535 |
return invoke(INVOKEINTERFACE, className, methodName, methodDescriptor, true); |
1536 |
} |
|
1537 |
||
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:
17255
diff
changeset
|
1538 |
static jdk.internal.org.objectweb.asm.Label[] getLabels(final Label... table) { |
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:
17255
diff
changeset
|
1539 |
final jdk.internal.org.objectweb.asm.Label[] internalLabels = new jdk.internal.org.objectweb.asm.Label[table.length]; |
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:
17255
diff
changeset
|
1540 |
for (int i = 0; i < table.length; i++) { |
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:
17255
diff
changeset
|
1541 |
internalLabels[i] = table[i].getLabel(); |
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:
17255
diff
changeset
|
1542 |
} |
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:
17255
diff
changeset
|
1543 |
return internalLabels; |
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:
17255
diff
changeset
|
1544 |
} |
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:
17255
diff
changeset
|
1545 |
|
16147 | 1546 |
/** |
1547 |
* Generate a lookup switch, popping the switch value from the stack |
|
1548 |
* |
|
1549 |
* @param defaultLabel default label |
|
1550 |
* @param values case values for the table |
|
1551 |
* @param table default label |
|
1552 |
*/ |
|
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:
17255
diff
changeset
|
1553 |
void lookupswitch(final Label defaultLabel, final int[] values, final Label... table) {//Collection<Label> table) { |
16147 | 1554 |
debug("lookupswitch", peekType()); |
24719 | 1555 |
adjustStackForSwitch(defaultLabel, table); |
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:
17255
diff
changeset
|
1556 |
method.visitLookupSwitchInsn(defaultLabel.getLabel(), values, getLabels(table)); |
24751 | 1557 |
doesNotContinueSequentially(); |
16147 | 1558 |
} |
1559 |
||
1560 |
/** |
|
1561 |
* Generate a table switch |
|
1562 |
* @param lo low value |
|
1563 |
* @param hi high value |
|
1564 |
* @param defaultLabel default label |
|
1565 |
* @param table label table |
|
1566 |
*/ |
|
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:
17255
diff
changeset
|
1567 |
void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) { |
16147 | 1568 |
debug("tableswitch", peekType()); |
24719 | 1569 |
adjustStackForSwitch(defaultLabel, table); |
1570 |
method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table)); |
|
24751 | 1571 |
doesNotContinueSequentially(); |
24719 | 1572 |
} |
1573 |
||
1574 |
private void adjustStackForSwitch(final Label defaultLabel, final Label... table) { |
|
16147 | 1575 |
popType(Type.INT); |
24751 | 1576 |
joinTo(defaultLabel); |
24719 | 1577 |
for(final Label label: table) { |
24751 | 1578 |
joinTo(label); |
24719 | 1579 |
} |
16147 | 1580 |
} |
1581 |
||
1582 |
/** |
|
1583 |
* Abstraction for performing a conditional jump of any type |
|
1584 |
* |
|
27368 | 1585 |
* @see Condition |
16147 | 1586 |
* |
1587 |
* @param cond the condition to test |
|
1588 |
* @param trueLabel the destination label is condition is true |
|
1589 |
*/ |
|
1590 |
void conditionalJump(final Condition cond, final Label trueLabel) { |
|
1591 |
conditionalJump(cond, cond != Condition.GT && cond != Condition.GE, trueLabel); |
|
1592 |
} |
|
1593 |
||
1594 |
/** |
|
1595 |
* Abstraction for performing a conditional jump of any type, |
|
1596 |
* including a dcmpg/dcmpl semantic for doubles. |
|
1597 |
* |
|
1598 |
* @param cond the condition to test |
|
1599 |
* @param isCmpG is this a dcmpg for numbers, false if it's a dcmpl |
|
1600 |
* @param trueLabel the destination label if condition is true |
|
1601 |
*/ |
|
1602 |
void conditionalJump(final Condition cond, final boolean isCmpG, final Label trueLabel) { |
|
1603 |
if (peekType().isCategory2()) { |
|
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1604 |
debug("[ld]cmp isCmpG=", isCmpG); |
16147 | 1605 |
pushType(get2n().cmp(method, isCmpG)); |
1606 |
jump(Condition.toUnary(cond), trueLabel, 1); |
|
1607 |
} else { |
|
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
1608 |
debug("if", cond); |
16147 | 1609 |
jump(Condition.toBinary(cond, peekType().isObject()), trueLabel, 2); |
1610 |
} |
|
1611 |
} |
|
1612 |
||
1613 |
/** |
|
1614 |
* Perform a non void return, popping the type from the stack |
|
1615 |
* |
|
1616 |
* @param type the type for the return |
|
1617 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1618 |
void _return(final Type type) { |
16147 | 1619 |
debug("return", type); |
1620 |
assert stack.size() == 1 : "Only return value on stack allowed at return point - depth=" + stack.size() + " stack = " + stack; |
|
1621 |
final Type stackType = peekType(); |
|
1622 |
if (!Type.areEquivalent(type, stackType)) { |
|
1623 |
convert(type); |
|
1624 |
} |
|
1625 |
popType(type)._return(method); |
|
24751 | 1626 |
doesNotContinueSequentially(); |
16147 | 1627 |
} |
1628 |
||
1629 |
/** |
|
1630 |
* Perform a return using the stack top value as the guide for the type |
|
1631 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1632 |
void _return() { |
16147 | 1633 |
_return(peekType()); |
1634 |
} |
|
1635 |
||
1636 |
/** |
|
1637 |
* Perform a void return. |
|
1638 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1639 |
void returnVoid() { |
16147 | 1640 |
debug("return [void]"); |
1641 |
assert stack.isEmpty() : stack; |
|
1642 |
method.visitInsn(RETURN); |
|
24751 | 1643 |
doesNotContinueSequentially(); |
16147 | 1644 |
} |
1645 |
||
1646 |
/** |
|
1647 |
* Perform a comparison of two number types that are popped from the stack |
|
1648 |
* |
|
1649 |
* @param isCmpG is this a dcmpg semantic, false if it's a dcmpl semantic |
|
1650 |
* |
|
1651 |
* @return the method emitter |
|
1652 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1653 |
MethodEmitter cmp(final boolean isCmpG) { |
16147 | 1654 |
pushType(get2n().cmp(method, isCmpG)); |
1655 |
return this; |
|
1656 |
} |
|
1657 |
||
1658 |
/** |
|
1659 |
* Helper function for jumps, conditional or not |
|
1660 |
* @param opcode opcode for jump |
|
1661 |
* @param label destination |
|
1662 |
* @param n elements on stack to compare, 0-2 |
|
1663 |
*/ |
|
1664 |
private void jump(final int opcode, final Label label, final int n) { |
|
1665 |
for (int i = 0; i < n; i++) { |
|
1666 |
assert peekType().isInteger() || peekType().isBoolean() || peekType().isObject() : "expecting integer type or object for jump, but found " + peekType(); |
|
1667 |
popType(); |
|
1668 |
} |
|
24751 | 1669 |
joinTo(label); |
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:
17255
diff
changeset
|
1670 |
method.visitJumpInsn(opcode, label.getLabel()); |
16147 | 1671 |
} |
1672 |
||
1673 |
/** |
|
1674 |
* Generate an if_acmpeq |
|
1675 |
* |
|
1676 |
* @param label label to true case |
|
1677 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1678 |
void if_acmpeq(final Label label) { |
16147 | 1679 |
debug("if_acmpeq", label); |
1680 |
jump(IF_ACMPEQ, label, 2); |
|
1681 |
} |
|
1682 |
||
1683 |
/** |
|
1684 |
* Generate an if_acmpne |
|
1685 |
* |
|
1686 |
* @param label label to true case |
|
1687 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1688 |
void if_acmpne(final Label label) { |
16147 | 1689 |
debug("if_acmpne", label); |
1690 |
jump(IF_ACMPNE, label, 2); |
|
1691 |
} |
|
1692 |
||
1693 |
/** |
|
1694 |
* Generate an ifnull |
|
1695 |
* |
|
1696 |
* @param label label to true case |
|
1697 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1698 |
void ifnull(final Label label) { |
16147 | 1699 |
debug("ifnull", label); |
1700 |
jump(IFNULL, label, 1); |
|
1701 |
} |
|
1702 |
||
1703 |
/** |
|
1704 |
* Generate an ifnonnull |
|
1705 |
* |
|
1706 |
* @param label label to true case |
|
1707 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1708 |
void ifnonnull(final Label label) { |
16147 | 1709 |
debug("ifnonnull", label); |
1710 |
jump(IFNONNULL, label, 1); |
|
1711 |
} |
|
1712 |
||
1713 |
/** |
|
1714 |
* Generate an ifeq |
|
1715 |
* |
|
1716 |
* @param label label to true case |
|
1717 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1718 |
void ifeq(final Label label) { |
16147 | 1719 |
debug("ifeq ", label); |
1720 |
jump(IFEQ, label, 1); |
|
1721 |
} |
|
1722 |
||
1723 |
/** |
|
1724 |
* Generate an if_icmpeq |
|
1725 |
* |
|
1726 |
* @param label label to true case |
|
1727 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1728 |
void if_icmpeq(final Label label) { |
16147 | 1729 |
debug("if_icmpeq", label); |
1730 |
jump(IF_ICMPEQ, label, 2); |
|
1731 |
} |
|
1732 |
||
1733 |
/** |
|
1734 |
* Generate an if_ne |
|
1735 |
* |
|
1736 |
* @param label label to true case |
|
1737 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1738 |
void ifne(final Label label) { |
16147 | 1739 |
debug("ifne", label); |
1740 |
jump(IFNE, label, 1); |
|
1741 |
} |
|
1742 |
||
1743 |
/** |
|
1744 |
* Generate an if_icmpne |
|
1745 |
* |
|
1746 |
* @param label label to true case |
|
1747 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1748 |
void if_icmpne(final Label label) { |
16147 | 1749 |
debug("if_icmpne", label); |
1750 |
jump(IF_ICMPNE, label, 2); |
|
1751 |
} |
|
1752 |
||
1753 |
/** |
|
1754 |
* Generate an iflt |
|
1755 |
* |
|
1756 |
* @param label label to true case |
|
1757 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1758 |
void iflt(final Label label) { |
16147 | 1759 |
debug("iflt", label); |
1760 |
jump(IFLT, label, 1); |
|
1761 |
} |
|
1762 |
||
1763 |
/** |
|
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:
24719
diff
changeset
|
1764 |
* Generate an if_icmplt |
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:
24719
diff
changeset
|
1765 |
* |
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:
24719
diff
changeset
|
1766 |
* @param label label to true case |
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:
24719
diff
changeset
|
1767 |
*/ |
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:
24719
diff
changeset
|
1768 |
void if_icmplt(final Label label) { |
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:
24719
diff
changeset
|
1769 |
debug("if_icmplt", label); |
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:
24719
diff
changeset
|
1770 |
jump(IF_ICMPLT, label, 2); |
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:
24719
diff
changeset
|
1771 |
} |
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:
24719
diff
changeset
|
1772 |
|
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:
24719
diff
changeset
|
1773 |
/** |
16147 | 1774 |
* Generate an ifle |
1775 |
* |
|
1776 |
* @param label label to true case |
|
1777 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1778 |
void ifle(final Label label) { |
16147 | 1779 |
debug("ifle", label); |
1780 |
jump(IFLE, label, 1); |
|
1781 |
} |
|
1782 |
||
1783 |
/** |
|
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:
24719
diff
changeset
|
1784 |
* Generate an if_icmple |
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:
24719
diff
changeset
|
1785 |
* |
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:
24719
diff
changeset
|
1786 |
* @param label label to true case |
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:
24719
diff
changeset
|
1787 |
*/ |
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:
24719
diff
changeset
|
1788 |
void if_icmple(final Label label) { |
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:
24719
diff
changeset
|
1789 |
debug("if_icmple", label); |
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:
24719
diff
changeset
|
1790 |
jump(IF_ICMPLE, label, 2); |
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:
24719
diff
changeset
|
1791 |
} |
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:
24719
diff
changeset
|
1792 |
|
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:
24719
diff
changeset
|
1793 |
/** |
16147 | 1794 |
* Generate an ifgt |
1795 |
* |
|
1796 |
* @param label label to true case |
|
1797 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1798 |
void ifgt(final Label label) { |
16147 | 1799 |
debug("ifgt", label); |
1800 |
jump(IFGT, label, 1); |
|
1801 |
} |
|
1802 |
||
1803 |
/** |
|
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:
24719
diff
changeset
|
1804 |
* Generate an if_icmpgt |
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:
24719
diff
changeset
|
1805 |
* |
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:
24719
diff
changeset
|
1806 |
* @param label label to true case |
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:
24719
diff
changeset
|
1807 |
*/ |
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:
24719
diff
changeset
|
1808 |
void if_icmpgt(final Label label) { |
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:
24719
diff
changeset
|
1809 |
debug("if_icmpgt", label); |
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:
24719
diff
changeset
|
1810 |
jump(IF_ICMPGT, label, 2); |
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:
24719
diff
changeset
|
1811 |
} |
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:
24719
diff
changeset
|
1812 |
|
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:
24719
diff
changeset
|
1813 |
/** |
16147 | 1814 |
* Generate an ifge |
1815 |
* |
|
1816 |
* @param label label to true case |
|
1817 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1818 |
void ifge(final Label label) { |
16147 | 1819 |
debug("ifge", label); |
1820 |
jump(IFGE, label, 1); |
|
1821 |
} |
|
1822 |
||
1823 |
/** |
|
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:
24719
diff
changeset
|
1824 |
* Generate an if_icmpge |
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:
24719
diff
changeset
|
1825 |
* |
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:
24719
diff
changeset
|
1826 |
* @param label label to true case |
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:
24719
diff
changeset
|
1827 |
*/ |
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:
24719
diff
changeset
|
1828 |
void if_icmpge(final Label label) { |
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:
24719
diff
changeset
|
1829 |
debug("if_icmpge", label); |
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:
24719
diff
changeset
|
1830 |
jump(IF_ICMPGE, label, 2); |
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:
24719
diff
changeset
|
1831 |
} |
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:
24719
diff
changeset
|
1832 |
|
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:
24719
diff
changeset
|
1833 |
/** |
16147 | 1834 |
* Unconditional jump to a label |
1835 |
* |
|
1836 |
* @param label destination label |
|
1837 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1838 |
void _goto(final Label label) { |
24719 | 1839 |
debug("goto", label); |
16147 | 1840 |
jump(GOTO, label, 0); |
24751 | 1841 |
doesNotContinueSequentially(); //whoever reaches the point after us provides the stack, because we don't |
1842 |
} |
|
1843 |
||
1844 |
/** |
|
1845 |
* Unconditional jump to the start label of a loop. It differs from ordinary {@link #_goto(Label)} in that it will |
|
1846 |
* preserve the current label stack, as the next instruction after the goto is loop body that the loop will come |
|
1847 |
* back to. Also used to jump at the start label of the continuation handler, as it behaves much like a loop test in |
|
1848 |
* the sense that after it is evaluated, it also jumps backwards. |
|
1849 |
* |
|
1850 |
* @param loopStart start label of a loop |
|
1851 |
*/ |
|
1852 |
void gotoLoopStart(final Label loopStart) { |
|
1853 |
debug("goto (loop)", loopStart); |
|
1854 |
jump(GOTO, loopStart, 0); |
|
16147 | 1855 |
} |
1856 |
||
1857 |
/** |
|
24751 | 1858 |
* Unconditional jump without any control flow and data flow testing. You should not normally use this method when |
1859 |
* generating code, except if you're very sure that you know what you're doing. Normally only used for the |
|
1860 |
* admittedly torturous control flow of continuation handler plumbing. |
|
1861 |
* @param target the target of the jump |
|
1862 |
*/ |
|
1863 |
void uncheckedGoto(final Label target) { |
|
1864 |
method.visitJumpInsn(GOTO, target.getLabel()); |
|
1865 |
} |
|
1866 |
||
1867 |
/** |
|
1868 |
* Potential transfer of control to a catch block. |
|
16147 | 1869 |
* |
24751 | 1870 |
* @param catchLabel destination catch label |
16147 | 1871 |
*/ |
24751 | 1872 |
void canThrow(final Label catchLabel) { |
1873 |
catchLabel.joinFromTry(stack, false); |
|
1874 |
} |
|
1875 |
||
16147 | 1876 |
/** |
1877 |
* A join in control flow - helper function that makes sure all entry stacks |
|
1878 |
* discovered for the join point so far are equivalent |
|
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:
17255
diff
changeset
|
1879 |
* |
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:
17255
diff
changeset
|
1880 |
* MergeStack: we are about to enter a label. If its stack, label.getStack() is null |
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:
17255
diff
changeset
|
1881 |
* we have never been here before. Then we are expected to carry a stack with us. |
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:
17255
diff
changeset
|
1882 |
* |
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:
17255
diff
changeset
|
1883 |
* @param label label |
16147 | 1884 |
*/ |
24751 | 1885 |
private void joinTo(final Label label) { |
1886 |
assert isReachable(); |
|
1887 |
label.joinFrom(stack); |
|
16147 | 1888 |
} |
1889 |
||
1890 |
/** |
|
1891 |
* Register a new label, enter it here. |
|
24751 | 1892 |
* @param label |
16147 | 1893 |
*/ |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1894 |
void label(final Label label) { |
24751 | 1895 |
breakLabel(label, -1); |
1896 |
} |
|
1897 |
||
1898 |
/** |
|
1899 |
* Register a new break target label, enter it here. |
|
1900 |
* |
|
1901 |
* @param label the label |
|
1902 |
* @param liveLocals the number of live locals at this label |
|
1903 |
*/ |
|
1904 |
void breakLabel(final Label label, final int liveLocals) { |
|
1905 |
if (!isReachable()) { |
|
1906 |
// If we emit a label, and the label's stack is null, it must not be reachable. |
|
1907 |
assert (label.getStack() == null) != label.isReachable(); |
|
1908 |
} else { |
|
1909 |
joinTo(label); |
|
1910 |
} |
|
1911 |
// Use label's stack as we might have no stack. |
|
1912 |
final Label.Stack labelStack = label.getStack(); |
|
1913 |
stack = labelStack == null ? null : labelStack.clone(); |
|
1914 |
if(stack != null && label.isBreakTarget() && liveLocals != -1) { |
|
1915 |
// This has to be done because we might not have another frame to provide us with its firstTemp if the label |
|
1916 |
// is only reachable through a break or continue statement; also in this case, the frame can actually |
|
1917 |
// give us a higher number of live locals, e.g. if it comes from a catch. Typical example: |
|
1918 |
// for(;;) { try{ throw 0; } catch(e) { break; } }. |
|
1919 |
// Since the for loop can only be exited through the break in the catch block, it'll bring with it the |
|
1920 |
// "e" as a live local, and we need to trim it off here. |
|
1921 |
assert stack.firstTemp >= liveLocals; |
|
1922 |
stack.firstTemp = liveLocals; |
|
16147 | 1923 |
} |
1924 |
debug_label(label); |
|
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:
17255
diff
changeset
|
1925 |
method.visitLabel(label.getLabel()); |
16147 | 1926 |
} |
1927 |
||
1928 |
/** |
|
1929 |
* Pop element from stack, convert to given type |
|
1930 |
* |
|
1931 |
* @param to type to convert to |
|
1932 |
* |
|
1933 |
* @return the method emitter |
|
1934 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
1935 |
MethodEmitter convert(final Type to) { |
24719 | 1936 |
final Type from = peekType(); |
1937 |
final Type type = from.convert(method, to); |
|
16147 | 1938 |
if (type != null) { |
24719 | 1939 |
if (!from.isEquivalentTo(to)) { |
1940 |
debug("convert", from, "->", to); |
|
16147 | 1941 |
} |
24719 | 1942 |
if (type != from) { |
1943 |
final int l0 = stack.getTopLocalLoad(); |
|
1944 |
popType(); |
|
1945 |
pushType(type); |
|
1946 |
// NOTE: conversions from a primitive type are considered to preserve the "load" property of the value |
|
1947 |
// on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an |
|
1948 |
// "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to |
|
1949 |
// long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error |
|
1950 |
// when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant |
|
1951 |
// would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L, |
|
1952 |
// and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a |
|
1953 |
// primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized |
|
1954 |
// rest-of that didn't exist in the more optimistic version that triggered the deoptimization. |
|
1955 |
// NOTE: as a more general observation, we could theoretically track the operations required to |
|
1956 |
// reproduce any stack value as long as they are all local loads, constant loads, and stack operations. |
|
1957 |
// We won't go there in the current system |
|
1958 |
if(!from.isObject()) { |
|
1959 |
stack.markLocalLoad(l0); |
|
1960 |
} |
|
1961 |
} |
|
16147 | 1962 |
} |
1963 |
return this; |
|
1964 |
} |
|
1965 |
||
1966 |
/** |
|
1967 |
* Helper function - expect two types that are equivalent |
|
1968 |
* |
|
1969 |
* @return common type |
|
1970 |
*/ |
|
1971 |
private Type get2() { |
|
1972 |
final Type p0 = popType(); |
|
1973 |
final Type p1 = popType(); |
|
1974 |
assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1; |
|
1975 |
return p0; |
|
1976 |
} |
|
1977 |
||
1978 |
/** |
|
1979 |
* Helper function - expect two types that are integer types and equivalent |
|
1980 |
* |
|
1981 |
* @return common type |
|
1982 |
*/ |
|
1983 |
private BitwiseType get2i() { |
|
24751 | 1984 |
final BitwiseType p0 = popBitwise(); |
1985 |
final BitwiseType p1 = popBitwise(); |
|
16147 | 1986 |
assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1; |
1987 |
return p0; |
|
1988 |
} |
|
1989 |
||
1990 |
/** |
|
1991 |
* Helper function - expect two types that are numbers and equivalent |
|
1992 |
* |
|
1993 |
* @return common type |
|
1994 |
*/ |
|
1995 |
private NumericType get2n() { |
|
1996 |
final NumericType p0 = popNumeric(); |
|
1997 |
final NumericType p1 = popNumeric(); |
|
1998 |
assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1; |
|
1999 |
return p0; |
|
2000 |
} |
|
2001 |
||
2002 |
/** |
|
2003 |
* Pop two numbers, perform addition and push result |
|
2004 |
* |
|
2005 |
* @return the method emitter |
|
2006 |
*/ |
|
24719 | 2007 |
MethodEmitter add(final int programPoint) { |
16147 | 2008 |
debug("add"); |
24719 | 2009 |
pushType(get2().add(method, programPoint)); |
16147 | 2010 |
return this; |
2011 |
} |
|
2012 |
||
2013 |
/** |
|
2014 |
* Pop two numbers, perform subtraction and push result |
|
2015 |
* |
|
2016 |
* @return the method emitter |
|
2017 |
*/ |
|
24719 | 2018 |
MethodEmitter sub(final int programPoint) { |
16147 | 2019 |
debug("sub"); |
24719 | 2020 |
pushType(get2n().sub(method, programPoint)); |
16147 | 2021 |
return this; |
2022 |
} |
|
2023 |
||
2024 |
/** |
|
2025 |
* Pop two numbers, perform multiplication and push result |
|
2026 |
* |
|
2027 |
* @return the method emitter |
|
2028 |
*/ |
|
24719 | 2029 |
MethodEmitter mul(final int programPoint) { |
16147 | 2030 |
debug("mul "); |
24719 | 2031 |
pushType(get2n().mul(method, programPoint)); |
16147 | 2032 |
return this; |
2033 |
} |
|
2034 |
||
2035 |
/** |
|
2036 |
* Pop two numbers, perform division and push result |
|
2037 |
* |
|
2038 |
* @return the method emitter |
|
2039 |
*/ |
|
24719 | 2040 |
MethodEmitter div(final int programPoint) { |
16147 | 2041 |
debug("div"); |
24719 | 2042 |
pushType(get2n().div(method, programPoint)); |
16147 | 2043 |
return this; |
2044 |
} |
|
2045 |
||
2046 |
/** |
|
2047 |
* Pop two numbers, calculate remainder and push result |
|
2048 |
* |
|
2049 |
* @return the method emitter |
|
2050 |
*/ |
|
24751 | 2051 |
MethodEmitter rem(final int programPoint) { |
16147 | 2052 |
debug("rem"); |
24751 | 2053 |
pushType(get2n().rem(method, programPoint)); |
16147 | 2054 |
return this; |
2055 |
} |
|
2056 |
||
2057 |
/** |
|
2058 |
* Retrieve the top <tt>count</tt> types on the stack without modifying it. |
|
2059 |
* |
|
2060 |
* @param count number of types to return |
|
2061 |
* @return array of Types |
|
2062 |
*/ |
|
2063 |
protected Type[] getTypesFromStack(final int count) { |
|
24719 | 2064 |
return stack.getTopTypes(count); |
2065 |
} |
|
16147 | 2066 |
|
24719 | 2067 |
int[] getLocalLoadsOnStack(final int from, final int to) { |
2068 |
return stack.getLocalLoads(from, to); |
|
2069 |
} |
|
2070 |
||
2071 |
int getStackSize() { |
|
2072 |
return stack.size(); |
|
16147 | 2073 |
} |
2074 |
||
24751 | 2075 |
int getFirstTemp() { |
2076 |
return stack.firstTemp; |
|
2077 |
} |
|
2078 |
||
2079 |
int getUsedSlotsWithLiveTemporaries() { |
|
2080 |
return stack.getUsedSlotsWithLiveTemporaries(); |
|
2081 |
} |
|
2082 |
||
16147 | 2083 |
/** |
2084 |
* Helper function to generate a function signature based on stack contents |
|
2085 |
* and argument count and return type |
|
2086 |
* |
|
2087 |
* @param returnType return type |
|
2088 |
* @param argCount argument count |
|
2089 |
* |
|
2090 |
* @return function signature for stack contents |
|
2091 |
*/ |
|
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2092 |
private String getDynamicSignature(final Type returnType, final int argCount) { |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2093 |
final Type[] paramTypes = new Type[argCount]; |
16147 | 2094 |
|
17527
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
2095 |
int pos = 0; |
16147 | 2096 |
for (int i = argCount - 1; i >= 0; i--) { |
27099
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2097 |
Type pt = stack.peek(pos++); |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2098 |
// "erase" specific ScriptObject subtype info - except for NativeArray. |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2099 |
// NativeArray is used for array/List/Deque conversion for Java calls. |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2100 |
if (ScriptObject.class.isAssignableFrom(pt.getTypeClass()) && |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2101 |
!NativeArray.class.isAssignableFrom(pt.getTypeClass())) { |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2102 |
pt = Type.SCRIPT_OBJECT; |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2103 |
} |
eceb216332cb
8050977: Java8 Javascript Nashorn exception: no current Global instance for nashorn
sundar
parents:
26890
diff
changeset
|
2104 |
paramTypes[i] = pt; |
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2105 |
} |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2106 |
final String descriptor = Type.getMethodDescriptor(returnType, paramTypes); |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2107 |
for (int i = 0; i < argCount; i++) { |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2108 |
popType(paramTypes[argCount - i - 1]); |
16147 | 2109 |
} |
2110 |
||
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2111 |
return descriptor; |
16147 | 2112 |
} |
2113 |
||
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24725
diff
changeset
|
2114 |
MethodEmitter invalidateSpecialName(final String name) { |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2115 |
switch (name) { |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2116 |
case "apply": |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2117 |
case "call": |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2118 |
debug("invalidate_name", "name=", name); |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2119 |
load("Function"); |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2120 |
invoke(ScriptRuntime.INVALIDATE_RESERVED_BUILTIN_NAME); |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26377
diff
changeset
|
2121 |
break; |
26886
18c744ab4df2
8059211: Changed ArrayData.length accessor to use the protected field and fixed javadoc warnings related to this
lagergren
parents:
26768
diff
changeset
|
2122 |
default: |
18c744ab4df2
8059211: Changed ArrayData.length accessor to use the protected field and fixed javadoc warnings related to this
lagergren
parents:
26768
diff
changeset
|
2123 |
break; |
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24725
diff
changeset
|
2124 |
} |
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24725
diff
changeset
|
2125 |
return this; |
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24725
diff
changeset
|
2126 |
} |
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24725
diff
changeset
|
2127 |
|
16147 | 2128 |
/** |
2129 |
* Generate a dynamic new |
|
2130 |
* |
|
2131 |
* @param argCount number of arguments |
|
2132 |
* @param flags callsite flags |
|
2133 |
* |
|
2134 |
* @return the method emitter |
|
2135 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2136 |
MethodEmitter dynamicNew(final int argCount, final int flags) { |
32048
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2137 |
return dynamicNew(argCount, flags, null); |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2138 |
} |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2139 |
|
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2140 |
/** |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2141 |
* Generate a dynamic new |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2142 |
* |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2143 |
* @param argCount number of arguments |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2144 |
* @param flags callsite flags |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2145 |
* @param msg additional message to be used when reporting error |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2146 |
* |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2147 |
* @return the method emitter |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2148 |
*/ |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2149 |
MethodEmitter dynamicNew(final int argCount, final int flags, final String msg) { |
24719 | 2150 |
assert !isOptimistic(flags); |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2151 |
debug("dynamic_new", "argcount=", argCount); |
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2152 |
final String signature = getDynamicSignature(Type.OBJECT, argCount); |
32048
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2153 |
method.visitInvokeDynamicInsn( |
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2154 |
msg != null && msg.length() < LARGE_STRING_THRESHOLD? NameCodec.encode(msg) : EMPTY_NAME, |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2155 |
signature, LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.NEW); |
16147 | 2156 |
pushType(Type.OBJECT); //TODO fix result type |
2157 |
return this; |
|
2158 |
} |
|
2159 |
||
2160 |
/** |
|
2161 |
* Generate a dynamic call |
|
2162 |
* |
|
2163 |
* @param returnType return type |
|
2164 |
* @param argCount number of arguments |
|
2165 |
* @param flags callsite flags |
|
2166 |
* |
|
2167 |
* @return the method emitter |
|
2168 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2169 |
MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) { |
32048
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2170 |
return dynamicCall(returnType, argCount, flags, null); |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2171 |
} |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2172 |
|
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2173 |
/** |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2174 |
* Generate a dynamic call |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2175 |
* |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2176 |
* @param returnType return type |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2177 |
* @param argCount number of arguments |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2178 |
* @param flags callsite flags |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2179 |
* @param msg additional message to be used when reporting error |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2180 |
* |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2181 |
* @return the method emitter |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2182 |
*/ |
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2183 |
MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags, final String msg) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2184 |
debug("dynamic_call", "args=", argCount, "returnType=", returnType); |
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2185 |
final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target) |
16147 | 2186 |
debug(" signature", signature); |
32048
8023426b93ab
8073733: TypeError messages with "call" and "new" could be improved
sundar
parents:
30391
diff
changeset
|
2187 |
method.visitInvokeDynamicInsn( |
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2188 |
msg != null && msg.length() < LARGE_STRING_THRESHOLD? NameCodec.encode(msg) : EMPTY_NAME, |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2189 |
signature, LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.CALL); |
16147 | 2190 |
pushType(returnType); |
2191 |
||
2192 |
return this; |
|
2193 |
} |
|
2194 |
||
24719 | 2195 |
MethodEmitter dynamicArrayPopulatorCall(final int argCount, final int startIndex) { |
24738
be2026c9717c
8039746: Transform applies to calls wherever possible, for ScriptFunctions and JSObjects.
lagergren
parents:
24725
diff
changeset
|
2196 |
debug("populate_array", "args=", argCount, "startIndex=", startIndex); |
24719 | 2197 |
final String signature = getDynamicSignature(Type.OBJECT_ARRAY, argCount); |
2198 |
method.visitInvokeDynamicInsn("populateArray", signature, POPULATE_ARRAY_BOOTSTRAP, startIndex); |
|
2199 |
pushType(Type.OBJECT_ARRAY); |
|
2200 |
return this; |
|
2201 |
} |
|
2202 |
||
16147 | 2203 |
/** |
2204 |
* Generate dynamic getter. Pop scope from stack. Push result |
|
2205 |
* |
|
2206 |
* @param valueType type of the value to set |
|
2207 |
* @param name name of property |
|
2208 |
* @param flags call site flags |
|
2209 |
* @param isMethod should it prefer retrieving methods |
|
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2210 |
* @param isIndex is this an index operation? |
16147 | 2211 |
* @return the method emitter |
2212 |
*/ |
|
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2213 |
MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod, final boolean isIndex) { |
27368 | 2214 |
if (name.length() > LARGE_STRING_THRESHOLD) { // use getIndex for extremely long names |
2215 |
return load(name).dynamicGetIndex(valueType, flags, isMethod); |
|
2216 |
} |
|
2217 |
||
24719 | 2218 |
debug("dynamic_get", name, valueType, getProgramPoint(flags)); |
16147 | 2219 |
|
2220 |
Type type = valueType; |
|
2221 |
if (type.isObject() || type.isBoolean()) { |
|
2222 |
type = Type.OBJECT; //promote e.g strings to object generic setter |
|
2223 |
} |
|
2224 |
||
2225 |
popType(Type.SCOPE); |
|
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2226 |
method.visitInvokeDynamicInsn(NameCodec.encode(name), |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2227 |
Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, isIndex)); |
16147 | 2228 |
|
2229 |
pushType(type); |
|
2230 |
convert(valueType); //most probably a nop |
|
2231 |
||
2232 |
return this; |
|
2233 |
} |
|
2234 |
||
2235 |
/** |
|
2236 |
* Generate dynamic setter. Pop receiver and property from stack. |
|
2237 |
* |
|
26377
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
25865
diff
changeset
|
2238 |
* @param name name of property |
028dad61662f
8051889: Implement block scoping in symbol assignment and scope computation
hannesw
parents:
25865
diff
changeset
|
2239 |
* @param flags call site flags |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2240 |
* @param isIndex is this an index operation? |
16147 | 2241 |
*/ |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2242 |
void dynamicSet(final String name, final int flags, final boolean isIndex) { |
27368 | 2243 |
if (name.length() > LARGE_STRING_THRESHOLD) { // use setIndex for extremely long names |
2244 |
load(name).swap().dynamicSetIndex(flags); |
|
2245 |
return; |
|
2246 |
} |
|
2247 |
||
2248 |
assert !isOptimistic(flags); |
|
2249 |
debug("dynamic_set", name, peekType()); |
|
16147 | 2250 |
|
20928
3ff39d5c8c08
8026137: Fix Issues with Binary Evaluation Order
lagergren
parents:
19095
diff
changeset
|
2251 |
Type type = peekType(); |
20937
6159db2e332a
8026292: Megamorphic setter fails with boolean value
hannesw
parents:
20928
diff
changeset
|
2252 |
if (type.isObject() || type.isBoolean()) { //promote strings to objects etc |
16147 | 2253 |
type = Type.OBJECT; |
2254 |
convert(Type.OBJECT); //TODO bad- until we specialize boolean setters, |
|
2255 |
} |
|
2256 |
popType(type); |
|
2257 |
popType(Type.SCOPE); |
|
2258 |
||
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2259 |
method.visitInvokeDynamicInsn(NameCodec.encode(name), |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2260 |
methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags | dynSetOperation(isIndex)); |
16147 | 2261 |
} |
2262 |
||
2263 |
/** |
|
2264 |
* Dynamic getter for indexed structures. Pop index and receiver from stack, |
|
2265 |
* generate appropriate signatures based on types |
|
2266 |
* |
|
2267 |
* @param result result type for getter |
|
2268 |
* @param flags call site flags for getter |
|
2269 |
* @param isMethod should it prefer retrieving methods |
|
2270 |
* |
|
2271 |
* @return the method emitter |
|
2272 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2273 |
MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) { |
24719 | 2274 |
assert result.getTypeClass().isPrimitive() || result.getTypeClass() == Object.class; |
2275 |
debug("dynamic_get_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags)); |
|
16147 | 2276 |
|
2277 |
Type resultType = result; |
|
2278 |
if (result.isBoolean()) { |
|
2279 |
resultType = Type.OBJECT; // INT->OBJECT to avoid another dimension of cross products in the getters. TODO |
|
2280 |
} |
|
2281 |
||
2282 |
Type index = peekType(); |
|
2283 |
if (index.isObject() || index.isBoolean()) { |
|
2284 |
index = Type.OBJECT; //e.g. string->object |
|
2285 |
convert(Type.OBJECT); |
|
2286 |
} |
|
2287 |
popType(); |
|
2288 |
||
2289 |
popType(Type.OBJECT); |
|
2290 |
||
2291 |
final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index); |
|
2292 |
||
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2293 |
method.visitInvokeDynamicInsn(EMPTY_NAME, signature, LINKERBOOTSTRAP, flags | dynGetOperation(isMethod, true)); |
16147 | 2294 |
pushType(resultType); |
2295 |
||
2296 |
if (result.isBoolean()) { |
|
2297 |
convert(Type.BOOLEAN); |
|
2298 |
} |
|
2299 |
||
2300 |
return this; |
|
2301 |
} |
|
2302 |
||
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:
24719
diff
changeset
|
2303 |
private static String getProgramPoint(final int flags) { |
24719 | 2304 |
if((flags & CALLSITE_OPTIMISTIC) == 0) { |
2305 |
return ""; |
|
2306 |
} |
|
2307 |
return "pp=" + String.valueOf((flags & (-1 << CALLSITE_PROGRAM_POINT_SHIFT)) >> CALLSITE_PROGRAM_POINT_SHIFT); |
|
2308 |
} |
|
2309 |
||
16147 | 2310 |
/** |
2311 |
* Dynamic setter for indexed structures. Pop value, index and receiver from |
|
2312 |
* stack, generate appropriate signature based on types |
|
2313 |
* |
|
2314 |
* @param flags call site flags for setter |
|
2315 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2316 |
void dynamicSetIndex(final int flags) { |
24719 | 2317 |
assert !isOptimistic(flags); |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2318 |
debug("dynamic_set_index", peekType(2), "[", peekType(1), "] =", peekType()); |
16147 | 2319 |
|
2320 |
Type value = peekType(); |
|
2321 |
if (value.isObject() || value.isBoolean()) { |
|
2322 |
value = Type.OBJECT; //e.g. STRING->OBJECT - one descriptor for all object types |
|
2323 |
convert(Type.OBJECT); |
|
2324 |
} |
|
2325 |
popType(); |
|
2326 |
||
2327 |
Type index = peekType(); |
|
2328 |
if (index.isObject() || index.isBoolean()) { |
|
2329 |
index = Type.OBJECT; //e.g. string->object |
|
2330 |
convert(Type.OBJECT); |
|
2331 |
} |
|
2332 |
popType(index); |
|
2333 |
||
2334 |
final Type receiver = popType(Type.OBJECT); |
|
2335 |
assert receiver.isObject(); |
|
2336 |
||
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2337 |
method.visitInvokeDynamicInsn(EMPTY_NAME, |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2338 |
methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2339 |
LINKERBOOTSTRAP, flags | NashornCallSiteDescriptor.SET_ELEMENT); |
16147 | 2340 |
} |
2341 |
||
2342 |
/** |
|
2343 |
* Load a key value in the proper form. |
|
2344 |
* |
|
2345 |
* @param key |
|
2346 |
*/ |
|
2347 |
//TODO move this and break it apart |
|
2348 |
MethodEmitter loadKey(final Object key) { |
|
2349 |
if (key instanceof IdentNode) { |
|
2350 |
method.visitLdcInsn(((IdentNode) key).getName()); |
|
2351 |
} else if (key instanceof LiteralNode) { |
|
2352 |
method.visitLdcInsn(((LiteralNode<?>)key).getString()); |
|
2353 |
} else { |
|
2354 |
method.visitLdcInsn(JSType.toString(key)); |
|
2355 |
} |
|
2356 |
pushType(Type.OBJECT); //STRING |
|
2357 |
return this; |
|
2358 |
} |
|
2359 |
||
2360 |
@SuppressWarnings("fallthrough") |
|
2361 |
private static Type fieldType(final String desc) { |
|
2362 |
switch (desc) { |
|
2363 |
case "Z": |
|
2364 |
case "B": |
|
2365 |
case "C": |
|
2366 |
case "S": |
|
2367 |
case "I": |
|
2368 |
return Type.INT; |
|
2369 |
case "F": |
|
2370 |
assert false; |
|
2371 |
case "D": |
|
2372 |
return Type.NUMBER; |
|
2373 |
case "J": |
|
2374 |
return Type.LONG; |
|
2375 |
default: |
|
2376 |
assert desc.startsWith("[") || desc.startsWith("L") : desc + " is not an object type"; |
|
2377 |
switch (desc.charAt(0)) { |
|
2378 |
case 'L': |
|
2379 |
return Type.OBJECT; |
|
2380 |
case '[': |
|
2381 |
return Type.typeFor(Array.newInstance(fieldType(desc.substring(1)).getTypeClass(), 0).getClass()); |
|
2382 |
default: |
|
2383 |
assert false; |
|
2384 |
} |
|
2385 |
return Type.OBJECT; |
|
2386 |
} |
|
2387 |
} |
|
2388 |
||
2389 |
/** |
|
2390 |
* Generate get for a field access |
|
2391 |
* |
|
2392 |
* @param fa the field access |
|
2393 |
* |
|
2394 |
* @return the method emitter |
|
2395 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2396 |
MethodEmitter getField(final FieldAccess fa) { |
16147 | 2397 |
return fa.get(this); |
2398 |
} |
|
2399 |
||
2400 |
/** |
|
2401 |
* Generate set for a field access |
|
2402 |
* |
|
2403 |
* @param fa the field access |
|
2404 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2405 |
void putField(final FieldAccess fa) { |
16147 | 2406 |
fa.put(this); |
2407 |
} |
|
2408 |
||
2409 |
/** |
|
2410 |
* Get the value of a non-static field, pop the receiver from the stack, |
|
2411 |
* push value to the stack |
|
2412 |
* |
|
2413 |
* @param className class |
|
2414 |
* @param fieldName field name |
|
2415 |
* @param fieldDescriptor field descriptor |
|
2416 |
* |
|
2417 |
* @return the method emitter |
|
2418 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2419 |
MethodEmitter getField(final String className, final String fieldName, final String fieldDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2420 |
debug("getfield", "receiver=", peekType(), className, ".", fieldName, fieldDescriptor); |
16147 | 2421 |
final Type receiver = popType(); |
2422 |
assert receiver.isObject(); |
|
2423 |
method.visitFieldInsn(GETFIELD, className, fieldName, fieldDescriptor); |
|
2424 |
pushType(fieldType(fieldDescriptor)); |
|
2425 |
return this; |
|
2426 |
} |
|
2427 |
||
2428 |
/** |
|
2429 |
* Get the value of a static field, push it to the stack |
|
2430 |
* |
|
2431 |
* @param className class |
|
2432 |
* @param fieldName field name |
|
2433 |
* @param fieldDescriptor field descriptor |
|
2434 |
* |
|
2435 |
* @return the method emitter |
|
2436 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2437 |
MethodEmitter getStatic(final String className, final String fieldName, final String fieldDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2438 |
debug("getstatic", className, ".", fieldName, ".", fieldDescriptor); |
16147 | 2439 |
method.visitFieldInsn(GETSTATIC, className, fieldName, fieldDescriptor); |
2440 |
pushType(fieldType(fieldDescriptor)); |
|
2441 |
return this; |
|
2442 |
} |
|
2443 |
||
2444 |
/** |
|
2445 |
* Pop value and field from stack and write to a non-static field |
|
2446 |
* |
|
2447 |
* @param className class |
|
2448 |
* @param fieldName field name |
|
2449 |
* @param fieldDescriptor field descriptor |
|
2450 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2451 |
void putField(final String className, final String fieldName, final String fieldDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2452 |
debug("putfield", "receiver=", peekType(1), "value=", peekType()); |
16147 | 2453 |
popType(fieldType(fieldDescriptor)); |
2454 |
popType(Type.OBJECT); |
|
2455 |
method.visitFieldInsn(PUTFIELD, className, fieldName, fieldDescriptor); |
|
2456 |
} |
|
2457 |
||
2458 |
/** |
|
2459 |
* Pop value from stack and write to a static field |
|
2460 |
* |
|
2461 |
* @param className class |
|
2462 |
* @param fieldName field name |
|
2463 |
* @param fieldDescriptor field descriptor |
|
2464 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2465 |
void putStatic(final String className, final String fieldName, final String fieldDescriptor) { |
17246
a1bcf4d2bff1
8013203: A collection of smaller speedups to compilation pipeline
attila
parents:
17233
diff
changeset
|
2466 |
debug("putfield", "value=", peekType()); |
16147 | 2467 |
popType(fieldType(fieldDescriptor)); |
2468 |
method.visitFieldInsn(PUTSTATIC, className, fieldName, fieldDescriptor); |
|
2469 |
} |
|
2470 |
||
2471 |
/** |
|
2472 |
* Register line number at a label |
|
2473 |
* |
|
2474 |
* @param line line number |
|
2475 |
*/ |
|
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:
17255
diff
changeset
|
2476 |
void lineNumber(final int line) { |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
2477 |
if (context.getEnv()._debug_lines) { |
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:
17255
diff
changeset
|
2478 |
debug_label("[LINE]", line); |
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:
17255
diff
changeset
|
2479 |
final jdk.internal.org.objectweb.asm.Label l = new jdk.internal.org.objectweb.asm.Label(); |
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:
17255
diff
changeset
|
2480 |
method.visitLabel(l); |
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:
17255
diff
changeset
|
2481 |
method.visitLineNumber(line, l); |
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:
17255
diff
changeset
|
2482 |
} |
16147 | 2483 |
} |
2484 |
||
24751 | 2485 |
void beforeJoinPoint(final JoinPredecessor joinPredecessor) { |
2486 |
LocalVariableConversion next = joinPredecessor.getLocalVariableConversion(); |
|
2487 |
while(next != null) { |
|
2488 |
final Symbol symbol = next.getSymbol(); |
|
2489 |
if(next.isLive()) { |
|
2490 |
emitLocalVariableConversion(next, true); |
|
2491 |
} else { |
|
2492 |
markDeadLocalVariable(symbol); |
|
2493 |
} |
|
2494 |
next = next.getNext(); |
|
2495 |
} |
|
2496 |
} |
|
2497 |
||
2498 |
void beforeTry(final TryNode tryNode, final Label recovery) { |
|
2499 |
LocalVariableConversion next = tryNode.getLocalVariableConversion(); |
|
2500 |
while(next != null) { |
|
2501 |
if(next.isLive()) { |
|
2502 |
final Type to = emitLocalVariableConversion(next, false); |
|
2503 |
recovery.getStack().onLocalStore(to, next.getSymbol().getSlot(to), true); |
|
2504 |
} |
|
2505 |
next = next.getNext(); |
|
2506 |
} |
|
2507 |
} |
|
2508 |
||
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2509 |
private static int dynGetOperation(final boolean isMethod, final boolean isIndex) { |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2510 |
if (isMethod) { |
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2511 |
return isIndex ? NashornCallSiteDescriptor.GET_METHOD_ELEMENT : NashornCallSiteDescriptor.GET_METHOD_PROPERTY; |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2512 |
} else { |
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2513 |
return isIndex ? NashornCallSiteDescriptor.GET_ELEMENT : NashornCallSiteDescriptor.GET_PROPERTY; |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2514 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2515 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2516 |
|
33343
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2517 |
private static int dynSetOperation(final boolean isIndex) { |
23abd10384a5
8139931: Introduce Operation objects in Dynalink instead of string encoding
attila
parents:
32781
diff
changeset
|
2518 |
return isIndex ? NashornCallSiteDescriptor.SET_ELEMENT : NashornCallSiteDescriptor.SET_PROPERTY; |
27976
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2519 |
} |
ef54dfb4fc7d
8066669: dust.js performance regression caused by primitive field conversion
hannesw
parents:
27368
diff
changeset
|
2520 |
|
24751 | 2521 |
private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) { |
2522 |
final Type from = conversion.getFrom(); |
|
2523 |
final Type to = conversion.getTo(); |
|
2524 |
final Symbol symbol = conversion.getSymbol(); |
|
2525 |
assert symbol.isBytecodeLocal(); |
|
2526 |
if(from == Type.UNDEFINED) { |
|
2527 |
loadUndefined(to); |
|
2528 |
} else { |
|
2529 |
load(symbol, from).convert(to); |
|
2530 |
} |
|
2531 |
store(symbol, to, onlySymbolLiveValue); |
|
2532 |
return to; |
|
2533 |
} |
|
2534 |
||
16147 | 2535 |
/* |
2536 |
* Debugging below |
|
2537 |
*/ |
|
2538 |
||
2539 |
private final FieldAccess ERR_STREAM = staticField(System.class, "err", PrintStream.class); |
|
2540 |
private final Call PRINT = virtualCallNoLookup(PrintStream.class, "print", void.class, Object.class); |
|
2541 |
private final Call PRINTLN = virtualCallNoLookup(PrintStream.class, "println", void.class, Object.class); |
|
2542 |
private final Call PRINT_STACKTRACE = virtualCallNoLookup(Throwable.class, "printStackTrace", void.class); |
|
2543 |
||
2544 |
/** |
|
2545 |
* Emit a System.err.print statement of whatever is on top of the bytecode stack |
|
2546 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2547 |
void print() { |
16147 | 2548 |
getField(ERR_STREAM); |
2549 |
swap(); |
|
2550 |
convert(Type.OBJECT); |
|
2551 |
invoke(PRINT); |
|
2552 |
} |
|
2553 |
||
2554 |
/** |
|
2555 |
* Emit a System.err.println statement of whatever is on top of the bytecode stack |
|
2556 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2557 |
void println() { |
16147 | 2558 |
getField(ERR_STREAM); |
2559 |
swap(); |
|
2560 |
convert(Type.OBJECT); |
|
2561 |
invoke(PRINTLN); |
|
2562 |
} |
|
2563 |
||
2564 |
/** |
|
2565 |
* Emit a System.err.print statement |
|
2566 |
* @param string string to print |
|
2567 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2568 |
void print(final String string) { |
16147 | 2569 |
getField(ERR_STREAM); |
2570 |
load(string); |
|
2571 |
invoke(PRINT); |
|
2572 |
} |
|
2573 |
||
2574 |
/** |
|
2575 |
* Emit a System.err.println statement |
|
2576 |
* @param string string to print |
|
2577 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2578 |
void println(final String string) { |
16147 | 2579 |
getField(ERR_STREAM); |
2580 |
load(string); |
|
2581 |
invoke(PRINTLN); |
|
2582 |
} |
|
2583 |
||
2584 |
/** |
|
2585 |
* Print a stacktrace to S |
|
2586 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2587 |
void stacktrace() { |
16147 | 2588 |
_new(Throwable.class); |
2589 |
dup(); |
|
2590 |
invoke(constructorNoLookup(Throwable.class)); |
|
2591 |
invoke(PRINT_STACKTRACE); |
|
2592 |
} |
|
2593 |
||
2594 |
private static int linePrefix = 0; |
|
2595 |
||
2596 |
/** |
|
2597 |
* Debug function that outputs generated bytecode and stack contents |
|
2598 |
* |
|
2599 |
* @param args debug information to print |
|
2600 |
*/ |
|
26887
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2601 |
@SuppressWarnings("unused") |
16147 | 2602 |
private void debug(final Object... args) { |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
2603 |
if (debug) { |
17756
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17527
diff
changeset
|
2604 |
debug(30, args); |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17527
diff
changeset
|
2605 |
} |
16147 | 2606 |
} |
2607 |
||
26887
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2608 |
private void debug(final String arg) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2609 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2610 |
debug(30, arg); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2611 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2612 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2613 |
|
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2614 |
private void debug(final Object arg0, final Object arg1) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2615 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2616 |
debug(30, new Object[] { arg0, arg1 }); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2617 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2618 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2619 |
|
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2620 |
private void debug(final Object arg0, final Object arg1, final Object arg2) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2621 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2622 |
debug(30, new Object[] { arg0, arg1, arg2 }); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2623 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2624 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2625 |
|
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2626 |
private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2627 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2628 |
debug(30, new Object[] { arg0, arg1, arg2, arg3 }); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2629 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2630 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2631 |
|
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2632 |
private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2633 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2634 |
debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 }); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2635 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2636 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2637 |
|
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2638 |
private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2639 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2640 |
debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 }); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2641 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2642 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2643 |
|
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2644 |
private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2645 |
if (debug) { |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2646 |
debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 }); |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2647 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2648 |
} |
f7e8b7f8f554
8059321: Decrease warmup time by caching common structures that were reused during parse
lagergren
parents:
26886
diff
changeset
|
2649 |
|
16147 | 2650 |
/** |
2651 |
* Debug function that outputs generated bytecode and stack contents |
|
2652 |
* for a label - indentation is currently the only thing that differs |
|
2653 |
* |
|
2654 |
* @param args debug information to print |
|
2655 |
*/ |
|
2656 |
private void debug_label(final Object... args) { |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
2657 |
if (debug) { |
17756
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17527
diff
changeset
|
2658 |
debug(22, args); |
daaa1e643f71
8006069: Range analysis first iteration, runtime specializations
lagergren
parents:
17527
diff
changeset
|
2659 |
} |
16147 | 2660 |
} |
2661 |
||
2662 |
private void debug(final int padConstant, final Object... args) { |
|
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
2663 |
if (debug) { |
16147 | 2664 |
final StringBuilder sb = new StringBuilder(); |
2665 |
int pad; |
|
2666 |
||
2667 |
sb.append('#'); |
|
2668 |
sb.append(++linePrefix); |
|
2669 |
||
2670 |
pad = 5 - sb.length(); |
|
2671 |
while (pad > 0) { |
|
2672 |
sb.append(' '); |
|
2673 |
pad--; |
|
2674 |
} |
|
2675 |
||
24751 | 2676 |
if (isReachable() && !stack.isEmpty()) { |
16147 | 2677 |
sb.append("{"); |
2678 |
sb.append(stack.size()); |
|
2679 |
sb.append(":"); |
|
17527
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
2680 |
for (int pos = 0; pos < stack.size(); pos++) { |
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
2681 |
final Type t = stack.peek(pos); |
16147 | 2682 |
|
2683 |
if (t == Type.SCOPE) { |
|
2684 |
sb.append("scope"); |
|
2685 |
} else if (t == Type.THIS) { |
|
2686 |
sb.append("this"); |
|
2687 |
} else if (t.isObject()) { |
|
2688 |
String desc = t.getDescriptor(); |
|
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2689 |
int i; |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2690 |
for (i = 0; desc.charAt(i) == '[' && i < desc.length(); i++) { |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2691 |
sb.append('['); |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2692 |
} |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16209
diff
changeset
|
2693 |
desc = desc.substring(i); |
16147 | 2694 |
final int slash = desc.lastIndexOf('/'); |
2695 |
if (slash != -1) { |
|
2696 |
desc = desc.substring(slash + 1, desc.length() - 1); |
|
2697 |
} |
|
2698 |
if ("Object".equals(desc)) { |
|
2699 |
sb.append('O'); |
|
2700 |
} else { |
|
2701 |
sb.append(desc); |
|
2702 |
} |
|
2703 |
} else { |
|
2704 |
sb.append(t.getDescriptor()); |
|
2705 |
} |
|
24719 | 2706 |
final int loadIndex = stack.localLoads[stack.sp - 1 - pos]; |
2707 |
if(loadIndex != Label.Stack.NON_LOAD) { |
|
2708 |
sb.append('(').append(loadIndex).append(')'); |
|
2709 |
} |
|
17527
6e45d9c2328c
8014329: Slim down the label stack structure in CodeGenerator
lagergren
parents:
17524
diff
changeset
|
2710 |
if (pos + 1 < stack.size()) { |
16147 | 2711 |
sb.append(' '); |
2712 |
} |
|
2713 |
} |
|
2714 |
sb.append('}'); |
|
2715 |
sb.append(' '); |
|
2716 |
} |
|
2717 |
||
2718 |
pad = padConstant - sb.length(); |
|
2719 |
while (pad > 0) { |
|
2720 |
sb.append(' '); |
|
2721 |
pad--; |
|
2722 |
} |
|
2723 |
||
2724 |
for (final Object arg : args) { |
|
2725 |
sb.append(arg); |
|
2726 |
sb.append(' '); |
|
2727 |
} |
|
2728 |
||
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24744
diff
changeset
|
2729 |
if (context.getEnv() != null) { //early bootstrap code doesn't have inited context yet |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
2730 |
log.info(sb); |
16147 | 2731 |
if (DEBUG_TRACE_LINE == linePrefix) { |
24744
5290da85fc3d
8038426: Move all loggers from process wide scope into Global scope
lagergren
parents:
24738
diff
changeset
|
2732 |
new Throwable().printStackTrace(log.getOutputStream()); |
16147 | 2733 |
} |
2734 |
} |
|
2735 |
} |
|
2736 |
} |
|
2737 |
||
2738 |
/** |
|
2739 |
* Set the current function node being emitted |
|
2740 |
* @param functionNode the function node |
|
2741 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16234
diff
changeset
|
2742 |
void setFunctionNode(final FunctionNode functionNode) { |
16147 | 2743 |
this.functionNode = functionNode; |
2744 |
} |
|
2745 |
||
24751 | 2746 |
/** |
2747 |
* Invoke to enforce assertions preventing load from a local variable slot that's known to not have been written to. |
|
2748 |
* Used by CodeGenerator, as it strictly enforces tracking of stores. Simpler uses of MethodEmitter, e.g. those |
|
2749 |
* for creating initializers for structure classes, array getters, etc. don't have strict tracking of stores, |
|
2750 |
* therefore they would fail if they had this assertion turned on. |
|
2751 |
*/ |
|
2752 |
void setPreventUndefinedLoad() { |
|
2753 |
this.preventUndefinedLoad = true; |
|
16147 | 2754 |
} |
17233 | 2755 |
|
24719 | 2756 |
private static boolean isOptimistic(final int flags) { |
2757 |
return (flags & CALLSITE_OPTIMISTIC) != 0; |
|
2758 |
} |
|
16147 | 2759 |
} |