Skip to content

Commit e5223e6

Browse files
committed
Promote SELECT to fast opcode (89) - used in every print statement
SELECT was previously SLOWOP_SELECT (20) but is actually hot path code called once for every print/say statement to get the default filehandle. Performance impact: - Eliminates SLOW_OP dispatch overhead - Reduces bytecode size by 1 byte per print statement - Improves CPU i-cache utilization Dense opcodes now: 0-89 (no gaps, maintains tableswitch optimization)
1 parent 0f20246 commit e5223e6

File tree

4 files changed

+30
-8
lines changed

4 files changed

+30
-8
lines changed

src/main/java/org/perlonjava/interpreter/BytecodeCompiler.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -816,8 +816,9 @@ public void visit(OperatorNode node) {
816816
}
817817
} else if (op.equals("select")) {
818818
// select FILEHANDLE or select()
819-
// Call IOOperator.select() which handles the logic
820-
// For now, emit a SLOW_OP that will call the operator at runtime
819+
// SELECT is a fast opcode (used in every print statement)
820+
// Format: [SELECT] [rd] [rs_list]
821+
// Effect: rd = IOOperator.select(registers[rs_list], SCALAR)
821822

822823
int rd = allocateRegister();
823824

@@ -827,9 +828,8 @@ public void visit(OperatorNode node) {
827828
node.operand.accept(this);
828829
int listReg = lastResultReg;
829830

830-
// Emit SLOW_OP with SLOWOP_SELECT
831-
emitWithToken(Opcodes.SLOW_OP, node.getIndex());
832-
emit(Opcodes.SLOWOP_SELECT);
831+
// Emit SELECT opcode
832+
emitWithToken(Opcodes.SELECT, node.getIndex());
833833
emit(rd);
834834
emit(listReg);
835835
} else {
@@ -840,9 +840,8 @@ public void visit(OperatorNode node) {
840840
emit(listReg);
841841
emit(0); // count = 0
842842

843-
// Emit SLOW_OP with SLOWOP_SELECT
844-
emitWithToken(Opcodes.SLOW_OP, node.getIndex());
845-
emit(Opcodes.SLOWOP_SELECT);
843+
// Emit SELECT opcode
844+
emitWithToken(Opcodes.SELECT, node.getIndex());
846845
emit(rd);
847846
emit(listReg);
848847
}

src/main/java/org/perlonjava/interpreter/BytecodeInterpreter.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,17 @@ public static RuntimeList execute(InterpretedCode code, RuntimeArray args, int c
849849
break;
850850
}
851851

852+
case Opcodes.SELECT: {
853+
// Select default output filehandle: rd = IOOperator.select(list, SCALAR)
854+
int rd = bytecode[pc++] & 0xFF;
855+
int listReg = bytecode[pc++] & 0xFF;
856+
857+
RuntimeList list = (RuntimeList) registers[listReg];
858+
RuntimeScalar result = org.perlonjava.operators.IOOperator.select(list, RuntimeContextType.SCALAR);
859+
registers[rd] = result;
860+
break;
861+
}
862+
852863
// =================================================================
853864
// SLOW OPERATIONS
854865
// =================================================================

src/main/java/org/perlonjava/interpreter/InterpretedCode.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,11 @@ public String disassemble() {
366366
sb.append("JOIN r").append(rd).append(" = join(r").append(separatorReg)
367367
.append(", r").append(listReg).append(")\n");
368368
break;
369+
case Opcodes.SELECT:
370+
rd = bytecode[pc++] & 0xFF;
371+
listReg = bytecode[pc++] & 0xFF;
372+
sb.append("SELECT r").append(rd).append(" = select(r").append(listReg).append(")\n");
373+
break;
369374
case Opcodes.SLOW_OP: {
370375
int slowOpId = bytecode[pc++] & 0xFF;
371376
String opName = SlowOpcodeHandler.getSlowOpName(slowOpId);

src/main/java/org/perlonjava/interpreter/Opcodes.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,13 @@ public class Opcodes {
376376
/** Join list elements with separator: rd = join(rs_separator, rs_list) */
377377
public static final byte JOIN = 88;
378378

379+
// =================================================================
380+
// I/O OPERATIONS (89)
381+
// =================================================================
382+
383+
/** Select default output filehandle: rd = IOOperator.select(rs_list, SCALAR) */
384+
public static final byte SELECT = 89;
385+
379386
// =================================================================
380387
// SLOW OPERATIONS (87) - Single opcode for rarely-used operations
381388
// =================================================================

0 commit comments

Comments
 (0)