It can happen that the inline cache changed since we got the request to JIT it. Therefore guard that we're actually seeing a proper class here so we fallback to regular sends in that case.
If the inline cache overflows too often, we don't use uncommon exit anymore, but fallback to a regular send. This helps performance for megamorphic call sites that keep seeing new types and are best off when falling back to a regular method send.
The multiple method cache entries already provide the same information. Since we already track those, we can remove the seen_classes since it basically just duplicates functionality.
Instead of keeping on the most recent call cached, we keep the last three that have happened. In case of overflow it always updates the latest entry. In the future we would want a smarter eviction algorithm to handle this.
Primitives can fail at any time, even during VM boot where the backtrace can be primitive or possibly missing. The following format of the PrimitiveFailure exception message provides all necessary information to index directly to the Ruby method and then to the primitive implementation: "[module scope]::class_name[.#]method_name primitive failed" This is the minimum required exception message. If there exists only a single possible cause of failure, that can be appended to, but does not replace, the basic exception message.
This happens quite a lot, especially since 27e43a6 which caused CI runs for 1.9 mode to run at least 30 seconds longer on my system locally. We use undefined here as the default value and as the marker to reset the value, since nil can be a valid value here and in that case we don't want to look it up each time either. The ontology change was needed, because otherwise undefined was not the correct value yet when the encodings were initialized.