diff --git a/.vscode/launch.json b/.vscode/launch.json index c6e32082..cb31d72f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -11,6 +11,8 @@ "cargo": { "args": [ "run", + "--features", + "no-startup", "--bin=monoruby", "--package=monoruby", ], diff --git a/Cargo.lock b/Cargo.lock index b809b569..40f51604 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" @@ -189,15 +189,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.18" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" dependencies = [ "shlex", ] @@ -230,9 +230,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -240,9 +240,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.17" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -252,9 +252,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -474,42 +474,42 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", @@ -542,9 +542,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "globset" @@ -580,9 +580,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -644,9 +644,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -693,9 +693,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -726,9 +726,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -736,9 +736,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -769,9 +769,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libredox" @@ -840,7 +840,7 @@ dependencies = [ [[package]] name = "monoasm" version = "0.1.0" -source = "git+https://github.com/sisshiki1969/monoasm.git#315e5449c4194a39c4cdcdbfcff6870243027b47" +source = "git+https://github.com/sisshiki1969/monoasm.git#66698b278459c007f896d65b660c8d29a3bc93c5" dependencies = [ "chrono", "libc", @@ -853,7 +853,7 @@ dependencies = [ [[package]] name = "monoasm_macro" version = "0.1.0" -source = "git+https://github.com/sisshiki1969/monoasm.git#315e5449c4194a39c4cdcdbfcff6870243027b47" +source = "git+https://github.com/sisshiki1969/monoasm.git#66698b278459c007f896d65b660c8d29a3bc93c5" dependencies = [ "proc-macro2", "quote", @@ -1016,18 +1016,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.4" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl" @@ -1105,9 +1105,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "ppv-lite86" @@ -1120,9 +1120,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] @@ -1195,9 +1195,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -1207,9 +1207,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -1218,9 +1218,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "region" @@ -1347,9 +1347,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" +checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" dependencies = [ "windows-sys 0.59.0", ] @@ -1369,9 +1369,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -1475,9 +1475,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.77" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -1519,9 +1519,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -1532,18 +1532,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", @@ -1636,9 +1636,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-bidi" -version = "0.3.15" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" @@ -1648,24 +1648,24 @@ checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "url" diff --git a/doc/ABIs.md b/doc/stack_frame.md similarity index 62% rename from doc/ABIs.md rename to doc/stack_frame.md index 66f9c900..a815e4e2 100644 --- a/doc/ABIs.md +++ b/doc/stack_frame.md @@ -4,23 +4,23 @@ ```text +-------------+ - +0x08 | return addr | + | return addr | +-------------+ - BP-> 0x00 | prev rbp | <- rbp・r14 - +-------------+ -CFP-> -0x08 | prev cfp | control frame - +-------------+ - -0x10 | lfp | + BP-> | prev rbp | <- rbp + +-------------+----------------- +CFP-> | prev cfp | + +-------------+ control frame + | lfp | +-------------+----------------- -DFP-> -0x18 | outer | + -0x00 | outer | <- r14 +-------------+ - -0x20 | meta | + -0x08 | meta | +-------------+ - -0x28 | block | + -0x10 | block | +-------------+ - -0x30 | self | local frame + -0x18 | self | local frame +-------------+ - -0x38 | arg0 | + -0x20 | arg0 | +-------------+ | : | +-------------+ @@ -35,25 +35,25 @@ DFP-> -0x18 | outer | ```text +-------------+ - | | <- rsp + -0x00 | | <- rsp +-------------+ - +0x08 | | + -0x08 | | +-------------+ - BP-> 0x00 | | <- r14 - +-------------+ -CFP-> -0x08 | prev cfp | control frame - +-------------+ - -0x10 | lfp | + -0x10 | | + +-------------+----------------- + -0x18 | prev cfp | + +-------------+ control frame + -0x20 | lfp | +-------------+----------------- -DFP-> -0x18 | outer | + -0x28 | outer | <- r14 +-------------+ - -0x20 | meta | + -0x30 | meta | +-------------+ - -0x28 | block | + -0x38 | block | +-------------+ - -0x30 | self | local frame + -0x40 | self | local frame +-------------+ - -0x38 | arg0 | + -0x48 | arg0 | +-------------+ | : | +-------------+ diff --git a/monoruby/Cargo.toml b/monoruby/Cargo.toml index 17b77919..212ed989 100644 --- a/monoruby/Cargo.toml +++ b/monoruby/Cargo.toml @@ -23,6 +23,7 @@ emit-asm = ["dump-bc"] emit-bc = ["dump-bc"] jit-log = [] jit-debug = [] +no-jit = [] deopt = ["jit-log", "dump-bc"] gc-log = [] gc-debug = [] @@ -30,7 +31,9 @@ gc-stress = [] profile = ["dump-bc"] perf = [] emit-cfg = ["dump-bc"] -test = ["emit-asm", "emit-bc", "jit-log", "jit-debug", "deopt", "gc-log", "gc-stress", "profile", "perf"] +no-gems = [] +no-startup = ["no-gems"] +test = ["no-gems", "emit-asm", "emit-bc", "jit-log", "jit-debug", "deopt", "gc-log", "gc-stress", "profile", "perf"] [dependencies] clap = { version = "4.1.4", features = ["derive"] } diff --git a/monoruby/build.rs b/monoruby/build.rs index 1c75c271..650bfa16 100644 --- a/monoruby/build.rs +++ b/monoruby/build.rs @@ -33,17 +33,6 @@ fn main() { } } - match Command::new("which").args(["ruby"]).output() { - Ok(output) => { - let dest_path = lib_path.clone().join("ruby_path"); - let load_path = std::str::from_utf8(&output.stdout).unwrap(); - fs::write(dest_path, load_path).unwrap(); - } - Err(_) => { - eprintln!("failed to read ruby path"); - } - } - let mut directories = vec![(std::path::PathBuf::from("startup"), lib_path)]; while let Some((from_dir, to_dir)) = directories.pop() { diff --git a/monoruby/src/builtins/class.rs b/monoruby/src/builtins/class.rs index 4ebaf00e..af70f98a 100644 --- a/monoruby/src/builtins/class.rs +++ b/monoruby/src/builtins/class.rs @@ -98,8 +98,7 @@ pub(super) fn gen_class_new( .. } = *callsite; ir.writeback_acc(bb); - ir.write_back_callargs(bb, callsite); - ir.unlink(bb, dst); + ir.write_back_callargs_and_dst(bb, callsite); ir.stack2reg(recv, GP::Rdi); let using = bb.get_using_xmm(); let error = ir.new_error(bb, pc); diff --git a/monoruby/src/builtins/fiber.rs b/monoruby/src/builtins/fiber.rs index e735e550..a8c468fd 100644 --- a/monoruby/src/builtins/fiber.rs +++ b/monoruby/src/builtins/fiber.rs @@ -65,9 +65,7 @@ fn fiber_yield_inline( let CallSiteInfo { args, pos_num, dst, .. } = *callsite; - ir.write_back_callargs(bb, callsite); - ir.unlink(bb, dst); - //ir.stack2reg(recv, GP::Rdi); + ir.write_back_callargs_and_dst(bb, callsite); let using = bb.get_using_xmm(); let error = ir.new_error(bb, pc); ir.inline(move |gen, labels| { diff --git a/monoruby/src/builtins/object/send.rs b/monoruby/src/builtins/object/send.rs index c9bceaf7..c2c3ae3c 100644 --- a/monoruby/src/builtins/object/send.rs +++ b/monoruby/src/builtins/object/send.rs @@ -55,8 +55,7 @@ fn object_send_inner( block_arg, .. } = *callsite; - ir.write_back_callargs(bb, callsite); - ir.unlink(bb, dst); + ir.write_back_callargs_and_dst(bb, callsite); ir.writeback_acc(bb); let using_xmm = bb.get_using_xmm(); let error = ir.new_error(bb, pc); diff --git a/monoruby/src/bytecode.rs b/monoruby/src/bytecode.rs index ff79c047..652a50dc 100644 --- a/monoruby/src/bytecode.rs +++ b/monoruby/src/bytecode.rs @@ -1,4 +1,4 @@ -use bytecodegen::{inst::FnInitInfo, BcIndex}; +use bytecodegen::BcIndex; use super::*; @@ -85,16 +85,6 @@ impl Bytecode { } } - pub fn from_fn_info(op1: u64, fn_info: &FnInitInfo) -> Self { - let FnInitInfo { - arg_num, - req_num, - info, - .. - } = fn_info; - Bytecode::from_with_num(op1, *req_num as u16, 0, *info as u16, *arg_num as u16) - } - pub fn from_with_value(op1: u64, val: Value) -> Self { Self { op1, @@ -148,10 +138,6 @@ impl Bytecode { ), } } - - pub fn u16(&self, id: usize) -> u16 { - (self.op2.0 >> (id * 16)) as u16 - } } #[derive(Debug, Clone, Copy, PartialEq)] diff --git a/monoruby/src/bytecodegen.rs b/monoruby/src/bytecodegen.rs index e7d3edd2..64974d4e 100644 --- a/monoruby/src/bytecodegen.rs +++ b/monoruby/src/bytecodegen.rs @@ -564,7 +564,7 @@ impl BytecodeGen { ir.add_local(*name); }); } - ir.gen_dummy_init(info.is_block_style()); + ir.gen_dummy_init(); ir } @@ -1359,13 +1359,9 @@ impl BytecodeGen { Ok((arg, len, splat_pos)) } - fn gen_dummy_init(&mut self, is_block: bool) { + fn gen_dummy_init(&mut self) { self.emit( - if is_block { - BytecodeInst::InitBlock(FnInitInfo::default()) - } else { - BytecodeInst::InitMethod(FnInitInfo::default()) - }, + BytecodeInst::InitMethod(FnInitInfo::default()), Loc::default(), ); } @@ -1383,14 +1379,7 @@ impl BytecodeGen { fn replace_init(&mut self, info: &ISeqInfo) { let fninfo = FnInitInfo::new(self.total_reg_num(), info); - self.ir[0] = ( - if info.is_block_style() { - BytecodeInst::InitBlock(fninfo) - } else { - BytecodeInst::InitMethod(fninfo) - }, - Loc::default(), - ); + self.ir[0] = (BytecodeInst::InitMethod(fninfo), Loc::default()); } } diff --git a/monoruby/src/bytecodegen/encode.rs b/monoruby/src/bytecodegen/encode.rs index 20140b38..96136a28 100644 --- a/monoruby/src/bytecodegen/encode.rs +++ b/monoruby/src/bytecodegen/encode.rs @@ -206,7 +206,7 @@ impl BytecodeGen { // terminal inst. Bytecode::from(enc_w(81, op1.0)) } - BytecodeInst::Break(reg) => { + BytecodeInst::BlockBreak(reg) => { // 82 let op1 = self.slot_id(®); // terminal inst. @@ -549,17 +549,12 @@ impl BytecodeGen { let op3 = self.slot_id(&src); Bytecode::from(enc_www(151, op1.0, op2, op3.0)) } - BytecodeInst::InitMethod(fn_info) => { - Bytecode::from_fn_info(enc_www_fn_info(170, &fn_info), &fn_info) - } + BytecodeInst::InitMethod(fn_info) => Bytecode::from(enc_www_fn_info(170, &fn_info)), BytecodeInst::ExpandArray(src, dst, len) => { let op1 = self.slot_id(&src); let op2 = self.slot_id(&dst); Bytecode::from(enc_www(171, op1.0, op2.0, len)) } - BytecodeInst::InitBlock(fn_info) => { - Bytecode::from_fn_info(enc_www_fn_info(172, &fn_info), &fn_info) - } BytecodeInst::AliasMethod { new, old } => { Bytecode::from_with_ident2(enc_www(173, 0, 0, 0), new, old) } @@ -748,14 +743,14 @@ fn enc_www(opcode: u16, op1: u16, op2: u16, op3: u16) -> u64 { fn enc_www_fn_info(opcode: u16, fn_info: &FnInitInfo) -> u64 { let FnInitInfo { reg_num, - reqopt_num, + arg_num, stack_offset, .. } = fn_info; enc_www( opcode, *reg_num as u16, - *reqopt_num as u16, + *arg_num as u16, *stack_offset as u16, ) } diff --git a/monoruby/src/bytecodegen/expression.rs b/monoruby/src/bytecodegen/expression.rs index 1ebe649a..f50cda97 100644 --- a/monoruby/src/bytecodegen/expression.rs +++ b/monoruby/src/bytecodegen/expression.rs @@ -551,7 +551,7 @@ impl BytecodeGen { Some(data) => data.clone(), None => { if self.is_block() { - self.gen_break(val, use_mode)?; + self.gen_block_break(val, use_mode)?; return Ok(()); } else { return Err(self.escape_from_eval("break", loc)); @@ -1157,13 +1157,13 @@ impl BytecodeGen { Ok(()) } - fn gen_break(&mut self, val: Node, use_mode: UseMode2) -> Result<()> { + fn gen_block_break(&mut self, val: Node, use_mode: UseMode2) -> Result<()> { if let Some(local) = self.is_refer_local(&val) { - self.emit(BytecodeInst::Break(local.into()), Loc::default()); + self.emit(BytecodeInst::BlockBreak(local.into()), Loc::default()); } else { self.gen_expr(val, UseMode2::Push)?; let ret = self.pop().into(); - self.emit(BytecodeInst::Break(ret), Loc::default()); + self.emit(BytecodeInst::BlockBreak(ret), Loc::default()); } if use_mode == UseMode2::Push { self.push(); diff --git a/monoruby/src/bytecodegen/inst.rs b/monoruby/src/bytecodegen/inst.rs index 7ac92125..69ac34b4 100644 --- a/monoruby/src/bytecodegen/inst.rs +++ b/monoruby/src/bytecodegen/inst.rs @@ -180,7 +180,7 @@ pub(super) enum BytecodeInst { }, Ret(BcReg), MethodRet(BcReg), - Break(BcReg), + BlockBreak(BcReg), Raise(BcReg), EnsureEnd, MethodCall(Box), @@ -188,7 +188,6 @@ pub(super) enum BytecodeInst { Yield(Box), InlineCache(Box), InitMethod(FnInitInfo), - InitBlock(FnInitInfo), MethodDef { name: IdentId, func: Box, @@ -256,7 +255,7 @@ impl BytecodeInst { Self::Br(_) | Self::Ret(_) | Self::MethodRet(_) - | Self::Break(_) + | Self::BlockBreak(_) | Self::Raise(_) | Self::OptCase { .. } => true, _ => false, @@ -268,10 +267,6 @@ impl BytecodeInst { pub(crate) struct FnInitInfo { pub reg_num: usize, pub arg_num: usize, - pub req_num: usize, - pub reqopt_num: usize, - /// bit 0:rest(yes=1 no =0) bit 1:block - pub info: usize, pub stack_offset: usize, } @@ -280,17 +275,10 @@ impl std::fmt::Debug for FnInitInfo { let FnInitInfo { reg_num, arg_num, - req_num, - reqopt_num, stack_offset, .. } = *self; - write!( - f, - "reg:{reg_num} arg:{arg_num} req:{req_num} opt:{} rest:{} stack_offset:{stack_offset}", - reqopt_num - req_num, - self.has_rest_param(), - ) + write!(f, "reg:{reg_num} arg:{arg_num} stack_offset:{stack_offset}",) } } @@ -298,20 +286,13 @@ impl FnInitInfo { pub(super) fn new(total_reg_num: usize, info: &ISeqInfo) -> Self { let reg_num = total_reg_num - 1; let arg_num = info.args.args_names.len(); - let stack_offset = (reg_num * 8 + LFP_ARG0 as usize + 15) >> 4; + let stack_offset = (reg_num * 8 + (RSP_LOCAL_FRAME + LFP_ARG0) as usize + 31) / 16; FnInitInfo { reg_num, arg_num, - req_num: info.req_num(), - reqopt_num: info.reqopt_num(), - info: info.info(), stack_offset, } } - - pub(super) fn has_rest_param(&self) -> bool { - (self.info & 0b1) != 0 - } } #[derive(Clone)] diff --git a/monoruby/src/compiler.rs b/monoruby/src/compiler.rs index 0e73f1e3..77b4ed2c 100644 --- a/monoruby/src/compiler.rs +++ b/monoruby/src/compiler.rs @@ -300,27 +300,6 @@ impl Codegen { self.return_addr_table.get(&return_addr).cloned() } - pub(crate) fn set_deopt_with_return_addr( - &mut self, - return_addr: CodePtr, - evict: AsmEvict, - evict_label: DestLabel, - ) { - self.asm_return_addr_table.insert(evict, return_addr); - self.return_addr_table - .insert(return_addr, (None, evict_label)); - } - - pub(crate) fn set_deopt_patch_point_with_return_addr( - &mut self, - return_addr: CodePtr, - patch_point: CodePtr, - ) { - self.return_addr_table - .entry(return_addr) - .and_modify(|e| e.0 = Some(patch_point)); - } - /// /// Check whether *addr* is in VM code or invokers. /// @@ -406,7 +385,7 @@ impl Codegen { ); } - fn restore_lbp(&mut self) { + fn restore_lfp(&mut self) { monoasm!( &mut self.jit, // restore lfp movq r14, [rbp - (BP_CFP + CFP_LFP)]; @@ -420,7 +399,7 @@ impl Codegen { lea r14, [rbp - (BP_CFP)]; movq [rbx + (EXECUTOR_CFP)], r14; ); - self.restore_lbp(); + self.restore_lfp(); } /// @@ -479,7 +458,7 @@ impl Codegen { monoasm! { &mut self.jit, // set self movq rsi, [rax - (LFP_SELF)]; - movq [rsp - (RSP_STACK_LFP + LFP_SELF)], rsi; + movq [rsp - (RSP_LOCAL_FRAME + LFP_SELF)], rsi; }; } @@ -488,21 +467,17 @@ impl Codegen { /// ### in /// - rax: outer_lfp /// - /// ### destroy - /// - rsi - /// fn set_block_outer(&mut self) { monoasm! { &mut self.jit, // set outer - lea rsi, [rax - (LFP_OUTER)]; - movq [rsp - (RSP_STACK_LFP + LFP_OUTER)], rsi; + movq [rsp - (RSP_LOCAL_FRAME + LFP_OUTER)], rax; }; } /// Set outer. fn set_method_outer(&mut self) { monoasm! { &mut self.jit, - movq [rsp - (RSP_STACK_LFP + LFP_OUTER)], 0; + movq [rsp - (RSP_LOCAL_FRAME + LFP_OUTER)], 0; }; } @@ -513,7 +488,7 @@ impl Codegen { fn set_lfp(&mut self) { monoasm!( &mut self.jit, // set lfp - lea r14, [rsp - (RSP_STACK_LFP)]; + lea r14, [rsp - (RSP_LOCAL_FRAME)]; movq [rsp - (RSP_CFP + CFP_LFP)], r14; ); } @@ -527,7 +502,7 @@ impl Codegen { self.push_frame(); self.set_lfp(); monoasm!( &mut self.jit, - call rax; + call rax; // CALL_SITE ); self.pop_frame(); } @@ -800,7 +775,6 @@ impl Codegen { /// - r15: &FuncData /// - rdx: src: *const Value /// - r8: CallsiteId - /// - r9: arg_num /// /// ### out /// - rax: arg_num: Value @@ -820,11 +794,11 @@ impl Codegen { ) { monoasm! { &mut self.jit, // rcx <- callee LFP - lea rcx, [rsp - (RSP_STACK_LFP)]; - // rdi <- stacck_offset + lea rcx, [rsp - (RSP_LOCAL_FRAME)]; + // rdi <- stack_offset movzxw rdi, [r15 + (FUNCDATA_OFS)]; shlq rdi, 4; - addq rdi, 24; + addq rdi, 8; subq rsp, rdi; pushq rdi; movq rdi, rbx; @@ -1006,7 +980,7 @@ fn f64_to_val(jit: &mut JitMemory) -> DestLabel { } fn unimplemented_inst(jit: &mut JitMemory) -> CodePtr { - let lebel = jit.get_current_address(); + let label = jit.get_current_address(); monoasm! { jit, movq rdi, rbx; movq rsi, r12; @@ -1016,7 +990,7 @@ fn unimplemented_inst(jit: &mut JitMemory) -> CodePtr { leave; ret; } - lebel + label } #[cfg(feature = "profile")] @@ -1116,7 +1090,7 @@ impl Globals { let _sourcemap = self.codegen - .compile(&self.store, func_id, self_value, position, entry_label); + .jit_compile(&self.store, func_id, self_value, position, entry_label); #[cfg(feature = "perf")] { let desc = format!("JIT:<{}>", self.func_description(func_id)); diff --git a/monoruby/src/compiler/jitgen.rs b/monoruby/src/compiler/jitgen.rs index ae8651be..afc8743b 100644 --- a/monoruby/src/compiler/jitgen.rs +++ b/monoruby/src/compiler/jitgen.rs @@ -17,6 +17,7 @@ use trace_ir::*; pub mod analysis; pub mod asmir; mod basic_block; +mod compile; mod guard; mod init_method; pub mod trace_ir; @@ -43,6 +44,20 @@ impl ContinuationInfo { } } +/// +/// Compile result of the current instruction. +/// +enum CompileResult { + /// continue to the next instruction. + Continue, + /// exit from the loop. + ExitLoop, + /// jump to another basic block. + Branch, + /// deoptimize and fallback to the interpreter. + Recompile, +} + /// /// Context for JIT compilation. /// @@ -130,28 +145,6 @@ struct JitContext { start_codepos: usize, } -/* -/// -/// Information of incoming branches to an each basic block. -/// -#[derive(Clone)] -pub(crate) struct Incoming(Vec>); - -impl std::ops::Deref for Incoming { - type Target = Vec>; - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl std::ops::Index for Incoming { - type Output = Vec; - fn index(&self, index: BcIndex) -> &Self::Output { - &self.0[index.0 as usize] - } -} -*/ - impl JitContext { /// /// Create new JitContext. @@ -260,751 +253,6 @@ impl JitContext { }, ); } - - fn compile_bb( - &mut self, - codegen: &mut Codegen, - store: &Store, - func: &ISeqInfo, - position: Option, - bbid: BasicBlockId, - ) -> AsmIr { - let mut ir = AsmIr::new(); - ir.inst.push(AsmInst::Label(self.basic_block_labels[&bbid])); - let mut bbctx = if let Some(bb) = self.target_ctx.remove(&bbid) { - bb - } else if let Some(bb) = self.incoming_context(&mut ir, func, bbid) { - self.gen_continuation(&mut ir); - bb - } else { - #[cfg(feature = "jit-debug")] - eprintln!("=== no entry"); - return ir; - }; - - let BasciBlockInfoEntry { begin, end, .. } = func.bb_info[bbid]; - for bc_pos in begin..=end { - ir.bc_index(bc_pos); - bbctx.next_sp = func.get_sp(bc_pos); - - match self.compile_inst(codegen, &mut ir, &mut bbctx, store, func, bc_pos) { - CompileResult::Continue => {} - CompileResult::Exit => return ir, - CompileResult::Recompile => { - let pc = func.get_pc(bc_pos); - ir.recompile_and_deopt(&mut bbctx, pc, position); - return ir; - } - CompileResult::Break => break, - } - - ir.clear(&mut bbctx); - bbctx.sp = bbctx.next_sp; - } - - let next_idx = end + 1; - if let Some(next_bbid) = func.bb_info.is_bb_head(next_idx) { - let label = codegen.jit.label(); - self.new_continue(func, end, next_bbid, bbctx, label); - if let Some(target_ctx) = self.incoming_context(&mut ir, func, next_bbid) { - self.gen_continuation(&mut ir); - assert!(self.target_ctx.insert(next_bbid, target_ctx).is_none()); - } - } - ir - } - - fn compile_inst( - &mut self, - codegen: &mut Codegen, - ir: &mut AsmIr, - bbctx: &mut BBContext, - store: &Store, - func: &ISeqInfo, - bc_pos: BcIndex, - ) -> CompileResult { - let pc = func.get_pc(bc_pos); - let trace_ir = func.trace_ir(store, bc_pos); - match trace_ir { - TraceIr::InitMethod { .. } => {} - TraceIr::LoopStart { .. } => { - self.loop_count += 1; - } - TraceIr::LoopEnd => { - assert_ne!(0, self.loop_count); - self.loop_count -= 1; - if self.is_loop && self.loop_count == 0 { - ir.deopt(bbctx, pc); - return CompileResult::Break; - } - } - TraceIr::Integer(dst, i) => { - ir.store_concrete_value(bbctx, dst, Value::i32(i)); - } - TraceIr::Symbol(dst, id) => { - ir.store_concrete_value(bbctx, dst, Value::symbol(id)); - } - TraceIr::Nil(dst) => { - ir.store_concrete_value(bbctx, dst, Value::nil()); - } - TraceIr::Literal(dst, val) => { - ir.unlink(bbctx, dst); - if val.is_packed_value() || val.is_float() { - ir.store_concrete_value(bbctx, dst, val); - } else { - ir.deep_copy_lit(bbctx, val); - ir.reg2acc_guarded(bbctx, GP::Rax, dst, Guarded::from_concrete_value(val)); - } - } - TraceIr::Array { dst, callid } => { - let CallSiteInfo { args, pos_num, .. } = store[callid]; - ir.write_back_range(bbctx, args, pos_num as u16); - ir.unlink(bbctx, dst); - ir.new_array(bbctx, callid); - ir.reg2acc_guarded(bbctx, GP::Rax, dst, Guarded::ArrayTy); - } - TraceIr::Lambda { dst, func_id } => { - ir.unlink(bbctx, dst); - ir.new_lambda(bbctx, func_id); - ir.rax2acc(bbctx, dst); - } - TraceIr::Hash { dst, args, len } => { - ir.write_back_range(bbctx, args, len * 2); - ir.unlink(bbctx, dst); - ir.new_hash(bbctx, args, len as _); - ir.rax2acc(bbctx, dst); - } - TraceIr::Range { - dst, - start, - end, - exclude_end, - } => { - ir.write_back_slots(bbctx, &[start, end]); - ir.unlink(bbctx, dst); - ir.new_range(bbctx, pc, start, end, exclude_end); - ir.rax2acc(bbctx, dst); - } - TraceIr::ArrayIndex { dst, base, idx } => { - ir.index( - bbctx, - dst, - base, - idx, - Some(ARRAY_CLASS), - Some(INTEGER_CLASS), - pc, - ); - } - TraceIr::Index { - dst, - base, - idx, - base_class, - idx_class, - } => { - if base_class.is_none() || idx_class.is_none() { - return CompileResult::Recompile; - } - ir.index(bbctx, dst, base, idx, base_class, idx_class, pc); - } - TraceIr::ArrayIndexAssign { src, base, idx } => { - ir.index_assign( - bbctx, - src, - base, - idx, - Some(ARRAY_CLASS), - Some(INTEGER_CLASS), - pc, - ); - } - TraceIr::IndexAssign { - src, - base, - idx, - base_class, - idx_class, - } => { - if base_class.is_none() || idx_class.is_none() { - return CompileResult::Recompile; - } - ir.index_assign(bbctx, src, base, idx, base_class, idx_class, pc); - } - TraceIr::LoadConst(dst, id) => { - ir.unlink(bbctx, dst); - - if let ConstCache { - cached_version, - cached_base_class, - cached_value: Some(cached_val), - } = store[id].cache - { - let base_slot = store[id].base; - if let Some(slot) = base_slot { - if let Some(base_class) = cached_base_class { - ir.fetch_to_reg(bbctx, slot, GP::Rax); - let deopt = ir.new_deopt(bbctx, pc); - ir.inst.push(AsmInst::GuardBaseClass { base_class, deopt }); - } else { - return CompileResult::Recompile; - } - } - let deopt = ir.new_deopt(bbctx, pc); - if let Some(f) = cached_val.try_float() { - let fdst = ir.store_new_both(bbctx, dst, Guarded::Float); - ir.inst.push(AsmInst::LoadFloatConstant { - fdst, - f, - cached_version, - deopt, - }); - ir.reg2stack(GP::Rax, dst); - } else { - ir.inst.push(AsmInst::LoadGenericConstant { - cached_val, - cached_version, - deopt, - }); - ir.rax2acc(bbctx, dst); - } - } else { - return CompileResult::Recompile; - } - } - TraceIr::StoreConst(src, id) => { - ir.fetch_to_reg(bbctx, src, GP::Rax); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::StoreConstant { id, using_xmm }); - } - TraceIr::BlockArgProxy(ret, outer) => { - ir.unlink(bbctx, ret); - ir.block_arg_proxy(ret, outer); - } - TraceIr::BlockArg(ret, outer) => { - ir.unlink(bbctx, ret); - ir.block_arg(bbctx, pc, ret, outer); - } - TraceIr::LoadIvar(ret, id, cached_class, cached_ivarid) => { - if let Some(cached_class) = cached_class { - ir.load_ivar(bbctx, id, ret, cached_class, cached_ivarid); - } else { - return CompileResult::Recompile; - } - } - TraceIr::StoreIvar(src, id, cached_class, cached_ivarid) => { - if let Some(cached_class) = cached_class { - ir.store_ivar(bbctx, id, src, pc, cached_class, cached_ivarid); - } else { - return CompileResult::Recompile; - } - } - TraceIr::LoadCvar { dst, name } => { - ir.jit_load_cvar(bbctx, pc, name, dst); - } - TraceIr::CheckCvar { dst, name } => { - ir.jit_check_cvar(bbctx, name, dst); - } - TraceIr::StoreCvar { src: val, name } => { - ir.jit_store_cvar(bbctx, pc, name, val); - } - TraceIr::LoadGvar { dst, name } => { - ir.jit_load_gvar(bbctx, name, dst); - } - TraceIr::StoreGvar { src: val, name } => { - ir.jit_store_gvar(bbctx, name, val); - } - TraceIr::LoadSvar { dst, id } => { - ir.unlink(bbctx, dst); - ir.load_svar(bbctx, id); - ir.rax2acc(bbctx, dst); - } - TraceIr::LoadDynVar(dst, src) => { - ir.unlink(bbctx, dst); - if !dst.is_self() { - ir.inst.push(AsmInst::LoadDynVar { src }); - ir.rax2acc(bbctx, dst); - } - } - TraceIr::StoreDynVar(dst, src) => { - ir.fetch_to_reg(bbctx, src, GP::Rdi); - ir.inst.push(AsmInst::StoreDynVar { dst, src: GP::Rdi }); - } - TraceIr::BitNot { - dst, - src, - src_class, - } => { - if src_class.is_none() { - return CompileResult::Recompile; - } - ir.fetch_to_reg(bbctx, src, GP::Rdi); - ir.generic_unop(bbctx, pc, bitnot_value); - ir.rax2acc(bbctx, dst); - } - TraceIr::Not { dst, src, .. } => { - if bbctx.is_truthy(src) { - ir.store_concrete_value(bbctx, dst, Value::bool(false)); - } else if bbctx.is_falsy(src) { - ir.store_concrete_value(bbctx, dst, Value::bool(true)); - } else { - ir.fetch_to_reg(bbctx, src, GP::Rdi); - ir.inst.push(AsmInst::Not); - ir.rax2acc(bbctx, dst); - } - } - TraceIr::FUnOp { kind, dst, src } => { - let deopt = ir.new_deopt(bbctx, pc); - let fsrc = ir.fetch_float_assume_float(bbctx, src, deopt); - let dst = ir.xmm_write(bbctx, dst); - ir.xmm_move(fsrc, dst); - ir.inst.push(AsmInst::XmmUnOp { kind, dst }); - } - TraceIr::IUnOp { kind, dst, src } => { - ir.fetch_to_reg(bbctx, src, GP::Rdi); - ir.generic_unop(bbctx, pc, kind.generic_func()); - ir.rax2acc(bbctx, dst); - } - TraceIr::UnOp { - kind, - dst, - src, - src_class, - } => { - if src_class.is_none() { - return CompileResult::Recompile; - } - ir.fetch_to_reg(bbctx, src, GP::Rdi); - ir.generic_unop(bbctx, pc, kind.generic_func()); - ir.rax2acc(bbctx, dst); - } - TraceIr::IBinOp { - kind, dst, mode, .. - } => { - ir.gen_binop_integer(bbctx, pc, kind, dst, mode); - } - TraceIr::FBinOp { - kind, - dst, - mode, - lhs_class, - rhs_class, - } => { - let deopt = ir.new_deopt(bbctx, pc); - let fmode = ir.fmode(&mode, bbctx, lhs_class, rhs_class, deopt); - if let Some(ret) = dst { - let dst = ir.xmm_write(bbctx, ret); - let using_xmm = bbctx.get_using_xmm(); - ir.xmm_binop(kind, fmode, dst, using_xmm); - } - } - TraceIr::BinOp { - kind, - dst, - mode, - lhs_class, - rhs_class, - } => { - if lhs_class.is_none() || rhs_class.is_none() { - return CompileResult::Recompile; - } - ir.fetch_binary(bbctx, mode); - ir.generic_binop(bbctx, pc, kind); - ir.rax2acc(bbctx, dst); - } - TraceIr::FCmp { - kind, - dst, - mode, - lhs_class, - rhs_class, - } => { - if kind != CmpKind::Cmp { - let deopt = ir.new_deopt(bbctx, pc); - let mode = ir.fmode(&mode, bbctx, lhs_class, rhs_class, deopt); - ir.unlink(bbctx, dst); - ir.clear(bbctx); - ir.inst.push(AsmInst::FloatCmp { kind, mode }); - } else { - ir.fetch_binary(bbctx, mode); - ir.generic_cmp(bbctx, pc, kind); - } - ir.rax2acc(bbctx, dst); - } - TraceIr::ICmp { kind, dst, mode } => { - ir.fetch_fixnum_binary(bbctx, pc, &mode); - ir.inst.push(AsmInst::IntegerCmp { kind, mode }); - ir.rax2acc(bbctx, dst); - } - TraceIr::Cmp { - kind, - dst, - mode, - lhs_class, - rhs_class, - } => { - if lhs_class.is_none() || rhs_class.is_none() { - return CompileResult::Recompile; - } - ir.fetch_binary(bbctx, mode); - ir.generic_cmp(bbctx, pc, kind); - ir.rax2acc(bbctx, dst); - } - TraceIr::FCmpBr { - kind, - dst, - mode, - lhs_class, - rhs_class, - dest, - brkind, - } => { - let index = bc_pos + 1; - let branch_dest = codegen.jit.label(); - let deopt = ir.new_deopt(bbctx, pc); - let mode = ir.fmode(&mode, bbctx, lhs_class, rhs_class, deopt); - ir.unlink(bbctx, dst); - ir.clear(bbctx); - ir.float_cmp_br(mode, kind, brkind, branch_dest); - self.new_branch(func, index, dest, bbctx.clone(), branch_dest); - } - TraceIr::ICmpBr { - kind, - dst, - mode, - dest, - brkind, - } => { - let index = bc_pos + 1; - let branch_dest = codegen.jit.label(); - ir.fetch_fixnum_binary(bbctx, pc, &mode); - ir.unlink(bbctx, dst); - ir.clear(bbctx); - ir.integer_cmp_br(mode, kind, brkind, branch_dest); - self.new_branch(func, index, dest, bbctx.clone(), branch_dest); - } - TraceIr::CmpBr { - kind, - dst, - mode, - dest, - brkind, - .. - } => { - let index = bc_pos + 1; - let branch_dest = codegen.jit.label(); - ir.fetch_binary(bbctx, mode); - ir.unlink(bbctx, dst); - ir.clear(bbctx); - ir.generic_cmp(bbctx, pc, kind); - ir.inst.push(AsmInst::GenericCondBr { - brkind, - branch_dest, - }); - self.new_branch(func, index, dest, bbctx.clone(), branch_dest); - } - TraceIr::Mov(dst, src) => { - ir.copy_slot(bbctx, src, dst); - } - TraceIr::ConcatStr(dst, arg, len) => { - ir.write_back_range(bbctx, arg, len); - ir.unlink(bbctx, dst); - let error = ir.new_error(bbctx, pc); - ir.concat_str(bbctx, arg, len); - ir.handle_error(error); - ir.rax2acc(bbctx, dst); - } - TraceIr::ConcatRegexp(dst, arg, len) => { - ir.write_back_range(bbctx, arg, len); - ir.unlink(bbctx, dst); - let error = ir.new_error(bbctx, pc); - ir.concat_regexp(bbctx, arg, len); - ir.handle_error(error); - ir.rax2acc(bbctx, dst); - } - TraceIr::ExpandArray { - src, - dst: (dst, len), - } => { - ir.fetch_to_reg(bbctx, src, GP::Rdi); - for reg in dst.0..dst.0 + len { - ir.unlink(bbctx, SlotId(reg)); - } - ir.expand_array(bbctx, dst, len); - } - TraceIr::AliasMethod { new, old } => { - //ir.write_back_slots(bb, &[new, old]); - ir.alias_method(bbctx, pc, new, old); - } - TraceIr::MethodCall { - callid, - recv_class, - fid, - version, - } - | TraceIr::MethodCallBlock { - callid, - recv_class, - fid, - version, - } => { - if let Some(fid) = fid { - let recv_class = recv_class.unwrap(); - if store[callid].block_fid.is_none() - && let Some(info) = store.inline_info.get_inline(fid) - { - let is_simple = store[callid].is_simple(); - if fid == OBJECT_SEND_FUNCID && store[callid].object_send_single_splat() { - let f = object_send_splat; - self.gen_inline_call( - ir, store, bbctx, f, fid, callid, recv_class, version, pc, - ); - } else if is_simple { - let f = &info.inline_gen; - self.gen_inline_call( - ir, store, bbctx, f, fid, callid, recv_class, version, pc, - ); - //} - } else { - if ir - .gen_call(store, bbctx, fid, recv_class, version, callid, pc) - .is_none() - { - return CompileResult::Recompile; - } - } - } else { - if ir - .gen_call(store, bbctx, fid, recv_class, version, callid, pc) - .is_none() - { - return CompileResult::Recompile; - } - } - } else { - return CompileResult::Recompile; - } - } - TraceIr::Yield { callid } => { - let callinfo = &store[callid]; - let dst = callinfo.dst; - ir.write_back_callargs(bbctx, &callinfo); - ir.unlink(bbctx, dst); - ir.writeback_acc(bbctx); - let using_xmm = bbctx.get_using_xmm(); - let error = ir.new_error(bbctx, pc); - let evict = ir.new_evict(); - ir.inst.push(AsmInst::Yield { - callid, - using_xmm, - error, - evict, - }); - ir.rax2acc(bbctx, dst); - } - TraceIr::InlineCache => {} - TraceIr::MethodDef { name, func_id } => { - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::MethodDef { - name, - func_id, - using_xmm, - }); - ir.check_bop(bbctx, pc); - } - TraceIr::SingletonMethodDef { obj, name, func_id } => { - ir.write_back_slots(bbctx, &[obj]); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::SingletonMethodDef { - obj, - name, - func_id, - using_xmm, - }); - ir.check_bop(bbctx, pc); - } - TraceIr::ClassDef { - dst, - base, - superclass, - name, - func_id, - } => { - self.class_def(ir, bbctx, dst, base, superclass, name, func_id, false, pc); - } - TraceIr::ModuleDef { - dst, - base, - name, - func_id, - } => { - self.class_def(ir, bbctx, dst, base, None, name, func_id, true, pc); - } - TraceIr::SingletonClassDef { dst, base, func_id } => { - self.singleton_class_def(ir, bbctx, dst, base, func_id, pc); - } - TraceIr::DefinedYield { dst } => { - ir.write_back_slots(bbctx, &[dst]); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::DefinedYield { dst, using_xmm }); - } - TraceIr::DefinedConst { dst, siteid } => { - ir.write_back_slots(bbctx, &[dst]); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::DefinedConst { - dst, - siteid, - using_xmm, - }); - } - TraceIr::DefinedMethod { dst, recv, name } => { - ir.write_back_slots(bbctx, &[dst, recv]); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::DefinedMethod { - dst, - recv, - name, - using_xmm, - }); - } - TraceIr::DefinedGvar { dst, name } => { - ir.write_back_slots(bbctx, &[dst]); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::DefinedGvar { - dst, - name, - using_xmm, - }); - } - TraceIr::DefinedIvar { dst, name } => { - ir.write_back_slots(bbctx, &[dst]); - let using_xmm = bbctx.get_using_xmm(); - ir.inst.push(AsmInst::DefinedIvar { - dst, - name, - using_xmm, - }); - } - TraceIr::Ret(ret) => { - ir.write_back_locals(bbctx); - ir.fetch_to_reg(bbctx, ret, GP::Rax); - ir.inst.push(AsmInst::Ret); - return CompileResult::Exit; - } - TraceIr::MethodRet(ret) => { - ir.write_back_locals(bbctx); - ir.fetch_to_reg(bbctx, ret, GP::Rax); - ir.inst.push(AsmInst::MethodRet(pc)); - return CompileResult::Exit; - } - TraceIr::Break(ret) => { - ir.write_back_locals(bbctx); - ir.fetch_to_reg(bbctx, ret, GP::Rax); - ir.inst.push(AsmInst::Break); - return CompileResult::Exit; - } - TraceIr::Raise(ret) => { - ir.write_back_locals(bbctx); - ir.fetch_to_reg(bbctx, ret, GP::Rax); - ir.inst.push(AsmInst::Raise); - return CompileResult::Exit; - } - TraceIr::EnsureEnd => { - ir.write_back_locals(bbctx); - ir.inst.push(AsmInst::EnsureEnd); - } - TraceIr::Br(dest_idx) => { - self.gen_branch(codegen, ir, bbctx, func, bc_pos, dest_idx); - return CompileResult::Exit; - } - TraceIr::CondBr(cond_, dest_idx, false, brkind) => { - if bbctx.is_truthy(cond_) { - if brkind == BrKind::BrIf { - self.gen_branch(codegen, ir, bbctx, func, bc_pos, dest_idx); - return CompileResult::Exit; - } - } else if bbctx.is_falsy(cond_) { - if brkind == BrKind::BrIfNot { - self.gen_branch(codegen, ir, bbctx, func, bc_pos, dest_idx); - return CompileResult::Exit; - } - } else { - let branch_dest = codegen.jit.label(); - ir.fetch_to_reg(bbctx, cond_, GP::Rax); - ir.inst.push(AsmInst::CondBr(brkind, branch_dest)); - self.new_branch(func, bc_pos, dest_idx, bbctx.clone(), branch_dest); - } - } - TraceIr::NilBr(cond_, dest_idx) => { - let branch_dest = codegen.jit.label(); - ir.fetch_to_reg(bbctx, cond_, GP::Rax); - ir.inst.push(AsmInst::NilBr(branch_dest)); - self.new_branch(func, bc_pos, dest_idx, bbctx.clone(), branch_dest); - } - TraceIr::CondBr(_, _, true, _) => {} - TraceIr::CheckLocal(local, dest_idx) => { - let branch_dest = codegen.jit.label(); - ir.fetch_to_reg(bbctx, local, GP::Rax); - ir.inst.push(AsmInst::CheckLocal(branch_dest)); - self.new_branch(func, bc_pos, dest_idx, bbctx.clone(), branch_dest); - } - TraceIr::OptCase { - cond, - min, - max, - dest_bb, - branch_table, - } => { - let else_idx = dest_bb[0]; - for bbid in dest_bb { - let branch_dest = codegen.jit.label(); - self.new_branch(func, bc_pos, bbid, bbctx.clone(), branch_dest); - } - let deopt = ir.new_deopt(bbctx, pc); - ir.fetch_guard_fixnum(bbctx, cond, GP::Rdi, deopt); - ir.opt_case(max, min, else_idx, branch_table); - return CompileResult::Exit; - } - } - CompileResult::Continue - } - - fn gen_branch( - &mut self, - codegen: &mut Codegen, - ir: &mut AsmIr, - bb: &mut BBContext, - func: &ISeqInfo, - bc_pos: BcIndex, - dest: BasicBlockId, - ) { - let branch_dest = codegen.jit.label(); - ir.inst.push(AsmInst::Br(branch_dest)); - self.new_branch(func, bc_pos, dest, bb.clone(), branch_dest); - } - - fn gen_inline_call( - &mut self, - ir: &mut AsmIr, - store: &Store, - bb: &mut BBContext, - f: impl Fn(&mut AsmIr, &Store, &mut BBContext, CallSiteId, BytecodePtr), - fid: FuncId, - callid: CallSiteId, - recv_class: ClassId, - version: u32, - pc: BytecodePtr, - ) { - let recv = store[callid].recv; - ir.fetch_to_reg(bb, recv, GP::Rdi); - let (deopt, error) = ir.new_deopt_error(bb, pc); - let using_xmm = bb.get_using_xmm(); - ir.guard_version(fid, version, callid, using_xmm, deopt, error); - if !recv.is_self() && !bb.is_class(recv, recv_class) { - ir.guard_class(bb, recv, GP::Rdi, recv_class, deopt); - } - f(ir, store, bb, callid, pc); - } } /// @@ -1252,7 +500,7 @@ impl MergeContext { } impl Codegen { - pub(super) fn compile( + pub(super) fn jit_compile( &mut self, store: &Store, func_id: FuncId, @@ -1311,12 +559,12 @@ impl Codegen { } None => BasicBlockId(func.bb_info.len() - 1), }; - - let mut bbir = vec![]; - for bbid in bb_begin..=bb_end { - let ir = ctx.compile_bb(self, store, func, position, bbid); - bbir.push((bbid, ir)); - } + let bbir: Vec<_> = (bb_begin..=bb_end) + .map(|bbid| { + let ir = ctx.compile_basic_block(self, store, func, position, bbid); + (bbid, ir) + }) + .collect(); ctx.backedge_branches(func); @@ -1336,9 +584,8 @@ impl Codegen { } assert!(ctx.continuation_bridge.is_none()); - let sourcemap = std::mem::take(&mut ctx.sourcemap); - self.jit.finalize(); + #[cfg(any(feature = "jit-debug", feature = "jit-log"))] { self.jit.select_page(0); @@ -1353,10 +600,10 @@ impl Codegen { eprintln!("<== finished compile. elapsed:{:?}", elapsed); self.jit_compile_time += elapsed; } - #[cfg(any(feature = "emit-asm", feature = "jit-debug"))] + #[cfg(feature = "emit-asm")] eprintln!("<== finished compile."); - sourcemap + ctx.sourcemap } #[cfg(feature = "emit-cfg")] @@ -1408,7 +655,9 @@ impl Codegen { for bc in begin..=end { if let Some(inst) = func.trace_ir(store, bc).format(store) { s += "|"; - let html = html_escape::encode_text(&inst).replace('|', "\\|"); + let html = html_escape::encode_text(&inst) + .replace('|', "\\|") + .replace('"', "\\\""); s += &format!("{} {}\\l", bc, html); } } @@ -1456,13 +705,6 @@ macro_rules! load_store { }; } -enum CompileResult { - Continue, - Break, - Exit, - Recompile, -} - impl Codegen { load_store!(rax); load_store!(rdi); diff --git a/monoruby/src/compiler/jitgen/analysis.rs b/monoruby/src/compiler/jitgen/analysis.rs index eb7df4ce..c02620e4 100644 --- a/monoruby/src/compiler/jitgen/analysis.rs +++ b/monoruby/src/compiler/jitgen/analysis.rs @@ -224,8 +224,7 @@ impl JitContext { info.use_range(args, len * 2); info.def(dst); } - TraceIr::ArrayIndex { dst, base, idx, .. } - | TraceIr::Index { dst, base, idx, .. } => { + TraceIr::Index { dst, base, idx, .. } => { info.use_slots(&[base, idx]); info.def(dst); } @@ -235,8 +234,7 @@ impl JitContext { info.use_slots(&[start, end]); info.def(dst); } - TraceIr::ArrayIndexAssign { src, base, idx, .. } - | TraceIr::IndexAssign { src, base, idx, .. } => { + TraceIr::IndexAssign { src, base, idx, .. } => { info.use_slots(&[src, base, idx]); } TraceIr::ClassDef { @@ -451,7 +449,7 @@ impl JitContext { info.def(dst); } TraceIr::MethodCall { callid, fid, .. } - | TraceIr::MethodCallBlock { callid, fid, .. } => { + | TraceIr::MethodCallWithBlock { callid, fid, .. } => { if store[callid].block_fid.is_none() && let Some(fid) = fid && let Some(inline_info) = store.inline_info.get_inline(fid) @@ -472,7 +470,7 @@ impl JitContext { TraceIr::InlineCache => {} TraceIr::Ret(src) | TraceIr::MethodRet(src) - | TraceIr::Break(src) + | TraceIr::BlockBreak(src) | TraceIr::Raise(src) => { info.r#use(src); } diff --git a/monoruby/src/compiler/jitgen/asmir.rs b/monoruby/src/compiler/jitgen/asmir.rs index 2e0a2da2..000ceaad 100644 --- a/monoruby/src/compiler/jitgen/asmir.rs +++ b/monoruby/src/compiler/jitgen/asmir.rs @@ -414,31 +414,6 @@ impl AsmIr { pub(super) fn handle_error(&mut self, error: AsmError) { self.inst.push(AsmInst::HandleError(error)); } - - /// - /// Attribute writer - /// - /// ### in - /// - rdi: receiver: Value - /// - rdx: value: Value - /// - pub(super) fn attr_writer(&mut self, bb: &BBContext, pc: BytecodePtr, ivar_id: IvarId) { - let using_xmm = bb.get_using_xmm(); - let error = self.new_error(bb, pc); - self.inst.push(AsmInst::AttrWriter { - using_xmm, - error, - ivar_id, - }); - } - - /// - /// ### in - /// - rdi: receiver: Value - /// - pub(super) fn attr_reader(&mut self, ivar_id: IvarId) { - self.inst.push(AsmInst::AttrReader { ivar_id }); - } } // write back operations @@ -456,10 +431,15 @@ impl AsmIr { } } - pub(crate) fn write_back_callargs(&mut self, bb: &mut BBContext, callsite: &CallSiteInfo) { - let CallSiteInfo { recv, .. } = callsite; + pub(crate) fn write_back_callargs_and_dst( + &mut self, + bb: &mut BBContext, + callsite: &CallSiteInfo, + ) { + let CallSiteInfo { recv, dst, .. } = callsite; self.write_back_slot(bb, *recv); self.write_back_args(bb, callsite); + self.unlink(bb, *dst); } fn write_back_args(&mut self, bb: &mut BBContext, callsite: &CallSiteInfo) { @@ -480,55 +460,18 @@ impl AsmIr { impl AsmIr { /// - /// ### in - /// rdi: receiver: Value + /// Set positional arguments for callee. /// - pub(super) fn send_cached( + fn set_arguments( &mut self, store: &Store, bb: &mut BBContext, - pc: BytecodePtr, callid: CallSiteId, callee_fid: FuncId, - recv_class: ClassId, - native: bool, - evict: AsmEvict, + pc: BytecodePtr, ) { - self.reg_move(GP::Rdi, GP::R13); - self.exec_gc(bb.get_register()); - let using_xmm = bb.get_using_xmm(); - self.xmm_save(using_xmm); let caller = &store[callid]; let callee = &store[callee_fid]; - self.set_arguments(bb, caller, callid, callee, pc); - self.unlink(bb, caller.dst); - self.clear(bb); - let error = self.new_error(bb, pc); - self.writeback_acc(bb); - let offset = ((RSP_STACK_LFP + LFP_ARG0) as usize + 8 * callee.total_args() + 8) / 16 * 16; - self.inst.push(AsmInst::SendCached { - callid, - callee_fid, - recv_class, - native, - offset, - using_xmm, - error, - evict, - }); - } - - /// - /// Set positional arguments for callee. - /// - fn set_arguments( - &mut self, - bb: &mut BBContext, - caller: &CallSiteInfo, - callid: CallSiteId, - callee: &FuncInfo, - pc: BytecodePtr, - ) { let args = caller.args; let pos_num = caller.pos_num; let kw_pos = caller.kw_pos; @@ -545,8 +488,6 @@ impl AsmIr { { // write back keyword arguments. for arg in kw_pos..kw_pos + kw_num { - //assert_eq!(kw_pos, args + pos_num); - //assert_eq!(kw_pos + kw_num, args + caller.len); self.write_back_slot(bb, arg); } // write back block argument. @@ -555,7 +496,7 @@ impl AsmIr { } let ofs = if (args..args + pos_num).any(|reg| matches!(bb.slot(reg), LinkMode::Xmm(_))) { - (RSP_STACK_LFP + LFP_ARG0 + (8 * pos_num) as i32 + 8) / 16 * 16 + (RSP_LOCAL_FRAME + LFP_ARG0 + (8 * pos_num) as i32 + 8) & !0xf } else { 0 }; @@ -563,48 +504,26 @@ impl AsmIr { self.reg_sub(GP::Rsp, ofs); for i in 0..pos_num { let reg = args + i; - let offset = ofs - (RSP_STACK_LFP + LFP_ARG0 + (8 * i) as i32); + let offset = ofs - (RSP_LOCAL_FRAME + LFP_ARG0 + (8 * i) as i32); self.fetch_to_rsp_offset(bb, reg, offset); } if pos_num != callee.max_positional_args() { self.inst.push(AsmInst::I32ToReg(0, GP::Rax)); for i in pos_num..callee.max_positional_args() { - let offset = ofs - (RSP_STACK_LFP + LFP_ARG0 as i32 + (8 * i) as i32); + let offset = ofs - (RSP_LOCAL_FRAME + LFP_ARG0 as i32 + (8 * i) as i32); self.reg2rsp_offset(GP::Rax, offset); } } self.reg_add(GP::Rsp, ofs); } else { self.write_back_args(bb, caller); - let meta = callee.meta(); - let offset = - ((RSP_STACK_LFP + LFP_ARG0) as usize + 8 * callee.max_positional_args() + 8) & !0xf; + let error = self.new_error(bb, pc); - self.inst.push(AsmInst::SetArguments { - callid, - args, - meta, - offset, - }); + self.inst.push(AsmInst::SetArguments { callid, callee_fid }); self.handle_error(error); } } - pub(super) fn send_not_cached(&mut self, bb: &BBContext, pc: BytecodePtr, callid: CallSiteId) { - let using_xmm = bb.get_using_xmm(); - let error = self.new_error(bb, pc); - let evict = self.new_evict(); - let self_class = bb.self_value.class(); - self.inst.push(AsmInst::SendNotCached { - self_class, - callid, - pc, - using_xmm, - error, - evict, - }); - } - pub(super) fn generic_unop(&mut self, bb: &BBContext, pc: BytecodePtr, func: UnaryOpFn) { let using_xmm = bb.get_using_xmm(); let error = self.new_error(bb, pc); @@ -1097,7 +1016,7 @@ pub(super) enum AsmInst { GuardClass(GP, ClassId, AsmDeopt), Ret, - Break, + BlockBreak, Raise, MethodRet(BytecodePtr), EnsureEnd, @@ -1146,9 +1065,7 @@ pub(super) enum AsmInst { /// SetArguments { callid: CallSiteId, - args: SlotId, - meta: Meta, - offset: usize, + callee_fid: FuncId, }, /// @@ -1172,23 +1089,31 @@ pub(super) enum AsmInst { AttrReader { ivar_id: IvarId, }, - ImmediateEvict { - evict: AsmEvict, - }, + /// + /// Send cached method /// /// ### in /// - rdi: receiver: Value /// + /// ### destroy + /// - caller save registers + /// - r15 + /// SendCached { callid: CallSiteId, recv_class: ClassId, callee_fid: FuncId, - native: bool, - offset: usize, using_xmm: UsingXmm, error: AsmError, evict: AsmEvict, }, + /// + /// Send non-cached method + /// + /// ### destroy + /// - caller save registers + /// - r15 + /// SendNotCached { callid: CallSiteId, self_class: ClassId, @@ -1204,6 +1129,9 @@ pub(super) enum AsmInst { error: AsmError, evict: AsmEvict, }, + ImmediateEvict { + evict: AsmEvict, + }, CheckBOP { deopt: AsmDeopt, }, @@ -1549,7 +1477,7 @@ impl AsmInst { } Self::GuardClass(gpr, class, _deopt) => format!("GuardClass {:?} {:?}", class, gpr), Self::Ret => "ret".to_string(), - Self::Break => "break".to_string(), + Self::BlockBreak => "break".to_string(), Self::Raise => "raise".to_string(), Self::MethodRet(_pc) => format!("method_return"), Self::EnsureEnd => "ensure_end".to_string(), diff --git a/monoruby/src/compiler/jitgen/asmir/compile.rs b/monoruby/src/compiler/jitgen/asmir/compile.rs index 5749b59f..8d469bb5 100644 --- a/monoruby/src/compiler/jitgen/asmir/compile.rs +++ b/monoruby/src/compiler/jitgen/asmir/compile.rs @@ -195,12 +195,10 @@ impl Codegen { AsmInst::WriteBack(wb) => self.gen_write_back(&wb), AsmInst::XmmSave(using_xmm) => self.xmm_save(using_xmm), AsmInst::ExecGc(wb) => self.execute_gc(Some(&wb)), - AsmInst::SetArguments { - callid, - args, - meta, - offset, - } => { + AsmInst::SetArguments { callid, callee_fid } => { + let meta = store[callee_fid].meta(); + let offset = store[callee_fid].get_offset(); + let args = store[callid].args; self.jit_set_arguments(callid, args, offset, meta); } @@ -213,7 +211,7 @@ impl Codegen { }; self.method_return(); } - AsmInst::Break => { + AsmInst::BlockBreak => { self.block_break(); self.epilogue(); } @@ -292,7 +290,9 @@ impl Codegen { AsmInst::ImmediateEvict { evict } => { let patch_point = self.jit.get_current_address(); let return_addr = self.asm_return_addr_table.get(&evict).unwrap(); - self.set_deopt_patch_point_with_return_addr(*return_addr, patch_point); + self.return_addr_table + .entry(*return_addr) + .and_modify(|e| e.0 = Some(patch_point)); } AsmInst::AttrWriter { ivar_id, @@ -308,16 +308,13 @@ impl Codegen { callid, callee_fid, recv_class, - native, - offset, using_xmm, error, evict, } => { let error = labels[error]; - let return_addr = self.send_cached( - store, callid, callee_fid, recv_class, native, offset, using_xmm, error, - ); + let return_addr = + self.send_cached(store, callid, callee_fid, recv_class, using_xmm, error); self.set_deopt_with_return_addr(return_addr, evict, labels[evict]); } AsmInst::SendNotCached { @@ -340,7 +337,8 @@ impl Codegen { evict, } => { let error = labels[error]; - self.gen_yield(store, callid, using_xmm, error, evict, labels[evict]); + let return_addr = self.gen_yield(store, callid, using_xmm, error); + self.set_deopt_with_return_addr(return_addr, evict, labels[evict]); } AsmInst::Not => { @@ -674,6 +672,17 @@ impl Codegen { } } + fn set_deopt_with_return_addr( + &mut self, + return_addr: CodePtr, + evict: AsmEvict, + evict_label: DestLabel, + ) { + self.asm_return_addr_table.insert(evict, return_addr); + self.return_addr_table + .insert(return_addr, (None, evict_label)); + } + /// /// Class version guard for JIT. /// @@ -761,16 +770,13 @@ impl Codegen { }; } else { monoasm!( &mut self.jit, - movq rax, [r14 - (LFP_OUTER)]; + movq rax, [r14]; ); for _ in 0..outer - 1 { monoasm!( &mut self.jit, movq rax, [rax]; ); } - monoasm!( &mut self.jit, - lea rax, [rax + (LFP_OUTER)]; - ); } } @@ -796,7 +802,7 @@ impl Codegen { movq rax, (runtime::gen_lambda); call rax; }; - self.restore_lbp(); + self.restore_lfp(); self.xmm_restore(using_xmm); } diff --git a/monoruby/src/compiler/jitgen/asmir/compile/definition.rs b/monoruby/src/compiler/jitgen/asmir/compile/definition.rs index b2e240e8..63695477 100644 --- a/monoruby/src/compiler/jitgen/asmir/compile/definition.rs +++ b/monoruby/src/compiler/jitgen/asmir/compile/definition.rs @@ -122,9 +122,9 @@ impl Codegen { movq r8, rax; movq rdi, [r8 + (FUNCDATA_META)]; - movq [rsp - (RSP_STACK_LFP + LFP_META)], rdi; - movq [rsp - (RSP_STACK_LFP + LFP_BLOCK)], 0; - movq [rsp - (RSP_STACK_LFP + LFP_SELF)], r15; + movq [rsp - (RSP_LOCAL_FRAME + LFP_META)], rdi; + movq [rsp - (RSP_LOCAL_FRAME + LFP_BLOCK)], 0; + movq [rsp - (RSP_LOCAL_FRAME + LFP_SELF)], r15; } self.set_method_outer(); monoasm! { &mut self.jit, diff --git a/monoruby/src/compiler/jitgen/asmir/compile/method_call.rs b/monoruby/src/compiler/jitgen/asmir/compile/method_call.rs index 8eb2f6ef..43cbafb8 100644 --- a/monoruby/src/compiler/jitgen/asmir/compile/method_call.rs +++ b/monoruby/src/compiler/jitgen/asmir/compile/method_call.rs @@ -36,7 +36,7 @@ impl Codegen { movq rsi, r12; movl rdx, (callid.get()); lea rcx, [r14 - (conv(args))]; - lea r8, [rsp - (RSP_STACK_LFP)]; // callee_lfp + lea r8, [rsp - (RSP_LOCAL_FRAME)]; // callee_lfp movq r9, (meta.get()); subq rsp, (offset); movq rax, (crate::runtime::jit_generic_set_arguments); @@ -44,9 +44,7 @@ impl Codegen { addq rsp, (offset); } } -} -impl Codegen { /// /// generate JIT code for a method call which was not cached. /// @@ -60,9 +58,6 @@ impl Codegen { error: DestLabel, ) -> CodePtr { let callsite = &store[callid]; - // argument registers: - // rdi: args len - // let resolved = self.jit.label(); let slow_path = self.jit.label(); let global_class_version = self.class_version; @@ -105,7 +100,7 @@ impl Codegen { // set prev_cfp pushq [rbx + (EXECUTOR_CFP)]; // set lfp - lea rax, [rsp + (24 - RSP_STACK_LFP)]; + lea rax, [rsp + (24 - RSP_LOCAL_FRAME)]; pushq rax; // set outer xorq rax, rax; @@ -274,8 +269,6 @@ impl Codegen { callid: CallSiteId, callee_fid: FuncId, recv_class: ClassId, - native: bool, - offset: usize, using_xmm: UsingXmm, error: DestLabel, ) -> CodePtr { @@ -285,19 +278,20 @@ impl Codegen { self.setup_frame(meta, caller); self.copy_keyword_args(caller, callee); if callee.kw_rest().is_some() || !caller.hash_splat_pos.is_empty() { + let offset = callee.get_offset(); self.handle_hash_splat_kw_rest(callid, meta, offset, error); } self.set_lfp(); self.push_frame(); - if native { + if callee.is_native() { self.call_codeptr(codeptr) } else { - match store[callee_fid].get_jit_code(recv_class) { + match callee.get_jit_code(recv_class) { Some(dest) => { monoasm! { &mut self.jit, - call dest; + call dest; // CALL_SITE } } None => { @@ -371,9 +365,7 @@ impl Codegen { callid: CallSiteId, using_xmm: UsingXmm, error: DestLabel, - deopt_lazy: AsmEvict, - deopt: DestLabel, - ) { + ) -> CodePtr { self.xmm_save(using_xmm); self.get_proc_data(); self.handle_error(error); @@ -389,11 +381,10 @@ impl Codegen { // set prev_cfp pushq [rbx + (EXECUTOR_CFP)]; // set lfp - lea rax, [rsp + (24 - RSP_STACK_LFP)]; + lea rax, [rsp + (24 - RSP_LOCAL_FRAME)]; pushq rax; // set outer - lea rax, [rdi - (LFP_OUTER)]; - pushq rax; + pushq rdi; // set meta pushq [r15 + (FUNCDATA_META)]; // set block @@ -407,7 +398,7 @@ impl Codegen { let return_addr = self.generic_call(callid, store[callid].args, error); self.xmm_restore(using_xmm); self.handle_error(error); - self.set_deopt_with_return_addr(return_addr, deopt_lazy, deopt); + return_addr } /// @@ -438,7 +429,7 @@ impl Codegen { fn call_codeptr(&mut self, codeptr: CodePtr) { let src_point = self.jit.get_current_address(); monoasm! { &mut self.jit, - call (codeptr - src_point - 5); + call (codeptr - src_point - 5); // CALL_SITE } } @@ -448,15 +439,15 @@ impl Codegen { /// fn call_funcdata(&mut self) -> CodePtr { monoasm! { &mut self.jit, - // set pc - movq r13, [r15 + (FUNCDATA_PC)]; // push cfp lea rsi, [rsp - (RSP_CFP)]; movq [rbx + (EXECUTOR_CFP)], rsi; } self.set_lfp(); monoasm! { &mut self.jit, - call [r15 + (FUNCDATA_CODEPTR)]; + // set pc + movq r13, [r15 + (FUNCDATA_PC)]; + call [r15 + (FUNCDATA_CODEPTR)]; // CALL_SITE } let return_addr = self.jit.get_current_address(); self.pop_frame(); @@ -480,12 +471,12 @@ impl Codegen { let caller_ofs = (kw_pos.0 as i32 + *caller as i32) * 8 + LFP_SELF; monoasm! { &mut self.jit, movq rax, [r14 - (caller_ofs)]; - movq [rsp - (RSP_STACK_LFP + callee_ofs)], rax; + movq [rsp - (RSP_LOCAL_FRAME + callee_ofs)], rax; } } None => { monoasm! { &mut self.jit, - movq [rsp - (RSP_STACK_LFP + callee_ofs)], 0; + movq [rsp - (RSP_LOCAL_FRAME + callee_ofs)], 0; } } } @@ -505,7 +496,7 @@ impl Codegen { movq rsi, r12; // &mut Globals movl rdx, (callid.get()); movq rcx, (meta.get()); - lea r8, [rsp - (RSP_STACK_LFP)]; // callee_lfp + lea r8, [rsp - (RSP_LOCAL_FRAME)]; // callee_lfp subq rsp, (offset); movq rax, (jit_handle_hash_splat_kw_rest); call rax; @@ -514,6 +505,15 @@ impl Codegen { self.handle_error(error); } + /// + /// Invoke method. + /// + /// ### in + /// - r15: &FuncData + /// + /// ### out + /// - rax: return value + /// fn generic_call(&mut self, callid: CallSiteId, args: SlotId, error: DestLabel) -> CodePtr { monoasm! { &mut self.jit, movl r8, (callid.get()); // CallSiteId @@ -661,7 +661,7 @@ impl Codegen { // set prev_cfp pushq [rbx + (EXECUTOR_CFP)]; // set lfp - lea rax, [rsp + (24 - RSP_STACK_LFP)]; + lea rax, [rsp + (24 - RSP_LOCAL_FRAME)]; pushq rax; // set outer xorq rax, rax; @@ -768,7 +768,7 @@ impl Codegen { cmpw rax, (pos_num - 1); jne arg_error; lea rdi, [r14 - (conv(args + 1usize))]; - lea rdx, [rsp - (RSP_STACK_LFP + LFP_ARG0)]; + lea rdx, [rsp - (RSP_LOCAL_FRAME + LFP_ARG0)]; movq r8, (pos_num); // src: rdi, dst: rdx loop0: diff --git a/monoruby/src/compiler/jitgen/asmir/compile/variables.rs b/monoruby/src/compiler/jitgen/asmir/compile/variables.rs index 55d1fb74..02cf7f33 100644 --- a/monoruby/src/compiler/jitgen/asmir/compile/variables.rs +++ b/monoruby/src/compiler/jitgen/asmir/compile/variables.rs @@ -185,7 +185,7 @@ impl Codegen { fn get_outer(&mut self, outer: usize) { monoasm!( &mut self.jit, - movq rax, [r14 - (LFP_OUTER)]; + movq rax, [r14]; ); for _ in 0..outer - 1 { monoasm!( &mut self.jit, diff --git a/monoruby/src/compiler/jitgen/asmir/definition.rs b/monoruby/src/compiler/jitgen/asmir/definition.rs index 46033277..a0d790f0 100644 --- a/monoruby/src/compiler/jitgen/asmir/definition.rs +++ b/monoruby/src/compiler/jitgen/asmir/definition.rs @@ -1,10 +1,9 @@ use super::*; -impl JitContext { +impl AsmIr { pub(in crate::compiler::jitgen) fn class_def( &mut self, - ir: &mut AsmIr, - bb: &mut BBContext, + bbctx: &mut BBContext, dst: Option, base: Option, superclass: Option, @@ -14,15 +13,15 @@ impl JitContext { pc: BytecodePtr, ) { if let Some(base) = base { - ir.write_back_slots(bb, &[base]); + self.write_back_slots(bbctx, &[base]); } if let Some(superclass) = superclass { - ir.write_back_slots(bb, &[superclass]); + self.write_back_slots(bbctx, &[superclass]); } - ir.unlink(bb, dst); - let using_xmm = bb.get_using_xmm(); - let error = ir.new_error(bb, pc); - ir.inst.push(AsmInst::ClassDef { + self.unlink(bbctx, dst); + let using_xmm = bbctx.get_using_xmm(); + let error = self.new_error(bbctx, pc); + self.inst.push(AsmInst::ClassDef { base, superclass, dst, @@ -36,18 +35,17 @@ impl JitContext { pub(in crate::compiler::jitgen) fn singleton_class_def( &mut self, - ir: &mut AsmIr, - bb: &mut BBContext, + bbctx: &mut BBContext, dst: Option, base: SlotId, func_id: FuncId, pc: BytecodePtr, ) { - ir.write_back_slots(bb, &[base]); - ir.unlink(bb, dst); - let using_xmm = bb.get_using_xmm(); - let error = ir.new_error(bb, pc); - ir.inst.push(AsmInst::SingletonClassDef { + self.write_back_slots(bbctx, &[base]); + self.unlink(bbctx, dst); + let using_xmm = bbctx.get_using_xmm(); + let error = self.new_error(bbctx, pc); + self.inst.push(AsmInst::SingletonClassDef { base, dst, func_id, diff --git a/monoruby/src/compiler/jitgen/asmir/method_call.rs b/monoruby/src/compiler/jitgen/asmir/method_call.rs index 76274581..79967509 100644 --- a/monoruby/src/compiler/jitgen/asmir/method_call.rs +++ b/monoruby/src/compiler/jitgen/asmir/method_call.rs @@ -1,7 +1,65 @@ use super::*; impl AsmIr { - pub(in crate::compiler::jitgen) fn gen_call( + pub(in crate::compiler::jitgen) fn compile_call( + &mut self, + store: &Store, + bbctx: &mut BBContext, + pc: BytecodePtr, + callid: CallSiteId, + recv_class: Option, + fid: Option, + version: u32, + ) -> CompileResult { + if let Some(fid) = fid { + let recv_class = recv_class.unwrap(); + if store[callid].block_fid.is_none() + && let Some(info) = store.inline_info.get_inline(fid) + { + let is_simple = store[callid].is_simple(); + if fid == OBJECT_SEND_FUNCID && store[callid].object_send_single_splat() { + let f = object_send_splat; + self.inline_call(store, bbctx, f, fid, callid, recv_class, version, pc); + CompileResult::Continue + } else if is_simple { + let f = &info.inline_gen; + self.inline_call(store, bbctx, f, fid, callid, recv_class, version, pc); + CompileResult::Continue + } else { + self.call(store, bbctx, fid, recv_class, version, callid, pc) + } + } else { + self.call(store, bbctx, fid, recv_class, version, callid, pc) + } + } else { + CompileResult::Recompile + } + } + + pub(in crate::compiler::jitgen) fn compile_yield( + &mut self, + store: &Store, + bbctx: &mut BBContext, + pc: BytecodePtr, + callid: CallSiteId, + ) { + let callinfo = &store[callid]; + let dst = callinfo.dst; + self.write_back_callargs_and_dst(bbctx, &callinfo); + self.writeback_acc(bbctx); + let using_xmm = bbctx.get_using_xmm(); + let error = self.new_error(bbctx, pc); + let evict = self.new_evict(); + self.inst.push(AsmInst::Yield { + callid, + using_xmm, + error, + evict, + }); + self.rax2acc(bbctx, dst); + } + + fn call( &mut self, store: &Store, bb: &mut BBContext, @@ -10,13 +68,12 @@ impl AsmIr { version: u32, callid: CallSiteId, pc: BytecodePtr, - ) -> Option<()> { + ) -> CompileResult { let CallSiteInfo { dst, recv, .. } = store[callid]; if recv.is_self() && bb.self_value.class() != recv_class { // the inline method cache is invalid because the receiver class is not matched. self.write_back_locals(bb); - self.write_back_callargs(bb, &store[callid]); - self.unlink(bb, dst); + self.write_back_callargs_and_dst(bb, &store[callid]); self.writeback_acc(bb); self.send_not_cached(bb, pc, callid); self.rax2acc(bb, dst); @@ -34,15 +91,40 @@ impl AsmIr { if !recv.is_self() && !bb.is_class(recv, recv_class) { self.guard_class(bb, recv, GP::Rdi, recv_class, deopt); } - let evict = self.gen_call_cached(store, bb, callid, fid, recv_class, pc)?; - self.rax2acc(bb, dst); - if let Some(evict) = evict { - self.inst.push(AsmInst::ImmediateEvict { evict }); - self[evict] = SideExit::Evict(Some((pc + 2, bb.get_write_back()))); + if let Some(evict) = self.call_cached(store, bb, callid, fid, recv_class, pc) { + self.rax2acc(bb, dst); + if let Some(evict) = evict { + self.inst.push(AsmInst::ImmediateEvict { evict }); + self[evict] = SideExit::Evict(Some((pc + 2, bb.get_write_back()))); + } + } else { + return CompileResult::Recompile; } } - Some(()) + CompileResult::Continue + } + + fn inline_call( + &mut self, + store: &Store, + bb: &mut BBContext, + f: impl Fn(&mut AsmIr, &Store, &mut BBContext, CallSiteId, BytecodePtr), + fid: FuncId, + callid: CallSiteId, + recv_class: ClassId, + version: u32, + pc: BytecodePtr, + ) { + let recv = store[callid].recv; + self.fetch_to_reg(bb, recv, GP::Rdi); + let (deopt, error) = self.new_deopt_error(bb, pc); + let using_xmm = bb.get_using_xmm(); + self.guard_version(fid, version, callid, using_xmm, deopt, error); + if !recv.is_self() && !bb.is_class(recv, recv_class) { + self.guard_class(bb, recv, GP::Rdi, recv_class, deopt); + } + f(self, store, bb, callid, pc); } /// @@ -51,7 +133,7 @@ impl AsmIr { /// ### in /// - rdi: receiver: Value /// - fn gen_call_cached( + fn call_cached( &mut self, store: &Store, bb: &mut BBContext, @@ -88,19 +170,87 @@ impl AsmIr { self.fetch_to_reg(bb, args, GP::Rdx); self.attr_writer(bb, pc, ivar_id); } - FuncKind::Builtin { .. } => { - let evict = self.new_evict(); - self.send_cached(store, bb, pc, callid, fid, recv_class, true, evict); - return Some(Some(evict)); - } - FuncKind::ISeq(_) => { + FuncKind::Builtin { .. } | FuncKind::ISeq(_) => { let evict = self.new_evict(); - self.send_cached(store, bb, pc, callid, fid, recv_class, false, evict); + self.send_cached(store, bb, pc, callid, fid, recv_class, evict); return Some(Some(evict)); } }; Some(None) } + + /// + /// ### in + /// rdi: receiver: Value + /// + fn send_cached( + &mut self, + store: &Store, + bb: &mut BBContext, + pc: BytecodePtr, + callid: CallSiteId, + callee_fid: FuncId, + recv_class: ClassId, + evict: AsmEvict, + ) { + self.reg_move(GP::Rdi, GP::R13); + self.exec_gc(bb.get_register()); + let using_xmm = bb.get_using_xmm(); + self.xmm_save(using_xmm); + self.set_arguments(store, bb, callid, callee_fid, pc); + self.unlink(bb, store[callid].dst); + self.clear(bb); + let error = self.new_error(bb, pc); + self.writeback_acc(bb); + self.inst.push(AsmInst::SendCached { + callid, + callee_fid, + recv_class, + using_xmm, + error, + evict, + }); + } + + fn send_not_cached(&mut self, bb: &BBContext, pc: BytecodePtr, callid: CallSiteId) { + let using_xmm = bb.get_using_xmm(); + let error = self.new_error(bb, pc); + let evict = self.new_evict(); + let self_class = bb.self_value.class(); + self.inst.push(AsmInst::SendNotCached { + self_class, + callid, + pc, + using_xmm, + error, + evict, + }); + } + + /// + /// Attribute writer + /// + /// ### in + /// - rdi: receiver: Value + /// - rdx: value: Value + /// + fn attr_writer(&mut self, bb: &BBContext, pc: BytecodePtr, ivar_id: IvarId) { + let using_xmm = bb.get_using_xmm(); + let error = self.new_error(bb, pc); + self.inst.push(AsmInst::AttrWriter { + using_xmm, + error, + ivar_id, + }); + } + + /// + /// ### in + /// - rdi: receiver: Value + /// + fn attr_reader(&mut self, ivar_id: IvarId) { + self.inst.push(AsmInst::AttrReader { ivar_id }); + } } #[cfg(test)] diff --git a/monoruby/src/compiler/jitgen/compile.rs b/monoruby/src/compiler/jitgen/compile.rs new file mode 100644 index 00000000..5054a861 --- /dev/null +++ b/monoruby/src/compiler/jitgen/compile.rs @@ -0,0 +1,647 @@ +use super::*; + +impl JitContext { + pub(super) fn compile_basic_block( + &mut self, + codegen: &mut Codegen, + store: &Store, + func: &ISeqInfo, + position: Option, + bbid: BasicBlockId, + ) -> AsmIr { + let mut ir = AsmIr::new(); + ir.inst.push(AsmInst::Label(self.basic_block_labels[&bbid])); + let mut bbctx = if let Some(bb) = self.target_ctx.remove(&bbid) { + bb + } else if let Some(bb) = self.incoming_context(&mut ir, func, bbid) { + self.gen_continuation(&mut ir); + bb + } else { + #[cfg(feature = "jit-debug")] + eprintln!("=== no entry"); + return ir; + }; + + let BasciBlockInfoEntry { begin, end, .. } = func.bb_info[bbid]; + for bc_pos in begin..=end { + ir.bc_index(bc_pos); + bbctx.next_sp = func.get_sp(bc_pos); + + match self.compile_instruction(codegen, &mut ir, &mut bbctx, store, func, bc_pos) { + CompileResult::Continue => {} + CompileResult::Branch => return ir, + CompileResult::Recompile => { + let pc = func.get_pc(bc_pos); + ir.recompile_and_deopt(&mut bbctx, pc, position); + return ir; + } + CompileResult::ExitLoop => break, + } + + ir.clear(&mut bbctx); + bbctx.sp = bbctx.next_sp; + } + + let next_idx = end + 1; + if let Some(next_bbid) = func.bb_info.is_bb_head(next_idx) { + let label = codegen.jit.label(); + self.new_continue(func, end, next_bbid, bbctx, label); + if let Some(target_ctx) = self.incoming_context(&mut ir, func, next_bbid) { + self.gen_continuation(&mut ir); + assert!(self.target_ctx.insert(next_bbid, target_ctx).is_none()); + } + } else { + unreachable!(); + } + ir + } + + fn compile_instruction( + &mut self, + codegen: &mut Codegen, + ir: &mut AsmIr, + bbctx: &mut BBContext, + store: &Store, + func: &ISeqInfo, + bc_pos: BcIndex, + ) -> CompileResult { + let pc = func.get_pc(bc_pos); + let trace_ir = func.trace_ir(store, bc_pos); + match trace_ir { + TraceIr::InitMethod { .. } => {} + TraceIr::LoopStart { .. } => { + self.loop_count += 1; + } + TraceIr::LoopEnd => { + assert_ne!(0, self.loop_count); + self.loop_count -= 1; + if self.is_loop && self.loop_count == 0 { + ir.deopt(bbctx, pc); + return CompileResult::ExitLoop; + } + } + TraceIr::Integer(dst, i) => { + ir.store_concrete_value(bbctx, dst, Value::i32(i)); + } + TraceIr::Symbol(dst, id) => { + ir.store_concrete_value(bbctx, dst, Value::symbol(id)); + } + TraceIr::Nil(dst) => { + ir.store_concrete_value(bbctx, dst, Value::nil()); + } + TraceIr::Literal(dst, val) => { + ir.unlink(bbctx, dst); + if val.is_packed_value() || val.is_float() { + ir.store_concrete_value(bbctx, dst, val); + } else { + ir.deep_copy_lit(bbctx, val); + ir.reg2acc_guarded(bbctx, GP::Rax, dst, Guarded::from_concrete_value(val)); + } + } + TraceIr::Array { dst, callid } => { + let CallSiteInfo { args, pos_num, .. } = store[callid]; + ir.write_back_range(bbctx, args, pos_num as u16); + ir.unlink(bbctx, dst); + ir.new_array(bbctx, callid); + ir.reg2acc_guarded(bbctx, GP::Rax, dst, Guarded::ArrayTy); + } + TraceIr::Lambda { dst, func_id } => { + ir.unlink(bbctx, dst); + ir.new_lambda(bbctx, func_id); + ir.rax2acc(bbctx, dst); + } + TraceIr::Hash { dst, args, len } => { + ir.write_back_range(bbctx, args, len * 2); + ir.unlink(bbctx, dst); + ir.new_hash(bbctx, args, len as _); + ir.rax2acc(bbctx, dst); + } + TraceIr::Range { + dst, + start, + end, + exclude_end, + } => { + ir.write_back_slots(bbctx, &[start, end]); + ir.unlink(bbctx, dst); + ir.new_range(bbctx, pc, start, end, exclude_end); + ir.rax2acc(bbctx, dst); + } + TraceIr::Index { + dst, + base, + idx, + base_class, + idx_class, + } => { + ir.index(bbctx, dst, base, idx, base_class, idx_class, pc); + } + TraceIr::IndexAssign { + src, + base, + idx, + base_class, + idx_class, + } => { + ir.index_assign(bbctx, src, base, idx, base_class, idx_class, pc); + } + TraceIr::LoadConst(dst, id) => { + ir.unlink(bbctx, dst); + + if let ConstCache { + cached_version, + cached_base_class, + cached_value: Some(cached_val), + } = store[id].cache + { + let base_slot = store[id].base; + if let Some(slot) = base_slot { + if let Some(base_class) = cached_base_class { + ir.fetch_to_reg(bbctx, slot, GP::Rax); + let deopt = ir.new_deopt(bbctx, pc); + ir.inst.push(AsmInst::GuardBaseClass { base_class, deopt }); + } else { + return CompileResult::Recompile; + } + } + let deopt = ir.new_deopt(bbctx, pc); + if let Some(f) = cached_val.try_float() { + let fdst = ir.store_new_both(bbctx, dst, Guarded::Float); + ir.inst.push(AsmInst::LoadFloatConstant { + fdst, + f, + cached_version, + deopt, + }); + ir.reg2stack(GP::Rax, dst); + } else { + ir.inst.push(AsmInst::LoadGenericConstant { + cached_val, + cached_version, + deopt, + }); + ir.rax2acc(bbctx, dst); + } + } else { + return CompileResult::Recompile; + } + } + TraceIr::StoreConst(src, id) => { + ir.fetch_to_reg(bbctx, src, GP::Rax); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::StoreConstant { id, using_xmm }); + } + TraceIr::BlockArgProxy(ret, outer) => { + ir.unlink(bbctx, ret); + ir.block_arg_proxy(ret, outer); + } + TraceIr::BlockArg(ret, outer) => { + ir.unlink(bbctx, ret); + ir.block_arg(bbctx, pc, ret, outer); + } + TraceIr::LoadIvar(ret, id, cached_class, cached_ivarid) => { + if let Some(cached_class) = cached_class { + ir.load_ivar(bbctx, id, ret, cached_class, cached_ivarid); + } else { + return CompileResult::Recompile; + } + } + TraceIr::StoreIvar(src, id, cached_class, cached_ivarid) => { + if let Some(cached_class) = cached_class { + ir.store_ivar(bbctx, id, src, pc, cached_class, cached_ivarid); + } else { + return CompileResult::Recompile; + } + } + TraceIr::LoadCvar { dst, name } => { + ir.jit_load_cvar(bbctx, pc, name, dst); + } + TraceIr::CheckCvar { dst, name } => { + ir.jit_check_cvar(bbctx, name, dst); + } + TraceIr::StoreCvar { src: val, name } => { + ir.jit_store_cvar(bbctx, pc, name, val); + } + TraceIr::LoadGvar { dst, name } => { + ir.jit_load_gvar(bbctx, name, dst); + } + TraceIr::StoreGvar { src: val, name } => { + ir.jit_store_gvar(bbctx, name, val); + } + TraceIr::LoadSvar { dst, id } => { + ir.unlink(bbctx, dst); + ir.load_svar(bbctx, id); + ir.rax2acc(bbctx, dst); + } + TraceIr::LoadDynVar(dst, src) => { + ir.unlink(bbctx, dst); + if !dst.is_self() { + ir.inst.push(AsmInst::LoadDynVar { src }); + ir.rax2acc(bbctx, dst); + } + } + TraceIr::StoreDynVar(dst, src) => { + ir.fetch_to_reg(bbctx, src, GP::Rdi); + ir.inst.push(AsmInst::StoreDynVar { dst, src: GP::Rdi }); + } + TraceIr::BitNot { + dst, + src, + src_class, + } => { + if src_class.is_none() { + return CompileResult::Recompile; + } + ir.fetch_to_reg(bbctx, src, GP::Rdi); + ir.generic_unop(bbctx, pc, bitnot_value); + ir.rax2acc(bbctx, dst); + } + TraceIr::Not { dst, src, .. } => { + if bbctx.is_truthy(src) { + ir.store_concrete_value(bbctx, dst, Value::bool(false)); + } else if bbctx.is_falsy(src) { + ir.store_concrete_value(bbctx, dst, Value::bool(true)); + } else { + ir.fetch_to_reg(bbctx, src, GP::Rdi); + ir.inst.push(AsmInst::Not); + ir.rax2acc(bbctx, dst); + } + } + TraceIr::FUnOp { kind, dst, src } => { + let deopt = ir.new_deopt(bbctx, pc); + let fsrc = ir.fetch_float_assume_float(bbctx, src, deopt); + let dst = ir.xmm_write(bbctx, dst); + ir.xmm_move(fsrc, dst); + ir.inst.push(AsmInst::XmmUnOp { kind, dst }); + } + TraceIr::IUnOp { kind, dst, src } => { + ir.fetch_to_reg(bbctx, src, GP::Rdi); + ir.generic_unop(bbctx, pc, kind.generic_func()); + ir.rax2acc(bbctx, dst); + } + TraceIr::UnOp { + kind, + dst, + src, + src_class, + } => { + if src_class.is_none() { + return CompileResult::Recompile; + } + ir.fetch_to_reg(bbctx, src, GP::Rdi); + ir.generic_unop(bbctx, pc, kind.generic_func()); + ir.rax2acc(bbctx, dst); + } + TraceIr::IBinOp { + kind, dst, mode, .. + } => { + ir.gen_binop_integer(bbctx, pc, kind, dst, mode); + } + TraceIr::FBinOp { + kind, + dst, + mode, + lhs_class, + rhs_class, + } => { + let deopt = ir.new_deopt(bbctx, pc); + let fmode = ir.fmode(&mode, bbctx, lhs_class, rhs_class, deopt); + if let Some(ret) = dst { + let dst = ir.xmm_write(bbctx, ret); + let using_xmm = bbctx.get_using_xmm(); + ir.xmm_binop(kind, fmode, dst, using_xmm); + } + } + TraceIr::BinOp { + kind, + dst, + mode, + lhs_class, + rhs_class, + } => { + if lhs_class.is_none() || rhs_class.is_none() { + return CompileResult::Recompile; + } + ir.fetch_binary(bbctx, mode); + ir.generic_binop(bbctx, pc, kind); + ir.rax2acc(bbctx, dst); + } + TraceIr::FCmp { + kind, + dst, + mode, + lhs_class, + rhs_class, + } => { + if kind != CmpKind::Cmp { + let deopt = ir.new_deopt(bbctx, pc); + let mode = ir.fmode(&mode, bbctx, lhs_class, rhs_class, deopt); + ir.unlink(bbctx, dst); + ir.clear(bbctx); + ir.inst.push(AsmInst::FloatCmp { kind, mode }); + } else { + ir.fetch_binary(bbctx, mode); + ir.generic_cmp(bbctx, pc, kind); + } + ir.rax2acc(bbctx, dst); + } + TraceIr::ICmp { kind, dst, mode } => { + ir.fetch_fixnum_binary(bbctx, pc, &mode); + ir.inst.push(AsmInst::IntegerCmp { kind, mode }); + ir.rax2acc(bbctx, dst); + } + TraceIr::Cmp { + kind, + dst, + mode, + lhs_class, + rhs_class, + } => { + if lhs_class.is_none() || rhs_class.is_none() { + return CompileResult::Recompile; + } + ir.fetch_binary(bbctx, mode); + ir.generic_cmp(bbctx, pc, kind); + ir.rax2acc(bbctx, dst); + } + TraceIr::FCmpBr { + kind, + dst, + mode, + lhs_class, + rhs_class, + dest, + brkind, + } => { + let index = bc_pos + 1; + let branch_dest = codegen.jit.label(); + let deopt = ir.new_deopt(bbctx, pc); + let mode = ir.fmode(&mode, bbctx, lhs_class, rhs_class, deopt); + ir.unlink(bbctx, dst); + ir.clear(bbctx); + ir.float_cmp_br(mode, kind, brkind, branch_dest); + self.new_branch(func, index, dest, bbctx.clone(), branch_dest); + } + TraceIr::ICmpBr { + kind, + dst, + mode, + dest, + brkind, + } => { + let index = bc_pos + 1; + let branch_dest = codegen.jit.label(); + ir.fetch_fixnum_binary(bbctx, pc, &mode); + ir.unlink(bbctx, dst); + ir.clear(bbctx); + ir.integer_cmp_br(mode, kind, brkind, branch_dest); + self.new_branch(func, index, dest, bbctx.clone(), branch_dest); + } + TraceIr::CmpBr { + kind, + dst, + mode, + dest, + brkind, + .. + } => { + let index = bc_pos + 1; + let branch_dest = codegen.jit.label(); + ir.fetch_binary(bbctx, mode); + ir.unlink(bbctx, dst); + ir.clear(bbctx); + ir.generic_cmp(bbctx, pc, kind); + ir.inst.push(AsmInst::GenericCondBr { + brkind, + branch_dest, + }); + self.new_branch(func, index, dest, bbctx.clone(), branch_dest); + } + TraceIr::Mov(dst, src) => { + ir.copy_slot(bbctx, src, dst); + } + TraceIr::ConcatStr(dst, arg, len) => { + ir.write_back_range(bbctx, arg, len); + ir.unlink(bbctx, dst); + let error = ir.new_error(bbctx, pc); + ir.concat_str(bbctx, arg, len); + ir.handle_error(error); + ir.rax2acc(bbctx, dst); + } + TraceIr::ConcatRegexp(dst, arg, len) => { + ir.write_back_range(bbctx, arg, len); + ir.unlink(bbctx, dst); + let error = ir.new_error(bbctx, pc); + ir.concat_regexp(bbctx, arg, len); + ir.handle_error(error); + ir.rax2acc(bbctx, dst); + } + TraceIr::ExpandArray { + src, + dst: (dst, len), + } => { + ir.fetch_to_reg(bbctx, src, GP::Rdi); + for reg in dst.0..dst.0 + len { + ir.unlink(bbctx, SlotId(reg)); + } + ir.expand_array(bbctx, dst, len); + } + TraceIr::AliasMethod { new, old } => { + ir.alias_method(bbctx, pc, new, old); + } + TraceIr::MethodCall { + callid, + recv_class, + fid, + version, + } + | TraceIr::MethodCallWithBlock { + callid, + recv_class, + fid, + version, + } => return ir.compile_call(store, bbctx, pc, callid, recv_class, fid, version), + TraceIr::Yield { callid } => { + ir.compile_yield(store, bbctx, pc, callid); + } + TraceIr::InlineCache => {} + TraceIr::MethodDef { name, func_id } => { + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::MethodDef { + name, + func_id, + using_xmm, + }); + ir.check_bop(bbctx, pc); + } + TraceIr::SingletonMethodDef { obj, name, func_id } => { + ir.write_back_slots(bbctx, &[obj]); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::SingletonMethodDef { + obj, + name, + func_id, + using_xmm, + }); + ir.check_bop(bbctx, pc); + } + TraceIr::ClassDef { + dst, + base, + superclass, + name, + func_id, + } => { + ir.class_def(bbctx, dst, base, superclass, name, func_id, false, pc); + } + TraceIr::ModuleDef { + dst, + base, + name, + func_id, + } => { + ir.class_def(bbctx, dst, base, None, name, func_id, true, pc); + } + TraceIr::SingletonClassDef { dst, base, func_id } => { + ir.singleton_class_def(bbctx, dst, base, func_id, pc); + } + TraceIr::DefinedYield { dst } => { + ir.write_back_slots(bbctx, &[dst]); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::DefinedYield { dst, using_xmm }); + } + TraceIr::DefinedConst { dst, siteid } => { + ir.write_back_slots(bbctx, &[dst]); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::DefinedConst { + dst, + siteid, + using_xmm, + }); + } + TraceIr::DefinedMethod { dst, recv, name } => { + ir.write_back_slots(bbctx, &[dst, recv]); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::DefinedMethod { + dst, + recv, + name, + using_xmm, + }); + } + TraceIr::DefinedGvar { dst, name } => { + ir.write_back_slots(bbctx, &[dst]); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::DefinedGvar { + dst, + name, + using_xmm, + }); + } + TraceIr::DefinedIvar { dst, name } => { + ir.write_back_slots(bbctx, &[dst]); + let using_xmm = bbctx.get_using_xmm(); + ir.inst.push(AsmInst::DefinedIvar { + dst, + name, + using_xmm, + }); + } + TraceIr::Ret(ret) => { + ir.write_back_locals(bbctx); + ir.fetch_to_reg(bbctx, ret, GP::Rax); + ir.inst.push(AsmInst::Ret); + return CompileResult::Branch; + } + TraceIr::MethodRet(ret) => { + ir.write_back_locals(bbctx); + ir.fetch_to_reg(bbctx, ret, GP::Rax); + ir.inst.push(AsmInst::MethodRet(pc)); + return CompileResult::Branch; + } + TraceIr::BlockBreak(ret) => { + ir.write_back_locals(bbctx); + ir.fetch_to_reg(bbctx, ret, GP::Rax); + ir.inst.push(AsmInst::BlockBreak); + return CompileResult::Branch; + } + TraceIr::Raise(ret) => { + ir.write_back_locals(bbctx); + ir.fetch_to_reg(bbctx, ret, GP::Rax); + ir.inst.push(AsmInst::Raise); + return CompileResult::Branch; + } + TraceIr::EnsureEnd => { + ir.write_back_locals(bbctx); + ir.inst.push(AsmInst::EnsureEnd); + } + TraceIr::Br(dest_idx) => { + self.compile_branch(codegen, ir, bbctx, func, bc_pos, dest_idx); + return CompileResult::Branch; + } + TraceIr::CondBr(cond_, dest_idx, false, brkind) => { + if bbctx.is_truthy(cond_) { + if brkind == BrKind::BrIf { + self.compile_branch(codegen, ir, bbctx, func, bc_pos, dest_idx); + return CompileResult::Branch; + } + } else if bbctx.is_falsy(cond_) { + if brkind == BrKind::BrIfNot { + self.compile_branch(codegen, ir, bbctx, func, bc_pos, dest_idx); + return CompileResult::Branch; + } + } else { + let branch_dest = codegen.jit.label(); + ir.fetch_to_reg(bbctx, cond_, GP::Rax); + ir.inst.push(AsmInst::CondBr(brkind, branch_dest)); + self.new_branch(func, bc_pos, dest_idx, bbctx.clone(), branch_dest); + } + } + TraceIr::NilBr(cond_, dest_idx) => { + let branch_dest = codegen.jit.label(); + ir.fetch_to_reg(bbctx, cond_, GP::Rax); + ir.inst.push(AsmInst::NilBr(branch_dest)); + self.new_branch(func, bc_pos, dest_idx, bbctx.clone(), branch_dest); + } + TraceIr::CondBr(_, _, true, _) => {} + TraceIr::CheckLocal(local, dest_idx) => { + let branch_dest = codegen.jit.label(); + ir.fetch_to_reg(bbctx, local, GP::Rax); + ir.inst.push(AsmInst::CheckLocal(branch_dest)); + self.new_branch(func, bc_pos, dest_idx, bbctx.clone(), branch_dest); + } + TraceIr::OptCase { + cond, + min, + max, + dest_bb, + branch_table, + } => { + let else_idx = dest_bb[0]; + for bbid in dest_bb { + let branch_dest = codegen.jit.label(); + self.new_branch(func, bc_pos, bbid, bbctx.clone(), branch_dest); + } + let deopt = ir.new_deopt(bbctx, pc); + ir.fetch_guard_fixnum(bbctx, cond, GP::Rdi, deopt); + ir.opt_case(max, min, else_idx, branch_table); + return CompileResult::Branch; + } + } + CompileResult::Continue + } + + fn compile_branch( + &mut self, + codegen: &mut Codegen, + ir: &mut AsmIr, + bbctx: &mut BBContext, + func: &ISeqInfo, + bc_pos: BcIndex, + dest: BasicBlockId, + ) { + let branch_dest = codegen.jit.label(); + ir.inst.push(AsmInst::Br(branch_dest)); + self.new_branch(func, bc_pos, dest, bbctx.clone(), branch_dest); + } +} diff --git a/monoruby/src/compiler/jitgen/init_method.rs b/monoruby/src/compiler/jitgen/init_method.rs index 55c120db..20330f7e 100644 --- a/monoruby/src/compiler/jitgen/init_method.rs +++ b/monoruby/src/compiler/jitgen/init_method.rs @@ -8,25 +8,24 @@ impl Codegen { ); match func.trace_ir(store, BcIndex::from(0)) { TraceIr::InitMethod(fn_info) => { - self.setup_stack(fn_info.stack_offset); self.init_func(&fn_info); } _ => unreachable!(), } } - fn setup_stack(&mut self, stack_offset: usize) { - monoasm!( &mut self.jit, - subq rsp, (stack_offset * 16); - ); - } - fn init_func(&mut self, fn_info: &FnInitInfo) { - // fill block parameter. let FnInitInfo { - reg_num, arg_num, .. + reg_num, + arg_num, + stack_offset, + .. } = *fn_info; + monoasm!( &mut self.jit, + subq rsp, (stack_offset * 16); + ); + let l1 = self.jit.label(); self.test_heap_frame(); monoasm! { &mut self.jit, diff --git a/monoruby/src/compiler/jitgen/trace_ir.rs b/monoruby/src/compiler/jitgen/trace_ir.rs index 2f7bfb9c..7cb7e4e3 100644 --- a/monoruby/src/compiler/jitgen/trace_ir.rs +++ b/monoruby/src/compiler/jitgen/trace_ir.rs @@ -53,11 +53,6 @@ pub(crate) enum TraceIr { end: SlotId, exclude_end: bool, }, - ArrayIndex { - dst: SlotId, - base: SlotId, - idx: SlotId, - }, Index { dst: SlotId, base: SlotId, @@ -65,11 +60,6 @@ pub(crate) enum TraceIr { base_class: Option, idx_class: Option, }, - ArrayIndexAssign { - src: SlotId, - base: SlotId, - idx: SlotId, - }, IndexAssign { src: SlotId, base: SlotId, @@ -203,10 +193,16 @@ pub(crate) enum TraceIr { /// return(%src) Ret(SlotId), + /// + /// Return from method. + /// /// method_return(%src) MethodRet(SlotId), - /// method_return(%src) - Break(SlotId), + /// + /// Break from block. + /// + /// break(%src) + BlockBreak(SlotId), /// raise(%src) Raise(SlotId), /// ensure_end @@ -230,7 +226,7 @@ pub(crate) enum TraceIr { fid: Option, version: u32, }, - MethodCallBlock { + MethodCallWithBlock { callid: CallSiteId, recv_class: Option, fid: Option, @@ -337,7 +333,10 @@ impl<'a> DefKind<'a> { impl TraceIr { pub(crate) fn get_exit_type(&self) -> Option { match self { - TraceIr::Ret(..) | TraceIr::MethodRet(..) | TraceIr::Break(..) | TraceIr::Raise(..) => { + TraceIr::Ret(..) + | TraceIr::MethodRet(..) + | TraceIr::BlockBreak(..) + | TraceIr::Raise(..) => { return Some(ExitType::Return); } TraceIr::Br(_) @@ -583,10 +582,6 @@ impl TraceIr { TraceIr::Hash { dst, args, len } => { format!("{:?} = hash[{:?}; {}]", dst, args, len) } - TraceIr::ArrayIndex { dst, base, idx } => { - let op1 = format!("{:?} = {:?}.[{:?}]", dst, base, idx); - fmt(store, op1, Some(ARRAY_CLASS), Some(INTEGER_CLASS)) - } TraceIr::Index { dst, base, @@ -597,10 +592,6 @@ impl TraceIr { let op1 = format!("{:?} = {:?}.[{:?}]", dst, base, idx); fmt(store, op1, *base_class, *idx_class) } - TraceIr::ArrayIndexAssign { src, base, idx } => { - let op1 = format!("{:?}:.[{:?}:] = {:?}", base, idx, src,); - fmt(store, op1, Some(ARRAY_CLASS), Some(INTEGER_CLASS)) - } TraceIr::IndexAssign { src, base, @@ -807,7 +798,7 @@ impl TraceIr { TraceIr::Ret(reg) => format!("ret {:?}", reg), TraceIr::MethodRet(reg) => format!("method_ret {:?}", reg), - TraceIr::Break(reg) => format!("break {:?}", reg), + TraceIr::BlockBreak(reg) => format!("break {:?}", reg), TraceIr::Raise(reg) => format!("raise {:?}", reg), TraceIr::EnsureEnd => format!("ensure_end"), TraceIr::Mov(dst, src) => format!("{:?} = {:?}", dst, src), @@ -817,7 +808,7 @@ impl TraceIr { fid, .. } - | TraceIr::MethodCallBlock { + | TraceIr::MethodCallWithBlock { callid, recv_class, fid, @@ -830,25 +821,10 @@ impl TraceIr { && (*fid == OBJECT_SEND_FUNCID && callsite.object_send_single_splat() || callsite.is_simple()) { - let CallSiteInfo { - recv, - args, - pos_num, - dst, - .. - } = *callsite; + let CallSiteInfo { recv, dst, .. } = *callsite; let name = &inline_info.name; - let op1 = if pos_num == 0 { - format!("{} = {:?}.inline {name}()", ret_str(dst), recv) - } else { - format!( - "{} = {:?}.inline {name}({:?}; {})", - ret_str(dst), - recv, - args, - pos_num, - ) - }; + let s = callsite.format_args(); + let op1 = format!("{} = {:?}.inline {name}{s}", ret_str(dst), recv,); format!("{:36} [{}]", op1, store.debug_class_name(*recv_class)) } else { let name = if let Some(name) = callsite.name { @@ -856,57 +832,16 @@ impl TraceIr { } else { "super".to_string() }; - let CallSiteInfo { - recv, - args, - pos_num, - kw_pos, - kw_args, - dst, - block_fid, - block_arg, - .. - } = callsite; - let has_splat = callsite.has_splat(); - // TODO: we must handle hash aplat arguments correctly. - let kw_len = kw_args.len(); - let op1 = format!( - "{} = {:?}.{name}({}{}{}){}", - ret_str(*dst), - recv, - if *pos_num == 0 { - "".to_string() - } else { - format!("{:?};{}{}", args, pos_num, if has_splat { "*" } else { "" }) - }, - if kw_len == 0 { - "".to_string() - } else { - format!(" kw:{:?};{}", kw_pos, kw_len) - }, - if let Some(block_arg) = block_arg { - format!(" &{:?}", block_arg) - } else { - "".to_string() - }, - if let Some(block_fid) = block_fid { - format!(" {{ {:?} }}", block_fid) - } else { - "".to_string() - }, - ); + let CallSiteInfo { recv, dst, .. } = callsite; + let s = callsite.format_args(); + let op1 = format!("{} = {:?}.{name}{s}", ret_str(*dst), recv,); format!("{:36} [{}]", op1, store.debug_class_name(*recv_class),) } } TraceIr::Yield { callid } => { - let CallSiteInfo { - args, pos_num, dst, .. - } = store[*callid]; - if pos_num == 0 { - format!("{} = yield", ret_str(dst)) - } else { - format!("{} = yield({:?}; {})", ret_str(dst), args, pos_num) - } + let dst = store[*callid].dst; + let s = store[*callid].format_args(); + format!("{} = yield{s}", ret_str(dst)) } TraceIr::InlineCache => return None, TraceIr::MethodDef { name, func_id } => { @@ -923,14 +858,18 @@ impl TraceIr { func_id, } => { format!( - "{} = class_def {}{name} < {:?}: {:?}", + "{} = class_def {}{name}{}: {:?}", ret_str(*dst), if let Some(base) = base { format!("{:?}::", base) } else { "".to_string() }, - superclass, + if let Some(superclass) = superclass { + format!(" < {:?}", superclass) + } else { + "".to_string() + }, func_id ) } @@ -978,21 +917,10 @@ impl TraceIr { TraceIr::AliasMethod { new, old } => { format!("alias_method({:?}<-{:?})", new, old) } - TraceIr::DefinedYield { dst: ret } => format!("{:?} = defined?(yield)", ret), - TraceIr::DefinedConst { dst: ret, siteid } => { - let ConstSiteInfo { - name, - prefix, - toplevel, - .. - } = &store[*siteid]; - let mut const_name = if *toplevel { "::" } else { "" }.to_string(); - for c in prefix { - c.append_to(&mut const_name); - const_name += "::"; - } - name.append_to(&mut const_name); - format!("{:?} = defined?(constant) {const_name}", ret) + TraceIr::DefinedYield { dst } => format!("{:?} = defined?(yield)", dst), + TraceIr::DefinedConst { dst, siteid } => { + let s = store[*siteid].format(); + format!("{:?} = defined?(constant) {s}", dst) } TraceIr::DefinedMethod { dst: ret, diff --git a/monoruby/src/compiler/vmgen.rs b/monoruby/src/compiler/vmgen.rs index fb95217b..3f2aeee2 100644 --- a/monoruby/src/compiler/vmgen.rs +++ b/monoruby/src/compiler/vmgen.rs @@ -890,9 +890,9 @@ impl Codegen { fn vm_loop_start(&mut self, no_jit: bool) -> CodePtr { let label = self.jit.get_current_address(); - let count = self.jit.label(); let compile = self.jit.label(); - if !no_jit { + if !no_jit && !cfg!(feature = "no-jit") { + let count = self.jit.label(); monoasm! { &mut self.jit, movq rax, [r13 - 8]; testq rax, rax; @@ -905,7 +905,7 @@ impl Codegen { }; }; self.fetch_and_dispatch(); - if !no_jit { + if !no_jit && !cfg!(feature = "no-jit") { monoasm!( &mut self.jit, compile: movq rdi, rbx; @@ -1009,7 +1009,7 @@ impl Codegen { movq rax, (runtime::gen_lambda); call rax; } - self.restore_lbp(); + self.restore_lfp(); monoasm! { &mut self.jit, movzxw rdi, [r13 - 12]; // r15 <- :1 negq rdi; @@ -1110,7 +1110,7 @@ impl Codegen { self.fetch2(); self.vm_get_slot_addr(GP::R15); monoasm! { &mut self.jit, - lea rax, [r14 - (LFP_OUTER)]; + movq rax, r14; testq rdi, rdi; jz loop_exit; loop_: @@ -1118,7 +1118,6 @@ impl Codegen { subl rdi, 1; jnz loop_; loop_exit: - lea rax, [rax + (LFP_OUTER)]; movq rax, [rax - (LFP_BLOCK)]; movq rdi, (Value::nil().id()); testq rax, rax; @@ -1146,7 +1145,7 @@ impl Codegen { self.fetch2(); self.vm_get_slot_addr(GP::R15); monoasm! { &mut self.jit, - lea rax, [r14 - (LFP_OUTER)]; + movq rax, r14; testq rdi, rdi; jz loop_exit; loop_: @@ -1154,7 +1153,6 @@ impl Codegen { subl rdi, 1; jnz loop_; loop_exit: - lea rax, [rax + (LFP_OUTER)]; movq rdx, [rax - (LFP_BLOCK)]; movq rdi, rbx; movq rsi, r12; diff --git a/monoruby/src/compiler/vmgen/definition.rs b/monoruby/src/compiler/vmgen/definition.rs index f7f3cdaf..181d159d 100644 --- a/monoruby/src/compiler/vmgen/definition.rs +++ b/monoruby/src/compiler/vmgen/definition.rs @@ -76,9 +76,9 @@ impl Codegen { movq r13, rax; movq rdi, [r13 + (FUNCDATA_META)]; - movq [rsp - (RSP_STACK_LFP + LFP_META)], rdi; - movq [rsp - (RSP_STACK_LFP + LFP_BLOCK)], 0; - movq [rsp - (RSP_STACK_LFP + LFP_SELF)], r15; + movq [rsp - (RSP_LOCAL_FRAME + LFP_META)], rdi; + movq [rsp - (RSP_LOCAL_FRAME + LFP_BLOCK)], 0; + movq [rsp - (RSP_LOCAL_FRAME + LFP_SELF)], r15; }; self.set_method_outer(); monoasm! { &mut self.jit, diff --git a/monoruby/src/compiler/vmgen/init_method.rs b/monoruby/src/compiler/vmgen/init_method.rs index 96fff22b..01248d3b 100644 --- a/monoruby/src/compiler/vmgen/init_method.rs +++ b/monoruby/src/compiler/vmgen/init_method.rs @@ -1,8 +1,8 @@ use super::*; -pub(crate) const INIT_METHOD_OFS: i32 = -16; +const INIT_METHOD_OFS: i32 = -16; +const INIT_METHOD_ARG: i32 = -14; const INIT_METHOD_REG: i32 = -12; -const INIT_METHOD_ARG: i32 = -2; impl Codegen { /// Initialize method frame @@ -11,7 +11,7 @@ impl Codegen { /// ~~~text /// -16 -14 -12 -10 -8 -6 -4 -2 /// +---+---+---+---++---+---+---+---+ - /// |ofs|rop|reg| op||req| | |arg| + /// |ofs|arg|reg| op|| | | | | /// +---+---+---+---++---+---+---+---+ /// rsi rdi r15 /// ~~~ @@ -19,33 +19,15 @@ impl Codegen { /// - +reg: a number of registers /// - +arg: a number of arguments. /// - +ofs: stack pointer offset - /// - req: a number of required arguments - /// - rop: req + optional arguments /// pub(super) fn vm_init(&mut self) -> CodePtr { let label = self.jit.get_current_address(); - self.stack_setup(); self.vm_init_func(); self.fill(NIL_VALUE); self.fetch_and_dispatch(); label } - /// - /// Setup stack pointer. - /// - /// ### destroy - /// - rax - /// - fn stack_setup(&mut self) { - monoasm! { &mut self.jit, - // setup stack pointer - movsxw rax, [r13 + (INIT_METHOD_OFS)]; - shlq rax, 4; - subq rsp, rax; - }; - } - /// /// ### in /// - r13: pc @@ -60,6 +42,10 @@ impl Codegen { /// fn vm_init_func(&mut self) { monoasm! { &mut self.jit, + // setup stack pointer + movsxw rax, [r13 + (INIT_METHOD_OFS)]; + shlq rax, 4; + subq rsp, rax; movzxw r15, [r13 + (INIT_METHOD_REG)]; movq rax, r15; // r15: reg_num subw rax, [r13 + (INIT_METHOD_ARG)]; // rax: reg_num - arg_num diff --git a/monoruby/src/compiler/vmgen/invoker.rs b/monoruby/src/compiler/vmgen/invoker.rs index 773d95cf..89cd21cd 100644 --- a/monoruby/src/compiler/vmgen/invoker.rs +++ b/monoruby/src/compiler/vmgen/invoker.rs @@ -149,7 +149,7 @@ impl Codegen { // r15 : &FuncData // set pc movq r13, [r15 + (FUNCDATA_PC)]; - call [r15 + (FUNCDATA_CODEPTR)]; + call [r15 + (FUNCDATA_CODEPTR)]; // CALL_SITE movq rdi, [rsp - (RSP_CFP)]; movq [rbx + (EXECUTOR_CFP)], rdi; }; @@ -336,7 +336,7 @@ impl Codegen { if invoke_block { monoasm! { &mut self.jit, // set block - movq [rsp - (RSP_STACK_LFP + LFP_BLOCK)], 0; + movq [rsp - (RSP_LOCAL_FRAME + LFP_BLOCK)], 0; movq rax, [rdx + (PROCINNER_OUTER)]; // rax <- outer_lfp movl rdx, [rdx + (PROCINNER_FUNCID)]; // rdx <- FuncId }; @@ -353,16 +353,16 @@ impl Codegen { self.get_func_data(); monoasm! { &mut self.jit, // set block - movq [rsp - (RSP_STACK_LFP + LFP_BLOCK)], r11; + movq [rsp - (RSP_LOCAL_FRAME + LFP_BLOCK)], r11; }; self.set_method_outer() } monoasm! { &mut self.jit, // set self - movq [rsp - (RSP_STACK_LFP + LFP_SELF)], rcx; + movq [rsp - (RSP_LOCAL_FRAME + LFP_SELF)], rcx; // set meta movq rsi, [r15 + (FUNCDATA_META)]; - movq [rsp - (RSP_STACK_LFP + LFP_META)], rsi; + movq [rsp - (RSP_LOCAL_FRAME + LFP_META)], rsi; }; } @@ -389,7 +389,7 @@ impl Codegen { negq r9; loop_: movq rax, [r8 + r10 * 8 - 8]; - movq [rsp + r9 * 8 - (RSP_STACK_LFP + LFP_SELF)], rax; + movq [rsp + r9 * 8 - (RSP_LOCAL_FRAME + LFP_SELF)], rax; subq r10, 1; addq r9, 1; jne loop_; @@ -412,7 +412,7 @@ impl Codegen { let loop_ = self.jit.label(); monoasm! { &mut self.jit, // set block - movq [rsp - (RSP_STACK_LFP + LFP_BLOCK)], r11; + movq [rsp - (RSP_LOCAL_FRAME + LFP_BLOCK)], r11; // r8 <- *args // r9 <- len movq rdi, r9; @@ -421,7 +421,7 @@ impl Codegen { negq r9; loop_: movq rax, [r8 + r9 * 8 + 8]; - movq [rsp + r9 * 8 - (RSP_STACK_LFP + LFP_SELF)], rax; + movq [rsp + r9 * 8 - (RSP_LOCAL_FRAME + LFP_SELF)], rax; addq r9, 1; jne loop_; loop_exit: @@ -460,7 +460,7 @@ impl Codegen { cmpw rdi, [r15 + (FUNCDATA_MIN)]; jeq exit; generic: - lea rdx, [rsp - (RSP_STACK_LFP)]; // callee lfp: Lfp + lea rdx, [rsp - (RSP_LOCAL_FRAME)]; // callee lfp: Lfp subq rsp, 4096; movq rcx, rdi; // arg_num movq rdi, rbx; // &mut Executor @@ -490,7 +490,7 @@ impl Codegen { // r15 : &FuncData // set pc movq r13, [r15 + (FUNCDATA_PC)]; - call [r15 + (FUNCDATA_CODEPTR)]; + call [r15 + (FUNCDATA_CODEPTR)]; // CALL_SITE movq rdi, [rsp - (RSP_CFP)]; movq [rbx + (EXECUTOR_CFP)], rdi; }; diff --git a/monoruby/src/compiler/vmgen/method_call.rs b/monoruby/src/compiler/vmgen/method_call.rs index b0568b1d..406a8e25 100644 --- a/monoruby/src/compiler/vmgen/method_call.rs +++ b/monoruby/src/compiler/vmgen/method_call.rs @@ -55,7 +55,7 @@ impl Codegen { // rdi: receiver: Value self.vm_get_slot_value(GP::Rdi); monoasm! { &mut self.jit, - movq [rsp - (RSP_STACK_LFP + LFP_SELF)], rdi; + movq [rsp - (RSP_LOCAL_FRAME + LFP_SELF)], rdi; call get_class; movl r15, rax; // r15: class of receiver: ClassId @@ -140,7 +140,7 @@ impl Codegen { monoasm! { &mut self.jit, // set meta movq rax, [r15 + (FUNCDATA_META)]; - movq [rsp - (RSP_STACK_LFP + LFP_META)], rax; + movq [rsp - (RSP_LOCAL_FRAME + LFP_META)], rax; } monoasm! { &mut self.jit, movzxw r9, [r13 + (POS_NUM)]; @@ -167,7 +167,7 @@ impl Codegen { jz generic; cmpw r9, [r15 + (FUNCDATA_MIN)]; jne generic; - movq [rsp - (RSP_STACK_LFP + LFP_BLOCK)], 0; + movq [rsp - (RSP_LOCAL_FRAME + LFP_BLOCK)], 0; // rdx : *args // r9 : len testq r9, r9; @@ -175,7 +175,7 @@ impl Codegen { negq r9; loop_: movq rax, [rdx + r9 * 8 + 8]; - movq [rsp + r9 * 8 - (RSP_STACK_LFP + LFP_SELF)], rax; + movq [rsp + r9 * 8 - (RSP_LOCAL_FRAME + LFP_SELF)], rax; addq r9, 1; jne loop_; exit: @@ -194,14 +194,12 @@ impl Codegen { self.generic_handle_arguments(runtime::vm_handle_arguments); self.vm_handle_error(); } - monoasm! { &mut self.jit, - // set pc - movq r13, [r15 + (FUNCDATA_PC)]; // r13: BcPc - } self.push_frame(); self.set_lfp(); monoasm! { &mut self.jit, - call [r15 + (FUNCDATA_CODEPTR)]; + // set pc + movq r13, [r15 + (FUNCDATA_PC)]; // r13: BcPc + call [r15 + (FUNCDATA_CODEPTR)]; // CALL_SITE } self.pop_frame(); monoasm! { &mut self.jit, diff --git a/monoruby/src/compiler/vmgen/variables.rs b/monoruby/src/compiler/vmgen/variables.rs index 3b0bbdd2..4a0c82ad 100644 --- a/monoruby/src/compiler/vmgen/variables.rs +++ b/monoruby/src/compiler/vmgen/variables.rs @@ -368,14 +368,13 @@ impl Codegen { let loop_exit = self.jit.label(); self.fetch3(); monoasm! { &mut self.jit, - movq rax, [r14 - (LFP_OUTER)]; + movq rax, [r14]; loop_: subq rsi, 1; jz loop_exit; movq rax, [rax]; jmp loop_; loop_exit: - lea rax, [rax + (LFP_OUTER)]; negq rdi; movq rax, [rax + rdi * 8 - (LFP_SELF)]; }; @@ -404,14 +403,13 @@ impl Codegen { let loop_exit = self.jit.label(); self.fetch3(); monoasm! { &mut self.jit, - movq rax, [r14 - (LFP_OUTER)]; + movq rax, [r14]; loop_: subq rdi, 1; jz loop_exit; movq rax, [rax]; jmp loop_; loop_exit: - lea rax, [rax + (LFP_OUTER)]; negq rsi; negq r15; movq rdi, [r14 + rsi * 8 - (LFP_SELF)]; diff --git a/monoruby/src/compiler/wrapper.rs b/monoruby/src/compiler/wrapper.rs index ad860580..ee6b828a 100644 --- a/monoruby/src/compiler/wrapper.rs +++ b/monoruby/src/compiler/wrapper.rs @@ -1,20 +1,20 @@ use super::*; impl Codegen { - pub(crate) fn gen_wrapper(&mut self, kind: FuncKind, no_jit: bool) -> DestLabel { + pub(crate) fn gen_wrapper(&mut self, kind: &FuncKind, no_jit: bool) -> DestLabel { let entry = self.jit.label(); self.jit.bind_label(entry); match kind { FuncKind::ISeq(_) => { - if !no_jit { - self.gen_jit_stub(entry) + if !no_jit && !cfg!(feature = "no-jit") { + self.gen_jit_stub(entry); } else { self.gen_vm_stub() } } - FuncKind::Builtin { abs_address } => self.wrap_native_func(abs_address), - FuncKind::AttrReader { ivar_name } => self.gen_attr_reader(ivar_name), - FuncKind::AttrWriter { ivar_name } => self.gen_attr_writer(ivar_name), + FuncKind::Builtin { abs_address } => self.wrap_native_func(*abs_address), + FuncKind::AttrReader { ivar_name } => self.gen_attr_reader(*ivar_name), + FuncKind::AttrWriter { ivar_name } => self.gen_attr_writer(*ivar_name), }; self.jit.finalize(); entry @@ -110,7 +110,7 @@ impl Codegen { pushq rbp; movq rbp, rsp; movzxw rax, [r14 - (LFP_META_REGNUM)]; - addq rax, (LFP_ARG0 / 8 + 1); + addq rax, ((RSP_LOCAL_FRAME + LFP_ARG0) / 8 + 1); andq rax, (-2); shlq rax, 3; subq rsp, rax; @@ -119,7 +119,7 @@ impl Codegen { movq rsi, r12; movq rdx, r14; // rdx <- lfp movq rax, (abs_address); - call rax; + call rax; // CALL_SITE leave; ret; diff --git a/monoruby/src/executor.rs b/monoruby/src/executor.rs index ed3c1c00..9dcc8049 100644 --- a/monoruby/src/executor.rs +++ b/monoruby/src/executor.rs @@ -15,21 +15,23 @@ pub type BuiltinFn = extern "C" fn(&mut Executor, &mut Globals, Lfp) -> Option Option; pub type UnaryOpFn = extern "C" fn(&mut Executor, &mut Globals, Value) -> Option; -pub(crate) const RSP_STACK_LFP: i32 = 40 - LFP_OFFSET; +pub(crate) const RSP_LOCAL_FRAME: i32 = 40; pub(crate) const RSP_CFP: i32 = 24; pub(crate) const BP_CFP: i32 = 8; + +// Control frame offsets pub(crate) const CFP_LFP: i32 = 8; -const LFP_OFFSET: i32 = 24; -pub(crate) const LFP_OUTER: i32 = 0 + LFP_OFFSET; +// Local frame offsets +pub(crate) const LFP_OUTER: i32 = 0; /// Meta 8bytes -pub(crate) const LFP_META: i32 = 8 + LFP_OFFSET; +pub(crate) const LFP_META: i32 = 8; /// Meta::Regnum 2bytes pub(crate) const LFP_META_REGNUM: i32 = LFP_META - META_REGNUM as i32; /// Meta::FuncId 4bytes //pub(crate) const LBP_META_FUNCID: i64 = LBP_META + META_FUNCID as i64; -pub(crate) const LFP_BLOCK: i32 = 16 + LFP_OFFSET; -pub(crate) const LFP_SELF: i32 = 24 + LFP_OFFSET; +pub(crate) const LFP_BLOCK: i32 = 16; +pub(crate) const LFP_SELF: i32 = 24; pub const LFP_ARG0: i32 = LFP_SELF + 8; pub(crate) const EXECUTOR_CFP: i64 = std::mem::offset_of!(Executor, cfp) as _; @@ -100,16 +102,22 @@ impl alloc::GC for Executor { impl Executor { pub fn init(globals: &mut Globals) -> Self { + #[cfg(not(feature = "no-startup"))] let mut executor = Self::default(); - let path = dirs::home_dir() - .unwrap() - .join(".monoruby") - .join("startup.rb"); - if let Err(err) = executor.require(globals, &path, false) { - err.show_error_message_and_all_loc(globals); - panic!("error occurred in startup."); + #[cfg(feature = "no-startup")] + let executor = Self::default(); + #[cfg(not(feature = "no-startup"))] + { + let path = dirs::home_dir() + .unwrap() + .join(".monoruby") + .join("startup.rb"); + if let Err(err) = executor.require(globals, &path, false) { + err.show_error_message_and_all_loc(globals); + panic!("error occurred in startup."); + } } - #[cfg(not(feature = "test"))] + #[cfg(not(feature = "no-gems"))] { executor .require(globals, &std::path::PathBuf::from("rubygems"), false) diff --git a/monoruby/src/executor/frame.rs b/monoruby/src/executor/frame.rs index 3909f699..a006612f 100644 --- a/monoruby/src/executor/frame.rs +++ b/monoruby/src/executor/frame.rs @@ -53,7 +53,7 @@ impl Cfp { /// Get outermost LFP. /// pub(crate) fn outermost_lfp(&self) -> Lfp { - self.lfp().outermost() + self.lfp().outermost().0 } /// @@ -164,7 +164,7 @@ impl alloc::GC for Lfp { v.0.mark(alloc) }; if let Some(outer) = self.outer() { - outer.lfp().mark(alloc); + outer.mark(alloc); } } } @@ -188,31 +188,48 @@ impl Lfp { /// fn cfp(&self) -> Cfp { assert!(self.on_stack()); - unsafe { Cfp::new(self.sub(BP_CFP as _) as _) } + unsafe { Cfp::new(self.as_ptr().add(16) as _) } } /// - /// Set outer. + /// Get outer LFP. /// - pub fn set_outer(&mut self, outer: Option) { - unsafe { - *(self.outer_address().0.as_ptr()) = outer; + pub fn outer(self) -> Option { + unsafe { *(self.0.as_ptr() as *mut Option) } + } + + /// + /// Get DFP of an outermost frame of *self*. + /// + fn outermost(&self) -> (Lfp, usize) { + let mut lfp = *self; + let mut depth = 0; + while let Some(outer) = lfp.outer() { + lfp = outer; + depth += 1; } + (lfp, depth) } - fn sub(self, count: i64) -> *mut u8 { - unsafe { self.as_ptr().sub(count as usize) } + /// + /// Get outermost LFP and the depth. + /// + pub(crate) fn outermost_lfp_depth(&self) -> (Lfp, usize) { + match self.outer() { + Some(lfp) => lfp.outermost(), + None => (*self, 0), + } } /// - /// Get the address of outer. + /// Set outer. /// - pub(crate) fn outer_address(self) -> Dfp { - unsafe { Dfp::new(self.sub(LFP_OUTER as _) as _) } + pub(crate) fn set_outer(&mut self, outer: Option) { + unsafe { *(self.0.as_ptr() as *mut Option) = outer } } - fn meta_mut(&mut self) -> &mut Meta { - unsafe { &mut *(self.sub(LFP_META as _) as *mut Meta) } + fn sub(self, count: i64) -> *mut u8 { + unsafe { self.as_ptr().sub(count as usize) } } pub fn on_stack(self) -> bool { @@ -271,9 +288,8 @@ impl Lfp { let mut heap_lfp = Lfp::new((Box::into_raw(v) as *mut u64 as usize + len - 8) as _); heap_lfp.meta_mut().set_on_heap(); cfp.set_lfp(heap_lfp); - if let Some(outer) = heap_lfp.outer() { - let outer_lfp = outer.lfp(); - let outer = outer_lfp.move_frame_to_heap().outer_address(); + if let Some(outer_lfp) = heap_lfp.outer() { + let outer = outer_lfp.move_frame_to_heap(); heap_lfp.set_outer(Some(outer)); } assert!(!heap_lfp.on_stack()); @@ -296,12 +312,6 @@ impl Lfp { v.push(meta.get()); // outer v.push(0); - // dummy - v.push(0); - // dummy - v.push(0); - // dummy - v.push(0); let v = v.into_boxed_slice(); let len = v.len() * 8; unsafe { @@ -312,9 +322,9 @@ impl Lfp { } pub fn dummy_heap_frame_with_self(self_val: Value) -> Self { + let v = vec![0, 0, self_val.id(), 0, 0, 0].into_boxed_slice(); + let len = v.len() * 8; unsafe { - let v = vec![0, 0, self_val.id(), 0, 0, 0, 0, 0, 0].into_boxed_slice(); - let len = v.len() * 8; let mut heap_lfp = Lfp::new((Box::into_raw(v) as *mut u64 as usize + len - 8) as _); heap_lfp.meta_mut().set_on_heap(); heap_lfp.meta_mut().set_reg_num(1); @@ -323,36 +333,6 @@ impl Lfp { } } - /// - /// Get outer DFP. - /// - pub fn outer(self) -> Option { - self.outer_address().outer() - } - - /// - /// Get outermost LFP. - /// - pub fn outermost(self) -> Lfp { - match self.outer() { - Some(dfp) => dfp.outermost().0.lfp(), - None => self, - } - } - - /// - /// Get outermost LFP and the depth. - /// - pub(crate) fn outermost_lfp_depth(&self) -> (Lfp, usize) { - match self.outer() { - Some(dfp) => { - let (dfp, depth) = dfp.outermost(); - (dfp.lfp(), depth) - } - None => (*self, 0), - } - } - /// /// Get Meta. /// @@ -360,6 +340,10 @@ impl Lfp { unsafe { &*(self.sub(LFP_META as _) as *const Meta) } } + fn meta_mut(&mut self) -> &mut Meta { + unsafe { &mut *(self.sub(LFP_META as _) as *mut Meta) } + } + /// /// Get block. /// @@ -500,49 +484,3 @@ impl Lfp { max } } - -/// -/// Dynamic frame pointer. -/// -/// The DFP points to a DFP in the frame that holds a scope outside the current frame. -/// -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] -#[repr(transparent)] -pub struct Dfp(std::ptr::NonNull>); - -impl Dfp { - unsafe fn new(ptr: *mut u8) -> Self { - Dfp(std::ptr::NonNull::new(ptr as *mut Option).unwrap()) - } - - fn get(&self) -> *const Option { - self.0.as_ptr() - } - - /// - /// Get DFP of an outer frame of *self*. - /// - pub fn outer(&self) -> Option { - unsafe { *self.get() } - } - - /// - /// Get DFP of an outermost frame of *self*. - /// - fn outermost(&self) -> (Dfp, usize) { - let mut dfp = *self; - let mut depth = 0; - while let Some(outer) = dfp.outer() { - dfp = outer; - depth += 1; - } - (dfp, depth) - } - - /// - /// Get LFP. - /// - pub fn lfp(&self) -> Lfp { - unsafe { Lfp::new((self.get() as *const u8).add(LFP_OUTER as usize) as _) } - } -} diff --git a/monoruby/src/globals.rs b/monoruby/src/globals.rs index 8079bbc1..a2126180 100644 --- a/monoruby/src/globals.rs +++ b/monoruby/src/globals.rs @@ -233,8 +233,7 @@ impl Globals { // set constants let pcg_name = env!("CARGO_PKG_NAME"); let pcg_version = env!("CARGO_PKG_VERSION"); - let description = format!("{pcg_name} {pcg_version} [x86_64-linux]",); - let val = Value::string_from_str(&description); + let val = Value::string(format!("{pcg_name} {pcg_version} [x86_64-linux]",)); globals.set_constant_by_str(OBJECT_CLASS, "RUBY_DESCRIPTION", val); let val = Value::string_from_str("ruby"); globals.set_constant_by_str(OBJECT_CLASS, "RUBY_ENGINE", val); @@ -245,7 +244,7 @@ impl Globals { .join("ruby_version"); let ruby_version = std::fs::read_to_string(&version_path).unwrap(); - let val = Value::string_from_vec(ruby_version.into_bytes()); + let val = Value::string(ruby_version); globals.set_constant_by_str(OBJECT_CLASS, "RUBY_VERSION", val); globals.set_constant_by_str(OBJECT_CLASS, "RUBY_ENGINE_VERSION", val); globals @@ -415,7 +414,7 @@ impl Globals { fn new_binding_frame(&mut self, fid: FuncId, self_val: Value, mut binding: Binding) { let meta = self.store[fid].meta(); let mut lfp = Lfp::heap_frame(self_val, meta); - lfp.set_outer(Some(binding.outer_lfp().outer_address())); + lfp.set_outer(Some(binding.outer_lfp())); if let Some(binding_lfp) = binding.binding() { let locals_len = self[binding_lfp.meta().func_id()].locals_len(); for i in 1..1 + locals_len { @@ -531,7 +530,7 @@ impl Globals { #[cfg(feature = "perf")] let pair = self.codegen.get_address_pair(); let kind = self[func_id].kind.clone(); - let entry = self.codegen.gen_wrapper(kind, self.no_jit); + let entry = self.codegen.gen_wrapper(&kind, self.no_jit); let codeptr = self.codegen.jit.get_label_address(entry); self[func_id].set_entry(entry, codeptr); #[cfg(feature = "perf")] diff --git a/monoruby/src/globals/dump.rs b/monoruby/src/globals/dump.rs index da1aaf78..7eb989de 100644 --- a/monoruby/src/globals/dump.rs +++ b/monoruby/src/globals/dump.rs @@ -22,7 +22,7 @@ impl Globals { }, match outer { None => "None".to_string(), - Some(outer) => format!("{:?}", outer.lfp()), + Some(outer) => format!("{:?}", outer), }, meta, ); diff --git a/monoruby/src/globals/store.rs b/monoruby/src/globals/store.rs index 34cb7b02..b87ecc5b 100644 --- a/monoruby/src/globals/store.rs +++ b/monoruby/src/globals/store.rs @@ -411,7 +411,6 @@ impl alloc::GC for ConstSiteInfo { } impl ConstSiteInfo { - //#[cfg(feature = "dump-bc")] pub fn format(&self) -> String { let ConstSiteInfo { name, @@ -422,12 +421,11 @@ impl ConstSiteInfo { } = self; let mut const_name = if *toplevel { "::" } else { "" }.to_string(); for c in prefix { - (*c).append_to(&mut const_name); - const_name += "::"; + const_name += &format!("{:?}::", c); } - (*name).append_to(&mut const_name); + const_name += &format!("{:?}", name); format!( - "{}const[{}]", + "{}{}", if let Some(base) = base { format!("{:?}::", base) } else { @@ -495,6 +493,55 @@ impl CallSiteInfo { pub fn object_send_single_splat(&self) -> bool { self.splat_pos.len() == 1 && self.pos_num == 1 && !self.kw_may_exists() } + + pub fn format_args(&self) -> String { + let CallSiteInfo { + pos_num, + splat_pos, + kw_pos, + kw_args, + hash_splat_pos, + block_arg, + block_fid, + args, + .. + } = self; + let mut s = String::new(); + if *pos_num > 0 { + for i in 0..*pos_num { + if i > 0 { + s += ","; + } + if splat_pos.contains(&i) { + s += "*"; + } + s += &format!("{:?}", *args + i); + } + } + for (i, (k, v)) in kw_args.iter().enumerate() { + if i > 0 || *pos_num > 0 { + s += ","; + } + s += &format!("{}:{:?}", k, *kw_pos + *v); + } + for pos in hash_splat_pos.iter() { + if s.len() > 0 { + s += ","; + } + s += &format!("**{:?}", pos); + } + if let Some(block_arg) = block_arg { + if s.len() > 0 { + s += ","; + } + s += &format!("&{:?}", block_arg); + } + s = format!("({})", s); + if let Some(block_fid) = block_fid { + s += &format!(" {{ {:?} }}", block_fid); + } + s + } } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/monoruby/src/globals/store/function.rs b/monoruby/src/globals/store/function.rs index 78e5ba96..c93a8886 100644 --- a/monoruby/src/globals/store/function.rs +++ b/monoruby/src/globals/store/function.rs @@ -62,7 +62,12 @@ impl FuncData { fn set_reg_num(&mut self, reg_num: u16) { self.meta.set_reg_num(reg_num); - self.ofs = ((reg_num as usize * 8 + LFP_SELF as usize + 15) >> 4) as u16; + self.set_offset(reg_num); + } + + fn set_offset(&mut self, reg_num: u16) { + self.ofs = + ((reg_num as usize * 8 + (RSP_LOCAL_FRAME + LFP_SELF) as usize + 31) / 16) as u16; } pub(in crate::globals) fn set_codeptr(&mut self, codeptr: monoasm::CodePtr) { @@ -107,7 +112,8 @@ impl std::fmt::Debug for Meta { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, - "{}{}{}{} {:?} reg_num:{}", + "{:?} {}{}{}{} reg_num:{}", + self.func_id(), if self.is_native() { "NATIVE " } else { "" }, if self.is_class_def() { "class_def " @@ -116,7 +122,6 @@ impl std::fmt::Debug for Meta { }, if self.is_simple() { "SIMPLE " } else { "" }, if self.on_stack() { "stack" } else { "heap" }, - self.func_id(), self.reg_num() ) } @@ -661,17 +666,18 @@ impl FuncInfo { let name = name.into(); let min = params.req_num() as u16; let max = params.reqopt_num() as u16; - let ofs = ((max as usize * 8 + LFP_ARG0 as usize + 15) >> 4) as u16; + let mut data = FuncData { + codeptr: None, + pc: None, + meta, + ofs: 0, + min, + max, + _padding: [0; 4], + }; + data.set_offset(max); Self { - data: FuncData { - codeptr: None, - pc: None, - meta, - ofs, - min, - max, - _padding: [0; 4], - }, + data, kind, ext: Box::new(FuncExt { name, @@ -903,6 +909,14 @@ impl FuncInfo { } } + pub(crate) fn is_native(&self) -> bool { + self.meta().is_native() + } + + pub(crate) fn get_offset(&self) -> usize { + ((RSP_LOCAL_FRAME + LFP_ARG0) as usize + 8 * self.total_args() + 8) & !0xf + } + /// /// Get the max number of positional arguments (= required + optional) of this function. /// @@ -1012,26 +1026,22 @@ impl FuncInfo { "<{}> {file_name}:{line}", globals.func_description(func.id()), ); - eprintln!("meta:{:?} {:?}", self.data.meta, self.kind); + eprintln!( + "{:?} local_vars:{} temp:{}", + self.data.meta, + func.local_num(), + func.temp_num + ); + eprintln!("{:?}", func.args); eprintln!("{:?}", func.get_exception_map()); for i in 0..func.bytecode().len() { - let trace_ir = func.trace_ir(&globals.store, BcIndex::from(i)); + let bc_pos = BcIndex::from(i); + if let Some(bbid) = func.bb_info.is_bb_head(bc_pos) { + eprintln!("{:?}", bbid); + }; + let trace_ir = func.trace_ir(&globals.store, bc_pos); if let Some(fmt) = trace_ir.format(&globals.store) { - eprint!( - "{}:{:05} [{:02}] ", - if func - .bb_info - .is_bb_head(bytecodegen::BcIndex::from(i)) - .is_some() - { - "+" - } else { - " " - }, - i, - func.sp[i].0 - ); - eprintln!("{}", fmt); + eprintln!("{bc_pos} [{:02}] {fmt}", func.sp[i].0); }; } eprintln!("------------------------------------"); diff --git a/monoruby/src/globals/store/iseq.rs b/monoruby/src/globals/store/iseq.rs index 7dba96f9..ee951520 100644 --- a/monoruby/src/globals/store/iseq.rs +++ b/monoruby/src/globals/store/iseq.rs @@ -218,27 +218,6 @@ impl ISeqInfo { self.non_temp_num as usize } - /*/// - /// Get a number of optional and rest parameters. - /// - pub(crate) fn optional_num(&self) -> usize { - self.args.pos_num - self.args.required_num - }*/ - - /// - /// Get a number of required parameters. - /// - pub(crate) fn req_num(&self) -> usize { - self.args.required_num - } - - /// - /// get a number of required or optional parameters. - /// - pub(crate) fn reqopt_num(&self) -> usize { - self.args.reqopt_num - } - /// /// Get a number of required + optional + rest arguments. /// @@ -246,18 +225,6 @@ impl ISeqInfo { self.args.pos_num } - /// - /// Get a parameter info. - /// - /// bit 0:rest(yes=1 no =0) bit 1:block - pub(crate) fn info(&self) -> usize { - (if self.args.block_param.is_some() { - 2 - } else { - 0 - }) + (self.args.pos_num - self.args.reqopt_num) - } - /// /// Get a block argument name. /// @@ -500,7 +467,7 @@ impl ISeqInfo { fid: pc.cached_fid(), version: (pc + 1).cached_version(), }, - 32..=33 => TraceIr::MethodCallBlock { + 32..=33 => TraceIr::MethodCallWithBlock { callid: op1_l.into(), recv_class: pc.cached_class1(), fid: pc.cached_fid(), @@ -586,7 +553,7 @@ impl ISeqInfo { }, 80 => TraceIr::Ret(SlotId::new(op1_w1)), 81 => TraceIr::MethodRet(SlotId::new(op1_w1)), - 82 => TraceIr::Break(SlotId::new(op1_w1)), + 82 => TraceIr::BlockBreak(SlotId::new(op1_w1)), 83 => TraceIr::Raise(SlotId::new(op1_w1)), 85 => TraceIr::EnsureEnd, 86 => TraceIr::ConcatRegexp(SlotId::from(op1_w1), SlotId::new(op2_w2), op3_w3), @@ -637,39 +604,25 @@ impl ISeqInfo { 132 => { let base_class = pc.classid1(); let idx_class = pc.classid2(); - if base_class == Some(ARRAY_CLASS) && idx_class == Some(INTEGER_CLASS) { - TraceIr::ArrayIndex { - dst: SlotId::new(op1_w1), - base: SlotId::new(op2_w2), - idx: SlotId::new(op3_w3), - } - } else { - TraceIr::Index { - dst: SlotId::new(op1_w1), - base: SlotId::new(op2_w2), - idx: SlotId::new(op3_w3), - base_class, - idx_class, - } + + TraceIr::Index { + dst: SlotId::new(op1_w1), + base: SlotId::new(op2_w2), + idx: SlotId::new(op3_w3), + base_class, + idx_class, } } 133 => { let base_class = pc.classid1(); let idx_class = pc.classid2(); - if base_class == Some(ARRAY_CLASS) && idx_class == Some(INTEGER_CLASS) { - TraceIr::ArrayIndexAssign { - src: SlotId::new(op1_w1), - base: SlotId::new(op2_w2), - idx: SlotId::new(op3_w3), - } - } else { - TraceIr::IndexAssign { - src: SlotId::new(op1_w1), - base: SlotId::new(op2_w2), - idx: SlotId::new(op3_w3), - base_class, - idx_class, - } + + TraceIr::IndexAssign { + src: SlotId::new(op1_w1), + base: SlotId::new(op2_w2), + idx: SlotId::new(op3_w3), + base_class, + idx_class, } } 134..=141 => { @@ -818,12 +771,9 @@ impl ISeqInfo { } } } - 170 | 172 => TraceIr::InitMethod(FnInitInfo { + 170 => TraceIr::InitMethod(FnInitInfo { reg_num: op1_w1 as usize, - arg_num: pc.u16(3) as usize, - reqopt_num: op2_w2 as usize, - req_num: pc.u16(0) as usize, - info: pc.u16(2) as usize, + arg_num: op2_w2 as usize, stack_offset: op3_w3 as usize, }), 171 => TraceIr::ExpandArray { diff --git a/monoruby/src/id_table.rs b/monoruby/src/id_table.rs index 2b8f86a1..9f93a767 100644 --- a/monoruby/src/id_table.rs +++ b/monoruby/src/id_table.rs @@ -168,14 +168,6 @@ impl IdentId { lhs.cmp(rhs) } - /// - /// Append the name of *self* to *s*. - /// - //#[cfg(feature = "dump-bc")] - pub(crate) fn append_to(self, s: &mut String) { - ID.read().unwrap().append_to(self, s); - } - /// /// Get instance variable name from *id*. /// @@ -301,14 +293,6 @@ impl IdentifierTable { &self.table[id.to_usize() - 1] } - /// - /// Append the name of *self* to *s*. - /// - //#[cfg(feature = "dump-bc")] - fn append_to(&self, id: IdentId, s: &mut String) { - s.push_str(self.table[id.to_usize() - 1].as_str()); - } - /// /// Get instance variable name from *id*. /// diff --git a/monoruby/src/tests.rs b/monoruby/src/tests.rs index d0d69744..6145e1fc 100644 --- a/monoruby/src/tests.rs +++ b/monoruby/src/tests.rs @@ -216,15 +216,6 @@ fn run_test_main(globals: &mut Globals, code: &str, no_gc: bool) -> Value { } fn run_ruby(globals: &mut Globals, code: &str) -> Value { - let ruby_path = dirs::home_dir() - .unwrap() - .join(".monoruby") - .join("ruby_path"); - let ruby_path = std::fs::read_to_string(&ruby_path) - .unwrap() - .trim_end() - .to_string(); - let code = format!( r#" ____a = ({}); @@ -236,8 +227,8 @@ fn run_ruby(globals: &mut Globals, code: &str) -> Value { let mut tmpfile = NamedTempFile::new().unwrap(); tmpfile.write_all(code.as_bytes()).unwrap(); - let res = match std::process::Command::new(dbg!(ruby_path)) - .args([tmpfile.path()]) + let res = match std::process::Command::new("bash") + .args(["-c", &format!("ruby {}", tmpfile.path().to_str().unwrap())]) .output() { Ok(output) => String::from_utf8(output.stdout).unwrap(), diff --git a/monoruby/src/value/rvalue.rs b/monoruby/src/value/rvalue.rs index 592dbfc2..5ffb0a06 100644 --- a/monoruby/src/value/rvalue.rs +++ b/monoruby/src/value/rvalue.rs @@ -441,7 +441,7 @@ impl RValue { fn object_debug(&self, store: &Store) -> String { if let Some(name) = self.get_ivar(store, IdentId::_NAME) { - name.debug(store) + name.debug_tos(store) } else { format!( "#<{}:0x{:016x}>",