Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Start transition to new CodeRef handling.
This doesn't rip out any of the "old way", just starts using the new
annotation for code ref static info instead.
  • Loading branch information
jnthn committed May 18, 2013
1 parent 66f45f7 commit 996eca2
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 32 deletions.
25 changes: 14 additions & 11 deletions src/vm/jvm/QAST/Compiler.nqp
Expand Up @@ -3061,9 +3061,9 @@ class QAST::CompilerJAST {
# Compile to JAST and register this block as the deserialization
# handler.
self.as_jast($block);
my $des_meth := JAST::Method.new( :name('deserializeIdx'), :returns('Integer'), :static(0) );
$des_meth.append(JAST::PushIndex.new( :value($*CODEREFS.cuid_to_idx($block.cuid)) ));
$des_meth.append(JAST::Instruction.new( :op('ireturn') ));
my $des_meth := JAST::Method.new( :name('deserializeCuid'), :returns($TYPE_STR), :static(0) );
$des_meth.append(JAST::PushSVal.new( :value($block.cuid) ));
$des_meth.append(JAST::Instruction.new( :op('areturn') ));
$*JCLASS.add_method($des_meth);
}

Expand All @@ -3075,9 +3075,9 @@ class QAST::CompilerJAST {
QAST::Op.new( :op('null') )
);
self.as_jast($load_block);
my $load_meth := JAST::Method.new( :name('loadIdx'), :returns('Integer'), :static(0) );
$load_meth.append(JAST::PushIndex.new( :value($*CODEREFS.cuid_to_idx($load_block.cuid)) ));
$load_meth.append(JAST::Instruction.new( :op('ireturn') ));
my $load_meth := JAST::Method.new( :name('loadCuid'), :returns($TYPE_STR), :static(0) );
$load_meth.append(JAST::PushSVal.new( :value($load_block.cuid) ));
$load_meth.append(JAST::Instruction.new( :op('areturn') ));
$*JCLASS.add_method($load_meth);
}

Expand Down Expand Up @@ -3109,9 +3109,9 @@ class QAST::CompilerJAST {
$*JCLASS.add_method($hll_meth);

# Add method that returns the mainline block.
my $mainline_meth := JAST::Method.new( :name('mainlineIdx'), :returns('Integer'), :static(0) );
$mainline_meth.append(JAST::PushIndex.new( :value($*CODEREFS.cuid_to_idx($cu[0].cuid)) ));
$mainline_meth.append(JAST::Instruction.new( :op('ireturn') ));
my $mainline_meth := JAST::Method.new( :name('mainlineCuid'), :returns($TYPE_STR), :static(0) );
$mainline_meth.append(JAST::PushSVal.new( :value($cu[0].cuid) ));
$mainline_meth.append(JAST::Instruction.new( :op('areturn') ));
$*JCLASS.add_method($mainline_meth);

return $*JCLASS;
Expand Down Expand Up @@ -3386,8 +3386,11 @@ class QAST::CompilerJAST {
$*BLOCK_TA.add_temps_to_method($*JMETH);

# Flatten handlers and store.
my @flat_handlers;
for @handlers { for $_ { nqp::push(@flat_handlers, $_) } }
my @flat_handlers := [nqp::elems(@handlers)];
for @handlers {
nqp::push(@flat_handlers, nqp::elems($_));
for $_ { nqp::push(@flat_handlers, $_) }
}
$*JMETH.cr_handlers(@flat_handlers);

# Add method body JAST.
Expand Down
3 changes: 3 additions & 0 deletions src/vm/jvm/QAST/JASTNodes.nqp
Expand Up @@ -128,6 +128,9 @@ class JAST::Method is JAST::Node {
@!arguments := [];
@!locals := [];
@!instructions := [];
$!cr_name := '';
$!cr_cuid := '';
$!cr_outer := '';
@!cr_olex := [];
@!cr_ilex := [];
@!cr_nlex := [];
Expand Down
Expand Up @@ -244,7 +244,7 @@ else if (curLine.startsWith("++ handlers ")) {
methodName, desc, null, null);

// Add code ref info annotation.
if (crName != null) {
if (crCuid != null && !crCuid.equals("")) {
Type crAnnType = Type.getType("Lorg/perl6/nqp/runtime/CodeRefAnnotation;");
AnnotationVisitor av = m.visitAnnotation(crAnnType.getDescriptor(), true);
av.visit("name", crName);
Expand Down
126 changes: 107 additions & 19 deletions src/vm/jvm/runtime/org/perl6/nqp/runtime/CompilationUnit.java
@@ -1,5 +1,11 @@
package org.perl6.nqp.runtime;

import java.lang.annotation.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

Expand Down Expand Up @@ -58,20 +64,75 @@ public static CompilationUnit setupCompilationUnit(ThreadContext tc, Class<?> cu
* Does initialization work for the compilation unit.
*/
public void initializeCompilationUnit(ThreadContext tc) {
/* Place code references into a lookup table by unique ID. Also
* make sure each code ref has the appropriate STable. */
/* Look through methods for code refs. */
STable BOOTCodeSTable = tc.gc.BOOTCode == null ? null : tc.gc.BOOTCode.st;
codeRefs = getCodeRefs();
for (CodeRef c : codeRefs) {
c.st = BOOTCodeSTable;
cuidToCodeRef.put(c.staticInfo.uniqueId, c);
ArrayList<CodeRef> codeRefList = new ArrayList<CodeRef>();
ArrayList<String> outerCuid = new ArrayList<String>();
Lookup l = MethodHandles.lookup();
boolean codeRefsFound = false;
try {
for (Method m : this.getClass().getDeclaredMethods()) {
if (m.isAnnotationPresent(CodeRefAnnotation.class)) {
/* Got a code ref annotation. Turn to method handle. */
CodeRefAnnotation cra = m.getAnnotation(CodeRefAnnotation.class);
MethodHandle mh = l.unreflect(m).bindTo(this);

/* Munge handlers. */
long[] flatHandlers = cra.handlers();
int hptr = 0;
int numHandlers = (int)flatHandlers[hptr++];
long[][] handlers = new long[numHandlers][];
for (int i = 0; i < numHandlers; i++) {
int handlerThings = (int)flatHandlers[hptr++];
handlers[i] = new long[handlerThings];
for (int j = 0; j < handlerThings; j++)
handlers[i][j] = flatHandlers[hptr++];
}

/* Create and store. */
String cuid = cra.cuid();
CodeRef cr = new CodeRef(this, mh, cra.name(), cuid,
cra.oLexicalNames(), cra.iLexicalNames(),
cra.nLexicalNames(), cra.sLexicalNames(),
handlers);
cr.st = BOOTCodeSTable;
codeRefList.add(cr);
cuidToCodeRef.put(cuid, cr);

/* Stash outer, for later resolution. */
outerCuid.add(cra.outerCuid());

codeRefsFound = true;
}
}

/* Resolve outers. */
codeRefs = codeRefList.toArray(new CodeRef[0]);
for (int i = 0; i < codeRefs.length; i++) {
CodeRef outer = cuidToCodeRef.get(outerCuid.get(i));
if (outer != null)
codeRefs[i].staticInfo.outerStaticInfo = outer.staticInfo;
}
}
catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}

/* Wire up outer relationships. */
int[] outerMap = getOuterMap();
for (int i = 0; i < outerMap.length; i += 2)
codeRefs[outerMap[i]].staticInfo.outerStaticInfo =
codeRefs[outerMap[i + 1]].staticInfo;
/* If we didn't find any by annotations, this is the fallback. */
if (!codeRefsFound) {
codeRefs = getCodeRefs();
for (CodeRef c : codeRefs) {
c.st = BOOTCodeSTable;
cuidToCodeRef.put(c.staticInfo.uniqueId, c);
}

/* Wire up outer relationships. */
int[] outerMap = getOuterMap();
for (int i = 0; i < outerMap.length; i += 2)
codeRefs[outerMap[i]].staticInfo.outerStaticInfo =
codeRefs[outerMap[i + 1]].staticInfo;
}

/* Build callsite descriptors. */
callSites = getCallSites();
Expand All @@ -80,29 +141,47 @@ public void initializeCompilationUnit(ThreadContext tc) {
hllConfig = tc.gc.getHLLConfigFor(this.hllName());

/* Run any deserialization code. */
int dIdx = deserializeIdx();
if (dIdx >= 0)
CodeRef desCodeRef = null;
String desCuid = deserializeCuid();
if (desCuid != null) {
desCodeRef = lookupCodeRef(desCuid);
}
else {
int dIdx = deserializeIdx();
if (dIdx >= 0)
desCodeRef = codeRefs[dIdx];
}
if (desCodeRef != null)
try {
Ops.invokeArgless(tc, codeRefs[dIdx]);
Ops.invokeArgless(tc, desCodeRef);
}
catch (Exception e)
{
throw ExceptionHandling.dieInternal(tc, e.getMessage());
throw ExceptionHandling.dieInternal(tc, e.toString());
}
}

/**
* Runs code in the on-load hook, if one is available.
*/
public void runLoadIfAvailable(ThreadContext tc) {
int lIdx = loadIdx();
if (lIdx >= 0)
CodeRef loadCodeRef = null;
String loadCuid = loadCuid();
if (loadCuid != null) {
loadCodeRef = lookupCodeRef(loadCuid);
}
else {
int lIdx = loadIdx();
if (lIdx >= 0)
loadCodeRef = codeRefs[lIdx];
}
if (loadCodeRef != null)
try {
Ops.invokeArgless(tc, codeRefs[lIdx]);
Ops.invokeArgless(tc, loadCodeRef);
}
catch (Exception e)
{
throw ExceptionHandling.dieInternal(tc, e.getMessage());
throw ExceptionHandling.dieInternal(tc, e.toString());
}
}

Expand Down Expand Up @@ -189,18 +268,27 @@ public void setLexValue(String uniqueId, String name, String scHandle, int scIdx
public int deserializeIdx() {
return -1;
}
public String deserializeCuid() {
return null;
}

/**
* Code generation overrides this if there's an SC to deserialize.
*/
public int loadIdx() {
return -1;
}
public String loadCuid() {
return null;
}

/**
* Code generation overrides this with the mainline blcok.
*/
public int mainlineIdx() {
return -1;
}
public String mainlineCuid() {
return null;
}
}
5 changes: 4 additions & 1 deletion src/vm/jvm/runtime/org/perl6/nqp/runtime/Ops.java
Expand Up @@ -4017,7 +4017,10 @@ public static long iscompunit(SixModelObject obj, ThreadContext tc) {
}
public static SixModelObject compunitmainline(SixModelObject obj, ThreadContext tc) {
EvalResult res = (EvalResult)obj;
return res.cu.codeRefs[res.cu.mainlineIdx()];
int mIdx = res.cu.mainlineIdx();
if (mIdx >= 0)
return res.cu.codeRefs[mIdx];
return res.cu.lookupCodeRef(res.cu.mainlineCuid());
}
public static SixModelObject compunitcodes(SixModelObject obj, ThreadContext tc) {
EvalResult res = (EvalResult)obj;
Expand Down

0 comments on commit 996eca2

Please sign in to comment.