ruby-changes:64676
From: Kenta <ko1@a...>
Date: Thu, 31 Dec 2020 02:19:55 +0900 (JST)
Subject: [ruby-changes:64676] a8014dae47 (master): [ruby/bigdecimal] Refactor object allocation
https://git.ruby-lang.org/ruby.git/commit/?id=a8014dae47 From a8014dae47cc777ce5e509c9401b67cacb6631ae Mon Sep 17 00:00:00 2001 From: Kenta Murata <mrkn@m...> Date: Thu, 31 Dec 2020 02:01:35 +0900 Subject: [ruby/bigdecimal] Refactor object allocation https://github.com/ruby/bigdecimal/commit/271cebe567 diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c index 13b2cdc..96fe253 100644 --- a/ext/bigdecimal/bigdecimal.c +++ b/ext/bigdecimal/bigdecimal.c @@ -266,7 +266,7 @@ again: https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L266 if (prec > (long)DBLE_FIG) goto SomeOneMayDoIt; d = RFLOAT_VALUE(v); if (!isfinite(d)) { - pv = VpCreateRbObject(1, NULL); + pv = VpCreateRbObject(1, NULL, true); VpDtoV(pv, d); return pv; } @@ -275,9 +275,9 @@ again: https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L275 goto again; } if (1/d < 0.0) { - return VpCreateRbObject(prec, "-0"); + return VpCreateRbObject(prec, "-0", true); } - return VpCreateRbObject(prec, "0"); + return VpCreateRbObject(prec, "0", true); case T_RATIONAL: if (prec < 0) goto unable_to_coerce_without_prec; @@ -306,20 +306,20 @@ again: https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L306 case T_FIXNUM: sprintf(szD, "%ld", FIX2LONG(v)); - return VpCreateRbObject(VpBaseFig() * 2 + 1, szD); + return VpCreateRbObject(VpBaseFig() * 2 + 1, szD, true); #ifdef ENABLE_NUMERIC_STRING case T_STRING: StringValueCStr(v); - return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1, - RSTRING_PTR(v)); + return VpCreateRbObject(RSTRING_LEN(v) + VpBaseFig() + 1, + RSTRING_PTR(v), true); #endif /* ENABLE_NUMERIC_STRING */ case T_BIGNUM: bg = rb_big2str(v, 10); PUSH(bg); - return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1, - RSTRING_PTR(bg)); + return VpCreateRbObject(strlen(RSTRING_PTR(bg)) + VpBaseFig() + 1, + RSTRING_PTR(bg), true); default: goto SomeOneMayDoIt; } @@ -559,7 +559,7 @@ BigDecimal_load(VALUE self, VALUE str) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L559 m = m*10 + (unsigned long)(ch-'0'); } if (m > VpBaseFig()) m -= VpBaseFig(); - GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self)); + GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true)); m /= VpBaseFig(); if (m && pv->MaxPrec > m) { pv->MaxPrec = m+1; @@ -774,21 +774,39 @@ GetPrecisionInt(VALUE v) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L774 return n; } +static VALUE +BigDecimal_wrap_struct(VALUE obj, Real *vp) +{ + assert(is_kind_of_BigDecimal(obj)); + assert(vp != NULL); + + if (vp->obj == obj && RTYPEDDATA_DATA(obj) == vp) + return obj; + + assert(RTYPEDDATA_DATA(obj) == NULL); + assert(vp->obj == 0); + + RTYPEDDATA_DATA(obj) = vp; + vp->obj = obj; + RB_OBJ_FREEZE(obj); + return obj; +} + VP_EXPORT Real * -VpNewRbClass(size_t mx, const char *str, VALUE klass) +VpNewRbClass(size_t mx, const char *str, VALUE klass, bool strict_p, bool raise_exception) { VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0); - Real *pv = VpAlloc(mx, str, 1, 1); - RTYPEDDATA_DATA(obj) = pv; - pv->obj = obj; - RB_OBJ_FREEZE(obj); + Real *pv = VpAlloc(mx, str, strict_p, raise_exception); + if (!pv) + return NULL; + BigDecimal_wrap_struct(obj, pv); return pv; } VP_EXPORT Real * -VpCreateRbObject(size_t mx, const char *str) +VpCreateRbObject(size_t mx, const char *str, bool raise_exception) { - return VpNewRbClass(mx, str, rb_cBigDecimal); + return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception); } #define VpAllocReal(prec) (Real *)VpMemAlloc(offsetof(Real, frac) + (prec) * sizeof(BDIGIT)) @@ -1076,11 +1094,11 @@ BigDecimal_add(VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1094 mx = GetAddSubPrec(a, b); if (mx == (size_t)-1L) { - GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0")); + GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true)); VpAddSub(c, a, b, 1); } else { - GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0")); + GUARD_OBJ(c, VpCreateRbObject(mx * (VpBaseFig() + 1), "0", true)); if(!mx) { VpSetInf(c, VpGetSign(a)); } @@ -1134,11 +1152,11 @@ BigDecimal_sub(VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1152 mx = GetAddSubPrec(a,b); if (mx == (size_t)-1L) { - GUARD_OBJ(c,VpCreateRbObject(VpBaseFig() + 1, "0")); + GUARD_OBJ(c, VpCreateRbObject(VpBaseFig() + 1, "0", true)); VpAddSub(c, a, b, -1); } else { - GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); + GUARD_OBJ(c,VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true)); if (!mx) { VpSetInf(c,VpGetSign(a)); } @@ -1351,7 +1369,7 @@ BigDecimal_neg(VALUE self) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1369 ENTER(5); Real *c, *a; GUARD_OBJ(a, GetVpValue(self, 1)); - GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0")); + GUARD_OBJ(c, VpCreateRbObject(a->Prec *(VpBaseFig() + 1), "0", true)); VpAsgn(c, a, -1); return VpCheckGetValue(c); } @@ -1393,7 +1411,7 @@ BigDecimal_mult(VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1411 SAVE(b); mx = a->Prec + b->Prec; - GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0")); + GUARD_OBJ(c, VpCreateRbObject(mx *(VpBaseFig() + 1), "0", true)); VpMult(c, a, b); return VpCheckGetValue(c); } @@ -1426,8 +1444,8 @@ BigDecimal_divide(Real **c, Real **res, Real **div, VALUE self, VALUE r) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1444 mx++; /* NOTE: An additional digit is needed for the compatibility to the version 1.2.1 and the former. */ mx = (mx + 1) * VpBaseFig(); - GUARD_OBJ((*c), VpCreateRbObject(mx, "#0")); - GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); + GUARD_OBJ((*c), VpCreateRbObject(mx, "#0", true)); + GUARD_OBJ((*res), VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true)); VpDivd(*c, *res, a, b); return Qnil; } @@ -1492,22 +1510,22 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1510 rb_raise(rb_eZeroDivError, "divided by 0"); } if (VpIsInf(a)) { - GUARD_OBJ(d, VpCreateRbObject(1, "0")); + GUARD_OBJ(d, VpCreateRbObject(1, "0", true)); VpSetInf(d, (SIGNED_VALUE)(VpGetSign(a) == VpGetSign(b) ? 1 : -1)); - GUARD_OBJ(c, VpCreateRbObject(1, "NaN")); + GUARD_OBJ(c, VpCreateRbObject(1, "NaN", true)); *div = d; *mod = c; return Qtrue; } if (VpIsInf(b)) { - GUARD_OBJ(d, VpCreateRbObject(1, "0")); + GUARD_OBJ(d, VpCreateRbObject(1, "0", true)); *div = d; *mod = a; return Qtrue; } if (VpIsZero(a)) { - GUARD_OBJ(c, VpCreateRbObject(1, "0")); - GUARD_OBJ(d, VpCreateRbObject(1, "0")); + GUARD_OBJ(c, VpCreateRbObject(1, "0", true)); + GUARD_OBJ(d, VpCreateRbObject(1, "0", true)); *div = d; *mod = c; return Qtrue; @@ -1516,17 +1534,17 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1534 mx = a->Prec + vabs(a->exponent); if (mx<b->Prec + vabs(b->exponent)) mx = b->Prec + vabs(b->exponent); mx = (mx + 1) * VpBaseFig(); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); - GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); + GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 +(VpBaseFig() + 1), "#0", true)); VpDivd(c, res, a, b); mx = c->Prec * (VpBaseFig() + 1); - GUARD_OBJ(d, VpCreateRbObject(mx, "0")); + GUARD_OBJ(d, VpCreateRbObject(mx, "0", true)); VpActiveRound(d, c, VP_ROUND_DOWN, 0); VpMult(res, d, b); VpAddSub(c, a, res, -1); if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) { VpAddSub(res, d, VpOne(), -1); - GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0")); + GUARD_OBJ(d, VpCreateRbObject(GetAddSubPrec(c, b)*(VpBaseFig() + 1), "0", true)); VpAddSub(d, c, b, 1); *div = res; *mod = d; @@ -1537,8 +1555,8 @@ BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1555 return Qtrue; NaN: - GUARD_OBJ(c, VpCreateRbObject(1, "NaN")); - GUARD_OBJ(d, VpCreateRbObject(1, "NaN")); + GUARD_OBJ(c, VpCreateRbObject(1, "NaN", true)); + GUARD_OBJ(d, VpCreateRbObject(1, "NaN", true)); *div = d; *mod = c; return Qtrue; @@ -1588,17 +1606,17 @@ BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) https://github.com/ruby/ruby/blob/trunk/ext/bigdecimal/bigdecimal.c#L1606 SAVE(b); mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig(); - GUARD_OBJ(c, VpCreateRbObject(mx, "0")); - GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0")); - GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0")); - GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0")); + GUARD_OBJ(c, VpCreateRbObject(mx, "0", true)); + GUARD_OBJ(res, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true)); + GUARD_OBJ(rr, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true)); + GUARD_OBJ(ff, VpCreateRbObject((mx+1) * 2 + (VpBaseFig() + 1), "#0", true)); VpDivd(c, res, a, b); mx = c->Prec *(VpBaseFig() + 1); - GUARD_OBJ(d, VpCreateRbObject(mx, "0")); - GUARD_OBJ(f, VpCreateRbObject(mx, "0")); + GUARD_OBJ(d, VpCreateRbObj (... truncated) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/