Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions benchmark/dir_pwd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
benchmark:
pwd: Dir.pwd
32 changes: 29 additions & 3 deletions dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,8 @@ dir_chdir(VALUE dir)
#endif
}

static VALUE last_cwd;

#ifndef _WIN32
static VALUE
getcwd_to_str(VALUE arg)
Expand All @@ -1604,20 +1606,43 @@ getcwd_xfree(VALUE arg)
return Qnil;
}

VALUE
rb_dir_getwd_ospath(void)
static VALUE
rb_dir_getwd_ospath_slowpath(void)
{
char *path = ruby_getcwd();
return rb_ensure(getcwd_to_str, (VALUE)path, getcwd_xfree, (VALUE)path);
}

VALUE
rb_dir_getwd_ospath(void)
{
char buf[PATH_MAX];
char *path = getcwd(buf, PATH_MAX);
if (!path) {
return rb_dir_getwd_ospath_slowpath();
}

VALUE cached_cwd = RUBY_ATOMIC_VALUE_LOAD(last_cwd);

if (!cached_cwd || strcmp(RSTRING_PTR(cached_cwd), path) != 0) {
#ifdef __APPLE__
cached_cwd = rb_str_normalize_ospath(path, strlen(path));
#else
cached_cwd = rb_str_new2(path);
#endif
rb_str_freeze(cached_cwd);
RUBY_ATOMIC_VALUE_SET(last_cwd, cached_cwd);
}
return cached_cwd;
}
#endif

VALUE
rb_dir_getwd(void)
{
rb_encoding *fs = rb_filesystem_encoding();
int fsenc = rb_enc_to_index(fs);
VALUE cwd = rb_dir_getwd_ospath();
VALUE cwd = rb_str_new_shared(rb_dir_getwd_ospath());

switch (fsenc) {
case ENCINDEX_US_ASCII:
Expand Down Expand Up @@ -4008,6 +4033,7 @@ Init_Dir(void)

rb_gc_register_address(&chdir_lock.path);
rb_gc_register_address(&chdir_lock.thread);
rb_gc_register_address(&last_cwd);

rb_cDir = rb_define_class("Dir", rb_cObject);

Expand Down
10 changes: 8 additions & 2 deletions file.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,9 +380,15 @@ rb_str_normalize_ospath(const char *ptr, long len)
const char *p = ptr;
const char *e = ptr + len;
const char *p1 = p;
VALUE str = rb_str_buf_new(len);
rb_encoding *enc = rb_utf8_encoding();
rb_enc_associate(str, enc);
VALUE str = rb_utf8_str_new(ptr, len);
if (RB_LIKELY(rb_enc_str_coderange(str) == ENC_CODERANGE_7BIT)) {
return str;
}
else {
str = rb_str_buf_new(len);
rb_enc_associate(str, enc);
}

while (p < e) {
int l, c;
Expand Down