1
package org.perl6.nqp.runtime;
3
import java.lang.invoke.*;
4
import java.lang.invoke.MethodHandles.Lookup;
6
import org.perl6.nqp.sixmodel.*;
7
import org.perl6.nqp.sixmodel.reprs.LexoticInstance;
9
public class IndyBootstrap {
10
public static CallSite wval_noa(Lookup caller, String name, MethodType type) {
12
/* Look up wval resolver method. */
13
MethodType resType = MethodType.methodType(SixModelObject.class,
14
MutableCallSite.class, String.class, int.class, ThreadContext.class);
15
MethodHandle res = caller.findStatic(IndyBootstrap.class, "wvalResolve_noa", resType);
17
/* Create a mutable callsite, and curry the resolver with it. */
18
MutableCallSite cs = new MutableCallSite(type);
19
cs.setTarget(MethodHandles.insertArguments(res, 0, cs));
21
/* Produce callsite; it'll be updated with the resolved WVal upon the
22
* first invocation. */
26
throw new RuntimeException(e);
30
public static SixModelObject wvalResolve_noa(MutableCallSite cs, String sc, int idx, ThreadContext tc) {
31
/* Look up the WVal. */
32
SixModelObject res = tc.gc.scs.get(sc).root_objects.get(idx);
34
/* Update this callsite, so that we never run the lookup again and instead
35
* just always use the resolved object. Discards incoming arguments, as
36
* they are no longer needed. */
37
if (!tc.curFrame.codeRef.staticInfo.compUnit.shared)
38
cs.setTarget(MethodHandles.dropArguments(
39
MethodHandles.constant(SixModelObject.class, res),
40
0, String.class, int.class, ThreadContext.class));
42
/* Hand back the resulting object, for this first call. */
46
public static CallSite subcall_noa(Lookup caller, String _, MethodType type) {
48
/* Look up subcall resolver method. */
49
MethodType resType = MethodType.methodType(void.class,
50
Lookup.class, MutableCallSite.class, String.class,
51
int.class, ThreadContext.class, Object[].class);
52
MethodHandle res = caller.findStatic(IndyBootstrap.class, "subcallResolve_noa", resType);
54
/* Create a mutable callsite, and curry the resolver with it and
56
MutableCallSite cs = new MutableCallSite(type);
57
cs.setTarget(MethodHandles
58
.insertArguments(res, 0, caller, cs)
59
.asCollector(Object[].class, type.parameterCount() - 3)
62
/* Produce callsite; it'll be updated with the resolved call upon the
63
* first invocation. */
67
throw new RuntimeException(e);
71
public static void subcallResolve_noa(Lookup caller, MutableCallSite cs, String name, int csIdx, ThreadContext tc, Object... args) {
72
/* Locate the thing to call. */
73
SixModelObject invokee = Ops.getlex(name, tc);
75
/* Don't update callsite in cases where it's not safe. */
76
boolean shared = tc.curFrame.codeRef.staticInfo.compUnit.shared;
77
if (invokee.st != null && invokee.st.ContainerSpec != null) {
78
invokee = Ops.decont(invokee, tc);
82
/* Resolve callsite descriptor. */
83
CallSiteDescriptor csd = csIdx >= 0
84
? tc.curFrame.codeRef.staticInfo.compUnit.callSites[csIdx]
86
CallSiteDescriptor csdOrig = csd;
88
/* If it's lexotic, then resolve to something to do the throwing. */
89
if (invokee instanceof LexoticInstance) {
90
/* Go by result type, updating callsite appropriately so we
91
* don't have to do this in the future. */
92
LexoticException throwee = tc.theLexotic;
93
throwee.target = ((LexoticInstance)invokee).target;
94
switch (csd.argFlags[0]) {
95
case CallSiteDescriptor.ARG_OBJ:
96
throwee.payload = (SixModelObject)args[0];
98
if (!shared) cs.setTarget(MethodHandles.insertArguments(
99
caller.findStatic(IndyBootstrap.class, "lexotic_o_noa",
100
MethodType.methodType(void.class, long.class, String.class, int.class,
101
ThreadContext.class, SixModelObject.class)),
104
catch (Exception e) {
105
throw new RuntimeException(e);
108
case CallSiteDescriptor.ARG_INT:
109
SixModelObject intBoxType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.intBoxType;
110
throwee.payload = Ops.box_i((long)args[0], intBoxType, tc);
112
if (!shared) cs.setTarget(MethodHandles.insertArguments(
113
caller.findStatic(IndyBootstrap.class, "lexotic_i_noa",
114
MethodType.methodType(void.class, long.class,
115
SixModelObject.class, String.class, int.class,
116
ThreadContext.class, long.class)),
117
0, throwee.target, intBoxType));
119
catch (Exception e) {
120
throw new RuntimeException(e);
123
case CallSiteDescriptor.ARG_NUM:
124
SixModelObject numBoxType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.numBoxType;
125
throwee.payload = Ops.box_n((double)args[0], numBoxType, tc);
127
if (!shared) cs.setTarget(MethodHandles.insertArguments(
128
caller.findStatic(IndyBootstrap.class, "lexotic_n_noa",
129
MethodType.methodType(void.class, long.class,
130
SixModelObject.class, String.class, int.class,
131
ThreadContext.class, double.class)),
132
0, throwee.target, numBoxType));
134
catch (Exception e) {
135
throw new RuntimeException(e);
138
case CallSiteDescriptor.ARG_STR:
139
SixModelObject strBoxType = tc.curFrame.codeRef.staticInfo.compUnit.hllConfig.strBoxType;
140
throwee.payload = Ops.box_s((String)args[0], strBoxType, tc);
142
if (!shared) cs.setTarget(MethodHandles.insertArguments(
143
caller.findStatic(IndyBootstrap.class, "lexotic_s_noa",
144
MethodType.methodType(void.class, long.class,
145
SixModelObject.class, String.class, int.class,
146
ThreadContext.class, String.class)),
147
0, throwee.target, strBoxType));
149
catch (Exception e) {
150
throw new RuntimeException(e);
154
throw ExceptionHandling.dieInternal(tc, "Invalid lexotic invocation argument");
159
/* Otherwise, get the code ref. */
161
if (invokee instanceof CodeRef) {
162
cr = (CodeRef)invokee;
165
InvocationSpec is = invokee.st.InvocationSpec;
167
throw ExceptionHandling.dieInternal(tc, "Can not invoke this object");
168
if (is.ClassHandle != null)
169
cr = (CodeRef)invokee.get_attribute_boxed(tc, is.ClassHandle, is.AttrName, is.Hint);
171
cr = (CodeRef)is.InvocationHandler;
172
csd = csd.injectInvokee(tc, args, invokee);
177
/* Now need to adapt to the target callsite by binding the CodeRef
178
* and callsite with what they've been resolved to. Don't do it if
179
* it's a compiler stub, though. */
180
if (!cr.isCompilerStub && !shared) {
182
MethodType invType = MethodType.methodType(void.class,
183
MethodHandle.class, String.class, CallSiteDescriptor.class,
184
ThreadContext.class, Object[].class);
185
MethodHandle inv = caller.findStatic(IndyBootstrap.class, "subInvoker", invType);
186
cs.setTarget(MethodHandles
188
MethodHandles.insertArguments(inv, 0, cr.staticInfo.mh, name, csdOrig),
189
0, String.class, int.class)
190
.asVarargsCollector(Object[].class)
191
.asType(cs.getTarget().type()));
193
catch (Throwable t) {
194
throw ExceptionHandling.dieInternal(tc, t);
198
/* Make the sub call directly for this initial call. */
200
cr.staticInfo.mh.invokeExact(tc, (CodeRef)cr, csd, args);
202
catch (ControlException e) {
205
catch (Throwable e) {
206
ExceptionHandling.dieInternal(tc, e);
210
public static void lexotic_o_noa(long target, String _, int __, ThreadContext tc, SixModelObject arg) {
211
LexoticException throwee = tc.theLexotic;
212
throwee.target = target;
213
throwee.payload = arg;
217
public static void lexotic_i_noa(long target, SixModelObject boxType, String _, int __, ThreadContext tc, long arg) {
218
LexoticException throwee = tc.theLexotic;
219
throwee.target = target;
220
throwee.payload = Ops.box_i(arg, boxType, tc);
224
public static void lexotic_n_noa(long target, SixModelObject boxType, String _, int __, ThreadContext tc, double arg) {
225
LexoticException throwee = tc.theLexotic;
226
throwee.target = target;
227
throwee.payload = Ops.box_n(arg, boxType, tc);
231
public static void lexotic_s_noa(long target, SixModelObject boxType, String _, int __, ThreadContext tc, String arg) {
232
LexoticException throwee = tc.theLexotic;
233
throwee.target = target;
234
throwee.payload = Ops.box_s(arg, boxType, tc);
238
public static void subInvoker(MethodHandle mh, String name, CallSiteDescriptor csd, ThreadContext tc, Object[] args) throws Throwable {
239
SixModelObject invokee = Ops.getlex(name, tc);
241
if (invokee instanceof CodeRef) {
242
cr = (CodeRef)invokee;
245
InvocationSpec is = invokee.st.InvocationSpec;
247
throw ExceptionHandling.dieInternal(tc, "Can not invoke this object");
248
if (is.ClassHandle != null)
249
cr = (CodeRef)invokee.get_attribute_boxed(tc, is.ClassHandle, is.AttrName, is.Hint);
251
cr = (CodeRef)is.InvocationHandler;
252
csd = csd.injectInvokee(tc, args, invokee);
256
mh.invokeExact(tc, cr, csd, args);
259
public static CallSite indcall_noa(Lookup caller, String _, MethodType type) {
261
/* Look up indirect call invoker method. */
262
MethodType resType = MethodType.methodType(void.class,
263
MutableCallSite.class, int.class, ThreadContext.class,
264
SixModelObject.class, Object[].class);
265
MethodHandle res = caller.findStatic(IndyBootstrap.class, "indcallInvoker_noa", resType);
267
/* Create a mutable callsite, and curry the resolver with it and
269
MutableCallSite cs = new MutableCallSite(type);
270
cs.setTarget(MethodHandles
271
.insertArguments(res, 0, cs)
272
.asCollector(Object[].class, type.parameterCount() - 3)
275
/* Produce callsite. */
278
catch (Exception e) {
279
throw new RuntimeException(e);
283
public static void indcallInvoker_noa(MutableCallSite cs, int csIdx,
284
ThreadContext tc, SixModelObject invokee, Object... args) {
285
/* Resolve callsite descriptor. */
286
CallSiteDescriptor csd = csIdx >= 0
287
? tc.curFrame.codeRef.staticInfo.compUnit.callSites[csIdx]
290
/* Get the code ref. */
292
invokee = Ops.decont(invokee, tc);
293
if (invokee instanceof LexoticInstance)
294
Ops.invokeLexotic(invokee, csd, args, tc);
295
if (invokee instanceof CodeRef) {
296
cr = (CodeRef)invokee;
299
InvocationSpec is = invokee.st.InvocationSpec;
301
throw ExceptionHandling.dieInternal(tc, "Can not invoke this object");
302
if (is.ClassHandle != null)
303
cr = (CodeRef)invokee.get_attribute_boxed(tc, is.ClassHandle, is.AttrName, is.Hint);
305
cr = (CodeRef)is.InvocationHandler;
306
csd = csd.injectInvokee(tc, args, invokee);
313
cr.staticInfo.mh.invokeExact(tc, cr, csd, args);
315
catch (ControlException e) {
318
catch (Throwable e) {
319
ExceptionHandling.dieInternal(tc, e);
323
public static CallSite methcall_noa(Lookup caller, String _, MethodType type) {
325
/* Look up methcall resolver method. */
326
MethodType resType = MethodType.methodType(void.class,
327
Lookup.class, MutableCallSite.class, String.class,
328
int.class, ThreadContext.class, Object[].class);
329
MethodHandle res = caller.findStatic(IndyBootstrap.class, "methcallResolve_noa", resType);
331
/* Create a mutable callsite, and curry the resolver with it and
332
* the method name. */
333
MutableCallSite cs = new MutableCallSite(type);
334
cs.setTarget(MethodHandles
335
.insertArguments(res, 0, caller, cs)
336
.asCollector(Object[].class, type.parameterCount() - 3)
339
/* Produce callsite; it'll build up a PIC over various polymorphic
343
catch (Exception e) {
344
throw new RuntimeException(e);
348
public static void methcallResolve_noa(Lookup caller, MutableCallSite cs, String name, int csIdx,
349
ThreadContext tc, Object... args) {
350
/* Resolve callsite descriptor. */
351
CallSiteDescriptor csd = csIdx >= 0
352
? tc.curFrame.codeRef.staticInfo.compUnit.callSites[csIdx]
355
/* Try to resolve method to a coderef. */
356
SixModelObject invocant = (SixModelObject)args[0];
357
SixModelObject invokee = Ops.findmethod(invocant, name, tc);
359
throw ExceptionHandling.dieInternal(tc,
360
"Method '" + name + "' not found for invocant of class '" + Ops.typeName(invocant, tc) + "'");
362
if (invokee instanceof CodeRef) {
363
cr = (CodeRef)invokee;
366
InvocationSpec is = invokee.st.InvocationSpec;
368
throw ExceptionHandling.dieInternal(tc, "Can not invoke this object");
369
if (is.ClassHandle != null)
370
cr = (CodeRef)invokee.get_attribute_boxed(tc, is.ClassHandle, is.AttrName, is.Hint);
372
cr = (CodeRef)is.InvocationHandler;
373
csd = csd.injectInvokee(tc, args, invokee);
378
/* Update callsite, stacking up guarded clauses. Don't do it if it
379
* is a dynamic compiler stub, though. */
380
/* XXX Needs fixing for no-optional-args workaround. */
381
/*if (!cr.isCompilerStub) {
382
MethodType gType = MethodType.methodType(boolean.class,
383
STable.class, ThreadContext.class, SixModelObject.class);
387
if (invocant.st.ContainerSpec == null) {
388
guard = caller.findStatic(IndyBootstrap.class, "stGuard", gType);
389
guardSTable = invocant.st;
392
guard = caller.findStatic(IndyBootstrap.class, "stGuardCont", gType);
393
guardSTable = Ops.decont(invocant, tc).st;
396
catch (Exception e) {
397
throw new RuntimeException(e);
400
MethodHandles.guardWithTest(
401
MethodHandles.insertArguments(guard, 0, guardSTable),
403
.insertArguments(cr.staticInfo.mh, 1, cr, csd)
404
.asVarargsCollector(Object[].class)
405
.asType(cs.getTarget().type()),
409
/* Make the call directly for this initial call. */
411
cr.staticInfo.mh.invokeExact(tc, cr, csd, args);
413
catch (ControlException e) {
416
catch (Throwable e) {
417
ExceptionHandling.dieInternal(tc, e);
421
public static boolean stGuard(STable expected, ThreadContext _, SixModelObject obj) {
422
return obj.st == expected;
425
public static boolean stGuardCont(STable expected, ThreadContext tc, SixModelObject obj) {
426
return Ops.decont(obj, tc).st == expected;
429
public static CallSite indmethcall_noa(Lookup caller, String _, MethodType type) {
431
/* Look up methcall invoker method. */
432
MethodType resType = MethodType.methodType(void.class,
433
MutableCallSite.class, int.class,
434
ThreadContext.class, String.class, Object[].class);
435
MethodHandle res = caller.findStatic(IndyBootstrap.class, "indmethcallInvoker_noa", resType);
437
/* Create a mutable callsite, and curry the resolver with it and
438
* the method name. */
439
MutableCallSite cs = new MutableCallSite(type);
440
cs.setTarget(MethodHandles
441
.insertArguments(res, 0, cs)
442
.asCollector(Object[].class, type.parameterCount() - 3)
445
/* Produce callsite. */
448
catch (Exception e) {
449
throw new RuntimeException(e);
453
public static void indmethcallInvoker_noa(MutableCallSite cs, int csIdx,
454
ThreadContext tc, String name, Object... args) {
455
/* Resolve callsite descriptor. */
456
CallSiteDescriptor csd = csIdx >= 0
457
? tc.curFrame.codeRef.staticInfo.compUnit.callSites[csIdx]
460
/* Try to resolve method to a coderef. */
461
SixModelObject invocant = (SixModelObject)args[0];
462
SixModelObject invokee = Ops.findmethod(invocant, name, tc);
464
throw ExceptionHandling.dieInternal(tc,
465
"Method '" + name + "' not found for invocant of class '" + Ops.typeName(invocant, tc) + "'");
467
if (invokee instanceof CodeRef) {
468
cr = (CodeRef)invokee;
471
InvocationSpec is = invokee.st.InvocationSpec;
473
throw ExceptionHandling.dieInternal(tc, "Can not invoke this object");
474
if (is.ClassHandle != null)
475
cr = (CodeRef)invokee.get_attribute_boxed(tc, is.ClassHandle, is.AttrName, is.Hint);
477
cr = (CodeRef)is.InvocationHandler;
478
csd = csd.injectInvokee(tc, args, invokee);
485
cr.staticInfo.mh.invokeExact(tc, cr, csd, args);
487
catch (ControlException e) {
490
catch (Throwable e) {
491
ExceptionHandling.dieInternal(tc, e);