Skip to content

Commit 7789c36

Browse files
committed
fix: windows free
1 parent 542c51c commit 7789c36

File tree

5 files changed

+91
-35
lines changed

5 files changed

+91
-35
lines changed

build.gradle.kts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,14 @@ signing {
147147
}
148148

149149
task<JExtractTask>("jextractLuacode") {
150-
header = file("native/luau/Compiler/include/luacode.h")
150+
// Note: we use the header from the build directory here because we need to catch "luau_ext_free" which is added
151+
// by native/build.gradle.kts
152+
header = file("native/build/root/luau/Compiler/include/luacode.h")
151153
targetPackage = "net.hollowcube.luau.internal.compiler"
152154
extraArgs = listOf(
153155
"--define-macro", "LUA_API=\"extern \\\"C\\\"\"",
154156
"--include-function", "luau_compile",
157+
"--include-function", "luau_ext_free",
155158
"--include-struct", "lua_CompileOptions",
156159
)
157160
}

native/build.gradle.kts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,35 @@ task<Copy>("copyForModification") {
2222
into(buildProjectDir)
2323
}
2424

25+
fun edit(file: File, edit: (String) -> String) {
26+
val originalText = file.readText()
27+
val modifiedText = edit(originalText)
28+
if (originalText != modifiedText) {
29+
file.writeText(modifiedText)
30+
}
31+
}
32+
2533
task("luauStaticToShared") {
2634
description = "Make Luau.Compiler and Luau.VM compile as shared libraries"
2735
dependsOn("copyForModification")
2836

29-
val targetFile = buildProjectDir.resolve("luau/CMakeLists.txt")
30-
inputs.file(targetFile)
31-
outputs.file(targetFile)
37+
val cmakeLists = buildProjectDir.resolve("luau/CMakeLists.txt")
38+
val luacodeHeader = buildProjectDir.resolve("luau/Compiler/include/luacode.h")
39+
val luacodeSource = buildProjectDir.resolve("luau/Compiler/src/lcode.cpp")
40+
inputs.files(cmakeLists, luacodeHeader, luacodeSource)
41+
outputs.files(cmakeLists, luacodeHeader, luacodeSource)
3242

3343
doLast {
34-
val originalText = targetFile.readText()
35-
val modifiedText = originalText
36-
.replace("add_library(Luau.Compiler STATIC)", "add_library(Luau.Compiler SHARED)")
37-
.replace("add_library(Luau.VM STATIC)", "add_library(Luau.VM SHARED)")
38-
39-
if (originalText != modifiedText) {
40-
targetFile.writeText(modifiedText)
44+
edit(cmakeLists) {
45+
return@edit it
46+
.replace("add_library(Luau.Compiler STATIC)", "add_library(Luau.Compiler SHARED)")
47+
.replace("add_library(Luau.VM STATIC)", "add_library(Luau.VM SHARED)")
48+
}
49+
edit(luacodeHeader) {
50+
return@edit "$it\n\nLUACODE_API void luau_ext_free(char *bytecode);"
51+
}
52+
edit(luacodeSource) {
53+
return@edit "$it\n\nvoid luau_ext_free(char *bytecode) {\n free(bytecode);\n}"
4154
}
4255
}
4356
}

src/generated/java/net/hollowcube/luau/internal/compiler/luacode_h.java

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,5 +129,62 @@ public static MemorySegment luau_compile(MemorySegment source, long size, Memory
129129
throw new AssertionError("should not reach here", ex$);
130130
}
131131
}
132+
133+
private static class luau_ext_free {
134+
public static final FunctionDescriptor DESC = FunctionDescriptor.ofVoid(
135+
luacode_h.C_POINTER
136+
);
137+
138+
public static final MemorySegment ADDR = luacode_h.findOrThrow("luau_ext_free");
139+
140+
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
141+
}
142+
143+
/**
144+
* Function descriptor for:
145+
* {@snippet lang=c :
146+
* extern void luau_ext_free(char *bytecode)
147+
* }
148+
*/
149+
public static FunctionDescriptor luau_ext_free$descriptor() {
150+
return luau_ext_free.DESC;
151+
}
152+
153+
/**
154+
* Downcall method handle for:
155+
* {@snippet lang=c :
156+
* extern void luau_ext_free(char *bytecode)
157+
* }
158+
*/
159+
public static MethodHandle luau_ext_free$handle() {
160+
return luau_ext_free.HANDLE;
161+
}
162+
163+
/**
164+
* Address for:
165+
* {@snippet lang=c :
166+
* extern void luau_ext_free(char *bytecode)
167+
* }
168+
*/
169+
public static MemorySegment luau_ext_free$address() {
170+
return luau_ext_free.ADDR;
171+
}
172+
173+
/**
174+
* {@snippet lang=c :
175+
* extern void luau_ext_free(char *bytecode)
176+
* }
177+
*/
178+
public static void luau_ext_free(MemorySegment bytecode) {
179+
var mh$ = luau_ext_free.HANDLE;
180+
try {
181+
if (TRACE_DOWNCALLS) {
182+
traceDowncall("luau_ext_free", bytecode);
183+
}
184+
mh$.invokeExact(bytecode);
185+
} catch (Throwable ex$) {
186+
throw new AssertionError("should not reach here", ex$);
187+
}
188+
}
132189
}
133190

src/main/java/net/hollowcube/luau/LuaStateImpl.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ public Object toLightUserDataTagged(int index) {
382382
@Override
383383
public Object toUserData(int index) {
384384
final MemorySegment ud = lua_touserdata(L, index);
385+
//todo NULL can be returned. //todo this call is not valid against userDataInt ud values. We need to include some metadata in
385386
return GlobalRef.get(ud.get(ValueLayout.JAVA_LONG, 0));
386387
}
387388

src/main/java/net/hollowcube/luau/compiler/LuauCompilerImpl.java

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
import org.jetbrains.annotations.NotNull;
77
import org.jetbrains.annotations.Nullable;
88

9-
import java.lang.foreign.*;
10-
import java.lang.invoke.MethodHandle;
9+
import java.lang.foreign.Arena;
10+
import java.lang.foreign.MemorySegment;
11+
import java.lang.foreign.ValueLayout;
1112
import java.nio.charset.StandardCharsets;
1213
import java.util.List;
1314

15+
import static net.hollowcube.luau.internal.compiler.luacode_h.luau_ext_free;
16+
1417
@SuppressWarnings("preview")
1518
record LuauCompilerImpl(
1619
@NotNull OptimizationLevel optimizationLevel,
@@ -27,19 +30,6 @@ record LuauCompilerImpl(
2730
NativeLibraryLoader.loadLibrary("compiler");
2831
}
2932

30-
private static final MethodHandle FREE_HANDLE;
31-
32-
static {
33-
// This is basically just a manually inlined version of what jextract would generate for `free`.
34-
35-
final SymbolLookup symbolLookup = SymbolLookup.loaderLookup().or(Linker.nativeLinker().defaultLookup());
36-
final MemorySegment freeAddr = symbolLookup.find("free")
37-
.orElseThrow(() -> new UnsatisfiedLinkError("unresolved symbol: free"));
38-
final FunctionDescriptor freeDesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS);
39-
40-
FREE_HANDLE = Linker.nativeLinker().downcallHandle(freeAddr, freeDesc);
41-
}
42-
4333
@Override
4434
public byte[] compile(byte @NotNull [] source) throws LuauCompileException {
4535
try (Arena arena = Arena.ofConfined()) {
@@ -50,7 +40,7 @@ public byte[] compile(byte @NotNull [] source) throws LuauCompileException {
5040
final MemorySegment result = luacode_h.luau_compile(sourceStr, source.length, compileOpts, bytecodeSize);
5141
final long length = bytecodeSize.get(ValueLayout.JAVA_LONG, 0);
5242
final byte[] bytecode = result.asSlice(0, length).toArray(ValueLayout.JAVA_BYTE);
53-
free(result);
43+
luau_ext_free(result);
5444

5545
// Bytecode now contains either an error or valid luau bytecode.
5646
// A zero in the first byte indicates that the rest is an error.
@@ -93,14 +83,6 @@ public byte[] compile(byte @NotNull [] source) throws LuauCompileException {
9383
return opts;
9484
}
9585

96-
private void free(@NotNull MemorySegment segment) {
97-
try {
98-
FREE_HANDLE.invokeExact(segment);
99-
} catch (Throwable ex) {
100-
throw new AssertionError("should not reach here", ex);
101-
}
102-
}
103-
10486
static final class BuilderImpl implements Builder {
10587
private OptimizationLevel optimizationLevel = OptimizationLevel.BASELINE;
10688
private DebugLevel debugLevel = DebugLevel.BACKTRACE;

0 commit comments

Comments
 (0)