Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 44 additions & 13 deletions scripts/check_java_inline_budget.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,19 +43,50 @@ def die(msg: str):
sys.exit(1)


def disassemble(classes: str) -> str:
"""One javap call for both frames -- two would be two JVM startups."""
def disassemble(classes: str) -> dict:
"""One javap call for both frames -- two would be two JVM startups.

Returned per class, NOT as one blob: the two signatures are distinct today
only by luck, and a search over the concatenation would happily answer for
the wrong class. javap also exits 0 when only SOME of the named classes
resolve, reporting the rest on stderr, so its status says nothing and the
stderr has to be read.
"""
names = ["io.github.talib." + c for c, _ in FRAMES]
try:
return subprocess.run(["javap", "-p", "-c", "-cp", classes] + names,
capture_output=True, text=True, check=True).stdout
except (subprocess.CalledProcessError, FileNotFoundError) as e:
die("javap could not read %s from %s: %s" % (", ".join(names), classes, e))


def code_length(out: str, cls: str, sig: re.Pattern) -> int:
lines = out.splitlines()
start = next((i for i, l in enumerate(lines) if sig.match(l)), None)
p = subprocess.run(["javap", "-p", "-c", "-cp", classes] + names,
capture_output=True, text=True)
except FileNotFoundError as e:
die("javap is not on PATH: %s" % e)
if p.returncode != 0:
die("javap failed on %s: %s" % (classes, p.stderr.strip() or p.stdout.strip()))
if p.stderr.strip():
die("javap could not read every class from %s -- it exits 0 for this, so "
"the gate must reject it explicitly: %s" % (classes, p.stderr.strip()))

# Split on the class header javap emits once per class.
sections, cur = {}, None
for line in p.stdout.splitlines():
m = re.match(r"(?:public |final |abstract )*class io\.github\.talib\.(\S+) ", line)
if m:
cur = m.group(1).rstrip("{").strip()
sections[cur] = []
elif cur is not None:
sections[cur].append(line)
for cls, _ in FRAMES:
if cls not in sections:
die("javap printed no section for io.github.talib.%s -- it was asked "
"for it and did not refuse, so the disassembly parse moved." % cls)
return sections


def code_length(sections: dict, cls: str, sig: re.Pattern) -> int:
lines = sections[cls]
matches = [i for i, l in enumerate(lines) if sig.match(l)]
if len(matches) > 1:
die("%s: %d methods match %s -- the gate cannot tell which frame it is "
"measuring." % (cls, len(matches), sig.pattern))
start = matches[0] if matches else None
if start is None:
die("%s: no method matching %s -- the signature moved, so this gate "
"measured NOTHING. Fix the pattern in this script rather than "
Expand All @@ -82,10 +113,10 @@ def main():
die("usage: check_java_inline_budget.py <classes-dir>")
classes = sys.argv[1]

out = disassemble(classes)
sections = disassemble(classes)
over = []
for cls, sig in FRAMES:
n = code_length(out, cls, sig)
n = code_length(sections, cls, sig)
name = "%s.%s" % (cls, "peek" if "peek" in sig.pattern else "maStepImpl")
print("%-24s %3d bytes (budget %d, %+d)" % (name, n, BUDGET, n - BUDGET))
if n > BUDGET:
Expand Down
11 changes: 7 additions & 4 deletions ta_codegen/generator/src/backends/java_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3107,14 +3107,17 @@ fn emit_dispatch(
}
}
}
// `return`, not `break`: the switch is the whole method body, so this
// costs a byte where the jump to the end cost three, and the step frame
// is 4 bytes over the same 325-byte budget the peek frame is kept under.
// Every arm returns, including `default` below, which is what makes
// javac reject anything emitted after this switch. Nothing may go
// there: the arms are the only writers of `sp.cur_*` and a tail would
// be dead on every real MAType, reached only by the unreachable
// default. Keep the two in step -- a `break` default silently restores
// the trap, at no saving.
let _ = writeln!(o, " return;");
let _ = writeln!(o, " }}");
}
let _ = writeln!(o, " default:");
let _ = writeln!(o, " break; /* unreachable: open rejects arms without a sub-stream */");
let _ = writeln!(o, " return; /* unreachable: open rejects arms without a sub-stream */");
let _ = writeln!(o, " }}");
let _ = writeln!(o, " }}");

Expand Down
2 changes: 1 addition & 1 deletion ta_codegen/output/java/fragments/Core_MA.java
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,7 @@ void maStepImpl( MaStream sp, double inReal )
return;
}
default:
break; /* unreachable: open rejects arms without a sub-stream */
return; /* unreachable: open rejects arms without a sub-stream */
}
}
private RetCode maOpenImpl( MaStream sp, double inReal[], int startIdx, int optInTimePeriod, MAType optInMAType )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
public final class BuildStamp {
/** Digest of the generated {@code Core} method text this build carries. */
public static final String GENCODE_DIGEST = "5582353372fbe611";
public static final String GENCODE_DIGEST = "854b585951e2c854";

private BuildStamp() {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113838,7 +113838,7 @@ void maStepImpl( MaStream sp, double inReal )
return;
}
default:
break; /* unreachable: open rejects arms without a sub-stream */
return; /* unreachable: open rejects arms without a sub-stream */
}
}
private RetCode maOpenImpl( MaStream sp, double inReal[], int startIdx, int optInTimePeriod, MAType optInMAType )
Expand Down
4 changes: 2 additions & 2 deletions ta_codegen/output/java/tools/TaCodegenServe.java
Original file line number Diff line number Diff line change
Expand Up @@ -113509,7 +113509,7 @@ void maStepImpl( MaStream sp, double inReal )
return;
}
default:
break; /* unreachable: open rejects arms without a sub-stream */
return; /* unreachable: open rejects arms without a sub-stream */
}
}
private RetCode maOpenImpl( MaStream sp, double inReal[], int startIdx, int optInTimePeriod, MAType optInMAType )
Expand Down Expand Up @@ -182174,7 +182174,7 @@ public ZlemaStream zlemaOpenAndFill( double inReal[], int optInTimePeriod, doubl

public class TaCodegenServe {
static Core core = new Core();
static final String SPLICED_GENCODE_DIGEST = "5582353372fbe611";
static final String SPLICED_GENCODE_DIGEST = "854b585951e2c854";
static final int MAX_ARRAY_SIZE = 200000;
static double[] refOpen = new double[MAX_ARRAY_SIZE];
static double[] refHigh = new double[MAX_ARRAY_SIZE];
Expand Down