summaryrefslogtreecommitdiff
path: root/vm_insnhelper.c
diff options
context:
space:
mode:
authork0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-10-20 07:43:50 (GMT)
committerk0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-10-20 07:43:50 (GMT)
commit8449f4992b9eee9a4948a90a24faa47c59d7f0db (patch)
tree139326978207a90fdd10f36c044bb410428590a1 /vm_insnhelper.c
parentb640b21d9c6698d2246d2e0eb785653b570adcea (diff)
vm_insnhelper.c: never cache getinstancevariable twice
We have several options to ensure there's no race condition between main thread and MJIT thead about IC reference: 1) Give up caching ivar for multiple classes (or multiple versions of the same class) in the same getinstancevariable (This commit's approach) 2) Allocate new inline cache every time Other ideas we could think of couldn't eliminate possibilities of race condition. In 2, it's memory allocation would be slow and it may trigger JIT cancellation frequently. So 1 would be fast for both VM and JIT situations. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@65213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'vm_insnhelper.c')
-rw-r--r--vm_insnhelper.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 3f09991..8c01a62 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -976,12 +976,20 @@ vm_getivar(VALUE obj, ID id, IC ic, struct rb_call_cache *cc, int is_attr)
if (index < ROBJECT_NUMIV(obj)) {
val = ROBJECT_IVPTR(obj)[index];
}
- if (!is_attr) {
- ic->ic_value.index = index;
- ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass);
- }
- else { /* call_info */
- cc->aux.index = (int)index + 1;
+ if (is_attr) { /* call_info */
+ cc->aux.index = (int)index + 1;
+ }
+ else { /* getinstancevariable */
+ if (ic->ic_serial == RUBY_VM_CLASS_SERIAL_UNSET) {
+ /* set ic_serial only for the first time */
+ ic->ic_value.index = index;
+ ic->ic_serial = RCLASS_SERIAL(RBASIC(obj)->klass);
+ }
+ else if (ic->ic_serial != RUBY_VM_CLASS_SERIAL_INVALID) {
+ /* never use cache for another class, to avoid race condition with MJIT worker
+ and to reduce the number of JIT cancellations by code generated for IC hit. */
+ ic->ic_serial = RUBY_VM_CLASS_SERIAL_INVALID;
+ }
}
}
}