Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -913,15 +913,16 @@ comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE

/*
* call-seq:
* complex * numeric -> new_complex
* self * other -> numeric
*
* Returns the product of +self+ and +numeric+:
* Returns the numeric product of +self+ and +other+:
*
* Complex.rect(9, 8) * 4 # => (36+32i)
* Complex.rect(20, 9) * 9.8 # => (196.0+88.2i)
* Complex.rect(2, 3) * Complex.rect(2, 3) # => (-5+12i)
* Complex.rect(900) * Complex.rect(1) # => (900+0i)
* Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i)
* Complex.rect(9, 8) * 4 # => (36+32i)
* Complex.rect(20, 9) * 9.8 # => (196.0+88.2i)
* Complex.rect(9, 8) * Rational(2, 3) # => ((6/1)+(16/3)*i)
*
*/
VALUE
Expand Down
3 changes: 0 additions & 3 deletions lib/rubygems/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -344,9 +344,6 @@ def approximate_recommendation

def <=>(other)
if String === other
unless Gem::Deprecate.skip
warn "comparing version objects with strings is deprecated and will be removed", uplevel: 1
end
return unless self.class.correct?(other)
return self <=> self.class.new(other)
end
Expand Down
63 changes: 48 additions & 15 deletions numeric.c
Original file line number Diff line number Diff line change
Expand Up @@ -1195,13 +1195,14 @@ rb_float_minus(VALUE x, VALUE y)
* call-seq:
* self * other -> numeric
*
* Returns a new \Float which is the product of +self+ and +other+:
* Returns the numeric product of +self+ and +other+:
*
* f = 3.14
* f * 2 # => 6.28
* f * 2.0 # => 6.28
* f * Rational(1, 2) # => 1.57
* f * Complex(2, 0) # => (6.28+0.0i)
*
*/

VALUE
Expand Down Expand Up @@ -4098,16 +4099,17 @@ fix_mul(VALUE x, VALUE y)

/*
* call-seq:
* self * numeric -> numeric_result
* self * other -> numeric
*
* Performs multiplication:
* Returns the numeric product of +self+ and +other+:
*
* 4 * 2 # => 8
* 4 * -2 # => -8
* -4 * 2 # => -8
* 4 * -2 # => -8
* 4 * 2.0 # => 8.0
* 4 * Rational(1, 3) # => (4/3)
* 4 * Complex(2, 0) # => (8+0i)
*
*/

VALUE
Expand Down Expand Up @@ -4590,17 +4592,48 @@ fix_pow(VALUE x, VALUE y)

/*
* call-seq:
* self ** numeric -> numeric_result
*
* Raises +self+ to the power of +numeric+:
*
* 2 ** 3 # => 8
* 2 ** -3 # => (1/8)
* -2 ** 3 # => -8
* -2 ** -3 # => (-1/8)
* 2 ** 3.3 # => 9.849155306759329
* 2 ** Rational(3, 1) # => (8/1)
* 2 ** Complex(3, 0) # => (8+0i)
* self ** exponent -> numeric
*
* Returns the value of base +self+ raised to the power +exponent+;
* see {Exponentiation}[https://en.wikipedia.org/wiki/Exponentiation]:
*
* # Result for non-negative Integer exponent is Integer.
* 2 ** 0 # => 1
* 2 ** 1 # => 2
* 2 ** 2 # => 4
* 2 ** 3 # => 8
* -2 ** 3 # => -8
* # Result for negative Integer exponent is Rational, not Float.
* 2 ** -3 # => (1/8)
* -2 ** -3 # => (-1/8)
*
* # Result for Float exponent is Float.
* 2 ** 0.0 # => 1.0
* 2 ** 1.0 # => 2.0
* 2 ** 2.0 # => 4.0
* 2 ** 3.0 # => 8.0
* -2 ** 3.0 # => -8.0
* 2 ** -3.0 # => 0.125
* -2 ** -3.0 # => -0.125
*
* # Result for non-negative Complex exponent is Complex with Integer parts.
* 2 ** Complex(0, 0) # => (1+0i)
* 2 ** Complex(1, 0) # => (2+0i)
* 2 ** Complex(2, 0) # => (4+0i)
* 2 ** Complex(3, 0) # => (8+0i)
* -2 ** Complex(3, 0) # => (-8+0i)
* # Result for negative Complex exponent is Complex with Rational parts.
* 2 ** Complex(-3, 0) # => ((1/8)+(0/1)*i)
* -2 ** Complex(-3, 0) # => ((-1/8)+(0/1)*i)
*
* # Result for Rational exponent is Rational.
* 2 ** Rational(0, 1) # => (1/1)
* 2 ** Rational(1, 1) # => (2/1)
* 2 ** Rational(2, 1) # => (4/1)
* 2 ** Rational(3, 1) # => (8/1)
* -2 ** Rational(3, 1) # => (-8/1)
* 2 ** Rational(-3, 1) # => (1/8)
* -2 ** Rational(-3, 1) # => (-1/8)
*
*/
VALUE
Expand Down
16 changes: 9 additions & 7 deletions rational.c
Original file line number Diff line number Diff line change
Expand Up @@ -853,15 +853,17 @@ f_muldiv(VALUE self, VALUE anum, VALUE aden, VALUE bnum, VALUE bden, int k)

/*
* call-seq:
* rat * numeric -> numeric
* self * other -> numeric
*
* Performs multiplication.
* Returns the numeric product of +self+ and +other+:
*
* Rational(9, 8) * 4 #=> (9/2)
* Rational(20, 9) * 9.8 #=> 21.77777777777778
* Rational(9, 8) * Complex(1, 2) # => ((9/8)+(9/4)*i)
* Rational(2, 3) * Rational(2, 3) #=> (4/9)
* Rational(900) * Rational(1) #=> (900/1)
* Rational(-2, 9) * Rational(-9, 2) #=> (1/1)
*
* Rational(2, 3) * Rational(2, 3) #=> (4/9)
* Rational(900) * Rational(1) #=> (900/1)
* Rational(-2, 9) * Rational(-9, 2) #=> (1/1)
* Rational(9, 8) * 4 #=> (9/2)
* Rational(20, 9) * 9.8 #=> 21.77777777777778
*/
VALUE
rb_rational_mul(VALUE self, VALUE other)
Expand Down
6 changes: 1 addition & 5 deletions test/rubygems/test_gem_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,11 +160,7 @@ def test_spaceship
[-1, "1.9.3.1"],
[nil, "whatever"],
].each do |cmp, string_ver|
actual_stdout, actual_stderr = capture_output do
assert_equal(cmp, v("1.9.3") <=> string_ver)
end
assert_empty actual_stdout
assert_match(/comparing version objects with strings is deprecated and will be removed/, actual_stderr)
assert_equal(cmp, v("1.9.3") <=> string_ver)
end
end

Expand Down
10 changes: 6 additions & 4 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,10 +654,12 @@ fn gen_guard_block_param_proxy(jit: &JITState, asm: &mut Assembler, level: u32,
}

fn gen_guard_not_frozen(jit: &JITState, asm: &mut Assembler, recv: Opnd, state: &FrameState) -> Opnd {
let ret = asm_ccall!(asm, rb_obj_frozen_p, recv);
asm_comment!(asm, "side-exit if rb_obj_frozen_p returns Qtrue");
asm.cmp(ret, Qtrue.into());
asm.je(side_exit(jit, state, GuardNotFrozen));
let recv = asm.load(recv);
// It's a heap object, so check the frozen flag
let flags = asm.load(Opnd::mem(64, recv, RUBY_OFFSET_RBASIC_FLAGS));
asm.test(flags, (RUBY_FL_FREEZE as u64).into());
// Side-exit if frozen
asm.jnz(side_exit(jit, state, GuardNotFrozen));
recv
}

Expand Down
2 changes: 2 additions & 0 deletions zjit/src/cruby_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ fn inline_array_push(fun: &mut hir::Function, block: hir::BlockId, recv: hir::In
fn inline_array_pop(fun: &mut hir::Function, block: hir::BlockId, recv: hir::InsnId, args: &[hir::InsnId], state: hir::InsnId) -> Option<hir::InsnId> {
// Only inline the case of no arguments.
let &[] = args else { return None; };
// We know that all Array are HeapObject, so no need to insert a GuardType(HeapObject).
let arr = fun.push_insn(block, hir::Insn::GuardNotFrozen { recv, state });
Some(fun.push_insn(block, hir::Insn::ArrayPop { array: arr, state }))
}
Expand Down Expand Up @@ -391,6 +392,7 @@ fn inline_string_setbyte(fun: &mut hir::Function, block: hir::BlockId, recv: hir
let unboxed_index = fun.push_insn(block, hir::Insn::GuardLess { left: unboxed_index, right: len, state });
let zero = fun.push_insn(block, hir::Insn::Const { val: hir::Const::CInt64(0) });
let _ = fun.push_insn(block, hir::Insn::GuardGreaterEq { left: unboxed_index, right: zero, state });
// We know that all String are HeapObject, so no need to insert a GuardType(HeapObject).
let recv = fun.push_insn(block, hir::Insn::GuardNotFrozen { recv, state });
let _ = fun.push_insn(block, hir::Insn::StringSetbyteFixnum { string: recv, index, value });
// String#setbyte returns the fixnum provided as its `value` argument back to the caller.
Expand Down
8 changes: 6 additions & 2 deletions zjit/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -903,7 +903,8 @@ pub enum Insn {
/// Side-exit if the block param has been modified or the block handler for the frame
/// is neither ISEQ nor ifunc, which makes it incompatible with rb_block_param_proxy.
GuardBlockParamProxy { level: u32, state: InsnId },
/// Side-exit if val is frozen.
/// Side-exit if val is frozen. Does *not* check if the val is an immediate; assumes that it is
/// a heap object.
GuardNotFrozen { recv: InsnId, state: InsnId },
/// Side-exit if left is not greater than or equal to right (both operands are C long).
GuardGreaterEq { left: InsnId, right: InsnId, state: InsnId },
Expand Down Expand Up @@ -2553,6 +2554,7 @@ impl Function {
//
// No need for a GuardShape.
if let OptimizedMethodType::StructAset = opt_type {
// We know that all Struct are HeapObject, so no need to insert a GuardType(HeapObject).
recv = self.push_insn(block, Insn::GuardNotFrozen { recv, state });
}

Expand Down Expand Up @@ -4150,7 +4152,6 @@ impl Function {
| Insn::IsNil { val }
| Insn::IsMethodCfunc { val, .. }
| Insn::GuardShape { val, .. }
| Insn::GuardNotFrozen { recv: val, .. }
| Insn::SetGlobal { val, .. }
| Insn::SetLocal { val, .. }
| Insn::SetClassVar { val, .. }
Expand All @@ -4169,6 +4170,9 @@ impl Function {
| Insn::DefinedIvar { self_val: val, .. } => {
self.assert_subtype(insn_id, val, types::BasicObject)
}
Insn::GuardNotFrozen { recv, .. } => {
self.assert_subtype(insn_id, recv, types::HeapBasicObject)
}
// Instructions with 2 Ruby object operands
Insn::SetIvar { self_val: left, val: right, .. }
| Insn::NewRange { low: left, high: right, .. }
Expand Down