Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use small integer identifiers for internal references to coderefs
  • Loading branch information
sorear committed Jun 21, 2013
1 parent 419102f commit 2d3a93c
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 16 deletions.
36 changes: 25 additions & 11 deletions src/vm/jvm/QAST/Compiler.nqp
Expand Up @@ -662,9 +662,9 @@ QAST::OperationsJAST.add_core_op('list_b', -> $qastcomp, $op {
unless nqp::istype($_, QAST::Block);
$il.append($DUP);
$il.append($ALOAD_0);
$il.append(JAST::PushSVal.new( :value($_.cuid) ));
$il.append(JAST::PushIndex.new( :value($qastcomp.cuid_to_qbid($_.cuid)) ));
$il.append(JAST::Instruction.new( :op('invokevirtual'),
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, $TYPE_STR ));
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, 'I' ));
$il.append($ALOAD_1);
$il.append(JAST::Instruction.new( :op('invokestatic'), $TYPE_OPS, 'push',
$TYPE_SMO, $TYPE_SMO, $TYPE_SMO, $TYPE_TC ));
Expand Down Expand Up @@ -2310,10 +2310,10 @@ QAST::OperationsJAST.add_core_op('setup_blv', -> $qastcomp, $op {
}
$il.append($ALOAD_0);
$il.append($ALOAD_1);
$il.append(JAST::PushSVal.new( :value($cuid) ));
$il.append(JAST::PushIndex.new( :value($qastcomp.cuid_to_qbid($cuid)) ));
$il.append(JAST::PushSVal.new( :value(nqp::join("\0", @bits)) ));
$il.append(JAST::Instruction.new( :op('invokevirtual'),
$TYPE_CU, 'setLexValues', 'Void', $TYPE_TC, $TYPE_STR, $TYPE_STR ));
$TYPE_CU, 'setLexValues', 'Void', $TYPE_TC, 'I', $TYPE_STR ));
}

$il.append($ACONST_NULL);
Expand Down Expand Up @@ -2825,6 +2825,11 @@ class QAST::CompilerJAST {
}
$best
}

method cuid_to_qbid(str $cuid) {
my $map := %*CUID_TO_QBID;
nqp::existskey($map, $cuid) ?? $map{$cuid} !! ($map{$cuid} := $*NEXT_QBID++);
}

multi method as_jast(QAST::CompUnit $cu, :$want) {
# A compilation-unit-wide source of IDs for handlers.
Expand All @@ -2840,7 +2845,17 @@ class QAST::CompilerJAST {
if +@($cu) != 1 || !nqp::istype($cu[0], QAST::Block) {
nqp::die("QAST::CompUnit should have one child that is a QAST::Block");
}


my %*CUID_TO_QBID;
my $*NEXT_QBID := 0;
# Pre-seed to make sure that qbids correspond to serialization IDs
my $comp_mode := $cu.compilation_mode;
if $comp_mode {
for $cu.code_ref_blocks() -> $qblock {
%*CUID_TO_QBID{$qblock.cuid} := $*NEXT_QBID++;
}
}

# Hash mapping blocks with static lexicals to an array of arrays. Each
# of the sub-arrays has the form [$name, $value, $flags], where flags
# are 0 = static lex, 1 = container, 2 = state container.
Expand All @@ -2852,7 +2867,6 @@ class QAST::CompilerJAST {
# If we are in compilation mode, or have pre-deserialization or
# post-deserialization tasks, handle those. Overall, the process
# is to desugar this into simpler QAST nodes, then compile those.
my $comp_mode := $cu.compilation_mode;
my @pre_des := $cu.pre_deserialize;
my @post_des := $cu.post_deserialize;
if %*BLOCK_LEX_VALUES {
Expand Down Expand Up @@ -3056,7 +3070,7 @@ class QAST::CompilerJAST {
# Create JAST method and register it with the block's compilation unit
# unique ID and name. (Note, always void return here as return values
# are handled out of band).
my $*JMETH := JAST::Method.new( :name(self.unique('qb_')), :returns('Void'), :static(1) );
my $*JMETH := JAST::Method.new( :name('qb_'~self.cuid_to_qbid($node.cuid)), :returns('Void'), :static(1) );
$*JMETH.cr_name($node.name);
$*JMETH.cr_cuid($node.cuid);
$*CODEREFS.register_method($*JMETH, $node.cuid);
Expand Down Expand Up @@ -3402,9 +3416,9 @@ class QAST::CompilerJAST {
$il.append($ALOAD_0);
$il.append($ALOAD_1);
$il.append($ALOAD_0);
$il.append(JAST::PushSVal.new( :value($node.cuid) ));
$il.append(JAST::PushIndex.new( :value(self.cuid_to_qbid($node.cuid)) ));
$il.append(JAST::Instruction.new( :op('invokevirtual'),
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, $TYPE_STR ));
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, 'I' ));
$il.append(JAST::Instruction.new( :op('getstatic'),
$TYPE_OPS, 'emptyCallSite', $TYPE_CSD ));
$il.append(JAST::Instruction.new( :op('getstatic'),
Expand Down Expand Up @@ -3869,9 +3883,9 @@ class QAST::CompilerJAST {
multi method as_jast(QAST::BVal $node, :$want) {
my $il := JAST::InstructionList.new();
$il.append($ALOAD_0);
$il.append(JAST::PushSVal.new( :value($node.value.cuid) ));
$il.append(JAST::PushIndex.new( :value(self.cuid_to_qbid($node.value.cuid)) ));
$il.append(JAST::Instruction.new( :op('invokevirtual'),
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, $TYPE_STR ));
$TYPE_CU, 'lookupCodeRef', $TYPE_CR, 'I' ));
result($il, $RT_OBJ)
}

Expand Down
41 changes: 36 additions & 5 deletions src/vm/jvm/runtime/org/perl6/nqp/runtime/CompilationUnit.java
Expand Up @@ -23,6 +23,11 @@ public abstract class CompilationUnit {
*/
private Map<String, CodeRef> cuidToCodeRef = new HashMap<String, CodeRef>();

/**
* Mapping of local integer IDs to matching code reference.
*/
private CodeRef[] qbidToCodeRef;

/**
* Array of all code references.
*/
Expand Down Expand Up @@ -83,12 +88,15 @@ public void initializeCompilationUnit(ThreadContext tc) {
Lookup l = MethodHandles.lookup();
boolean codeRefsFound = false;
try {
Method[] mlist = this.getClass().getDeclaredMethods();
qbidToCodeRef = new CodeRef[mlist.length];

for (Method m : this.getClass().getDeclaredMethods()) {
CodeRefAnnotation cra = m.getAnnotation(CodeRefAnnotation.class);
if (cra != null) {
/* Got a code ref annotation. Turn to method handle. */
MethodHandle mh = l.unreflect(m).bindTo(this);

/* Munge handlers. */
long[] flatHandlers = cra.handlers();
int hptr = 0;
Expand All @@ -103,15 +111,24 @@ public void initializeCompilationUnit(ThreadContext tc) {

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

if (name.startsWith("qb_")) {
int i = 3;
int imax = name.length();
int acc = 0;
while (i < imax) acc = acc * 10 + (int)name.charAt(i++) - (int)'0';
if (acc >= 0 && acc < qbidToCodeRef.length) qbidToCodeRef[acc] = cr;
}

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

Expand Down Expand Up @@ -185,17 +202,31 @@ public void runLoadIfAvailable(ThreadContext tc) {
/**
* Turns a compilation unit unique ID into the matching code-ref.
*/
public CodeRef lookupCodeRef(String uniqueId) {
public CodeRef lookupCodeRef(String uniqueId) { /*FOR_STAGE0*/
return cuidToCodeRef.get(uniqueId);
}

/**
* Turns a local integer ID into the matching code-ref.
*/
public CodeRef lookupCodeRef(int localId) {
return qbidToCodeRef[localId];
}

/**
* Parses a bunch of info on static lexical values for a block and
* installs each of them. TODO: lazify so we don't do it for blocks we
* never execute.
*/
public void setLexValues(ThreadContext tc, String uniqueId, String toParse) {
CodeRef cr = cuidToCodeRef.get(uniqueId);
public void setLexValues(ThreadContext tc, int localId, String toParse) {
setLexValues(tc, qbidToCodeRef[localId], toParse);
}

public void setLexValues(ThreadContext tc, String uniqueId, String toParse) { /*FOR_STAGE0*/
setLexValues(tc, cuidToCodeRef.get(uniqueId), toParse);
}

private void setLexValues(ThreadContext tc, CodeRef cr, String toParse) {
String[] bits = toParse.split("\\x00");
for (int i = 0; i < bits.length; i += 4) {
String lexName = bits[i];
Expand Down

0 comments on commit 2d3a93c

Please sign in to comment.