# Monkey Patch Detection in Ruby

DevFeed: [Monkey Patch Detection in Ruby](<https://devfeed.tech/articles/monkey-patch-detection-in-ruby-39000.md>)

Original publisher: [Read original article](<https://tenderlovemaking.com/2024/10/16/monkey-patch-detection-in-ruby/>)

Published: 2024-10-16T23:13:00Z

Content type: tutorial

Language: en

Sources: [Aaron Patterson](<https://devfeed.tech/sources/aaron-patterson.md>)

Topics: [Ruby](<https://devfeed.tech/topics/ruby.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [implementation](<https://devfeed.tech/topics/implementation.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [code](<https://devfeed.tech/tags/code.md>), [implementation](<https://devfeed.tech/tags/implementation.md>), [monkey-patching](<https://devfeed.tech/tags/monkey-patching.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [ruby](<https://devfeed.tech/tags/ruby.md>)

## AI overview

This article explains how CRuby detects monkey patches to methods involved in optimizations and de-optimizes when a relevant method is redefined. It describes method tables, redefinition checks, global flags, and class bitmap mappings.

## Source excerpt

My last post detailed one way that CRuby will eliminate some intermediate array allocations when using methods like Array#hash and Array#max. Part of the technique hinges on detecting when someone monkey patches array. Today, I thought we'd dive a little bit in to how CRuby detects and de-optimizes itself when these "important" methods get monkey patched. Monkey Patching Problem The optimization in the previous post made the assumption that the implementation Array#max was the original definition (as defined in Ruby itself). But the Ruby language allows us to reopen classes, redefine any methods we want, and that those methods will "just work". For example, if someone were to reopen Array and define a new max method, we would need to respect that monkey patch: class Array def max "hello!" end end puts [1, 2].max # => "hello!" In fact, a monkey patch implementation could mutate the array itself, so we're definitely required to allocate an array in the case that someone added their own max method: class Array def max self << :neat self end end x = [1, 2].max p x # => [1, 2, :neat] So how does CRuby detect that a method has been monkey patched? Method Definition Time Every time a method is defined, an entry is stored in a hash table pointed to by the current class. We call this the "method table", but you'll see it referred to as M_TBL or RCLASS_M_TBL in the code. The key to the hash is simply the method name as an ID type (an integer which represents a Ruby Symbol), and the value of the hash is a method entry structure. If there was already an entry in the table, then we know it's a "redefinition" (a.k.a. "monkey patch"), and we end up calling rb_vm_check_redefinition_opt_method here. rb_vm_check_redefinition_opt_method checks to see if this is a method we "care" about. Methods we "care" about are typically ones where we've made some kind of optimization and we need to deoptimize if someone redefines them. If the redefined method is something we care to detect, then w