summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ruby/ruby.h15
-rw-r--r--internal.h52
-rw-r--r--vm_core.h29
-rw-r--r--vm_eval.c33
4 files changed, 62 insertions, 67 deletions
diff --git a/include/ruby/ruby.h b/include/ruby/ruby.h
index 67ef3f4df2..947b3d44b8 100644
--- a/include/ruby/ruby.h
+++ b/include/ruby/ruby.h
@@ -1892,10 +1892,6 @@ VALUE rb_funcallv_public(VALUE, ID, int, const VALUE*);
#define rb_funcall3 rb_funcallv_public
VALUE rb_funcall_passing_block(VALUE, ID, int, const VALUE*);
VALUE rb_funcall_with_block(VALUE, ID, int, const VALUE*, VALUE);
-#if GCC_VERSION_SINCE(3, 3, 0)
-__attribute__((__nonnull__ (1))) /* TODO: should check using configure */
-#endif
-VALUE rb_funcallv_with_cc(void**, VALUE, ID, int, const VALUE*);
int rb_scan_args(int, const VALUE*, const char*, ...);
VALUE rb_call_super(int, const VALUE*);
VALUE rb_current_receiver(void);
@@ -2611,19 +2607,10 @@ __extension__({ \
const VALUE rb_funcall_args[] = {__VA_ARGS__}; \
const int rb_funcall_nargs = \
(int)(sizeof(rb_funcall_args) / sizeof(VALUE)); \
- static void *rb_funcall_opaque_cc = NULL; \
- rb_funcallv_with_cc(&rb_funcall_opaque_cc, \
- recv, mid, \
+ rb_funcallv(recv, mid, \
rb_varargs_argc_check(rb_funcall_argc, rb_funcall_nargs), \
rb_funcall_nargs ? rb_funcall_args : NULL); \
})
-
-# define rb_funcallv(recv, mid, argc, argv) \
-__extension__({ \
- static void *rb_funcallv_opaque_cc = NULL; \
- rb_funcallv_with_cc(&rb_funcallv_opaque_cc, \
- recv, mid, argc,argv); \
- })
#endif
#ifndef RUBY_DONT_SUBST
diff --git a/internal.h b/internal.h
index ddc9195668..14f78301fb 100644
--- a/internal.h
+++ b/internal.h
@@ -2314,6 +2314,58 @@ void Init_vm_stack_canary(void);
/* vm_method.c */
void Init_eval_method(void);
+enum method_missing_reason {
+ MISSING_NOENTRY = 0x00,
+ MISSING_PRIVATE = 0x01,
+ MISSING_PROTECTED = 0x02,
+ MISSING_FCALL = 0x04,
+ MISSING_VCALL = 0x08,
+ MISSING_SUPER = 0x10,
+ MISSING_MISSING = 0x20,
+ MISSING_NONE = 0x40
+};
+struct rb_callable_method_entry_struct;
+struct rb_execution_context_struct;
+struct rb_control_frame_struct;
+struct rb_calling_info;
+struct rb_call_info;
+struct rb_call_cache {
+ /* inline cache: keys */
+ rb_serial_t method_state;
+ rb_serial_t class_serial;
+
+ /* inline cache: values */
+ const struct rb_callable_method_entry_struct *me;
+
+ VALUE (*call)(struct rb_execution_context_struct *ec,
+ struct rb_control_frame_struct *cfp,
+ struct rb_calling_info *calling,
+ const struct rb_call_info *ci,
+ struct rb_call_cache *cc);
+
+ union {
+ unsigned int index; /* used by ivar */
+ enum method_missing_reason method_missing_reason; /* used by method_missing */
+ int inc_sp; /* used by cfunc */
+ } aux;
+};
+struct rb_call_cache_and_mid {
+ struct rb_call_cache cc;
+ ID mid;
+};
+VALUE rb_funcallv_with_cc(struct rb_call_cache_and_mid*, VALUE, ID, int, const VALUE*)
+#if GCC_VERSION_SINCE(3, 3, 0) && defined(__OPTIMIZE__)
+__attribute__((__visibility__("default"), __nonnull__(1)))
+# define rb_funcallv(recv, mid, argc, argv) \
+ __extension__({ \
+ static struct rb_call_cache_and_mid \
+ rb_funcallv_opaque_cc = { {0, }, 0, }; \
+ rb_funcallv_with_cc(&rb_funcallv_opaque_cc, \
+ recv, mid, argc,argv); \
+ })
+#endif
+ ;
+
/* miniprelude.c, prelude.c */
void Init_prelude(void);
diff --git a/vm_core.h b/vm_core.h
index eec80e41ef..60c258e1f3 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -234,17 +234,6 @@ union iseq_inline_storage_entry {
struct iseq_inline_cache_entry cache;
};
-enum method_missing_reason {
- MISSING_NOENTRY = 0x00,
- MISSING_PRIVATE = 0x01,
- MISSING_PROTECTED = 0x02,
- MISSING_FCALL = 0x04,
- MISSING_VCALL = 0x08,
- MISSING_SUPER = 0x10,
- MISSING_MISSING = 0x20,
- MISSING_NONE = 0x40
-};
-
struct rb_call_info {
/* fixed at compile time */
ID mid;
@@ -268,27 +257,9 @@ struct rb_calling_info {
int argc;
};
-struct rb_call_cache;
struct rb_execution_context_struct;
typedef VALUE (*vm_call_handler)(struct rb_execution_context_struct *ec, struct rb_control_frame_struct *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc);
-struct rb_call_cache {
- /* inline cache: keys */
- rb_serial_t method_state;
- rb_serial_t class_serial;
-
- /* inline cache: values */
- const rb_callable_method_entry_t *me;
-
- vm_call_handler call;
-
- union {
- unsigned int index; /* used by ivar */
- enum method_missing_reason method_missing_reason; /* used by method_missing */
- int inc_sp; /* used by cfunc */
- } aux;
-};
-
#if 1
#define CoreDataFromValue(obj, type) (type*)DATA_PTR(obj)
#else
diff --git a/vm_eval.c b/vm_eval.c
index 852aacba45..ccf24b347e 100644
--- a/vm_eval.c
+++ b/vm_eval.c
@@ -876,34 +876,19 @@ rb_funcallv_public(VALUE recv, ID mid, int argc, const VALUE *argv)
* \param argv pointer to an array of method arguments
*/
VALUE
-rb_funcallv_with_cc(void **ptr, VALUE recv, ID mid, int argc, const VALUE *argv)
+rb_funcallv_with_cc(struct rb_call_cache_and_mid *cc, VALUE recv, ID mid, int argc, const VALUE *argv)
{
- VM_ASSERT(ptr);
- struct opaque {
- struct rb_call_cache cc;
- ID mid;
- } *cc;
- if (UNLIKELY(! *ptr)) {
- *ptr = ZALLOC(struct opaque);
- }
- cc = *ptr;
-
- const struct rb_call_info ci = { mid, VM_CALL_ARGS_SIMPLE, argc, };
- if (UNLIKELY(cc->mid != mid)) {
- *cc = (struct opaque) /* reset */ { { 0, }, mid, };
- return rb_funcallv(recv, mid, argc, argv);
- }
- else {
+ if (LIKELY(cc->mid == mid)) {
+ const struct rb_call_info ci = { mid, VM_CALL_ARGS_SIMPLE, argc, };
vm_search_method(&ci, &cc->cc, recv);
- }
- if (UNLIKELY(UNDEFINED_METHOD_ENTRY_P(cc->cc.me))) {
- /* :FIXME: this path can be made faster */
- return rb_funcallv(recv, mid, argc, argv);
- }
- else {
- return rb_vm_call0(GET_EC(), recv, mid, argc, argv, cc->cc.me);
+ if (LIKELY(! UNDEFINED_METHOD_ENTRY_P(cc->cc.me))) {
+ return rb_vm_call0(GET_EC(), recv, mid, argc, argv, cc->cc.me);
+ }
}
+
+ *cc = (struct rb_call_cache_and_mid) /* reset */ { { 0, }, mid, };
+ return rb_funcallv(recv, mid, argc, argv);
}
VALUE