1 /*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
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.nashorn.internal.lookup.Lookup.MH;
29
30 import java.lang.invoke.MethodHandle;
31 import java.lang.invoke.MethodHandles;
32 import java.util.Iterator;
33 import jdk.nashorn.internal.codegen.types.Type;
34 import jdk.nashorn.internal.runtime.ScriptFunction;
35 import jdk.nashorn.internal.runtime.ScriptObject;
36 import jdk.nashorn.internal.runtime.Source;
37
38 /**
39 * This class represents constant names of variables, methods and fields in
40 * the compiler
41 */
42
43 public enum CompilerConstants {
44
45 /** the __FILE__ variable */
46 __FILE__,
47
48 /** the __DIR__ variable */
49 __DIR__,
50
51 /** the __LINE__ variable */
52 __LINE__,
53
54 /** lazy prefix for classes of jitted methods */
55 LAZY("Lazy"),
56
57 /** constructor name */
58 INIT("<init>"),
59
60 /** static initializer name */
61 CLINIT("<clinit>"),
62
63 /** eval name */
64 EVAL("eval"),
65
66 /** source name and class */
67 SOURCE("source", Source.class),
68
69 /** constants name and class */
70 CONSTANTS("constants", Object[].class),
71
72 /** strict mode field name and type */
73 STRICT_MODE("strictMode", boolean.class),
74
75 /** default script name */
76 DEFAULT_SCRIPT_NAME("Script"),
77
78 /** function prefix for anonymous functions */
79 ANON_FUNCTION_PREFIX("L:"),
80
81 /** method name for Java method that is script entry point */
82 RUN_SCRIPT("runScript"),
83
84 /**
85 * "this" name symbol for a parameter representing ECMAScript "this" in static methods that are compiled
86 * representations of ECMAScript functions. It is not assigned a slot, as its position in the method signature is
87 * dependent on other factors (most notably, callee can precede it).
88 */
89 THIS("this"),
90
91 /** this debugger symbol */
92 THIS_DEBUGGER(":this"),
93
94 /** scope name, type and slot */
95 SCOPE(":scope", ScriptObject.class, 2),
96
97 /** the return value variable name were intermediate results are stored for scripts */
98 RETURN(":return"),
99
100 /** the callee value variable when necessary */
101 CALLEE(":callee", ScriptFunction.class),
102
103 /** the varargs variable when necessary */
104 VARARGS(":varargs", Object[].class),
105
106 /** the arguments variable (visible to function body). Initially set to ARGUMENTS, but can be reassigned by code in
107 * the function body.*/
108 ARGUMENTS_VAR("arguments", Object.class),
109
110 /** the internal arguments object, when necessary (not visible to scripts, can't be reassigned). */
111 ARGUMENTS(":arguments", ScriptObject.class),
112
113 /** prefix for iterators for for (x in ...) */
114 ITERATOR_PREFIX(":i", Iterator.class),
115
116 /** prefix for tag variable used for switch evaluation */
117 SWITCH_TAG_PREFIX(":s"),
118
119 /** prefix for all exceptions */
120 EXCEPTION_PREFIX(":e", Throwable.class),
121
122 /** prefix for quick slots generated in Store */
123 QUICK_PREFIX(":q"),
124
125 /** prefix for temporary variables */
126 TEMP_PREFIX(":t"),
127
128 /** prefix for literals */
129 LITERAL_PREFIX(":l"),
130
131 /** prefix for regexps */
132 REGEX_PREFIX(":r"),
133
134 /** "this" used in non-static Java methods; always in slot 0 */
135 JAVA_THIS(null, 0),
136
137 /** Map parameter in scope object constructors; always in slot 1 */
138 INIT_MAP(null, 1),
139
140 /** Parent scope parameter in scope object constructors; always in slot 2 */
141 INIT_SCOPE(null, 2),
142
143 /** Arguments parameter in scope object constructors; in slot 3 when present */
144 INIT_ARGUMENTS(null, 3),
145
146 /** prefix for all ScriptObject subclasses with fields, @see ObjectGenerator */
147 JS_OBJECT_PREFIX("JO"),
148
149 /** name for allocate method in JO objects */
150 ALLOCATE("allocate"),
151
152 /** prefix for split methods, @see Splitter */
153 SPLIT_PREFIX(":split"),
154
155 /** prefix for split array method and slot */
156 SPLIT_ARRAY_ARG(":split_array", 3),
157
158 /** get string from constant pool */
159 GET_STRING(":getString"),
160
161 /** get map */
162 GET_MAP(":getMap"),
163
164 /** get map */
165 SET_MAP(":setMap"),
166
167 /** get array prefix */
168 GET_ARRAY_PREFIX(":get"),
169
170 /** get array suffix */
171 GET_ARRAY_SUFFIX("$array");
172
173 /**
174 * Prefix used for internal methods generated in script clases.
175 */
176 public static final String INTERNAL_METHOD_PREFIX = ":";
177
178 private final String symbolName;
179 private final Class<?> type;
180 private final int slot;
181
182 private CompilerConstants() {
183 this.symbolName = name();
184 this.type = null;
185 this.slot = -1;
186 }
187
188 private CompilerConstants(final String symbolName) {
189 this(symbolName, -1);
190 }
191
192 private CompilerConstants(final String symbolName, final int slot) {
193 this(symbolName, null, slot);
194 }
195
196 private CompilerConstants(final String symbolName, final Class<?> type) {
197 this(symbolName, type, -1);
198 }
199
200 private CompilerConstants(final String symbolName, final Class<?> type, final int slot) {
201 this.symbolName = symbolName;
202 this.type = type;
203 this.slot = slot;
204 }
205
206 /**
207 * Return the tag for this compile constant. Deliberately avoiding "name" here
208 * not to conflate with enum implementation. This is the master string for the
209 * constant - every constant has one.
210 *
211 * @return the tag
212 */
213 public final String symbolName() {
214 return symbolName;
215 }
216
217 /**
218 * Return the type for this compile constant
219 *
220 * @return type for this constant's instances, or null if N/A
221 */
222 public final Class<?> type() {
223 return type;
224 }
225
226 /**
227 * Return the slot for this compile constant
228 *
229 * @return byte code slot where constant is stored or -1 if N/A
230 */
231 public final int slot() {
232 return slot;
233 }
234
235 /**
236 * Return a descriptor for this compile constant. Only relevant if it has
237 * a type
238 *
239 * @return descriptor the descriptor
240 */
241 public final String descriptor() {
242 assert type != null : " asking for descriptor of typeless constant";
243 return typeDescriptor(type);
244 }
245
246 /**
247 * Get the internal class name for a type
248 *
249 * @param type a type
250 * @return the internal name for this type
251 */
252 public static String className(final Class<?> type) {
253 return Type.getInternalName(type);
254 }
255
256 /**
257 * Get the method descriptor for a given method type collection
258 *
259 * @param rtype return type
260 * @param ptypes parameter types
261 *
262 * @return internal descriptor for this method
263 */
264 public static String methodDescriptor(final Class<?> rtype, final Class<?>... ptypes) {
265 return Type.getMethodDescriptor(rtype, ptypes);
266 }
267
268 /**
269 * Get the type descriptor for a type
270 *
271 * @param clazz a type
272 *
273 * @return the internal descriptor for this type
274 */
275 public static String typeDescriptor(final Class<?> clazz) {
276 return Type.typeFor(clazz).getDescriptor();
277 }
278
279 /**
280 * Create a call representing a void constructor for a given type. Don't
281 * attempt to look this up at compile time
282 *
283 * @param clazz the class
284 *
285 * @return Call representing void constructor for type
286 */
287 public static Call constructorNoLookup(final Class<?> clazz) {
288 return specialCallNoLookup(clazz, INIT.symbolName(), void.class);
289 }
290
291 /**
292 * Create a call representing a constructor for a given type. Don't
293 * attempt to look this up at compile time
294 *
295 * @param className the type class name
296 * @param ptypes the parameter types for the constructor
297 *
298 * @return Call representing constructor for type
299 */
300 public static Call constructorNoLookup(final String className, final Class<?>... ptypes) {
301 return specialCallNoLookup(className, INIT.symbolName(), methodDescriptor(void.class, ptypes));
302 }
303
304 /**
305 * Create a call representing a constructor for a given type. Don't
306 * attempt to look this up at compile time
307 *
308 * @param clazz the class name
309 * @param ptypes the parameter types for the constructor
310 *
311 * @return Call representing constructor for type
312 */
313 public static Call constructorNoLookup(final Class<?> clazz, final Class<?>... ptypes) {
314 return specialCallNoLookup(clazz, INIT.symbolName(), void.class, ptypes);
315 }
316
317 /**
318 * Create a call representing an invokespecial to a given method. Don't
319 * attempt to look this up at compile time
320 *
321 * @param className the class name
322 * @param name the method name
323 * @param desc the descriptor
324 *
325 * @return Call representing specified invokespecial call
326 */
327 public static Call specialCallNoLookup(final String className, final String name, final String desc) {
328 return new Call(null, className, name, desc) {
329 @Override
330 public MethodEmitter invoke(final MethodEmitter method) {
331 return method.invokespecial(className, name, descriptor);
332 }
333 };
334 }
335
336 /**
337 * Create a call representing an invokespecial to a given method. Don't
338 * attempt to look this up at compile time
339 *
340 * @param clazz the class
341 * @param name the method name
342 * @param rtype the return type
343 * @param ptypes the parameter types
344 *
345 * @return Call representing specified invokespecial call
346 */
347 public static Call specialCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
348 return specialCallNoLookup(className(clazz), name, methodDescriptor(rtype, ptypes));
349 }
350
351 /**
352 * Create a call representing an invokestatic to a given method. Don't
353 * attempt to look this up at compile time
354 *
355 * @param className the class name
356 * @param name the method name
357 * @param desc the descriptor
358 *
359 * @return Call representing specified invokestatic call
360 */
361 public static Call staticCallNoLookup(final String className, final String name, final String desc) {
362 return new Call(null, className, name, desc) {
363 @Override
364 public MethodEmitter invoke(final MethodEmitter method) {
365 return method.invokestatic(className, name, descriptor);
366 }
367 };
368 }
369
370 /**
371 * Create a call representing an invokestatic to a given method. Don't
372 * attempt to look this up at compile time
373 *
374 * @param clazz the class
375 * @param name the method name
376 * @param rtype the return type
377 * @param ptypes the parameter types
378 *
379 * @return Call representing specified invokestatic call
380 */
381 public static Call staticCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
382 return staticCallNoLookup(className(clazz), name, methodDescriptor(rtype, ptypes));
383 }
384
385 /**
386 * Create a call representing an invokevirtual to a given method. Don't
387 * attempt to look this up at compile time
388 *
389 * @param clazz the class
390 * @param name the method name
391 * @param rtype the return type
392 * @param ptypes the parameter types
393 *
394 * @return Call representing specified invokevirtual call
395 */
396 public static Call virtualCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
397 return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
398 @Override
399 public MethodEmitter invoke(final MethodEmitter method) {
400 return method.invokevirtual(className, name, descriptor);
401 }
402 };
403 }
404
405 /**
406 * Create a call representing an invokeinterface to a given method. Don't
407 * attempt to look this up at compile time
408 *
409 * @param clazz the class
410 * @param name the method name
411 * @param rtype the return type
412 * @param ptypes the parameter types
413 *
414 * @return Call representing specified invokeinterface call
415 */
416 public static Call interfaceCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
417 return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
418 @Override
419 public MethodEmitter invoke(final MethodEmitter method) {
420 return method.invokeinterface(className, name, descriptor);
421 }
422 };
423 }
424
425 /**
426 * Create a FieldAccess representing a virtual field, that can be subject to put
427 * or get operations
428 *
429 * @param className name of the class where the field is a member
430 * @param name name of the field
431 * @param desc type descriptor of the field
432 *
433 * @return a field access object giving access code generation method for the virtual field
434 */
435 public static FieldAccess virtualField(final String className, final String name, final String desc) {
436 return new FieldAccess(className, name, desc) {
437 @Override
438 public MethodEmitter get(final MethodEmitter method) {
439 return method.getField(className, name, descriptor);
440 }
441
442 @Override
443 public void put(final MethodEmitter method) {
444 method.putField(className, name, descriptor);
445 }
446 };
447 }
448
449 /**
450 * Create a FieldAccess representing a virtual field, that can be subject to put
451 * or get operations
452 *
453 * @param clazz class where the field is a member
454 * @param name name of the field
455 * @param type type of the field
456 *
457 * @return a field access object giving access code generation method for the virtual field
458 */
459 public static FieldAccess virtualField(final Class<?> clazz, final String name, final Class<?> type) {
460 return virtualField(className(clazz), name, typeDescriptor(type));
461 }
462
463 /**
464 * Create a FieldAccess representing a static field, that can be subject to put
465 * or get operations
466 *
467 * @param className name of the class where the field is a member
468 * @param name name of the field
469 * @param desc type descriptor of the field
470 *
471 * @return a field access object giving access code generation method for the static field
472 */
473 public static FieldAccess staticField(final String className, final String name, final String desc) {
474 return new FieldAccess(className, name, desc) {
475 @Override
476 public MethodEmitter get(final MethodEmitter method) {
477 return method.getStatic(className, name, descriptor);
478 }
479
480 @Override
481 public void put(final MethodEmitter method) {
482 method.putStatic(className, name, descriptor);
483 }
484 };
485 }
486
487 /**
488 * Create a FieldAccess representing a static field, that can be subject to put
489 * or get operations
490 *
491 * @param clazz class where the field is a member
492 * @param name name of the field
493 * @param type type of the field
494 *
495 * @return a field access object giving access code generation method for the virtual field
496 */
497 public static FieldAccess staticField(final Class<?> clazz, final String name, final Class<?> type) {
498 return staticField(className(clazz), name, typeDescriptor(type));
499 }
500
501 /**
502 * Create a static call, given an explicit lookup, looking up the method handle for it at the same time
503 *
504 * @param lookup the lookup
505 * @param clazz the class
506 * @param name the name of the method
507 * @param rtype the return type
508 * @param ptypes the parameter types
509 *
510 * @return the call object representing the static call
511 */
512 public static Call staticCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
513 return new Call(MH.findStatic(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
514 @Override
515 public MethodEmitter invoke(final MethodEmitter method) {
516 return method.invokestatic(className, name, descriptor);
517 }
518 };
519 }
520
521 /**
522 * Create a virtual call, given an explicit lookup, looking up the method handle for it at the same time
523 *
524 * @param lookup the lookup
525 * @param clazz the class
526 * @param name the name of the method
527 * @param rtype the return type
528 * @param ptypes the parameter types
529 *
530 * @return the call object representing the virtual call
531 */
532 public static Call virtualCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
533 return new Call(MH.findVirtual(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
534 @Override
535 public MethodEmitter invoke(final MethodEmitter method) {
536 return method.invokevirtual(className, name, descriptor);
537 }
538 };
539 }
540
541 /**
542 * Private class representing an access. This can generate code into a method code or
543 * a field access.
544 */
545 private abstract static class Access {
546 protected final MethodHandle methodHandle;
547 protected final String className;
548 protected final String name;
549 protected final String descriptor;
550
551 /**
552 * Constructor
553 *
554 * @param methodHandle methodHandle or null if none
555 * @param className class name for access
556 * @param name field or method name for access
557 * @param descriptor descriptor for access field or method
558 */
559 protected Access(final MethodHandle methodHandle, final String className, final String name, final String descriptor) {
560 this.methodHandle = methodHandle;
561 this.className = className;
562 this.name = name;
563 this.descriptor = descriptor;
564 }
565
566 /**
567 * Get the method handle, or null if access hasn't been looked up
568 *
569 * @return method handle
570 */
571 public MethodHandle methodHandle() {
572 return methodHandle;
573 }
574
575 /**
576 * Get the class name of the access
577 *
578 * @return the class name
579 */
580 public String className() {
581 return className;
582 }
583
584 /**
585 * Get the field name or method name of the access
586 *
587 * @return the name
588 */
589 public String name() {
590 return name;
591 }
592
593 /**
594 * Get the descriptor of the method or field of the access
595 *
596 * @return the descriptor
597 */
598 public String descriptor() {
599 return descriptor;
600 }
601 }
602
603 /**
604 * Field access - this can be used for generating code for static or
605 * virtual field accesses
606 */
607 public abstract static class FieldAccess extends Access {
608 /**
609 * Constructor
610 *
611 * @param className name of the class where the field is
612 * @param name name of the field
613 * @param descriptor descriptor of the field
614 */
615 protected FieldAccess(final String className, final String name, final String descriptor) {
616 super(null, className, name, descriptor);
617 }
618
619 /**
620 * Generate get code for the field
621 *
622 * @param emitter a method emitter
623 *
624 * @return the method emitter
625 */
626 protected abstract MethodEmitter get(final MethodEmitter emitter);
627
628 /**
629 * Generate put code for the field
630 *
631 * @param emitter a method emitter
632 */
633 protected abstract void put(final MethodEmitter emitter);
634 }
635
636 /**
637 * Call - this can be used for generating code for different types of calls
638 */
639 public abstract static class Call extends Access {
640
641 /**
642 * Constructor
643 *
644 * @param className class name for the method of the call
645 * @param name method name
646 * @param descriptor method descriptor
647 */
648 protected Call(final String className, final String name, final String descriptor) {
649 super(null, className, name, descriptor);
650 }
651
652 /**
653 * Constructor
654 *
655 * @param methodHandle method handle for the call if resolved
656 * @param className class name for the method of the call
657 * @param name method name
658 * @param descriptor method descriptor
659 */
660 protected Call(final MethodHandle methodHandle, final String className, final String name, final String descriptor) {
661 super(methodHandle, className, name, descriptor);
662 }
663
664 /**
665 * Generate invocation code for the method
666 *
667 * @param emitter a method emitter
668 *
669 * @return the method emitter
670 */
671 protected abstract MethodEmitter invoke(final MethodEmitter emitter);
672 }
673
674 }
--- EOF ---