diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index f2e3df51cb2957..8afa726334a90c 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -37,21 +37,23 @@ jobs: env: MSYSTEM: ${{ matrix.msystem }} MSYS2_ARCH: >- - ${{ - contains(matrix.msystem, 'arm64') && 'aarch64' || - contains(matrix.msystem, '64') && 'x86_64' || 'i686' - }} + ${{ case( + contains(matrix.msystem, 'arm64'), 'aarch64', + contains(matrix.msystem, '64'), 'x86_64', + 'i686' + ) }} MINGW_PACKAGE_PREFIX: >- mingw-w${{ endsWith(matrix.msystem, '64') && '64' || '32' - }}-${{ - startsWith(matrix.msystem, 'clang') && 'clang' || - startsWith(matrix.msystem, 'ucrt') && 'ucrt' || + }}-${{ case( + startsWith(matrix.msystem, 'clang'), 'clang', + startsWith(matrix.msystem, 'ucrt'), 'ucrt', 'mingw' - }}-${{ - contains(matrix.msystem, 'arm64') && 'aarch64' || - endsWith(matrix.msystem, '64') && 'x86_64' || 'i686' - }} + ) }}-${{ case( + contains(matrix.msystem, 'arm64'), 'aarch64', + endsWith(matrix.msystem, '64'), 'x86_64', + 'i686' + ) }} CFLAGS: '-mtune=generic -O3 -pipe' CXXFLAGS: '-mtune=generic -O3 -pipe' CPPFLAGS: '-D_FORTIFY_SOURCE=2 -D__USE_MINGW_ANSI_STDIO=1 -DFD_SETSIZE=2048' diff --git a/zjit/src/backend/lir.rs b/zjit/src/backend/lir.rs index de3e55ac000c88..18cac5086faa1c 100644 --- a/zjit/src/backend/lir.rs +++ b/zjit/src/backend/lir.rs @@ -2202,7 +2202,7 @@ impl Assembler }); #[cfg(feature = "disasm")] - if get_option!(dump_disasm) { + if get_option!(dump_disasm) && ret.is_ok() { let end_addr = cb.get_write_ptr(); let disasm = crate::disasm::disasm_addr_range(cb, start_addr.raw_ptr(cb) as usize, end_addr.raw_ptr(cb) as usize); println!("{}", disasm); diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index ba6ce8365eb4a1..7cb117eca5be4c 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -3198,6 +3198,12 @@ impl Function { self.push_insn_id(block, insn_id); continue; } + // Check if the args are compatible before emitting any assmptions + let Ok((send_state, processed_args, kw_bits)) = self.prepare_direct_send_args(block, &args, ci, iseq, state) + .inspect_err(|&reason| self.set_dynamic_send_reason(insn_id, reason)) else { + self.push_insn_id(block, insn_id); continue; + }; + // Check singleton class assumption first, before emitting other patchpoints if !self.assume_no_singleton_classes(block, klass, state) { self.set_dynamic_send_reason(insn_id, SingletonClassSeen); @@ -3212,11 +3218,6 @@ impl Function { recv = self.push_insn(block, Insn::GuardType { val: recv, guard_type: Type::from_profiled_type(profiled_type), state }); } - let Ok((send_state, processed_args, kw_bits)) = self.prepare_direct_send_args(block, &args, ci, iseq, state) - .inspect_err(|&reason| self.set_dynamic_send_reason(insn_id, reason)) else { - self.push_insn_id(block, insn_id); continue; - }; - let send_direct = self.push_insn(block, Insn::SendDirect { recv, cd, cme, iseq, args: processed_args, kw_bits, state: send_state, blockiseq }); self.make_equal_to(insn_id, send_direct); } else if !has_block && def_type == VM_METHOD_TYPE_BMETHOD { @@ -3236,6 +3237,12 @@ impl Function { self.push_insn_id(block, insn_id); continue; } + // Check if the args are compatible before emitting any assmptions + let Ok((send_state, processed_args, kw_bits)) = self.prepare_direct_send_args(block, &args, ci, iseq, state) + .inspect_err(|&reason| self.set_dynamic_send_reason(insn_id, reason)) else { + self.push_insn_id(block, insn_id); continue; + }; + // Patch points: // Check for "defined with an un-shareable Proc in a different Ractor" if !procv.shareable_p() && !self.assume_single_ractor_mode(block, state) { @@ -3253,11 +3260,6 @@ impl Function { recv = self.push_insn(block, Insn::GuardType { val: recv, guard_type: Type::from_profiled_type(profiled_type), state }); } - let Ok((send_state, processed_args, kw_bits)) = self.prepare_direct_send_args(block, &args, ci, iseq, state) - .inspect_err(|&reason| self.set_dynamic_send_reason(insn_id, reason)) else { - self.push_insn_id(block, insn_id); continue; - }; - let send_direct = self.push_insn(block, Insn::SendDirect { recv, cd, cme, iseq, args: processed_args, kw_bits, state: send_state, blockiseq: None }); self.make_equal_to(insn_id, send_direct); } else if !has_block && def_type == VM_METHOD_TYPE_IVAR && args.is_empty() { @@ -3601,6 +3603,7 @@ impl Function { continue; } + // Check if the args are compatible before emitting any assmptions let Ok((send_state, processed_args, kw_bits)) = self.prepare_direct_send_args(block, &args, ci, super_iseq, state) .inspect_err(|&reason| self.set_dynamic_send_reason(insn_id, reason)) else { self.push_insn_id(block, insn_id); continue; diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index 202d92b833e0d4..1d3b062a58b09c 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -3561,8 +3561,8 @@ mod hir_opt_tests { v15:Fixnum[2] = Const Value(2) PatchPoint NoSingletonClass(Object@0x1000) PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010) - v25:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] - v27:BasicObject = SendDirect v25, 0x1038, :foo (0x1048), v13, v15, v11 + v26:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] + v27:BasicObject = SendDirect v26, 0x1038, :foo (0x1048), v13, v15, v11 CheckInterrupts Return v27 "); @@ -3592,8 +3592,8 @@ mod hir_opt_tests { v15:Fixnum[1] = Const Value(1) PatchPoint NoSingletonClass(Object@0x1000) PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010) - v25:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] - v27:BasicObject = SendDirect v25, 0x1038, :foo (0x1048), v11, v15, v13 + v26:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] + v27:BasicObject = SendDirect v26, 0x1038, :foo (0x1048), v11, v15, v13 CheckInterrupts Return v27 "); @@ -3661,8 +3661,8 @@ mod hir_opt_tests { v26:Fixnum[3] = Const Value(3) PatchPoint NoSingletonClass(Object@0x1000) PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010) - v42:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] - v44:BasicObject = SendDirect v42, 0x1038, :foo (0x1048), v20, v22, v26, v24 + v43:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] + v44:BasicObject = SendDirect v43, 0x1038, :foo (0x1048), v20, v22, v26, v24 v30:ArrayExact = NewArray v39, v44 CheckInterrupts Return v30 @@ -3690,19 +3690,19 @@ mod hir_opt_tests { bb3(v6:BasicObject): v11:Fixnum[1] = Const Value(1) v13:Fixnum[3] = Const Value(3) + v34:Fixnum[4] = Const Value(4) PatchPoint NoSingletonClass(Object@0x1000) PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010) - v36:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] - v37:Fixnum[4] = Const Value(4) - v39:BasicObject = SendDirect v36, 0x1038, :foo (0x1048), v11, v13, v37 + v38:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] + v39:BasicObject = SendDirect v38, 0x1038, :foo (0x1048), v11, v13, v34 v18:Fixnum[1] = Const Value(1) v20:Fixnum[2] = Const Value(2) v22:Fixnum[40] = Const Value(40) v24:Fixnum[30] = Const Value(30) PatchPoint NoSingletonClass(Object@0x1000) PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010) - v42:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] - v44:BasicObject = SendDirect v42, 0x1038, :foo (0x1048), v18, v20, v24, v22 + v43:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] + v44:BasicObject = SendDirect v43, 0x1038, :foo (0x1048), v18, v20, v24, v22 v28:ArrayExact = NewArray v39, v44 CheckInterrupts Return v28 @@ -3810,6 +3810,60 @@ mod hir_opt_tests { "); } + #[test] + fn test_send_hash_to_kwarg_only_method() { + eval(r#" + def callee(a:) = a + def test = callee({a: 1}) + begin; test; rescue ArgumentError; end + begin; test; rescue ArgumentError; end + "#); + assert_snapshot!(hir_string("test"), @r" + fn test@:3: + bb1(): + EntryPoint interpreter + v1:BasicObject = LoadSelf + Jump bb3(v1) + bb2(): + EntryPoint JIT(0) + v4:BasicObject = LoadArg :self@0 + Jump bb3(v4) + bb3(v6:BasicObject): + v11:HashExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) + v12:HashExact = HashDup v11 + v14:BasicObject = Send v6, :callee, v12 # SendFallbackReason: Argument count does not match parameter count + CheckInterrupts + Return v14 + "); + } + + #[test] + fn test_send_hash_to_optional_kwarg_only_method() { + eval(r#" + def callee(a: nil) = a + def test = callee({a: 1}) + begin; test; rescue ArgumentError; end + begin; test; rescue ArgumentError; end + "#); + assert_snapshot!(hir_string("test"), @r" + fn test@:3: + bb1(): + EntryPoint interpreter + v1:BasicObject = LoadSelf + Jump bb3(v1) + bb2(): + EntryPoint JIT(0) + v4:BasicObject = LoadArg :self@0 + Jump bb3(v4) + bb3(v6:BasicObject): + v11:HashExact[VALUE(0x1000)] = Const Value(VALUE(0x1000)) + v12:HashExact = HashDup v11 + v14:BasicObject = Send v6, :callee, v12 # SendFallbackReason: Argument count does not match parameter count + CheckInterrupts + Return v14 + "); + } + #[test] fn specialize_call_to_iseq_with_optional_param_kw_using_default() { eval(" @@ -3829,11 +3883,11 @@ mod hir_opt_tests { v4:BasicObject = LoadArg :self@0 Jump bb3(v4) bb3(v6:BasicObject): + v17:Fixnum[1] = Const Value(1) PatchPoint NoSingletonClass(Object@0x1000) PatchPoint MethodRedefined(Object@0x1000, foo@0x1008, cme:0x1010) - v19:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] - v20:Fixnum[1] = Const Value(1) - v22:BasicObject = SendDirect v19, 0x1038, :foo (0x1048), v20 + v21:HeapObject[class_exact*:Object@VALUE(0x1000)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1000)] + v22:BasicObject = SendDirect v21, 0x1038, :foo (0x1048), v17 CheckInterrupts Return v22 "); diff --git a/zjit/src/hir/tests.rs b/zjit/src/hir/tests.rs index aa71daa0e80567..2f868b02fc36d8 100644 --- a/zjit/src/hir/tests.rs +++ b/zjit/src/hir/tests.rs @@ -119,11 +119,11 @@ mod snapshot_tests { v13:Fixnum[1] = Const Value(1) v15:Fixnum[2] = Const Value(2) v16:Any = Snapshot FrameState { pc: 0x1008, stack: [v6, v11, v13, v15], locals: [] } + v23:Any = Snapshot FrameState { pc: 0x1008, stack: [v6, v13, v15, v11], locals: [] } PatchPoint NoSingletonClass(Object@0x1010) PatchPoint MethodRedefined(Object@0x1010, foo@0x1018, cme:0x1020) - v25:HeapObject[class_exact*:Object@VALUE(0x1010)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1010)] - v26:Any = Snapshot FrameState { pc: 0x1008, stack: [v6, v13, v15, v11], locals: [] } - v27:BasicObject = SendDirect v25, 0x1048, :foo (0x1058), v13, v15, v11 + v26:HeapObject[class_exact*:Object@VALUE(0x1010)] = GuardType v6, HeapObject[class_exact*:Object@VALUE(0x1010)] + v27:BasicObject = SendDirect v26, 0x1048, :foo (0x1058), v13, v15, v11 v18:Any = Snapshot FrameState { pc: 0x1060, stack: [v27], locals: [] } PatchPoint NoTracePoint CheckInterrupts