From dc2bab3f100b9c7903ea34cc323823f641885228 Mon Sep 17 00:00:00 2001 From: Erica Marigold Date: Tue, 21 Nov 2023 22:36:45 +0530 Subject: [PATCH] feat: initial unfinished rewrite for perf --- Cargo.lock | 54 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/cli/build.rs | 36 +++++++++++++++++-------- src/cli/mod.rs | 69 +++++++++++++++++++++++++++++++++++++----------- 4 files changed, 134 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de92911..90a3106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -468,6 +468,30 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-utils" version = "0.8.16" @@ -1127,6 +1151,7 @@ dependencies = [ "path-clean", "pin-project", "rand", + "rayon", "rbx_binary", "rbx_cookie", "rbx_dom_weak", @@ -1192,6 +1217,15 @@ version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -1547,6 +1581,26 @@ dependencies = [ "getrandom 0.2.10", ] +[[package]] +name = "rayon" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "rbx_binary" version = "0.7.3" diff --git a/Cargo.toml b/Cargo.toml index 6474e9d..8338685 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,6 +124,7 @@ regex = { optional = true, version = "1.7", default-features = false, features = "unicode-perl", ] } rustyline = { optional = true, version = "12.0" } +rayon = "1.8" ### ROBLOX diff --git a/src/cli/build.rs b/src/cli/build.rs index 398286a..724ca5c 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -13,26 +13,40 @@ pub async fn build_standalone + Into>( ) -> Result<()> { // First, we read the contents of the lune interpreter as our starting point let mut patched_bin = fs::read(env::current_exe()?).await?; + let base_bin_offset = u64::try_from(patched_bin.len() - 1)?; + + println!("base offset: {}", base_bin_offset); // The signature which separates indicates the presence of bytecode to execute // If a binary contains this signature, that must mean it is a standalone binar - let signature: Vec = vec![0x12, 0xed, 0x93, 0x14, 0x28]; + let signature: Vec = vec![0x4f, 0x3e, 0xf8, 0x41, 0xc3, 0x3a, 0x52, 0x16]; + + // Compile luau input into bytecode + let bytecode = LuaCompiler::new() + .set_optimization_level(2) + .set_coverage_level(0) + .set_debug_level(0) + .compile(code); + + println!("{}", bytecode.len()); + + patched_bin.append(&mut bytecode.clone()); + + let mut meta = base_bin_offset.to_ne_bytes().to_vec(); + + // bytecode base size files signature + // meta.append(&mut [0, 0, 0, 0].to_vec()); // 4 extra padding bytes after 4 byte u64 + meta.append(&mut (bytecode.len() as u64).to_ne_bytes().to_vec()); // FIXME: len is greater than u8::max + meta.append(&mut 1_u64.to_ne_bytes().to_vec()); // Number of files, padded with null bytes + // meta.append(&mut [0, 0, 0, 0].to_vec()); // 4 extra padding bytes after 4 byte u32 + + patched_bin.append(&mut meta); // Append the signature to the base binary for byte in signature { patched_bin.push(byte); } - // Compile luau input into bytecode - let mut bytecode = LuaCompiler::new() - .set_optimization_level(2) - .set_coverage_level(0) - .set_debug_level(0) - .compile(code); - - // Append compiled bytecode to binary and finalize - patched_bin.append(&mut bytecode); - // Write the compiled binary to file fs::write(output_path, patched_bin).await?; diff --git a/src/cli/mod.rs b/src/cli/mod.rs index e2c0345..a0946d6 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -151,27 +151,66 @@ impl Cli { } // Signature which is only present in standalone lune binaries - let signature: Vec = vec![0x12, 0xed, 0x93, 0x14, 0x28]; + let signature: Vec = vec![0x4f, 0x3e, 0xf8, 0x41, 0xc3, 0x3a, 0x52, 0x16]; // Read the current lune binary to memory let bin = read_to_vec(env::current_exe()?).await?; + // let mut bin = vec![0; tmp_bin.len() % signature.len()]; + + // println!("padding: {:?}", bin); + + // bin.append(&mut tmp_bin); + + let mut bytecode_offset = 0; + let mut bytecode_size = 0; + + // println!("{}",); + + for (idx, chunk) in bin.rchunks(signature.len()).enumerate() { + if idx == 0 && chunk != signature { + // We don't have a standalone binary + break; + } + + if idx == 3 { + bytecode_offset = u64::from_ne_bytes(chunk.try_into()?); + } + + if idx == 2 { + bytecode_size = u64::from_ne_bytes(chunk.try_into()?); + } + } + + if bytecode_offset != 0 && bytecode_size != 0 { + Lune::new() + .with_args(self.script_args.clone()) + .run( + "STANDALONE", + &bin[usize::try_from(bytecode_offset).unwrap() + ..usize::try_from(bytecode_offset + bytecode_size).unwrap()], + ) + .await?; + } + + return repl::show_interface().await; // Check to see if the lune executable includes the signature - return match bin - .windows(signature.len()) - .position(|block| block == signature) - { - // If we find the signature, all bytes after the 5 signature bytes must be bytecode - Some(offset) => Ok(Lune::new() - .with_args(self.script_args) - .run("STANDALONE", &bin[offset + signature.len()..bin.len()]) - .await?), + // return match bin + // .clone() + // .par_windows(signature.len()) + // // .rev() + // .position_any(|block| block == signature) + // { + // // If we find the signature, all bytes after the 5 signature bytes must be bytecode + // Some(offset) => { + // // let offset = bin.len() - 1 - back_offset; + // } - // If we did not generate any typedefs, know we're not a precompiled bin and - // we know that the user did not provide any other options, and in that - // case we should enter the REPL - None => repl::show_interface().await, - }; + // // If we did not generate any typedefs, know we're not a precompiled bin and + // // we know that the user did not provide any other options, and in that + // // case we should enter the REPL + // None => repl::show_interface().await, + // }; } // Figure out if we should read from stdin or from a file, // reading from stdin is marked by passing a single "-"