diff --git a/string.c b/string.c index 711918b..d4cbcbe 100644 --- a/string.c +++ b/string.c @@ -406,10 +406,19 @@ str_new(VALUE klass, const char *ptr, long len) return str; } +extern void rb_obj_call_init_fast(VALUE obj, int argc, VALUE *argv); + VALUE rb_str_new(const char *ptr, long len) { - return str_new(rb_cString, ptr, len); + /* str is already initialized by original initialize within str_new() */ + VALUE str = str_new(rb_cString, ptr, len); + + /* speed: call initialize only if it was redefined. See #4893 */ + /* passing str itself as parameter, avoiding need for a temp str */ + rb_obj_call_init_fast((VALUE)str, 1, &str); + + return str; } VALUE diff --git a/vm_method.c b/vm_method.c index 86ff2ee..43c50b9 100644 --- a/vm_method.c +++ b/vm_method.c @@ -258,6 +258,34 @@ method_added(VALUE klass, ID mid) } } +/* use class-variable (bit-flag). TODO: move to header file */ +#define FL_CALL_INIT FL_USER18 + +void +rb_set_call_flags(VALUE klass, ID mid, int set) +{ +/* if used for more classes, introduce FL_FAST_CLASS to mark*/ + + if (ruby_running && mid == idInitialize && klass == rb_cString) { + if (set) { + FL_SET(klass, FL_CALL_INIT); + } else { + FL_UNSET(klass, FL_CALL_INIT); + } + } +} + +void +rb_obj_call_init_fast(VALUE obj, int argc, VALUE *argv) +{ +/* use only in fast_classes like String. Method lookup and call of initialize + will be done only, if initialize was redefined. */ + + if (FL_TEST(CLASS_OF(obj), FL_CALL_INIT)) { + rb_obj_call_init(obj, argc, argv); + } +} + rb_method_entry_t * rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_flag_t noex) { @@ -304,6 +332,9 @@ rb_add_method(VALUE klass, ID mid, rb_method_type_t type, void *opts, rb_method_ default: rb_bug("rb_add_method: unsupported method type (%d)\n", type); } + + rb_set_call_flags(klass, mid, TRUE); + if (type != VM_METHOD_TYPE_UNDEF) { method_added(klass, mid); } @@ -441,7 +472,7 @@ remove_method(VALUE klass, ID mid) rb_vm_check_redefinition_opt_method(me); rb_clear_cache_for_undef(klass, mid); rb_unlink_method_entry(me); - + rb_set_call_flags(klass, mid, FALSE); CALL_METHOD_HOOK(klass, removed, mid); } @@ -628,6 +659,8 @@ rb_undef(VALUE klass, ID id) rb_add_method(klass, id, VM_METHOD_TYPE_UNDEF, 0, NOEX_PUBLIC); + rb_set_call_flags(klass, id, FALSE); + CALL_METHOD_HOOK(klass, undefined, id); }