author | lagergren |
Thu, 25 Sep 2014 15:53:47 +0200 | |
changeset 26768 | 751b0f427090 |
parent 26506 | 7d55cc7fc301 |
child 27206 | d4a707c9db5a |
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.ACC_FINAL; |
|
29 |
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PRIVATE; |
|
30 |
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_PUBLIC; |
|
31 |
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_STATIC; |
|
32 |
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_SUPER; |
|
33 |
import static jdk.internal.org.objectweb.asm.Opcodes.ACC_VARARGS; |
|
34 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEINTERFACE; |
|
35 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESPECIAL; |
|
36 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC; |
|
37 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKEVIRTUAL; |
|
38 |
import static jdk.internal.org.objectweb.asm.Opcodes.H_NEWINVOKESPECIAL; |
|
39 |
import static jdk.internal.org.objectweb.asm.Opcodes.V1_7; |
|
40 |
import static jdk.nashorn.internal.codegen.CompilerConstants.CLINIT; |
|
41 |
import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS; |
|
42 |
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_ARRAY_PREFIX; |
|
43 |
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_ARRAY_SUFFIX; |
|
44 |
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP; |
|
45 |
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING; |
|
46 |
import static jdk.nashorn.internal.codegen.CompilerConstants.INIT; |
|
47 |
import static jdk.nashorn.internal.codegen.CompilerConstants.SET_MAP; |
|
48 |
import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE; |
|
49 |
import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE; |
|
50 |
import static jdk.nashorn.internal.codegen.CompilerConstants.className; |
|
51 |
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor; |
|
52 |
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor; |
|
24729
2b13051f2122
8037534: Use scope types to determine optimistic types
attila
parents:
24725
diff
changeset
|
53 |
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup; |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
54 |
import java.io.ByteArrayOutputStream; |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
55 |
import java.io.PrintWriter; |
24719 | 56 |
import java.security.AccessController; |
57 |
import java.security.PrivilegedAction; |
|
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26506
diff
changeset
|
58 |
import java.util.Collections; |
16147 | 59 |
import java.util.EnumSet; |
60 |
import java.util.HashSet; |
|
61 |
import java.util.Set; |
|
62 |
import jdk.internal.org.objectweb.asm.ClassWriter; |
|
63 |
import jdk.internal.org.objectweb.asm.MethodVisitor; |
|
64 |
import jdk.internal.org.objectweb.asm.util.TraceClassVisitor; |
|
65 |
import jdk.nashorn.internal.codegen.types.Type; |
|
66 |
import jdk.nashorn.internal.ir.FunctionNode; |
|
17233 | 67 |
import jdk.nashorn.internal.ir.SplitNode; |
24719 | 68 |
import jdk.nashorn.internal.ir.debug.NashornClassReader; |
69 |
import jdk.nashorn.internal.ir.debug.NashornTextifier; |
|
70 |
import jdk.nashorn.internal.runtime.Context; |
|
16147 | 71 |
import jdk.nashorn.internal.runtime.PropertyMap; |
24719 | 72 |
import jdk.nashorn.internal.runtime.RewriteException; |
16147 | 73 |
import jdk.nashorn.internal.runtime.ScriptObject; |
74 |
import jdk.nashorn.internal.runtime.Source; |
|
75 |
||
76 |
/** |
|
77 |
* The interface responsible for speaking to ASM, emitting classes, |
|
78 |
* fields and methods. |
|
79 |
* <p> |
|
80 |
* This file contains the ClassEmitter, which is the master object |
|
81 |
* responsible for writing byte codes. It utilizes a MethodEmitter |
|
82 |
* for method generation, which also the NodeVisitors own, to keep |
|
83 |
* track of the current code generator and what it is doing. |
|
84 |
* <p> |
|
85 |
* There is, however, nothing stopping you from using this in a |
|
86 |
* completely self contained environment, for example in ObjectGenerator |
|
87 |
* where there are no visitors or external hooks. |
|
88 |
* <p> |
|
89 |
* MethodEmitter makes it simple to generate code for methods without |
|
90 |
* having to do arduous type checking. It maintains a type stack |
|
91 |
* and will pick the appropriate operation for all operations sent to it |
|
92 |
* We also allow chained called to a MethodEmitter for brevity, e.g. |
|
93 |
* it is legal to write _new(className).dup() or |
|
94 |
* load(slot).load(slot2).xor().store(slot3); |
|
95 |
* <p> |
|
96 |
* If running with assertions enabled, any type conflict, such as different |
|
97 |
* bytecode stack sizes or operating on the wrong type will be detected |
|
98 |
* and an error thrown. |
|
99 |
* <p> |
|
100 |
* There is also a very nice debug interface that can emit formatted |
|
101 |
* bytecodes that have been written. This is enabled by setting the |
|
16272 | 102 |
* environment "nashorn.codegen.debug" to true, or --log=codegen:{@literal <level>} |
16147 | 103 |
* <p> |
104 |
* A ClassEmitter implements an Emitter - i.e. it needs to have |
|
105 |
* well defined start and end calls for whatever it is generating. Assertions |
|
106 |
* detect if this is not true |
|
107 |
* |
|
108 |
* @see Compiler |
|
109 |
*/ |
|
110 |
public class ClassEmitter implements Emitter { |
|
24719 | 111 |
/** Default flags for class generation - public class */ |
112 |
private static final EnumSet<Flag> DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC); |
|
16147 | 113 |
|
114 |
/** Sanity check flag - have we started on a class? */ |
|
115 |
private boolean classStarted; |
|
116 |
||
117 |
/** Sanity check flag - have we ended this emission? */ |
|
118 |
private boolean classEnded; |
|
119 |
||
120 |
/** |
|
121 |
* Sanity checks - which methods have we currently |
|
122 |
* started for generation in this class? |
|
123 |
*/ |
|
124 |
private final HashSet<MethodEmitter> methodsStarted; |
|
125 |
||
126 |
/** The ASM classwriter that we use for all bytecode operations */ |
|
127 |
protected final ClassWriter cw; |
|
128 |
||
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16250
diff
changeset
|
129 |
/** The script environment */ |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
130 |
protected final Context context; |
16147 | 131 |
|
132 |
/** Compile unit class name. */ |
|
133 |
private String unitClassName; |
|
134 |
||
135 |
/** Set of constants access methods required. */ |
|
136 |
private Set<Class<?>> constantMethodNeeded; |
|
137 |
||
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
138 |
private int methodCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
139 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
140 |
private int initCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
141 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
142 |
private int clinitCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
143 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
144 |
private int fieldCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
145 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
146 |
private final Set<String> methodNames; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
147 |
|
16147 | 148 |
/** |
149 |
* Constructor - only used internally in this class as it breaks |
|
150 |
* abstraction towards ASM or other code generator below |
|
151 |
* |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16250
diff
changeset
|
152 |
* @param env script environment |
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16250
diff
changeset
|
153 |
* @param cw ASM classwriter |
16147 | 154 |
*/ |
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
155 |
private ClassEmitter(final Context context, final ClassWriter cw) { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
156 |
this.context = context; |
16147 | 157 |
this.cw = cw; |
158 |
this.methodsStarted = new HashSet<>(); |
|
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
159 |
this.methodNames = new HashSet<>(); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
160 |
} |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
161 |
|
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26506
diff
changeset
|
162 |
/** |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26506
diff
changeset
|
163 |
* Return the method names encountered |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26506
diff
changeset
|
164 |
* @return method names |
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26506
diff
changeset
|
165 |
*/ |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
166 |
public Set<String> getMethodNames() { |
26768
751b0f427090
8025435: Optimistic builtins support, implemented initial optimistic versions of push, pop, and charCodeAt
lagergren
parents:
26506
diff
changeset
|
167 |
return Collections.unmodifiableSet(methodNames); |
16147 | 168 |
} |
169 |
||
170 |
/** |
|
171 |
* Constructor |
|
172 |
* |
|
16262
75513555e603
8008731: Separate configuration environment (options, error/output writer etc.) from Context
sundar
parents:
16250
diff
changeset
|
173 |
* @param env script environment |
16147 | 174 |
* @param className name of class to weave |
175 |
* @param superClassName super class name for class |
|
176 |
* @param interfaceNames names of interfaces implemented by this class, or null if none |
|
177 |
*/ |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
178 |
ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
179 |
this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS)); |
16147 | 180 |
cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, interfaceNames); |
181 |
} |
|
182 |
||
183 |
/** |
|
184 |
* Constructor from the compiler |
|
185 |
* |
|
18618
136279c4cbe6
8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents:
17233
diff
changeset
|
186 |
* @param env Script environment |
136279c4cbe6
8019157: Avoid calling ScriptObject.setProto() if possible
hannesw
parents:
17233
diff
changeset
|
187 |
* @param sourceName Source name |
16147 | 188 |
* @param unitClassName Compile unit class name. |
189 |
* @param strictMode Should we generate this method in strict mode |
|
190 |
*/ |
|
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
191 |
ClassEmitter(final Context context, final String sourceName, final String unitClassName, final boolean strictMode) { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
192 |
this(context, |
16147 | 193 |
new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) { |
194 |
private static final String OBJECT_CLASS = "java/lang/Object"; |
|
195 |
||
196 |
@Override |
|
197 |
protected String getCommonSuperClass(final String type1, final String type2) { |
|
198 |
try { |
|
199 |
return super.getCommonSuperClass(type1, type2); |
|
200 |
} catch (final RuntimeException e) { |
|
201 |
if (isScriptObject(Compiler.SCRIPTS_PACKAGE, type1) && isScriptObject(Compiler.SCRIPTS_PACKAGE, type2)) { |
|
202 |
return className(ScriptObject.class); |
|
203 |
} |
|
204 |
return OBJECT_CLASS; |
|
205 |
} |
|
206 |
} |
|
207 |
}); |
|
208 |
||
209 |
this.unitClassName = unitClassName; |
|
210 |
this.constantMethodNeeded = new HashSet<>(); |
|
211 |
||
16275 | 212 |
cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, unitClassName, null, pathName(jdk.nashorn.internal.scripts.JS.class.getName()), null); |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
213 |
cw.visitSource(sourceName, null); |
16147 | 214 |
|
215 |
defineCommonStatics(strictMode); |
|
216 |
} |
|
217 |
||
24745
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
218 |
Context getContext() { |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
219 |
return context; |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
220 |
} |
3a6e1477362b
8041434: Add synchronization to the common global constants structure
lagergren
parents:
24729
diff
changeset
|
221 |
|
16147 | 222 |
/** |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
223 |
* Returns the name of the compile unit class name. |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
224 |
* @return the name of the compile unit class name. |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
225 |
*/ |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
226 |
String getUnitClassName() { |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
227 |
return unitClassName; |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
228 |
} |
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
229 |
|
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
230 |
/** |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
231 |
* Get the method count, including init and clinit methods |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
232 |
* @return method count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
233 |
*/ |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
234 |
public int getMethodCount() { |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
235 |
return methodCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
236 |
} |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
237 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
238 |
/** |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
239 |
* Get the clinit count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
240 |
* @return clinit count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
241 |
*/ |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
242 |
public int getClinitCount() { |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
243 |
return clinitCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
244 |
} |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
245 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
246 |
/** |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
247 |
* Get the init count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
248 |
* @return init count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
249 |
*/ |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
250 |
public int getInitCount() { |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
251 |
return initCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
252 |
} |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
253 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
254 |
/** |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
255 |
* Get the field count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
256 |
* @return field count |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
257 |
*/ |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
258 |
public int getFieldCount() { |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
259 |
return fieldCount; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
260 |
} |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
261 |
|
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
262 |
/** |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
263 |
* Convert a binary name to a package/class name. |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
264 |
* |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
265 |
* @param name Binary name. |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
266 |
* @return Package/class name. |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
267 |
*/ |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
268 |
private static String pathName(final String name) { |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
269 |
return name.replace('.', '/'); |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
270 |
} |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
271 |
|
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
272 |
/** |
16147 | 273 |
* Define the static fields common in all scripts. |
274 |
* @param strictMode Should we generate this method in strict mode |
|
275 |
*/ |
|
276 |
private void defineCommonStatics(final boolean strictMode) { |
|
277 |
// source - used to store the source data (text) for this script. Shared across |
|
278 |
// compile units. Set externally by the compiler. |
|
17233 | 279 |
field(EnumSet.of(Flag.PRIVATE, Flag.STATIC), SOURCE.symbolName(), Source.class); |
16147 | 280 |
|
281 |
// constants - used to the constants array for this script. Shared across |
|
282 |
// compile units. Set externally by the compiler. |
|
17233 | 283 |
field(EnumSet.of(Flag.PRIVATE, Flag.STATIC), CONSTANTS.symbolName(), Object[].class); |
16147 | 284 |
|
285 |
// strictMode - was this script compiled in strict mode. Set externally by the compiler. |
|
17233 | 286 |
field(EnumSet.of(Flag.PUBLIC, Flag.STATIC, Flag.FINAL), STRICT_MODE.symbolName(), boolean.class, strictMode); |
16147 | 287 |
} |
288 |
||
289 |
/** |
|
290 |
* Define static utilities common needed in scripts. These are per compile unit |
|
291 |
* and therefore have to be defined here and not in code gen. |
|
292 |
*/ |
|
293 |
private void defineCommonUtilities() { |
|
294 |
assert unitClassName != null; |
|
295 |
||
296 |
if (constantMethodNeeded.contains(String.class)) { |
|
297 |
// $getString - get the ith entry from the constants table and cast to String. |
|
17233 | 298 |
final MethodEmitter getStringMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), GET_STRING.symbolName(), String.class, int.class); |
16147 | 299 |
getStringMethod.begin(); |
17233 | 300 |
getStringMethod.getStatic(unitClassName, CONSTANTS.symbolName(), CONSTANTS.descriptor()) |
16147 | 301 |
.load(Type.INT, 0) |
302 |
.arrayload() |
|
303 |
.checkcast(String.class) |
|
304 |
._return(); |
|
305 |
getStringMethod.end(); |
|
306 |
} |
|
307 |
||
308 |
if (constantMethodNeeded.contains(PropertyMap.class)) { |
|
309 |
// $getMap - get the ith entry from the constants table and cast to PropertyMap. |
|
17233 | 310 |
final MethodEmitter getMapMethod = method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), GET_MAP.symbolName(), PropertyMap.class, int.class); |
16147 | 311 |
getMapMethod.begin(); |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
312 |
getMapMethod.loadConstants() |
16147 | 313 |
.load(Type.INT, 0) |
314 |
.arrayload() |
|
315 |
.checkcast(PropertyMap.class) |
|
316 |
._return(); |
|
317 |
getMapMethod.end(); |
|
318 |
||
319 |
// $setMap - overwrite an existing map. |
|
17233 | 320 |
final MethodEmitter setMapMethod = method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), SET_MAP.symbolName(), void.class, int.class, PropertyMap.class); |
16147 | 321 |
setMapMethod.begin(); |
16530
201d682e75f4
8010652: Eliminate non-child references in Block/FunctionNode, and make few node types immutable
attila
parents:
16275
diff
changeset
|
322 |
setMapMethod.loadConstants() |
16147 | 323 |
.load(Type.INT, 0) |
324 |
.load(Type.OBJECT, 1) |
|
325 |
.arraystore(); |
|
326 |
setMapMethod.returnVoid(); |
|
327 |
setMapMethod.end(); |
|
328 |
} |
|
329 |
||
330 |
// $getXXXX$array - get the ith entry from the constants table and cast to XXXX[]. |
|
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
331 |
for (final Class<?> clazz : constantMethodNeeded) { |
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
332 |
if (clazz.isArray()) { |
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
333 |
defineGetArrayMethod(clazz); |
16147 | 334 |
} |
335 |
} |
|
336 |
} |
|
337 |
||
338 |
/** |
|
24729
2b13051f2122
8037534: Use scope types to determine optimistic types
attila
parents:
24725
diff
changeset
|
339 |
* Constructs a primitive specific method for getting the ith entry from the constants table as an array. |
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
340 |
* @param clazz Array class. |
16147 | 341 |
*/ |
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
342 |
private void defineGetArrayMethod(final Class<?> clazz) { |
16147 | 343 |
assert unitClassName != null; |
344 |
||
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
345 |
final String methodName = getArrayMethodName(clazz); |
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
346 |
final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, clazz, int.class); |
16147 | 347 |
|
348 |
getArrayMethod.begin(); |
|
17233 | 349 |
getArrayMethod.getStatic(unitClassName, CONSTANTS.symbolName(), CONSTANTS.descriptor()) |
16147 | 350 |
.load(Type.INT, 0) |
351 |
.arrayload() |
|
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
352 |
.checkcast(clazz) |
24729
2b13051f2122
8037534: Use scope types to determine optimistic types
attila
parents:
24725
diff
changeset
|
353 |
.invoke(virtualCallNoLookup(clazz, "clone", Object.class)) |
2b13051f2122
8037534: Use scope types to determine optimistic types
attila
parents:
24725
diff
changeset
|
354 |
.checkcast(clazz) |
16147 | 355 |
._return(); |
356 |
getArrayMethod.end(); |
|
357 |
} |
|
358 |
||
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
359 |
|
16147 | 360 |
/** |
361 |
* Generate the name of a get array from constant pool method. |
|
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
362 |
* @param clazz Name of array class. |
16147 | 363 |
* @return Method name. |
364 |
*/ |
|
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
365 |
static String getArrayMethodName(final Class<?> clazz) { |
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
366 |
assert clazz.isArray(); |
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
367 |
return GET_ARRAY_PREFIX.symbolName() + clazz.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName(); |
16147 | 368 |
} |
369 |
||
370 |
/** |
|
371 |
* Ensure a get constant method is issued for the class. |
|
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
372 |
* @param clazz Class of constant. |
16147 | 373 |
*/ |
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
374 |
void needGetConstantMethod(final Class<?> clazz) { |
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
375 |
constantMethodNeeded.add(clazz); |
16147 | 376 |
} |
377 |
||
378 |
/** |
|
379 |
* Inspect class name and decide whether we are generating a ScriptObject class |
|
380 |
* |
|
381 |
* @param scriptPrefix the script class prefix for the current script |
|
382 |
* @param type the type to check |
|
383 |
* |
|
384 |
* @return true if type is ScriptObject |
|
385 |
*/ |
|
386 |
private static boolean isScriptObject(final String scriptPrefix, final String type) { |
|
387 |
if (type.startsWith(scriptPrefix)) { |
|
388 |
return true; |
|
389 |
} else if (type.equals(CompilerConstants.className(ScriptObject.class))) { |
|
390 |
return true; |
|
391 |
} else if (type.startsWith(Compiler.OBJECTS_PACKAGE)) { |
|
392 |
return true; |
|
393 |
} |
|
394 |
||
395 |
return false; |
|
396 |
} |
|
397 |
||
398 |
/** |
|
399 |
* Call at beginning of class emission |
|
400 |
* @see Emitter |
|
401 |
*/ |
|
402 |
@Override |
|
403 |
public void begin() { |
|
404 |
classStarted = true; |
|
405 |
} |
|
406 |
||
407 |
/** |
|
408 |
* Call at end of class emission |
|
409 |
* @see Emitter |
|
410 |
*/ |
|
411 |
@Override |
|
412 |
public void end() { |
|
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
413 |
assert classStarted : "class not started for " + unitClassName; |
16147 | 414 |
|
415 |
if (unitClassName != null) { |
|
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
416 |
final MethodEmitter initMethod = init(EnumSet.of(Flag.PRIVATE)); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
417 |
initMethod.begin(); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
418 |
initMethod.load(Type.OBJECT, 0); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
419 |
initMethod.newInstance(jdk.nashorn.internal.scripts.JS.class); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
420 |
initMethod.returnVoid(); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
421 |
initMethod.end(); |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
422 |
|
16147 | 423 |
defineCommonUtilities(); |
424 |
} |
|
425 |
||
426 |
cw.visitEnd(); |
|
427 |
classStarted = false; |
|
428 |
classEnded = true; |
|
429 |
assert methodsStarted.isEmpty() : "methodsStarted not empty " + methodsStarted; |
|
430 |
} |
|
431 |
||
432 |
/** |
|
433 |
* Disassemble an array of byte code. |
|
434 |
* @param bytecode byte array representing bytecode |
|
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
435 |
* @return disassembly as human readable string |
16147 | 436 |
*/ |
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
437 |
static String disassemble(final byte[] bytecode) { |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
438 |
final ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
439 |
try (final PrintWriter pw = new PrintWriter(baos)) { |
24719 | 440 |
final NashornClassReader cr = new NashornClassReader(bytecode); |
441 |
final Context ctx = AccessController.doPrivileged(new PrivilegedAction<Context>() { |
|
442 |
@Override |
|
443 |
public Context run() { |
|
444 |
return Context.getContext(); |
|
445 |
} |
|
446 |
}); |
|
24721
81f70e23cd3b
8036127: Prototype filter needs to be applied to getter guard as well, not just getter
lagergren
parents:
24719
diff
changeset
|
447 |
final TraceClassVisitor tcv = new TraceClassVisitor(null, new NashornTextifier(ctx.getEnv(), cr), pw); |
24719 | 448 |
cr.accept(tcv, 0); |
16233
95d3e01c04c3
8008199: Lazy compilation and trampoline implementation
lagergren
parents:
16151
diff
changeset
|
449 |
} |
24719 | 450 |
|
451 |
final String str = new String(baos.toByteArray()); |
|
452 |
return str; |
|
16147 | 453 |
} |
454 |
||
455 |
/** |
|
456 |
* Call back from MethodEmitter for method start |
|
457 |
* |
|
458 |
* @see MethodEmitter |
|
459 |
* |
|
460 |
* @param method method emitter. |
|
461 |
*/ |
|
462 |
void beginMethod(final MethodEmitter method) { |
|
463 |
assert !methodsStarted.contains(method); |
|
464 |
methodsStarted.add(method); |
|
465 |
} |
|
466 |
||
467 |
/** |
|
468 |
* Call back from MethodEmitter for method end |
|
469 |
* |
|
470 |
* @see MethodEmitter |
|
471 |
* |
|
472 |
* @param method |
|
473 |
*/ |
|
474 |
void endMethod(final MethodEmitter method) { |
|
475 |
assert methodsStarted.contains(method); |
|
476 |
methodsStarted.remove(method); |
|
477 |
} |
|
478 |
||
17233 | 479 |
SplitMethodEmitter method(final SplitNode splitNode, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
480 |
methodCount++; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
481 |
methodNames.add(methodName); |
17233 | 482 |
return new SplitMethodEmitter(this, methodVisitor(EnumSet.of(Flag.PUBLIC, Flag.STATIC), methodName, rtype, ptypes), splitNode); |
483 |
} |
|
484 |
||
16147 | 485 |
/** |
486 |
* Add a new method to the class - defaults to public method |
|
487 |
* |
|
488 |
* @param methodName name of method |
|
489 |
* @param rtype return type of the method |
|
490 |
* @param ptypes parameter types the method |
|
491 |
* |
|
492 |
* @return method emitter to use for weaving this method |
|
493 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
494 |
MethodEmitter method(final String methodName, final Class<?> rtype, final Class<?>... ptypes) { |
16147 | 495 |
return method(DEFAULT_METHOD_FLAGS, methodName, rtype, ptypes); //TODO why public default ? |
496 |
} |
|
497 |
||
498 |
/** |
|
499 |
* Add a new method to the class - defaults to public method |
|
500 |
* |
|
501 |
* @param methodFlags access flags for the method |
|
502 |
* @param methodName name of method |
|
503 |
* @param rtype return type of the method |
|
504 |
* @param ptypes parameter types the method |
|
505 |
* |
|
506 |
* @return method emitter to use for weaving this method |
|
507 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
508 |
MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
509 |
methodCount++; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
510 |
methodNames.add(methodName); |
17233 | 511 |
return new MethodEmitter(this, methodVisitor(methodFlags, methodName, rtype, ptypes)); |
16147 | 512 |
} |
513 |
||
514 |
/** |
|
515 |
* Add a new method to the class - defaults to public method |
|
516 |
* |
|
517 |
* @param methodName name of method |
|
518 |
* @param descriptor descriptor of method |
|
519 |
* |
|
520 |
* @return method emitter to use for weaving this method |
|
521 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
522 |
MethodEmitter method(final String methodName, final String descriptor) { |
16147 | 523 |
return method(DEFAULT_METHOD_FLAGS, methodName, descriptor); |
524 |
} |
|
525 |
||
526 |
/** |
|
527 |
* Add a new method to the class - defaults to public method |
|
528 |
* |
|
529 |
* @param methodFlags access flags for the method |
|
530 |
* @param methodName name of method |
|
531 |
* @param descriptor descriptor of method |
|
532 |
* |
|
533 |
* @return method emitter to use for weaving this method |
|
534 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
535 |
MethodEmitter method(final EnumSet<Flag> methodFlags, final String methodName, final String descriptor) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
536 |
methodCount++; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
537 |
methodNames.add(methodName); |
16147 | 538 |
return new MethodEmitter(this, cw.visitMethod(Flag.getValue(methodFlags), methodName, descriptor, null, null)); |
539 |
} |
|
540 |
||
541 |
/** |
|
542 |
* Add a new method to the class, representing a function node |
|
543 |
* |
|
544 |
* @param functionNode the function node to generate a method for |
|
545 |
* @return method emitter to use for weaving this method |
|
546 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
547 |
MethodEmitter method(final FunctionNode functionNode) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
548 |
methodCount++; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
549 |
methodNames.add(functionNode.getName()); |
24719 | 550 |
final FunctionSignature signature = new FunctionSignature(functionNode); |
16147 | 551 |
final MethodVisitor mv = cw.visitMethod( |
552 |
ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0), |
|
553 |
functionNode.getName(), |
|
24719 | 554 |
signature.toString(), |
16147 | 555 |
null, |
556 |
null); |
|
557 |
||
24751 | 558 |
return new MethodEmitter(this, mv, functionNode); |
16147 | 559 |
} |
560 |
||
561 |
/** |
|
24719 | 562 |
* Add a new method to the class, representing a rest-of version of the function node |
563 |
* |
|
564 |
* @param functionNode the function node to generate a method for |
|
565 |
* @return method emitter to use for weaving this method |
|
566 |
*/ |
|
567 |
MethodEmitter restOfMethod(final FunctionNode functionNode) { |
|
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
568 |
methodCount++; |
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
569 |
methodNames.add(functionNode.getName()); |
24719 | 570 |
final MethodVisitor mv = cw.visitMethod( |
571 |
ACC_PUBLIC | ACC_STATIC, |
|
572 |
functionNode.getName(), |
|
573 |
Type.getMethodDescriptor(functionNode.getReturnType().getTypeClass(), RewriteException.class), |
|
574 |
null, |
|
575 |
null); |
|
576 |
||
24751 | 577 |
return new MethodEmitter(this, mv, functionNode); |
24719 | 578 |
} |
579 |
||
580 |
||
581 |
/** |
|
16147 | 582 |
* Start generating the <clinit> method in the class |
583 |
* |
|
584 |
* @return method emitter to use for weaving <clinit> |
|
585 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
586 |
MethodEmitter clinit() { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
587 |
clinitCount++; |
17233 | 588 |
return method(EnumSet.of(Flag.STATIC), CLINIT.symbolName(), void.class); |
16147 | 589 |
} |
590 |
||
591 |
/** |
|
592 |
* Start generating an <init>()V method in the class |
|
593 |
* |
|
594 |
* @return method emitter to use for weaving <init>()V |
|
595 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
596 |
MethodEmitter init() { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
597 |
initCount++; |
17233 | 598 |
return method(INIT.symbolName(), void.class); |
16147 | 599 |
} |
600 |
||
601 |
/** |
|
602 |
* Start generating an <init>()V method in the class |
|
603 |
* |
|
604 |
* @param ptypes parameter types for constructor |
|
605 |
* @return method emitter to use for weaving <init>()V |
|
606 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
607 |
MethodEmitter init(final Class<?>... ptypes) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
608 |
initCount++; |
17233 | 609 |
return method(INIT.symbolName(), void.class, ptypes); |
16147 | 610 |
} |
611 |
||
612 |
/** |
|
613 |
* Start generating an <init>(...)V method in the class |
|
614 |
* |
|
615 |
* @param flags access flags for the constructor |
|
616 |
* @param ptypes parameter types for the constructor |
|
617 |
* |
|
618 |
* @return method emitter to use for weaving <init>(...)V |
|
619 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
620 |
MethodEmitter init(final EnumSet<Flag> flags, final Class<?>... ptypes) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
621 |
initCount++; |
17233 | 622 |
return method(flags, INIT.symbolName(), void.class, ptypes); |
16147 | 623 |
} |
624 |
||
625 |
/** |
|
626 |
* Add a field to the class, initialized to a value |
|
627 |
* |
|
628 |
* @param fieldFlags flags, e.g. should it be static or public etc |
|
629 |
* @param fieldName name of field |
|
630 |
* @param fieldType the type of the field |
|
631 |
* @param value the value |
|
632 |
* |
|
633 |
* @see ClassEmitter.Flag |
|
634 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
635 |
final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType, final Object value) { |
26506
7d55cc7fc301
8057703: More empty classes generated by Nashorn
lagergren
parents:
25865
diff
changeset
|
636 |
fieldCount++; |
16147 | 637 |
cw.visitField(Flag.getValue(fieldFlags), fieldName, typeDescriptor(fieldType), null, value).visitEnd(); |
638 |
} |
|
639 |
||
640 |
/** |
|
641 |
* Add a field to the class |
|
642 |
* |
|
643 |
* @param fieldFlags access flags for the field |
|
644 |
* @param fieldName name of field |
|
645 |
* @param fieldType type of the field |
|
646 |
* |
|
647 |
* @see ClassEmitter.Flag |
|
648 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
649 |
final void field(final EnumSet<Flag> fieldFlags, final String fieldName, final Class<?> fieldType) { |
16147 | 650 |
field(fieldFlags, fieldName, fieldType, null); |
651 |
} |
|
652 |
||
653 |
/** |
|
654 |
* Add a field to the class - defaults to public |
|
655 |
* |
|
656 |
* @param fieldName name of field |
|
657 |
* @param fieldType type of field |
|
658 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
659 |
final void field(final String fieldName, final Class<?> fieldType) { |
16147 | 660 |
field(EnumSet.of(Flag.PUBLIC), fieldName, fieldType, null); |
661 |
} |
|
662 |
||
663 |
/** |
|
664 |
* Return a bytecode array from this ClassEmitter. The ClassEmitter must |
|
665 |
* have been ended (having its end function called) for this to work. |
|
666 |
* |
|
667 |
* @return byte code array for generated class, null if class generation hasn't been ended with {@link ClassEmitter#end()} |
|
668 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
669 |
byte[] toByteArray() { |
16147 | 670 |
assert classEnded; |
671 |
if (!classEnded) { |
|
672 |
return null; |
|
673 |
} |
|
674 |
||
675 |
return cw.toByteArray(); |
|
676 |
} |
|
677 |
||
678 |
/** |
|
679 |
* Abstraction for flags used in class emission |
|
680 |
* |
|
681 |
* We provide abstraction separating these from the underlying bytecode |
|
682 |
* emitter. |
|
683 |
* |
|
684 |
* Flags are provided for method handles, protection levels, static/virtual |
|
685 |
* fields/methods. |
|
686 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
687 |
static enum Flag { |
16147 | 688 |
/** method handle with static access */ |
689 |
HANDLE_STATIC(H_INVOKESTATIC), |
|
690 |
/** method handle with new invoke special access */ |
|
691 |
HANDLE_NEWSPECIAL(H_NEWINVOKESPECIAL), |
|
692 |
/** method handle with invoke special access */ |
|
693 |
HANDLE_SPECIAL(H_INVOKESPECIAL), |
|
694 |
/** method handle with invoke virtual access */ |
|
695 |
HANDLE_VIRTUAL(H_INVOKEVIRTUAL), |
|
696 |
/** method handle with invoke interface access */ |
|
697 |
HANDLE_INTERFACE(H_INVOKEINTERFACE), |
|
698 |
||
699 |
/** final access */ |
|
700 |
FINAL(ACC_FINAL), |
|
701 |
/** static access */ |
|
702 |
STATIC(ACC_STATIC), |
|
703 |
/** public access */ |
|
704 |
PUBLIC(ACC_PUBLIC), |
|
705 |
/** private access */ |
|
706 |
PRIVATE(ACC_PRIVATE); |
|
707 |
||
708 |
private int value; |
|
709 |
||
710 |
private Flag(final int value) { |
|
711 |
this.value = value; |
|
712 |
} |
|
713 |
||
714 |
/** |
|
715 |
* Get the value of this flag |
|
716 |
* @return the int value |
|
717 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
718 |
int getValue() { |
16147 | 719 |
return value; |
720 |
} |
|
721 |
||
722 |
/** |
|
723 |
* Return the corresponding ASM flag value for an enum set of flags |
|
724 |
* |
|
725 |
* @param flags enum set of flags |
|
726 |
* @return an integer value representing the flags intrinsic values or:ed together |
|
727 |
*/ |
|
16240
e1468b33e201
8008239: Unpublicized parts of the code generator package that were only package internal.
lagergren
parents:
16233
diff
changeset
|
728 |
static int getValue(final EnumSet<Flag> flags) { |
16147 | 729 |
int v = 0; |
730 |
for (final Flag flag : flags) { |
|
731 |
v |= flag.getValue(); |
|
732 |
} |
|
733 |
return v; |
|
734 |
} |
|
735 |
} |
|
17233 | 736 |
|
24725
7bb1f687a852
8033334: Make sure that scope depth information is maintained in the RecompilableScriptFunctionDatas, to avoid unnecessary slow proto linkage when doing on demand compilation
lagergren
parents:
24721
diff
changeset
|
737 |
private MethodVisitor methodVisitor(final EnumSet<Flag> flags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) { |
17233 | 738 |
return cw.visitMethod(Flag.getValue(flags), methodName, methodDescriptor(rtype, ptypes), null, null); |
739 |
} |
|
740 |
||
16147 | 741 |
} |