perf(vm): in-place Plus/Minus/Mult with tInt fast path
Apply the sp-rewrite shape to the three binary arithmetic ops. The tInt==tInt fast branch reads scalar directly (skips the AsNumInt method) so the hot path is int64 ops + an overflow check; mixed-type branches keep AsNumDouble unchanged. PRG tight loops (FOR counter, SUM accumulators outside SQL aggregate path) skip one cachedNil store and two bounds-check sequences per op. Verification - go test ./... ALL PASS - FiveSql2 test_sql1999 43/43 - tests/compat_harbour 56/56 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,47 +20,50 @@ import "math"
|
||||
// Date + Numeric -> Date
|
||||
// Timestamp + Numeric -> Timestamp
|
||||
func (t *Thread) Plus() {
|
||||
b := t.pop()
|
||||
a := t.pop()
|
||||
t.sp -= 2
|
||||
a := t.stack[t.sp]
|
||||
b := t.stack[t.sp+1]
|
||||
t.stack[t.sp+1] = cachedNil
|
||||
dst := &t.stack[t.sp]
|
||||
|
||||
// Fast path: Int + Int
|
||||
if a.IsNumInt() && b.IsNumInt() {
|
||||
an, bn := a.AsNumInt(), b.AsNumInt()
|
||||
// Fast path: Int + Int (tInt tag — skip tLong to stay branch-light)
|
||||
if a.Type() == tInt && b.Type() == tInt {
|
||||
an, bn := int64(a.scalar), int64(b.scalar)
|
||||
r := an + bn
|
||||
// Overflow detection (Harbour pattern)
|
||||
if (bn >= 0 && r >= an) || (bn < 0 && r < an) {
|
||||
t.push(MakeNumInt(r))
|
||||
*dst = MakeNumInt(r)
|
||||
} else {
|
||||
t.push(MakeDoubleAuto(float64(an) + float64(bn)))
|
||||
*dst = MakeDoubleAuto(float64(an) + float64(bn))
|
||||
}
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Numeric + Numeric -> Double
|
||||
if a.IsNumeric() && b.IsNumeric() {
|
||||
ad, bd := a.AsNumDouble(), b.AsNumDouble()
|
||||
dec := maxDec(a.Decimal(), b.Decimal())
|
||||
t.push(MakeDouble(ad+bd, 255, dec))
|
||||
*dst = MakeDouble(ad+bd, 255, dec)
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// String + String -> concatenation
|
||||
if a.IsString() && b.IsString() {
|
||||
t.push(MakeString(a.AsString() + b.AsString()))
|
||||
*dst = MakeString(a.AsString() + b.AsString())
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Date + Numeric -> Date (add days — truncate fractional)
|
||||
if a.IsDate() && b.IsNumeric() {
|
||||
t.push(MakeDate(a.AsJulian() + int64(b.AsNumDouble())))
|
||||
*dst = MakeDate(a.AsJulian() + int64(b.AsNumDouble()))
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
if a.IsNumeric() && b.IsDate() {
|
||||
t.push(MakeDate(int64(a.AsNumDouble()) + b.AsJulian()))
|
||||
*dst = MakeDate(int64(a.AsNumDouble()) + b.AsJulian())
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Timestamp + Numeric -> Timestamp
|
||||
if a.IsTimestamp() && b.IsNumeric() {
|
||||
days := int64(b.AsNumDouble())
|
||||
frac := b.AsNumDouble() - float64(days)
|
||||
@@ -74,7 +77,8 @@ func (t *Thread) Plus() {
|
||||
newJulian--
|
||||
newTime += 86400000
|
||||
}
|
||||
t.push(MakeTimestamp(newJulian, newTime))
|
||||
*dst = MakeTimestamp(newJulian, newTime)
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
@@ -84,50 +88,53 @@ func (t *Thread) Plus() {
|
||||
// Minus pops two values, pushes their difference.
|
||||
// Harbour: hb_vmMinus (hvm.c:3401)
|
||||
func (t *Thread) Minus() {
|
||||
b := t.pop()
|
||||
a := t.pop()
|
||||
t.sp -= 2
|
||||
a := t.stack[t.sp]
|
||||
b := t.stack[t.sp+1]
|
||||
t.stack[t.sp+1] = cachedNil
|
||||
dst := &t.stack[t.sp]
|
||||
|
||||
// Fast path: Int - Int
|
||||
if a.IsNumInt() && b.IsNumInt() {
|
||||
an, bn := a.AsNumInt(), b.AsNumInt()
|
||||
if a.Type() == tInt && b.Type() == tInt {
|
||||
an, bn := int64(a.scalar), int64(b.scalar)
|
||||
r := an - bn
|
||||
if (bn <= 0 && r >= an) || (bn > 0 && r < an) {
|
||||
t.push(MakeNumInt(r))
|
||||
*dst = MakeNumInt(r)
|
||||
} else {
|
||||
t.push(MakeDoubleAuto(float64(an) - float64(bn)))
|
||||
*dst = MakeDoubleAuto(float64(an) - float64(bn))
|
||||
}
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Numeric - Numeric -> Double
|
||||
if a.IsNumeric() && b.IsNumeric() {
|
||||
ad, bd := a.AsNumDouble(), b.AsNumDouble()
|
||||
dec := maxDec(a.Decimal(), b.Decimal())
|
||||
t.push(MakeDouble(ad-bd, 255, dec))
|
||||
*dst = MakeDouble(ad-bd, 255, dec)
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Date - Date -> Long (difference in days)
|
||||
if a.IsDate() && b.IsDate() {
|
||||
t.push(MakeLong(a.AsJulian() - b.AsJulian()))
|
||||
*dst = MakeLong(a.AsJulian() - b.AsJulian())
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Date - Numeric -> Date
|
||||
if a.IsDate() && b.IsNumeric() {
|
||||
t.push(MakeDate(a.AsJulian() - int64(b.AsNumDouble())))
|
||||
*dst = MakeDate(a.AsJulian() - int64(b.AsNumDouble()))
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
// Timestamp - Timestamp -> Double or Long
|
||||
if a.IsTimestamp() && b.IsTimestamp() {
|
||||
dayDiff := a.AsJulian() - b.AsJulian()
|
||||
timeDiff := a.AsTimeMs() - b.AsTimeMs()
|
||||
if timeDiff != 0 {
|
||||
t.push(MakeDoubleAuto(float64(dayDiff) + float64(timeDiff)/86400000.0))
|
||||
*dst = MakeDoubleAuto(float64(dayDiff) + float64(timeDiff)/86400000.0)
|
||||
} else {
|
||||
t.push(MakeLong(dayDiff))
|
||||
*dst = MakeLong(dayDiff)
|
||||
}
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
@@ -138,21 +145,26 @@ func (t *Thread) Minus() {
|
||||
// Harbour: hb_vmMult (hvm.c:3510)
|
||||
// Decimal rule: dec = dec1 + dec2
|
||||
func (t *Thread) Mult() {
|
||||
b := t.pop()
|
||||
a := t.pop()
|
||||
t.sp -= 2
|
||||
a := t.stack[t.sp]
|
||||
b := t.stack[t.sp+1]
|
||||
t.stack[t.sp+1] = cachedNil
|
||||
dst := &t.stack[t.sp]
|
||||
|
||||
if a.IsNumInt() && b.IsNumInt() {
|
||||
an, bn := a.AsNumInt(), b.AsNumInt()
|
||||
if a.Type() == tInt && b.Type() == tInt {
|
||||
an, bn := int64(a.scalar), int64(b.scalar)
|
||||
if an == 0 || bn == 0 {
|
||||
t.push(MakeNumInt(0))
|
||||
*dst = MakeNumInt(0)
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
r := an * bn
|
||||
if r/an == bn {
|
||||
t.push(MakeNumInt(r))
|
||||
*dst = MakeNumInt(r)
|
||||
} else {
|
||||
t.push(MakeDoubleAuto(float64(an) * float64(bn)))
|
||||
*dst = MakeDoubleAuto(float64(an) * float64(bn))
|
||||
}
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
@@ -162,7 +174,8 @@ func (t *Thread) Mult() {
|
||||
if dec > 255 {
|
||||
dec = 255
|
||||
}
|
||||
t.push(MakeDouble(ad*bd, 255, dec))
|
||||
*dst = MakeDouble(ad*bd, 255, dec)
|
||||
t.sp++
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user