From 54b35f93252b097922ee580ce4df69a4c6612095 Mon Sep 17 00:00:00 2001 From: CharlesKWON Date: Sat, 18 Apr 2026 03:16:01 +0900 Subject: [PATCH] perf(vm): in-place And/Or with logical-only fast path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fold And/Or into the same in-place sp-rewrite shape as Not/LessEqual. Both args must be tLogical — short-circuit on the raw scalar field so the hot path is pure integer arithmetic + two cached bool Values. Verification - go test ./... ALL PASS - FiveSql2 test_sql1999 43/43 - tests/compat_harbour 56/56 Co-Authored-By: Claude Opus 4.7 (1M context) --- hbrt/ops_compare.go | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/hbrt/ops_compare.go b/hbrt/ops_compare.go index 8982c83..4d0c274 100644 --- a/hbrt/ops_compare.go +++ b/hbrt/ops_compare.go @@ -209,22 +209,38 @@ func (t *Thread) Not() { // And pops two values, pushes logical AND. // Harbour evaluates both sides (no short-circuit in VM ops). func (t *Thread) And() { - b := t.pop() - a := t.pop() - if !a.IsLogical() || !b.IsLogical() { - panic(t.argError(".AND.", a, b)) + t.sp -= 2 + a := t.stack[t.sp] + b := t.stack[t.sp+1] + t.stack[t.sp+1] = cachedNil + if a.Type() == tLogical && b.Type() == tLogical { + if a.scalar != 0 && b.scalar != 0 { + t.stack[t.sp] = cachedTrue + } else { + t.stack[t.sp] = cachedFalse + } + t.sp++ + return } - t.push(MakeBool(a.AsBool() && b.AsBool())) + panic(t.argError(".AND.", a, b)) } // Or pops two values, pushes logical OR. func (t *Thread) Or() { - b := t.pop() - a := t.pop() - if !a.IsLogical() || !b.IsLogical() { - panic(t.argError(".OR.", a, b)) + t.sp -= 2 + a := t.stack[t.sp] + b := t.stack[t.sp+1] + t.stack[t.sp+1] = cachedNil + if a.Type() == tLogical && b.Type() == tLogical { + if a.scalar != 0 || b.scalar != 0 { + t.stack[t.sp] = cachedTrue + } else { + t.stack[t.sp] = cachedFalse + } + t.sp++ + return } - t.push(MakeBool(a.AsBool() || b.AsBool())) + panic(t.argError(".OR.", a, b)) } // InString implements the $ operator: "bc" $ "abcde" → .T.