diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-10-23 17:53:35 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2015-10-23 17:53:35 +0000 |
commit | 2be37dabfac10abed4954797c25a4c67df0a8b0a (patch) | |
tree | 7991edac0f5872f2c8ac7aecffed6e87226518ed /tool | |
parent | c369c817199ab66909775d6f340923b4f4af1bbf (diff) | |
download | ruby-2be37dabfac10abed4954797c25a4c67df0a8b0a.tar.gz |
* vm_insnhelper.c: introduce new call handler for simple ISeqs.
vm_call_iseq_setup_normal_0start() is simple, however it has
some loops/conditions depends on ISeq::param.size and
ISeq::local_size (in vm_push_frame(), inlined into this function).
There are many simple methods which has a few parameters and local
variables. So that this patch introduces several special functions
generated in vm_call_iseq_optimized.inc by
tool/mk_call_iseq_optimized.rb.
This script makes
vm_call_iseq_setup_normal_0start_Xparams_Ylocals()
where X is 0 to 3 and Y is 1 to 6 (as current setting).
In this case, X * Y = 24 functions are created.
These functions creates fast method dispatch by inlining
vm_push_frame() with immediate params/locals sizes.
On my laptop, we can have the following results.
vm2_method* 1.083 (8.3% faster)
vm2_poly_method* 0.961 (3.4% slower)
It shows 8.3% faster for inner loop method dispatch (hit inline
cache), but 3.4% slower when inline cache miss because we need
to find a suitable call handler.
* common.mk: add a rule for vm_call_iseq_optimized.inc.
* tool/mk_call_iseq_optimized.rb: added.
* vm.c: include vm_call_iseq_optimized.inc.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52254 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'tool')
-rw-r--r-- | tool/mk_call_iseq_optimized.rb | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/tool/mk_call_iseq_optimized.rb b/tool/mk_call_iseq_optimized.rb new file mode 100644 index 0000000000..d99de0a46b --- /dev/null +++ b/tool/mk_call_iseq_optimized.rb @@ -0,0 +1,72 @@ +
+puts <<EOS
+#if 1 /* enable or disable this optimization */
+
+/* DO NOT EDIT THIS FILE DIRECTLY
+ *
+ * This file is enerated by tool/mkcall_iseq.rb
+ */
+
+EOS
+
+P = (0..3)
+L = (1..6)
+
+def fname param, local
+ "vm_call_iseq_setup_normal_0start_#{param}params_#{local}locals"
+end
+
+P.each{|param|
+ L.each{|local|
+ puts <<EOS
+static VALUE
+#{fname(param, local)}(rb_thread_t *th, rb_control_frame_t *cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, struct rb_call_cache *cc)
+{
+ return vm_call_iseq_setup_normal(th, cfp, calling, ci, cc, 0, #{param}, #{local});
+}
+
+EOS
+ #
+ }
+}
+
+puts <<EOS
+/* vm_call_iseq_handlers[param][local] */
+static const vm_call_handler vm_call_iseq_handlers[][#{L.to_a.size}] = {
+#{P.map{|param| '{' + L.map{|local| fname(param, local)}.join(",\n ") + '}'}.join(",\n")}
+};
+
+static inline vm_call_handler
+vm_call_iseq_setup_func(const struct rb_call_info *ci, const int param_size, const int local_size)
+{
+ if (UNLIKELY(ci->flag & VM_CALL_TAILCALL)) {
+ return vm_call_iseq_setup_tailcall_0start;
+ }
+ else if (0) { /* to disable optimize */
+ return vm_call_iseq_setup_normal_0start;
+ }
+ else {
+ if (param_size <= #{P.end} &&
+ local_size <= #{L.end}) {
+ VM_ASSERT(local_size != 0);
+ return vm_call_iseq_handlers[param_size][local_size-1];
+ }
+ return vm_call_iseq_setup_normal_0start;
+ }
+}
+
+#else
+
+
+static inline vm_call_handler
+vm_call_iseq_setup_func(const struct rb_call_info *ci, struct rb_call_cache *cc)
+{
+ if (UNLIKELY(ci->flag & VM_CALL_TAILCALL)) {
+ return vm_call_iseq_setup_tailcall_0start;
+ }
+ else {
+ return vm_call_iseq_setup_normal_0start;
+ }
+}
+#endif
+EOS
|