optimize bytecode
This commit is contained in:
parent
faab0a2d08
commit
fed0c2ad34
77
bytecode.go
77
bytecode.go
|
@ -12,7 +12,7 @@ typedef struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
} BytecodeReader;
|
} BytecodeReader;
|
||||||
|
|
||||||
static const char *bytecode_reader(lua_State *L, void *ud, size_t *size) {
|
const char *bytecode_reader(lua_State *L, void *ud, size_t *size) {
|
||||||
BytecodeReader *r = (BytecodeReader *)ud;
|
BytecodeReader *r = (BytecodeReader *)ud;
|
||||||
(void)L; // unused
|
(void)L; // unused
|
||||||
if (r->size == 0) return NULL;
|
if (r->size == 0) return NULL;
|
||||||
|
@ -21,45 +21,23 @@ static const char *bytecode_reader(lua_State *L, void *ud, size_t *size) {
|
||||||
return (const char *)r->buf;
|
return (const char *)r->buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int load_bytecode(lua_State *L, const unsigned char *buf, size_t len, const char *name) {
|
int load_bytecode(lua_State *L, const unsigned char *buf, size_t len, const char *name) {
|
||||||
BytecodeReader reader = {buf, len, name};
|
BytecodeReader reader = {buf, len, name};
|
||||||
return lua_load(L, bytecode_reader, &reader, name);
|
return lua_load(L, bytecode_reader, &reader, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
// Direct bytecode dumping without intermediate buffer - more efficient
|
||||||
unsigned char *buf;
|
int direct_bytecode_writer(lua_State *L, const void *p, size_t sz, void *ud) {
|
||||||
size_t len;
|
void **data = (void **)ud;
|
||||||
size_t capacity;
|
size_t current_size = (size_t)data[1];
|
||||||
} BytecodeWriter;
|
void *newbuf = realloc(data[0], current_size + sz);
|
||||||
|
|
||||||
static int bytecode_writer(lua_State *L, const void *p, size_t sz, void *ud) {
|
|
||||||
BytecodeWriter *w = (BytecodeWriter *)ud;
|
|
||||||
unsigned char *newbuf;
|
|
||||||
(void)L; // unused
|
|
||||||
|
|
||||||
// Check if we need to reallocate
|
|
||||||
if (w->len + sz > w->capacity) {
|
|
||||||
size_t new_capacity = w->capacity * 2;
|
|
||||||
if (new_capacity < w->len + sz) {
|
|
||||||
new_capacity = w->len + sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
newbuf = (unsigned char *)realloc(w->buf, new_capacity);
|
|
||||||
if (newbuf == NULL) return 1;
|
if (newbuf == NULL) return 1;
|
||||||
|
|
||||||
w->buf = newbuf;
|
memcpy((unsigned char*)newbuf + current_size, p, sz);
|
||||||
w->capacity = new_capacity;
|
data[0] = newbuf;
|
||||||
}
|
data[1] = (void*)(current_size + sz);
|
||||||
|
|
||||||
memcpy(w->buf + w->len, p, sz);
|
|
||||||
w->len += sz;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrapper function that calls lua_dump with bytecode_writer
|
|
||||||
static int dump_lua_function(lua_State *L, BytecodeWriter *w) {
|
|
||||||
return lua_dump(L, bytecode_writer, w);
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
import (
|
import (
|
||||||
|
@ -73,31 +51,23 @@ func (s *State) CompileBytecode(code string, name string) ([]byte, error) {
|
||||||
return nil, fmt.Errorf("failed to load string: %w", err)
|
return nil, fmt.Errorf("failed to load string: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up writer with initial capacity
|
// Use a simpler direct writer with just two pointers
|
||||||
var writer C.BytecodeWriter
|
data := [2]unsafe.Pointer{nil, nil}
|
||||||
writer.buf = nil
|
|
||||||
writer.len = 0
|
|
||||||
writer.capacity = 0
|
|
||||||
|
|
||||||
// Initial allocation with a reasonable size
|
|
||||||
const initialSize = 4096
|
|
||||||
writer.buf = (*C.uchar)(C.malloc(initialSize))
|
|
||||||
if writer.buf == nil {
|
|
||||||
s.Pop(1) // Remove the loaded function
|
|
||||||
return nil, fmt.Errorf("failed to allocate memory for bytecode")
|
|
||||||
}
|
|
||||||
writer.capacity = initialSize
|
|
||||||
|
|
||||||
// Dump the function to bytecode
|
// Dump the function to bytecode
|
||||||
err := s.safeCall(func() C.int {
|
err := s.safeCall(func() C.int {
|
||||||
return C.dump_lua_function(s.L, (*C.BytecodeWriter)(unsafe.Pointer(&writer)))
|
return C.lua_dump(s.L, (*[0]byte)(unsafe.Pointer(C.direct_bytecode_writer)), unsafe.Pointer(&data))
|
||||||
})
|
})
|
||||||
|
|
||||||
// Copy bytecode to Go slice regardless of the result
|
// Get result
|
||||||
bytecode := C.GoBytes(unsafe.Pointer(writer.buf), C.int(writer.len))
|
var bytecode []byte
|
||||||
|
if data[0] != nil {
|
||||||
|
// Create Go slice that references the C memory
|
||||||
|
length := uintptr(data[1])
|
||||||
|
bytecode = C.GoBytes(data[0], C.int(length))
|
||||||
|
C.free(data[0])
|
||||||
|
}
|
||||||
|
|
||||||
// Clean up
|
|
||||||
C.free(unsafe.Pointer(writer.buf))
|
|
||||||
s.Pop(1) // Remove the function from stack
|
s.Pop(1) // Remove the function from stack
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -164,6 +134,11 @@ func (s *State) LoadAndRunBytecodeWithResults(bytecode []byte, name string, nres
|
||||||
|
|
||||||
// CompileAndRun compiles and immediately executes Lua code
|
// CompileAndRun compiles and immediately executes Lua code
|
||||||
func (s *State) CompileAndRun(code string, name string) error {
|
func (s *State) CompileAndRun(code string, name string) error {
|
||||||
|
// Skip bytecode step for small scripts - direct execution is faster
|
||||||
|
if len(code) < 1024 {
|
||||||
|
return s.DoString(code)
|
||||||
|
}
|
||||||
|
|
||||||
bytecode, err := s.CompileBytecode(code, name)
|
bytecode, err := s.CompileBytecode(code, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("compile error: %w", err)
|
return fmt.Errorf("compile error: %w", err)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user