author | hannesw |
Mon, 18 Feb 2013 10:36:18 +0100 | |
changeset 16244 | 12f06c992c3a |
parent 16226 | 0e4f37e6cc40 |
child 16272 | 675a0caf75bc |
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.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup; |
|
29 |
import static jdk.nashorn.internal.codegen.types.Type.BOOLEAN; |
|
30 |
import static jdk.nashorn.internal.codegen.types.Type.INT; |
|
31 |
import static jdk.nashorn.internal.runtime.linker.Lookup.MH; |
|
32 |
||
33 |
import java.lang.invoke.CallSite; |
|
34 |
import java.lang.invoke.MethodHandle; |
|
35 |
import java.lang.invoke.MethodHandles; |
|
36 |
import java.lang.invoke.MethodType; |
|
37 |
import java.lang.invoke.MutableCallSite; |
|
38 |
import java.util.HashMap; |
|
39 |
import java.util.Map; |
|
40 |
import jdk.nashorn.internal.codegen.CompilerConstants.Call; |
|
41 |
import jdk.nashorn.internal.codegen.types.Type; |
|
42 |
import jdk.nashorn.internal.ir.RuntimeNode; |
|
43 |
import jdk.nashorn.internal.ir.RuntimeNode.Request; |
|
44 |
import jdk.nashorn.internal.runtime.ScriptRuntime; |
|
16226
0e4f37e6cc40
8007915: Nashorn IR, codegen, parser packages and Context instance should be inaccessible to user code
sundar
parents:
16210
diff
changeset
|
45 |
import jdk.nashorn.internal.runtime.linker.Bootstrap; |
16147 | 46 |
import jdk.nashorn.internal.runtime.linker.Lookup; |
47 |
import jdk.nashorn.internal.runtime.linker.MethodHandleFactory; |
|
48 |
||
49 |
/** |
|
50 |
* Optimistic call site that assumes its Object arguments to be of a boxed type. |
|
51 |
* Gradually reverts to wider boxed types if the assumption for the RuntimeNode |
|
52 |
* is proven wrong. Finally reverts to the generic ScriptRuntime method. |
|
53 |
* |
|
54 |
* This is used from the CodeGenerator when we have a runtime node, but 1 or more |
|
55 |
* primitive arguments. This class generated appropriate specializations, for example |
|
56 |
* {@code Object a === int b} is a good idea to specialize to {@code ((Integer)a).intValue() == b} |
|
57 |
* surrounded by catch blocks that will try less narrow specializations |
|
58 |
*/ |
|
16226
0e4f37e6cc40
8007915: Nashorn IR, codegen, parser packages and Context instance should be inaccessible to user code
sundar
parents:
16210
diff
changeset
|
59 |
public final class RuntimeCallSite extends MutableCallSite { |
0e4f37e6cc40
8007915: Nashorn IR, codegen, parser packages and Context instance should be inaccessible to user code
sundar
parents:
16210
diff
changeset
|
60 |
static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "runtimeBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class); |
16147 | 61 |
|
62 |
private static final MethodHandle NEXT = findOwnMH("next", MethodHandle.class); |
|
63 |
||
64 |
private final RuntimeNode.Request request; |
|
65 |
||
66 |
private String name; |
|
67 |
||
68 |
/** |
|
69 |
* A specialized runtime node, i.e. on where we know at least one more specific type than object |
|
70 |
*/ |
|
71 |
static final class SpecializedRuntimeNode { |
|
72 |
private static final char REQUEST_SEPARATOR = ':'; |
|
73 |
||
74 |
private final RuntimeNode.Request request; |
|
75 |
||
76 |
private final Type[] parameterTypes; |
|
77 |
||
78 |
private final Type returnType; |
|
79 |
||
80 |
/** |
|
81 |
* Constructor. |
|
82 |
* |
|
83 |
* @param request runtime node request to specialize |
|
84 |
* @param parameterTypes parameter types of the call site |
|
85 |
* @param returnType return type of the call site |
|
86 |
*/ |
|
87 |
SpecializedRuntimeNode(final RuntimeNode.Request request, final Type[] parameterTypes, final Type returnType) { |
|
88 |
this.request = request; |
|
89 |
this.parameterTypes = parameterTypes; |
|
90 |
this.returnType = returnType; |
|
91 |
} |
|
92 |
||
93 |
/** |
|
94 |
* The first type to try to use for this genrated runtime node |
|
95 |
* |
|
96 |
* @return a type |
|
97 |
*/ |
|
98 |
public Type firstTypeGuess() { |
|
99 |
Type widest = Type.UNKNOWN; |
|
100 |
for (final Type type : parameterTypes) { |
|
101 |
if (type.isObject()) { |
|
102 |
continue; |
|
103 |
} |
|
104 |
widest = Type.widest(type, widest); |
|
105 |
} |
|
106 |
widest = Type.widest(widest, firstTypeGuessForObject(request)); |
|
107 |
||
108 |
return widest; |
|
109 |
} |
|
110 |
||
111 |
private static Type firstTypeGuessForObject(final Request request) { |
|
112 |
switch (request) { |
|
113 |
case ADD: |
|
114 |
return INT; |
|
115 |
default: |
|
116 |
return BOOLEAN; |
|
117 |
} |
|
118 |
} |
|
119 |
||
120 |
Request getRequest() { |
|
121 |
return request; |
|
122 |
} |
|
123 |
||
124 |
Type[] getParameterTypes() { |
|
125 |
return parameterTypes; |
|
126 |
} |
|
127 |
||
128 |
Type getReturnType() { |
|
129 |
return returnType; |
|
130 |
} |
|
131 |
||
132 |
private static char descFor(final Type type) { |
|
133 |
if (type.isObject()) { |
|
134 |
return 'O'; |
|
135 |
} |
|
136 |
return type.getDescriptor().charAt(0); |
|
137 |
} |
|
138 |
||
139 |
@Override |
|
140 |
public boolean equals(final Object other) { |
|
141 |
if (other instanceof SpecializedRuntimeNode) { |
|
142 |
final SpecializedRuntimeNode otherNode = (SpecializedRuntimeNode)other; |
|
143 |
||
144 |
if (!otherNode.getReturnType().equals(getReturnType())) { |
|
145 |
return false; |
|
146 |
} |
|
147 |
||
148 |
if (getParameterTypes().length != otherNode.getParameterTypes().length) { |
|
149 |
return false; |
|
150 |
} |
|
151 |
||
152 |
for (int i = 0; i < getParameterTypes().length; i++) { |
|
153 |
if (!Type.areEquivalent(getParameterTypes()[i], otherNode.getParameterTypes()[i])) { |
|
154 |
return false; |
|
155 |
} |
|
156 |
} |
|
157 |
||
158 |
return otherNode.getRequest().equals(getRequest()); |
|
159 |
} |
|
160 |
||
161 |
return false; |
|
162 |
} |
|
163 |
||
164 |
@Override |
|
165 |
public int hashCode() { |
|
166 |
int hashCode = getRequest().toString().hashCode(); |
|
167 |
hashCode ^= getReturnType().hashCode(); |
|
168 |
for (final Type type : getParameterTypes()) { |
|
169 |
hashCode ^= type.hashCode(); |
|
170 |
} |
|
171 |
return hashCode; |
|
172 |
} |
|
173 |
||
174 |
@Override |
|
175 |
public String toString() { |
|
176 |
final StringBuilder sb = new StringBuilder(); |
|
177 |
sb.append(getRequest().toString()); |
|
178 |
sb.append(REQUEST_SEPARATOR); |
|
179 |
sb.append(descFor(getReturnType())); |
|
180 |
||
181 |
for (final Type type : getParameterTypes()) { |
|
182 |
sb.append(descFor(type)); |
|
183 |
} |
|
184 |
||
185 |
return sb.toString(); |
|
186 |
} |
|
187 |
||
188 |
String getName(final Type extraType) { |
|
189 |
return toString() + "_" + descFor(extraType); |
|
190 |
} |
|
191 |
||
192 |
String getInitialName() { |
|
193 |
return getName(firstTypeGuess()); |
|
194 |
} |
|
195 |
} |
|
196 |
||
197 |
||
198 |
/** |
|
199 |
* Constructor |
|
200 |
* |
|
201 |
* @param type method type for call site |
|
202 |
* @param name name of runtime call |
|
203 |
*/ |
|
16226
0e4f37e6cc40
8007915: Nashorn IR, codegen, parser packages and Context instance should be inaccessible to user code
sundar
parents:
16210
diff
changeset
|
204 |
public RuntimeCallSite(final MethodType type, final String name) { |
16147 | 205 |
super(type); |
206 |
this.name = name; |
|
207 |
this.request = Request.valueOf(name.substring(0, name.indexOf(SpecializedRuntimeNode.REQUEST_SEPARATOR))); |
|
208 |
setTarget(makeMethod(name)); |
|
209 |
} |
|
210 |
||
211 |
private String nextName(final String requestName) { |
|
212 |
if (requestName.equals(request.toString())) { |
|
213 |
return null; |
|
214 |
} |
|
215 |
||
216 |
final char[] c = requestName.toCharArray(); |
|
217 |
final int last = c.length - 1; |
|
218 |
||
219 |
if (c[last - 1] != '_') { |
|
220 |
return null; |
|
221 |
} |
|
222 |
||
223 |
switch (c[last]) { |
|
224 |
case 'Z': |
|
225 |
c[last] = 'I'; |
|
226 |
break; |
|
227 |
case 'I': |
|
228 |
c[last] = 'J'; |
|
229 |
break; |
|
230 |
case 'J': |
|
231 |
c[last] = 'D'; |
|
232 |
break; |
|
233 |
case 'D': |
|
234 |
default: |
|
235 |
return request.toString(); |
|
236 |
} |
|
237 |
||
238 |
return new String(c); |
|
239 |
} |
|
240 |
||
241 |
private boolean isSpecialized(final String requestName) { |
|
242 |
return nextName(requestName) != null; |
|
243 |
} |
|
244 |
||
245 |
private MethodHandle makeMethod(final String requestName) { |
|
246 |
MethodHandle mh; |
|
247 |
||
248 |
if (isSpecialized(requestName)) { |
|
249 |
final Class<?> boxedType; |
|
250 |
final Class<?> primitiveType; |
|
251 |
||
252 |
switch (requestName.charAt(requestName.length() - 1)) { |
|
253 |
case 'Z': |
|
254 |
boxedType = Boolean.class; |
|
255 |
primitiveType = int.class; |
|
256 |
break; |
|
257 |
case 'I': |
|
258 |
boxedType = Integer.class; |
|
259 |
primitiveType = int.class; |
|
260 |
break; |
|
261 |
case 'J': |
|
262 |
boxedType = Long.class; |
|
263 |
primitiveType = long.class; |
|
264 |
break; |
|
265 |
case 'D': |
|
266 |
boxedType = Number.class; |
|
267 |
primitiveType = double.class; |
|
268 |
break; |
|
269 |
default: |
|
270 |
throw new RuntimeException("should not reach here"); |
|
271 |
} |
|
272 |
||
273 |
final boolean isStrictCmp = (request == Request.EQ_STRICT || request == Request.NE_STRICT); |
|
274 |
||
275 |
if (isStrictCmp && |
|
276 |
(boxedType != Boolean.class && |
|
277 |
(type().parameterType(0) == boolean.class || |
|
278 |
type().parameterType(1) == boolean.class))) { |
|
279 |
// number and boolean are never strictly equal, e.g. 0 !== false |
|
280 |
mh = MH.dropArguments(MH.constant(boolean.class, request == Request.NE_STRICT), 0, type().parameterArray()); |
|
281 |
} else { |
|
16244
12f06c992c3a
8008351: Avoid using String.replace(String, String) in codegen
hannesw
parents:
16226
diff
changeset
|
282 |
mh = METHODS.get(request.nonStrictName() + primitiveType.getSimpleName()); |
16147 | 283 |
// unbox objects |
284 |
||
285 |
for (int i = 0; i < type().parameterCount(); i++) { |
|
286 |
if (!type().parameterType(i).isPrimitive()) { |
|
287 |
mh = MH.filterArguments(mh, i, UNBOX.get(boxedType)); |
|
288 |
} |
|
289 |
} |
|
290 |
||
291 |
mh = Lookup.filterReturnType(mh, type().returnType()); |
|
292 |
mh = MH.explicitCastArguments(mh, type()); |
|
293 |
} |
|
294 |
||
295 |
final MethodHandle fallback = MH.foldArguments(MethodHandles.exactInvoker(type()), MH.bindTo(NEXT, this)); |
|
296 |
||
297 |
MethodHandle guard; |
|
298 |
if (type().parameterType(0).isPrimitive()) { |
|
299 |
guard = MH.insertArguments( |
|
300 |
MH.dropArguments(CHECKCAST, 1, type().parameterType(0)), 0, boxedType); |
|
301 |
} else if (type().parameterType(1).isPrimitive()) { |
|
302 |
guard = MH.insertArguments( |
|
303 |
MH.dropArguments(CHECKCAST, 2, type().parameterType(1)), 0, boxedType); |
|
304 |
} else { |
|
305 |
assert !type().parameterType(0).isPrimitive() && !type().parameterType(1).isPrimitive(); |
|
306 |
guard = MH.insertArguments(CHECKCAST2, 0, boxedType); |
|
307 |
} |
|
308 |
||
309 |
if (request == Request.ADD && boxedType == Integer.class) { |
|
310 |
// int add needs additional overflow check |
|
311 |
MethodHandle addcheck = ADDCHECK; |
|
312 |
for (int i = 0; i < type().parameterCount(); i++) { |
|
313 |
if (!type().parameterType(i).isPrimitive()) { |
|
314 |
addcheck = MH.filterArguments(addcheck, i, UNBOX.get(boxedType)); |
|
315 |
} |
|
316 |
} |
|
317 |
addcheck = MH.explicitCastArguments(addcheck, type().changeReturnType(boolean.class)); |
|
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16151
diff
changeset
|
318 |
guard = MH.guardWithTest(upcastGuard(guard), addcheck, |
16147 | 319 |
MH.dropArguments(MH.constant(boolean.class, false), 0, type().parameterArray())); |
320 |
} |
|
321 |
||
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16151
diff
changeset
|
322 |
return MH.guardWithTest(upcastGuard(guard), mh, fallback); |
16147 | 323 |
} |
324 |
||
325 |
// generic fallback |
|
326 |
return MH.explicitCastArguments(Lookup.filterReturnType(GENERIC_METHODS.get(request.name()), type().returnType()), type()); |
|
327 |
} |
|
328 |
||
16210
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16151
diff
changeset
|
329 |
private MethodHandle upcastGuard(final MethodHandle guard) { |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16151
diff
changeset
|
330 |
return MH.asType(guard, type().changeReturnType(boolean.class)); |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16151
diff
changeset
|
331 |
} |
8ad1381b69d0
8007215: Varargs broken for the case of passing more than the arg limit arguments.
lagergren
parents:
16151
diff
changeset
|
332 |
|
16147 | 333 |
/** |
334 |
* This is public just so that the generated specialization code can |
|
335 |
* use it to get the next wider typed method |
|
336 |
* |
|
337 |
* Do not call directly |
|
338 |
* |
|
339 |
* @return next wider specialization method for this RuntimeCallSite |
|
340 |
*/ |
|
341 |
public MethodHandle next() { |
|
342 |
this.name = nextName(name); |
|
343 |
final MethodHandle next = makeMethod(name); |
|
344 |
setTarget(next); |
|
345 |
return next; |
|
346 |
} |
|
347 |
||
348 |
@Override |
|
349 |
public String toString() { |
|
350 |
return super.toString() + " " + name; |
|
351 |
} |
|
352 |
||
353 |
/** Method cache */ |
|
354 |
private static final Map<String, MethodHandle> METHODS; |
|
355 |
||
356 |
/** Generic method cache */ |
|
357 |
private static final Map<String, MethodHandle> GENERIC_METHODS; |
|
358 |
||
359 |
/** Unbox cache */ |
|
360 |
private static final Map<Class<?>, MethodHandle> UNBOX; |
|
361 |
||
362 |
private static final MethodHandle CHECKCAST = findOwnMH("checkcast", boolean.class, Class.class, Object.class); |
|
363 |
private static final MethodHandle CHECKCAST2 = findOwnMH("checkcast", boolean.class, Class.class, Object.class, Object.class); |
|
364 |
private static final MethodHandle ADDCHECK = findOwnMH("ADDcheck", boolean.class, int.class, int.class); |
|
365 |
||
366 |
/** |
|
367 |
* Build maps of correct boxing operations |
|
368 |
*/ |
|
369 |
static { |
|
370 |
UNBOX = new HashMap<>(); |
|
371 |
UNBOX.put(Boolean.class, findOwnMH("unboxZ", int.class, Object.class)); |
|
372 |
UNBOX.put(Integer.class, findOwnMH("unboxI", int.class, Object.class)); |
|
373 |
UNBOX.put(Long.class, findOwnMH("unboxJ", long.class, Object.class)); |
|
374 |
UNBOX.put(Number.class, findOwnMH("unboxD", double.class, Object.class)); |
|
375 |
||
376 |
METHODS = new HashMap<>(); |
|
377 |
||
378 |
for (final Request req : Request.values()) { |
|
379 |
if (req.canSpecialize()) { |
|
380 |
if (req.name().endsWith("_STRICT")) { |
|
381 |
continue; |
|
382 |
} |
|
383 |
||
384 |
final boolean isCmp = Request.isComparison(req); |
|
385 |
||
386 |
METHODS.put(req.name() + "int", findOwnMH(req.name(), (isCmp ? boolean.class : int.class), int.class, int.class)); |
|
387 |
METHODS.put(req.name() + "long", findOwnMH(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class)); |
|
388 |
METHODS.put(req.name() + "double", findOwnMH(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class)); |
|
389 |
} |
|
390 |
} |
|
391 |
||
392 |
GENERIC_METHODS = new HashMap<>(); |
|
393 |
for (final Request req : Request.values()) { |
|
394 |
if (req.canSpecialize()) { |
|
395 |
GENERIC_METHODS.put(req.name(), MH.findStatic(MethodHandles.lookup(), ScriptRuntime.class, req.name(), |
|
396 |
MH.type(req.getReturnType().getTypeClass(), Object.class, Object.class))); |
|
397 |
} |
|
398 |
} |
|
399 |
} |
|
400 |
||
401 |
/** |
|
402 |
* Specialized version of != operator for two int arguments. Do not call directly. |
|
403 |
* @param a int |
|
404 |
* @param b int |
|
405 |
* @return a != b |
|
406 |
*/ |
|
407 |
public static boolean NE(final int a, final int b) { |
|
408 |
return a != b; |
|
409 |
} |
|
410 |
||
411 |
/** |
|
412 |
* Specialized version of != operator for two double arguments. Do not call directly. |
|
413 |
* @param a double |
|
414 |
* @param b double |
|
415 |
* @return a != b |
|
416 |
*/ |
|
417 |
public static boolean NE(final double a, final double b) { |
|
418 |
return a != b; |
|
419 |
} |
|
420 |
||
421 |
/** |
|
422 |
* Specialized version of != operator for two long arguments. Do not call directly. |
|
423 |
* @param a long |
|
424 |
* @param b long |
|
425 |
* @return a != b |
|
426 |
*/ |
|
427 |
public static boolean NE(final long a, final long b) { |
|
428 |
return a != b; |
|
429 |
} |
|
430 |
||
431 |
/** |
|
432 |
* Specialized version of == operator for two int arguments. Do not call directly. |
|
433 |
* @param a int |
|
434 |
* @param b int |
|
435 |
* @return a == b |
|
436 |
*/ |
|
437 |
public static boolean EQ(final int a, final int b) { |
|
438 |
return a == b; |
|
439 |
} |
|
440 |
||
441 |
/** |
|
442 |
* Specialized version of == operator for two double arguments. Do not call directly. |
|
443 |
* @param a double |
|
444 |
* @param b double |
|
445 |
* @return a == b |
|
446 |
*/ |
|
447 |
public static boolean EQ(final double a, final double b) { |
|
448 |
return a == b; |
|
449 |
} |
|
450 |
||
451 |
/** |
|
452 |
* Specialized version of == operator for two long arguments. Do not call directly. |
|
453 |
* @param a long |
|
454 |
* @param b long |
|
455 |
* @return a == b |
|
456 |
*/ |
|
457 |
public static boolean EQ(final long a, final long b) { |
|
458 |
return a == b; |
|
459 |
} |
|
460 |
||
461 |
/** |
|
462 |
* Specialized version of < operator for two int arguments. Do not call directly. |
|
463 |
* @param a int |
|
464 |
* @param b int |
|
465 |
* @return a < b |
|
466 |
*/ |
|
467 |
public static boolean LT(final int a, final int b) { |
|
468 |
return a < b; |
|
469 |
} |
|
470 |
||
471 |
/** |
|
472 |
* Specialized version of < operator for two double arguments. Do not call directly. |
|
473 |
* @param a double |
|
474 |
* @param b double |
|
475 |
* @return a < b |
|
476 |
*/ |
|
477 |
public static boolean LT(final double a, final double b) { |
|
478 |
return a < b; |
|
479 |
} |
|
480 |
||
481 |
/** |
|
482 |
* Specialized version of < operator for two long arguments. Do not call directly. |
|
483 |
* @param a long |
|
484 |
* @param b long |
|
485 |
* @return a < b |
|
486 |
*/ |
|
487 |
public static boolean LT(final long a, final long b) { |
|
488 |
return a < b; |
|
489 |
} |
|
490 |
||
491 |
/** |
|
492 |
* Specialized version of <= operator for two int arguments. Do not call directly. |
|
493 |
* @param a int |
|
494 |
* @param b int |
|
495 |
* @return a <= b |
|
496 |
*/ |
|
497 |
public static boolean LE(final int a, final int b) { |
|
498 |
return a <= b; |
|
499 |
} |
|
500 |
||
501 |
/** |
|
502 |
* Specialized version of <= operator for two double arguments. Do not call directly. |
|
503 |
* @param a double |
|
504 |
* @param b double |
|
505 |
* @return a <= b |
|
506 |
*/ |
|
507 |
public static boolean LE(final double a, final double b) { |
|
508 |
return a <= b; |
|
509 |
} |
|
510 |
||
511 |
/** |
|
512 |
* Specialized version of <= operator for two long arguments. Do not call directly. |
|
513 |
* @param a long |
|
514 |
* @param b long |
|
515 |
* @return a <= b |
|
516 |
*/ |
|
517 |
public static boolean LE(final long a, final long b) { |
|
518 |
return a <= b; |
|
519 |
} |
|
520 |
||
521 |
/** |
|
522 |
* Specialized version of > operator for two int arguments. Do not call directly. |
|
523 |
* @param a int |
|
524 |
* @param b int |
|
525 |
* @return a > b |
|
526 |
*/ |
|
527 |
public static boolean GT(final int a, final int b) { |
|
528 |
return a > b; |
|
529 |
} |
|
530 |
||
531 |
/** |
|
532 |
* Specialized version of > operator for two double arguments. Do not call directly. |
|
533 |
* @param a double |
|
534 |
* @param b double |
|
535 |
* @return a > b |
|
536 |
*/ |
|
537 |
public static boolean GT(final double a, final double b) { |
|
538 |
return a > b; |
|
539 |
} |
|
540 |
||
541 |
/** |
|
542 |
* Specialized version of > operator for two long arguments. Do not call directly. |
|
543 |
* @param a long |
|
544 |
* @param b long |
|
545 |
* @return a > b |
|
546 |
*/ |
|
547 |
public static boolean GT(final long a, final long b) { |
|
548 |
return a > b; |
|
549 |
} |
|
550 |
||
551 |
/** |
|
552 |
* Specialized version of >= operator for two int arguments. Do not call directly. |
|
553 |
* @param a int |
|
554 |
* @param b int |
|
555 |
* @return a >= b |
|
556 |
*/ |
|
557 |
public static boolean GE(final int a, final int b) { |
|
558 |
return a >= b; |
|
559 |
} |
|
560 |
||
561 |
/** |
|
562 |
* Specialized version of >= operator for two double arguments. Do not call directly. |
|
563 |
* @param a double |
|
564 |
* @param b double |
|
565 |
* @return a >= b |
|
566 |
*/ |
|
567 |
public static boolean GE(final double a, final double b) { |
|
568 |
return a >= b; |
|
569 |
} |
|
570 |
||
571 |
/** |
|
572 |
* Specialized version of >= operator for two long arguments. Do not call directly. |
|
573 |
* @param a long |
|
574 |
* @param b long |
|
575 |
* @return a >= b |
|
576 |
*/ |
|
577 |
public static boolean GE(final long a, final long b) { |
|
578 |
return a >= b; |
|
579 |
} |
|
580 |
||
581 |
/** |
|
582 |
* Specialized version of + operator for two int arguments. Do not call directly. |
|
583 |
* @param a int |
|
584 |
* @param b int |
|
585 |
* @return a + b |
|
586 |
*/ |
|
587 |
public static int ADD(final int a, final int b) { |
|
588 |
return a + b; |
|
589 |
} |
|
590 |
||
591 |
/** |
|
592 |
* Specialized version of + operator for two long arguments. Do not call directly. |
|
593 |
* @param a long |
|
594 |
* @param b long |
|
595 |
* @return a + b |
|
596 |
*/ |
|
597 |
public static long ADD(final long a, final long b) { |
|
598 |
return a + b; |
|
599 |
} |
|
600 |
||
601 |
/** |
|
602 |
* Specialized version of + operator for two double arguments. Do not call directly. |
|
603 |
* @param a double |
|
604 |
* @param b double |
|
605 |
* @return a + b |
|
606 |
*/ |
|
607 |
public static double ADD(final double a, final double b) { |
|
608 |
return a + b; |
|
609 |
} |
|
610 |
||
611 |
/** |
|
612 |
* Check that ints are addition compatible, i.e. their sum is equal to the sum |
|
613 |
* of them cast to long. Otherwise the addition will overflow. Do not call directly. |
|
614 |
* |
|
615 |
* @param a int |
|
616 |
* @param b int |
|
617 |
* |
|
618 |
* @return true if addition does not overflow |
|
619 |
*/ |
|
620 |
public static boolean ADDcheck(final int a, final int b) { |
|
621 |
return (a + b == (long)a + (long)b); |
|
622 |
} |
|
623 |
||
624 |
/** |
|
625 |
* Checkcast used for specialized ops. Do not call directly |
|
626 |
* |
|
627 |
* @param type to to check against |
|
628 |
* @param obj object to check for type |
|
629 |
* |
|
630 |
* @return true if type check holds |
|
631 |
*/ |
|
632 |
public static boolean checkcast(final Class<?> type, final Object obj) { |
|
633 |
return type.isInstance(obj); |
|
634 |
} |
|
635 |
||
636 |
/** |
|
637 |
* Checkcast used for specialized ops. Do not call directly |
|
638 |
* |
|
639 |
* @param type type to check against |
|
640 |
* @param objA first object to check against type |
|
641 |
* @param objB second object to check against type |
|
642 |
* |
|
643 |
* @return true if type check holds for both objects |
|
644 |
*/ |
|
645 |
public static boolean checkcast(final Class<?> type, final Object objA, final Object objB) { |
|
646 |
return type.isInstance(objA) && type.isInstance(objB); |
|
647 |
} |
|
648 |
||
649 |
/** |
|
650 |
* Unbox a java.lang.Boolean. Do not call directly |
|
651 |
* @param obj object to cast to int and unbox |
|
652 |
* @return an int value for the boolean, 1 is true, 0 is false |
|
653 |
*/ |
|
654 |
public static int unboxZ(final Object obj) { |
|
655 |
return (boolean)obj ? 1 : 0; |
|
656 |
} |
|
657 |
||
658 |
/** |
|
659 |
* Unbox a java.lang.Integer. Do not call directly |
|
660 |
* @param obj object to cast to int and unbox |
|
661 |
* @return an int |
|
662 |
*/ |
|
663 |
public static int unboxI(final Object obj) { |
|
664 |
return (int)obj; |
|
665 |
} |
|
666 |
||
667 |
/** |
|
668 |
* Unbox a java.lang.Long. Do not call directly |
|
669 |
* @param obj object to cast to long and unbox |
|
670 |
* @return a long |
|
671 |
*/ |
|
672 |
public static long unboxJ(final Object obj) { |
|
673 |
return (long)obj; |
|
674 |
} |
|
675 |
||
676 |
/** |
|
677 |
* Unbox a java.lang.Number. Do not call directly |
|
678 |
* @param obj object to cast to Number and unbox |
|
679 |
* @return a double |
|
680 |
*/ |
|
681 |
public static double unboxD(final Object obj) { |
|
682 |
return ((Number)obj).doubleValue(); |
|
683 |
} |
|
684 |
||
685 |
private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { |
|
686 |
try { |
|
687 |
return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types)); |
|
688 |
} catch (final MethodHandleFactory.LookupException e) { |
|
689 |
return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types)); |
|
690 |
} |
|
691 |
} |
|
692 |
||
693 |
} |