summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authorAaron Patterson <tenderlove@ruby-lang.org>2022-03-07 11:08:15 -0800
committerAaron Patterson <aaron.patterson@gmail.com>2022-03-10 08:44:28 -0800
commit67faea970857c292ae35dadd103287d4f4449a58 (patch)
tree8658e97b0aedde5ced412ad5a38b6b840eacd389 /vm_insnhelper.c
parent702f40628ad0e56cb42337fb2b0c53e0b901ed4d (diff)
Small optimization for the opt_and instruction
This change eagerly performs a bitwise and on the parameters. If both parameters are fixnums, then the result value should also be a fixnum. We can just test the bit on the result and return if it's a fixnum. Otherwise return Qundef.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/5629
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 27d9d13aac..f6d9c2c634 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -5335,9 +5335,15 @@ vm_opt_ltlt(VALUE recv, VALUE obj)
static VALUE
vm_opt_and(VALUE recv, VALUE obj)
{
- if (FIXNUM_2_P(recv, obj) &&
+ // If recv and obj are both fixnums, then the bottom tag bit
+ // will be 1 on both. 1 & 1 == 1, so the result value will also
+ // be a fixnum. If either side is *not* a fixnum, then the tag bit
+ // will be 0, and we return Qundef.
+ VALUE ret = ((SIGNED_VALUE) recv) & ((SIGNED_VALUE) obj);
+
+ if (FIXNUM_P(ret) &&
BASIC_OP_UNREDEFINED_P(BOP_AND, INTEGER_REDEFINED_OP_FLAG)) {
- return (recv & obj) | 1;
+ return ret;
}
else {
return Qundef;