Skip to content

Commit

Permalink
should not raise an exception, so implement vm_fast_mod(). fix #1471
Browse files Browse the repository at this point in the history
The modulo between the Fixnum/Float is improved the performance by this patch.

* before
      user     system      total        real
  1.000000   0.000000   1.000000 (  1.000743)
  1.030000   0.000000   1.030000 (  1.030479)
  1.090000   0.000000   1.090000 (  1.097021)

* after
      user     system      total        real
  0.570000   0.000000   0.570000 (  0.577238)
  1.040000   0.000000   1.040000 (  1.031634)
  0.540000   0.000000   0.540000 (  0.539968)

Test Script:
----
require 'benchmark'

Benchmark.bm do |x|
  x.report do
    10_000_000.times do
      42 % 1
    end
  end

  x.report do
    10_000_000.times do
      42 % 1.0
    end
  end

  x.report do
    10_000_000.times do
      42.0 % 1.0
    end
  end
end
  • Loading branch information
Watson1978 committed May 15, 2012
1 parent 9dec8ce commit a3b91c6
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 1 deletion.
6 changes: 5 additions & 1 deletion compiler.cpp
Expand Up @@ -172,6 +172,7 @@ RoxorCompiler::RoxorCompiler(bool _debug_mode)
fastMinusFunc = get_function("vm_fast_minus");
fastMultFunc = get_function("vm_fast_mult");
fastDivFunc = get_function("vm_fast_div");
fastModFunc = get_function("vm_fast_mod");
fastLtFunc = get_function("vm_fast_lt");
fastLeFunc = get_function("vm_fast_le");
fastGtFunc = get_function("vm_fast_gt");
Expand Down Expand Up @@ -2298,7 +2299,7 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
return pn;
}
// Pure arithmetic operations.
else if (sel == selPLUS || sel == selMINUS || sel == selDIV
else if (sel == selPLUS || sel == selMINUS || sel == selDIV || sel == selMOD
|| sel == selMULT || sel == selLT || sel == selLE
|| sel == selGT || sel == selGE || sel == selEq
|| sel == selNeq || sel == selEqq) {
Expand All @@ -2320,6 +2321,9 @@ RoxorCompiler::compile_optimized_dispatch_call(SEL sel, int argc,
else if (sel == selDIV) {
func = fastDivFunc;
}
else if (sel == selMOD) {
func = fastModFunc;
}
else if (sel == selMULT) {
func = fastMultFunc;
}
Expand Down
1 change: 1 addition & 0 deletions compiler.h
Expand Up @@ -159,6 +159,7 @@ class RoxorCompiler {
Function *fastMinusFunc;
Function *fastMultFunc;
Function *fastDivFunc;
Function *fastModFunc;
Function *fastLtFunc;
Function *fastLeFunc;
Function *fastGtFunc;
Expand Down
1 change: 1 addition & 0 deletions exported_symbols_list
Expand Up @@ -14,6 +14,7 @@ _rstr_concat
_selPLUS
_selMINUS
_selDIV
_selMOD
_selMULT
_selLT
_selLE
Expand Down
58 changes: 58 additions & 0 deletions kernel.c
Expand Up @@ -438,6 +438,64 @@ vm_fast_div(VALUE left, VALUE right, unsigned char overriden)
return vm_dispatch(0, left, selDIV, NULL, 0, 1, &right);
}

PRIMITIVE VALUE
vm_fast_mod(VALUE left, VALUE right, unsigned char overriden)
{
if (overriden == 0 && NUMERIC_IMM_P(left) && NUMERIC_IMM_P(right)) {
if (FIXNUM_P(left) && FIXNUM_P(right)) {
const long x = FIX2LONG(left);
const long y = FIX2LONG(right);
long div, mod;

if (y == 0) {
rb_num_zerodiv();
}
if (y < 0) {
if (x < 0) {
div = -x / -y;
}
else {
div = - (x / -y);
}
}
else {
if (x < 0) {
div = - (-x / y);
}
else {
div = x / y;
}
}
mod = x - div*y;
if ((mod < 0 && y > 0) || (mod > 0 && y < 0)) {
mod += y;
div -= 1;
}
return LONG2FIX(mod);
}
else if (FIXFLOAT_P(left) && FIXFLOAT_P(right)) {
const double x = IMM2DBL(left);
const double y = IMM2DBL(right);
double div, mod;

#ifdef HAVE_FMOD
mod = fmod(x, y);
#else
double z;
modf(x/y, &z);
mod = x - z * y;
#endif
div = (x - mod) / y;
if (y * mod < 0) {
mod += y;
div -= 1.0;
}
return DBL2FIXFLOAT(mod);
}
}
return vm_dispatch(0, left, selMOD, NULL, 0, 1, &right);
}

PRIMITIVE VALUE
vm_fast_lt(VALUE left, VALUE right, unsigned char overriden)
{
Expand Down

0 comments on commit a3b91c6

Please sign in to comment.