Skip to content

Commit cef89b9

Browse files
authored
Merge pull request #380 from MetricsHub/codex/add-new-opcode-and-optimize-tuple-handling
Optimize tuples for constant fields ($0, $1, etc.)
2 parents 1e3b2a4 + 2f5ec39 commit cef89b9

File tree

5 files changed

+186
-97
lines changed

5 files changed

+186
-97
lines changed

src/main/java/org/metricshub/jawk/backend/AVM.java

Lines changed: 26 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.io.IOException;
2626
import java.io.PrintStream;
2727
import java.io.StringReader;
28-
import java.math.BigDecimal;
2928
import java.util.ArrayList;
3029
import java.util.Collections;
3130
import java.util.Enumeration;
@@ -283,32 +282,7 @@ public Object eval(AwkTuples tuples, String input) throws IOException {
283282
return operandStack.size() == 0 ? null : pop();
284283
}
285284

286-
private static int parseIntField(Object obj, PositionTracker position) {
287-
if (obj instanceof Number) {
288-
double num = ((Number) obj).doubleValue();
289-
if (num < 0) {
290-
throw new AwkRuntimeException(position.lineNumber(), "Field $(" + obj.toString() + ") is incorrect.");
291-
}
292-
return (int) num;
293-
}
294-
295-
String str = obj.toString();
296-
if (str.isEmpty()) {
297-
return 0;
298-
}
299-
300-
try {
301-
double num = new BigDecimal(str).doubleValue();
302-
if (num < 0) {
303-
throw new AwkRuntimeException(position.lineNumber(), "Field $(" + obj.toString() + ") is incorrect.");
304-
}
305-
return (int) num;
306-
} catch (NumberFormatException nfe) {
307-
return 0;
308-
}
309-
}
310-
311-
private void setNumOnJRT(int fieldNum, double num) {
285+
private void setNumOnJRT(long fieldNum, double num, PositionTracker position) {
312286
String numString;
313287
if (JRT.isActuallyLong(num)) {
314288
numString = Long.toString((long) Math.rint(num));
@@ -321,7 +295,7 @@ private void setNumOnJRT(int fieldNum, double num) {
321295
jrt.setInputLine(numString.toString());
322296
jrt.jrtParseFields();
323297
} else {
324-
jrt.jrtSetInputField(numString, fieldNum);
298+
jrt.jrtSetInputField(numString, fieldNum, position);
325299
}
326300
}
327301

@@ -692,23 +666,14 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
692666
// stack[0] = field number
693667
// stack[1] = value
694668
Object fieldNumObj = pop();
695-
int fieldNum;
696-
if (fieldNumObj instanceof Number) {
697-
fieldNum = ((Number) fieldNumObj).intValue();
698-
} else {
699-
try {
700-
fieldNum = Integer.parseInt(fieldNumObj.toString());
701-
} catch (NumberFormatException nfe) {
702-
fieldNum = 0;
703-
}
704-
}
669+
long fieldNum = JRT.parseFieldNumber(fieldNumObj, position);
705670
String value = pop().toString();
706671
push(value); // leave the result on the stack
707672
if (fieldNum == 0) {
708673
jrt.setInputLine(value);
709674
jrt.jrtParseFields();
710675
} else {
711-
jrt.jrtSetInputField(value, fieldNum);
676+
jrt.jrtSetInputField(value, fieldNum, position);
712677
}
713678
position.next();
714679
break;
@@ -773,12 +738,12 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
773738
// stack[0] = dollar_fieldNumber
774739
// stack[1] = inc value
775740

776-
// same code as GET_INPUT_FIELD:
777-
int fieldnum = parseIntField(pop(), position);
741+
// same code as GET_INPUT_FIELD:
742+
long fieldnum = JRT.parseFieldNumber(pop(), position);
778743
double incval = JRT.toDouble(pop());
779744

780-
// except here, get the number, and add the incvalue
781-
Object numObj = jrt.jrtGetInputField(fieldnum);
745+
// except here, get the number, and add the incvalue
746+
Object numObj = jrt.jrtGetInputField(fieldnum, position);
782747
double num;
783748
switch (opcode) {
784749
case PLUS_EQ_INPUT_FIELD:
@@ -802,7 +767,7 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
802767
default:
803768
throw new Error("Invalid opcode here: " + opcode);
804769
}
805-
setNumOnJRT(fieldnum, num);
770+
setNumOnJRT(fieldnum, num, position);
806771

807772
// put the result value on the stack
808773
push(num);
@@ -888,12 +853,12 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
888853
}
889854
case INC_DOLLAR_REF: {
890855
// stack[0] = dollar index (field number)
891-
int fieldnum = parseIntField(pop(), position);
856+
long fieldnum = JRT.parseFieldNumber(pop(), position);
892857

893-
Object numObj = jrt.jrtGetInputField(fieldnum);
858+
Object numObj = jrt.jrtGetInputField(fieldnum, position);
894859
double original = JRT.toDouble(numObj);
895860
double num = original + 1;
896-
setNumOnJRT(fieldnum, num);
861+
setNumOnJRT(fieldnum, num, position);
897862

898863
if (JRT.isActuallyLong(original)) {
899864
push((long) Math.rint(original));
@@ -907,12 +872,12 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
907872
case DEC_DOLLAR_REF: {
908873
// stack[0] = dollar index (field number)
909874
// same code as GET_INPUT_FIELD:
910-
int fieldnum = parseIntField(pop(), position);
875+
long fieldnum = JRT.parseFieldNumber(pop(), position);
911876

912-
Object numObj = jrt.jrtGetInputField(fieldnum);
877+
Object numObj = jrt.jrtGetInputField(fieldnum, position);
913878
double original = JRT.toDouble(numObj);
914879
double num = original - 1;
915-
setNumOnJRT(fieldnum, num);
880+
setNumOnJRT(fieldnum, num, position);
916881

917882
if (JRT.isActuallyLong(original)) {
918883
push((long) Math.rint(original));
@@ -1110,7 +1075,7 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
11101075
// stack[3] = ere
11111076
boolean isGsub = position.boolArg(0);
11121077
String convfmt = getCONVFMT().toString();
1113-
int fieldNum = (int) JRT.toDouble(pop());
1078+
long fieldNum = JRT.parseFieldNumber(pop(), position);
11141079
String orig = JRT.toAwkString(pop(), convfmt, locale);
11151080
String repl = JRT.toAwkString(pop(), convfmt, locale);
11161081
String ere = JRT.toAwkString(pop(), convfmt, locale);
@@ -1125,7 +1090,7 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
11251090
jrt.setInputLine(newstring);
11261091
jrt.jrtParseFields();
11271092
} else {
1128-
jrt.jrtSetInputField(newstring, fieldNum);
1093+
jrt.jrtSetInputField(newstring, fieldNum, position);
11291094
}
11301095
position.next();
11311096
break;
@@ -1679,9 +1644,15 @@ public void interpret(AwkTuples tuples) throws ExitException, IOException {
16791644
break;
16801645
}
16811646
case GET_INPUT_FIELD: {
1682-
// stack[0] = field number
1683-
int fieldnum = parseIntField(pop(), position);
1684-
push(jrt.jrtGetInputField(fieldnum));
1647+
// stack[0] = field number
1648+
Object fieldNumber = pop();
1649+
push(jrt.jrtGetInputField(fieldNumber, position));
1650+
position.next();
1651+
break;
1652+
}
1653+
case GET_INPUT_FIELD_CONST: {
1654+
long fieldnum = position.intArg(0);
1655+
push(jrt.jrtGetInputField(fieldnum, position));
16851656
position.next();
16861657
break;
16871658
}

src/main/java/org/metricshub/jawk/intermediate/AwkTuples.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,17 @@ public void getInputField() {
10561056
queue.add(new Tuple(Opcode.GET_INPUT_FIELD));
10571057
}
10581058

1059+
/**
1060+
* <p>
1061+
* getInputField.
1062+
* </p>
1063+
*
1064+
* @param fieldIndex a long
1065+
*/
1066+
public void getInputField(long fieldIndex) {
1067+
queue.add(new Tuple(Opcode.GET_INPUT_FIELD_CONST, fieldIndex));
1068+
}
1069+
10591070
/**
10601071
* <p>
10611072
* consumeInput.
@@ -1586,6 +1597,24 @@ private boolean peepholeOptimizePass() {
15861597
Tuple tuple = original.get(oldIndex);
15871598
Object literal = literalValue(tuple);
15881599
if (literal != null && !hasResolvedAddress(oldIndex)) {
1600+
if ((oldIndex + 1) < originalSize) {
1601+
Tuple nextTuple = original.get(oldIndex + 1);
1602+
if (nextTuple.getOpcode() == Opcode.GET_INPUT_FIELD
1603+
&& !hasResolvedAddress(oldIndex + 1)) {
1604+
PositionTracker position = new PositionTracker(original);
1605+
position.jump(oldIndex + 1);
1606+
long fieldIndex = JRT.parseFieldNumber(literal, position);
1607+
Tuple replacement = createGetInputFieldConst(
1608+
fieldIndex,
1609+
tuple.getLineno());
1610+
optimizedQueue.add(replacement);
1611+
indexMapping[oldIndex] = newIndex;
1612+
oldIndex += 2;
1613+
newIndex++;
1614+
modified = true;
1615+
continue;
1616+
}
1617+
}
15891618
if ((oldIndex + 2) < originalSize) {
15901619
Tuple nextTuple = original.get(oldIndex + 1);
15911620
Tuple opTuple = original.get(oldIndex + 2);
@@ -1787,6 +1816,12 @@ private Tuple createLiteralPush(Object value, int lineNumber) {
17871816
return tuple;
17881817
}
17891818

1819+
private Tuple createGetInputFieldConst(long fieldIndex, int lineNumber) {
1820+
Tuple tuple = new Tuple(Opcode.GET_INPUT_FIELD_CONST, fieldIndex);
1821+
tuple.setLineNumber(lineNumber);
1822+
return tuple;
1823+
}
1824+
17901825
private boolean hasResolvedAddress(int index) {
17911826
return addressManager.getAddress(index) != null;
17921827
}

src/main/java/org/metricshub/jawk/intermediate/Opcode.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,6 +859,15 @@ public enum Opcode {
859859
* Stack after: x ...
860860
*/
861861
GET_INPUT_FIELD,
862+
/**
863+
* Pushes an input field onto the stack using an embedded field index.
864+
* <p>
865+
* Argument: field-id
866+
* <p>
867+
* Stack before: ...<br/>
868+
* Stack after: x ...
869+
*/
870+
GET_INPUT_FIELD_CONST,
862871
/**
863872
* Consume next line of input; assigning $0 and recalculating $1, $2, etc.
864873
* The input can come from the following sources:

0 commit comments

Comments
 (0)