Skip to content
371 changes: 162 additions & 209 deletions src/main/java/org/perlonjava/backend/bytecode/BytecodeCompiler.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,12 @@ public static RuntimeList execute(InterpretedCode code, RuntimeArray args, int c
int rd = bytecode[pc++];
int nameIdx = bytecode[pc++];
String name = code.stringPool[nameIdx];
registers[rd] = GlobalVariable.getGlobalCodeRef(name);
if (name.equals("__SUB__")) {
// __SUB__ returns the current subroutine being executed
registers[rd] = RuntimeCode.selfReferenceMaybeNull(code.__SUB__);
} else {
registers[rd] = GlobalVariable.getGlobalCodeRef(name);
}
}

case Opcodes.STORE_GLOBAL_CODE -> {
Expand Down
206 changes: 84 additions & 122 deletions src/main/java/org/perlonjava/backend/bytecode/CompileAssignment.java

Large diffs are not rendered by default.

269 changes: 66 additions & 203 deletions src/main/java/org/perlonjava/backend/bytecode/CompileBinaryOperator.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class CompileBinaryOperatorHelper {
*/
public static int compileBinaryOperatorSwitch(BytecodeCompiler bytecodeCompiler, String operator, int rs1, int rs2, int tokenIndex) {
// Allocate result register
int rd = bytecodeCompiler.allocateRegister();
int rd = bytecodeCompiler.allocateOutputRegister();

// Emit opcode based on operator
switch (operator) {
Expand Down
742 changes: 372 additions & 370 deletions src/main/java/org/perlonjava/backend/bytecode/CompileOperator.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ public String disassemble() {
sb.append("Bytecode length: ").append(bytecode.length).append(" shorts\n\n");

int pc = 0;
try {
while (pc < bytecode.length) {
int startPc = pc;
int opcode = bytecode[pc++];
Expand Down Expand Up @@ -1961,8 +1962,11 @@ public String disassemble() {
rd = bytecode[pc++];
nameIdx = bytecode[pc++];
int rbhBeginId = bytecode[pc++];
String rbhName = (nameIdx >= 0 && nameIdx < stringPool.length)
? stringPool[nameIdx]
: "<invalid:" + nameIdx + ">";
sb.append("RETRIEVE_BEGIN_HASH r").append(rd).append(" = BEGIN_").append(rbhBeginId)
.append("::").append(stringPool[nameIdx]).append("\n");
.append("::").append(rbhName).append("\n");
break;
}

Expand Down Expand Up @@ -2298,12 +2302,26 @@ public String disassemble() {
sb.append("RESTORE_REGEX_STATE r").append(rrsDummy).append("\n");
break;
}
case Opcodes.SLOW_OP: {
// Deprecated: SLOW_OP was removed, all operations now use direct opcodes
// Format was: SLOW_OP slow_op_id rd argsReg ctx
int slowOpId = bytecode[pc++];
rd = bytecode[pc++];
int slowArgsReg = bytecode[pc++];
int slowCtx = bytecode[pc++];
sb.append("SLOW_OP(").append(slowOpId).append(") r").append(rd)
.append(" = slow(r").append(slowArgsReg).append(", ctx=").append(slowCtx).append(")\n");
break;
}

default:
sb.append("UNKNOWN(").append(opcode).append(")\n");
break;
}
}
} catch (ArrayIndexOutOfBoundsException e) {
sb.append("\n*** Disassembly error at pc=").append(pc).append(": ").append(e.getMessage()).append(" ***\n");
}
return sb.toString();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,10 @@ public static int executeCreateClosure(int[] bytecode, int pc, RuntimeBase[] reg
// Create a new InterpretedCode with the captured variables
InterpretedCode closureCode = template.withCapturedVars(capturedVars);

// Wrap in RuntimeScalar
registers[rd] = new RuntimeScalar(closureCode);
// Wrap in RuntimeScalar and set __SUB__ for self-reference
RuntimeScalar codeRef = new RuntimeScalar(closureCode);
closureCode.__SUB__ = codeRef;
registers[rd] = codeRef;
return pc;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,9 @@ public static ListNode handleNamedSubWithFilter(Parser parser, String subName, S
interpretedCode.subName = placeholder.subName;
interpretedCode.packageName = placeholder.packageName;

// Set the __SUB__ field for self-reference
interpretedCode.__SUB__ = codeRef;

// Update placeholder in-place: set methodHandle to delegate to InterpretedCode
placeholder.methodHandle = RuntimeCode.lookup.findVirtual(
InterpretedCode.class, "apply", RuntimeCode.methodType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ protected boolean removeEldestEntry(Map.Entry<Class<?>, MethodHandle> eldest) {
public RuntimeList constantValue;
// Field to hold the thread compiling this code
public Supplier<Void> compilerSupplier;
// Self-reference for __SUB__ (set after construction for InterpretedCode)
public RuntimeScalar __SUB__;

/**
* Constructs a RuntimeCode instance with the specified prototype and attributes.
Expand Down