Skip to content

Commit e2cabc2

Browse files
committed
* gc.c (newobj_of): divide fast path and slow path
to avoid register savings for fast path. This idea is given by Kazuho Oku <[email protected]>. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52072 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 9fe491e commit e2cabc2

File tree

2 files changed

+77
-33
lines changed

2 files changed

+77
-33
lines changed

ChangeLog

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
Wed Oct 07 20:17:29 2015 Koichi Sasada <[email protected]>
2+
3+
* gc.c (newobj_of): divide fast path and slow path
4+
to avoid register savings for fast path.
5+
6+
This idea is given by Kazuho Oku <[email protected]>.
7+
18
Wed Oct 7 17:30:50 2015 Nobuyoshi Nakada <[email protected]>
29

310
* string.c (rb_str_times): optimize for the argument 0 and 1.

gc.c

Lines changed: 70 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,16 @@ heap_get_freeobj_from_next_freepage(rb_objspace_t *objspace, rb_heap_t *heap)
16541654
return p;
16551655
}
16561656

1657+
static inline VALUE
1658+
heap_get_freeobj_head(rb_objspace_t *objspace, rb_heap_t *heap)
1659+
{
1660+
RVALUE *p = heap->freelist;
1661+
if (LIKELY(p != NULL)) {
1662+
heap->freelist = p->as.free.next;
1663+
}
1664+
return (VALUE)p;
1665+
}
1666+
16571667
static inline VALUE
16581668
heap_get_freeobj(rb_objspace_t *objspace, rb_heap_t *heap)
16591669
{
@@ -1683,44 +1693,17 @@ gc_event_hook_body(rb_thread_t *th, rb_objspace_t *objspace, const rb_event_flag
16831693
EXEC_EVENT_HOOK(th, event, th->cfp->self, 0, 0, data);
16841694
}
16851695

1696+
#define gc_event_hook_needed_p(objspace, event) ((objspace)->hook_events & (event))
1697+
16861698
#define gc_event_hook(objspace, event, data) do { \
1687-
if (UNLIKELY((objspace)->hook_events & (event))) { \
1699+
if (gc_event_hook_needed_p(objspace, event)) { \
16881700
gc_event_hook_body(GET_THREAD(), (objspace), (event), (data)); \
16891701
} \
16901702
} while (0)
16911703

1692-
static VALUE
1693-
newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
1704+
static inline VALUE
1705+
newobj_of_init(rb_objspace_t *objspace, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, VALUE obj, int hook_needed)
16941706
{
1695-
rb_objspace_t *objspace = &rb_objspace;
1696-
VALUE obj;
1697-
1698-
#if GC_DEBUG_STRESS_TO_CLASS
1699-
if (UNLIKELY(stress_to_class)) {
1700-
long i, cnt = RARRAY_LEN(stress_to_class);
1701-
const VALUE *ptr = RARRAY_CONST_PTR(stress_to_class);
1702-
for (i = 0; i < cnt; ++i) {
1703-
if (klass == ptr[i]) rb_memerror();
1704-
}
1705-
}
1706-
#endif
1707-
1708-
if (UNLIKELY(during_gc || ruby_gc_stressful)) {
1709-
if (during_gc) {
1710-
dont_gc = 1;
1711-
during_gc = 0;
1712-
rb_bug("object allocation during garbage collection phase");
1713-
}
1714-
1715-
if (ruby_gc_stressful) {
1716-
if (!garbage_collect(objspace, FALSE, FALSE, FALSE, GPR_FLAG_NEWOBJ)) {
1717-
rb_memerror();
1718-
}
1719-
}
1720-
}
1721-
1722-
obj = heap_get_freeobj(objspace, heap_eden);
1723-
17241707
if (RGENGC_CHECK_MODE > 0) assert(BUILTIN_TYPE(obj) == T_NONE);
17251708

17261709
/* OBJSETUP */
@@ -1773,7 +1756,10 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
17731756
#endif
17741757

17751758
objspace->total_allocated_objects++;
1776-
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj);
1759+
1760+
if (hook_needed) {
1761+
gc_event_hook(objspace, RUBY_INTERNAL_EVENT_NEWOBJ, obj);
1762+
}
17771763
gc_report(5, objspace, "newobj: %s\n", obj_info(obj));
17781764

17791765
#if RGENGC_OLD_NEWOBJ_CHECK > 0
@@ -1798,6 +1784,57 @@ newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
17981784
return obj;
17991785
}
18001786

1787+
NOINLINE(static VALUE newobj_of_slowpass(rb_objspace_t *objspace, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int hook_needed));
1788+
1789+
static VALUE
1790+
newobj_of_slowpass(rb_objspace_t *objspace, VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3, int hook_needed)
1791+
{
1792+
VALUE obj;
1793+
1794+
if (UNLIKELY(during_gc || ruby_gc_stressful)) {
1795+
if (during_gc) {
1796+
dont_gc = 1;
1797+
during_gc = 0;
1798+
rb_bug("object allocation during garbage collection phase");
1799+
}
1800+
1801+
if (ruby_gc_stressful) {
1802+
if (!garbage_collect(objspace, FALSE, FALSE, FALSE, GPR_FLAG_NEWOBJ)) {
1803+
rb_memerror();
1804+
}
1805+
}
1806+
}
1807+
1808+
obj = heap_get_freeobj(objspace, heap_eden);
1809+
return newobj_of_init(objspace, klass, flags, v1, v2, v3, obj, hook_needed);
1810+
}
1811+
1812+
static VALUE
1813+
newobj_of(VALUE klass, VALUE flags, VALUE v1, VALUE v2, VALUE v3)
1814+
{
1815+
rb_objspace_t *objspace = &rb_objspace;
1816+
VALUE obj;
1817+
int hook_needed = gc_event_hook_needed_p(objspace, RUBY_INTERNAL_EVENT_NEWOBJ);
1818+
1819+
#if GC_DEBUG_STRESS_TO_CLASS
1820+
if (UNLIKELY(stress_to_class)) {
1821+
long i, cnt = RARRAY_LEN(stress_to_class);
1822+
const VALUE *ptr = RARRAY_CONST_PTR(stress_to_class);
1823+
for (i = 0; i < cnt; ++i) {
1824+
if (klass == ptr[i]) rb_memerror();
1825+
}
1826+
}
1827+
#endif
1828+
1829+
if (LIKELY(!(during_gc || ruby_gc_stressful) && hook_needed == FALSE &&
1830+
(obj = heap_get_freeobj_head(objspace, heap_eden)) != Qfalse)) {
1831+
return newobj_of_init(objspace, klass, flags, v1, v2, v3, obj, FALSE);
1832+
}
1833+
else {
1834+
return newobj_of_slowpass(objspace, klass, flags, v1, v2, v3, hook_needed);
1835+
}
1836+
}
1837+
18011838
VALUE
18021839
rb_newobj(void)
18031840
{

0 commit comments

Comments
 (0)