Skip to content

Commit 67d0805

Browse files
committed
build fixes
1 parent e9c344e commit 67d0805

4 files changed

Lines changed: 43 additions & 12 deletions

File tree

de.peeeq.wurstscript/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def j25Launcher = toolchainSvc.launcherFor(java.toolchain)
3939

4040
tasks.withType(JavaExec).configureEach {
4141
javaLauncher.set(j25Launcher)
42+
jvmArgs('-XX:+UnlockExperimentalVMOptions', '-XX:+UseCompactObjectHeaders')
4243
}
4344

4445
tasks.withType(JavaCompile).configureEach { options.release = 25 }
@@ -244,6 +245,8 @@ test {
244245
'-Xmx2g', // local: give it room to finish and dump
245246
'-XX:MaxMetaspaceSize=256m',
246247
'-XX:+HeapDumpOnOutOfMemoryError',
248+
'-XX:+UnlockExperimentalVMOptions', // needed for UseCompactObjectHeaders until it graduates
249+
'-XX:+UseCompactObjectHeaders', // Java 24+: 8-byte headers (vs 16) — big win for AST-heavy workloads
247250
)
248251
}
249252

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/LuaNativeLowering.java

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@
1818
* <b>context-callback natives</b> ({@code ForForce}, {@code ForGroup}, …) –
1919
* replaced 1:1 by their {@code __wurst_} prefixed equivalents, whose Lua
2020
* implementations are provided by {@link de.peeeq.wurstscript.translation.lua.translation.LuaNatives}.</li>
21-
* <li><b>Non-native blizzard.j BJ functions with at least one handle-typed parameter</b>
22-
* – wrapped by a generated IM function that first checks each handle param for
21+
* <li><b>All other BJ calls with at least one handle-typed parameter</b> – wrapped
22+
* by a generated IM function that first checks each required handle param for
2323
* {@code null} and returns the type-appropriate default (0 / 0.0 / false / "" / nil),
2424
* then delegates to the original BJ function. This matches Jass behavior, which
2525
* silently returns defaults on null-handle calls instead of crashing.
26-
* Common.j natives are intentionally excluded: they either accept {@code nil} natively
27-
* (e.g. {@code TriggerRegisterPlayerUnitEvent} with a null filter) or are already
28-
* covered by categories 1 and 2 above.</li>
26+
* {@code boolexpr} and {@code code} typed params are intentionally skipped: these
27+
* are optional/nullable in Jass (e.g. the filter arg of
28+
* {@code TriggerRegisterPlayerUnitEvent}) and passing {@code nil} is valid.</li>
2929
* </ol>
3030
*
3131
* <p>IS_NATIVE stubs added for category 1 and 2 are recognised by
@@ -197,7 +197,7 @@ private ImFunction computeReplacement(ImFunction bj) {
197197
return createNativeStub("__wurst_" + name, bj);
198198
} else if (CONTEXT_CALLBACK_NATIVE_NAMES.contains(name)) {
199199
return createNativeStub("__wurst_" + name, bj);
200-
} else if (hasHandleParam(bj) && !bj.isNative()) {
200+
} else if (hasHandleParam(bj)) {
201201
return createNilSafeWrapper(bj);
202202
}
203203
return null;
@@ -247,10 +247,12 @@ private static ImFunction createNilSafeWrapper(ImFunction bjNative) {
247247

248248
ImStmts body = JassIm.ImStmts();
249249

250-
// Null-check each handle param: if param == null then return <default> end
250+
// Null-check each required handle param: if param == null then return <default> end
251+
// boolexpr and code params are intentionally skipped — they are optional/nullable
252+
// in Jass (e.g. the filter arg of TriggerRegisterPlayerUnitEvent).
251253
ImExpr returnDefault = defaultValueExpr(bjNative.getReturnType());
252254
for (ImVar param : paramVars) {
253-
if (isHandleType(param.getType())) {
255+
if (isHandleType(param.getType()) && !isNullableHandleType(param.getType())) {
254256
ImExpr condition = JassIm.ImOperatorCall(WurstOperator.EQ, JassIm.ImExprs(
255257
JassIm.ImVarAccess(param),
256258
JassIm.ImNull(param.getType().copy())
@@ -304,6 +306,22 @@ static boolean isHandleType(ImType type) {
304306
return !n.equals("integer") && !n.equals("real") && !n.equals("boolean") && !n.equals("string");
305307
}
306308

309+
/**
310+
* Returns true for handle types that are valid to pass as {@code null} in Jass without
311+
* triggering a null-handle crash. These params are skipped in nil-safety wrappers.
312+
*
313+
* <p>{@code boolexpr} and {@code code} are the canonical optional types: every WC3
314+
* API that takes them (filter, condition, action callbacks) accepts {@code null} to
315+
* mean "no callback".
316+
*/
317+
static boolean isNullableHandleType(ImType type) {
318+
if (!(type instanceof ImSimpleType)) {
319+
return false;
320+
}
321+
String n = ((ImSimpleType) type).getTypename();
322+
return n.equals("boolexpr") || n.equals("code");
323+
}
324+
307325
private static boolean shouldRewriteGetHandleId(ImFunctionCall call) {
308326
if (call.getArguments().size() != 1) {
309327
return true;
@@ -320,9 +338,14 @@ public static boolean usesLuaObjectIdentityHandleId(ImType type) {
320338
}
321339

322340
private static boolean isCompatGetHandleIdFunction(ImFunction f) {
323-
return f.getParameters().size() == 1
324-
&& f.getName().endsWith("_getHandleId")
325-
&& !f.getName().endsWith("_getTCHandleId");
341+
if (f.getParameters().size() != 1
342+
|| !f.getName().endsWith("_getHandleId")
343+
|| f.getName().endsWith("_getTCHandleId")) {
344+
return false;
345+
}
346+
// Restrict to WC3 simple handle types (ImSimpleType). User-defined Wurst classes
347+
// use ImClassType and must not have their call sites replaced.
348+
return isHandleType(f.getParameters().get(0).getType());
326349
}
327350

328351
/** Returns an IM expression representing the safe default for the given return type. */

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/lua/translation/LuaTranslator.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,11 @@ private boolean rewriteGetHandleIdCompatFunction(ImFunction f, LuaFunction lf) {
520520
return false;
521521
}
522522
ImVar firstParam = f.getParameters().get(0);
523+
// Restrict to WC3 simple handle types. User-defined Wurst classes use ImClassType
524+
// and must not have their function body replaced.
525+
if (!LuaNativeLowering.isHandleType(firstParam.getType())) {
526+
return false;
527+
}
523528
LuaExpr arg = LuaAst.LuaExprVarAccess(luaVar.getFor(firstParam));
524529
// Only called when ENABLE_SELECTIVE_GET_HANDLE_ID_SHIMMING is true.
525530
// Shim opaque runtime handles; keep native GetHandleId for enum-like handles.

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaTranslationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2475,7 +2475,7 @@ public void getHandleIdAssertionDoesNotFalsePositiveOnDeclarations() {
24752475

24762476
@Test
24772477
public void externNativesWithHandleParamsGetNilSafetyWrapper() throws IOException {
2478-
// BJ natives (IS_BJ) with handle-type parameters must be wrapped at the IM level
2478+
// IS_BJ functions with handle-type parameters must be wrapped at the IM level
24792479
// so that passing nil returns a safe default instead of crashing the Lua runtime.
24802480
// GetUnitTypeId is a common.j native (IS_BJ) with a handle param, returns integer.
24812481
// Result is used in print() so the optimizer does not dead-code-eliminate the call.

0 commit comments

Comments
 (0)