Skip to content

Commit 6dc84fb

Browse files
committedApr 30, 2016
Merge remote-tracking branch 'origin' into profiler
2 parents 90db74d + 0b306fb commit 6dc84fb

31 files changed

+318
-294
lines changed
 

Diff for: ‎Gemfile.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ GEM
44
daedalus-core (0.5.0)
55
rake (10.5.0)
66
redcard (1.1.0)
7-
rubinius-ast (3.4)
7+
rubinius-ast (3.5)
88
rubinius-bridge (2.2)
99
redcard (~> 1.0)
1010
rubinius-code (3.0)

Diff for: ‎core/rubinius.rb

-5
Original file line numberDiff line numberDiff line change
@@ -219,11 +219,6 @@ def self.thread_state
219219
raise PrimitiveFailure, "Rubinius.thread_state primitive failed"
220220
end
221221

222-
def self.check_interrupts
223-
Rubinius.primitive :vm_check_interrupts
224-
raise PrimitiveFailure, "Rubinius.check_interrupts primitive failed"
225-
end
226-
227222
# Used to invoke a CompiledCode instance as a script body. Sets up the MAIN
228223
# object as self and bypasses JIT'ing (because why JIT a script you only run
229224
# once).

Diff for: ‎gems_list.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ rake-10.5.0.gem
99
rb-readline-0.5.3.gem
1010
rdoc-4.2.2.gem
1111
redcard-1.1.0.gem
12-
rubinius-ast-3.4.gem
12+
rubinius-ast-3.5.gem
1313
rubinius-bridge-2.2.gem
1414
rubinius-code-3.0.gem
1515
rubinius-compiler-3.3.gem

Diff for: ‎machine/builtin/block_environment.cpp

+7-7
Original file line numberDiff line numberDiff line change
@@ -444,17 +444,17 @@ namespace rubinius {
444444
call_frame->flags = invocation.flags | CallFrame::cMultipleScopes
445445
| CallFrame::cBlock;
446446

447-
state->vm()->push_call_frame(call_frame, previous_frame);
447+
if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
448+
return NULL;
449+
}
448450

449451
Object* value = NULL;
450452

451-
// Check the stack and interrupts here rather than in the interpreter
452-
// loop itself.
453-
if(state->check_interrupts(state)) {
454-
value = (*mcode->run)(state, mcode);
455-
}
453+
value = (*mcode->run)(state, mcode);
456454

457-
state->vm()->pop_call_frame(previous_frame);
455+
if(!state->vm()->pop_call_frame(state, previous_frame)) {
456+
return NULL;
457+
}
458458

459459
return value;
460460
}

Diff for: ‎machine/builtin/channel.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ namespace rubinius {
134134
ts.tv_nsec = nano % NANOSECONDS;
135135
}
136136

137-
if(!state->check_async(state)) {
137+
if(state->vm()->thread_interrupted_p(state)) {
138138
return NULL;
139139
}
140140

@@ -161,7 +161,7 @@ namespace rubinius {
161161

162162
// or there are values available.
163163
if(self->semaphore_count() > 0 || !self->value()->empty_p()) break;
164-
if(!state->check_async(state)) {
164+
if(state->vm()->thread_interrupted_p(state)) {
165165
exception = true;
166166
break;
167167
}
@@ -173,7 +173,7 @@ namespace rubinius {
173173
self->unpin();
174174
self->_waiters_--;
175175

176-
if(exception || !state->check_async(state)) return NULL;
176+
if(exception) return NULL;
177177

178178
if(self->semaphore_count() > 0) {
179179
self->dec_semaphore_count();

Diff for: ‎machine/builtin/fiber.cpp

+7-2
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ namespace rubinius {
9898

9999
// TODO: CallFrame: return from this function
100100

101-
assert(0 && "fatal start_on_stack error");
101+
rubinius::bug("returning from Fiber::start_on_stack");
102102
#else
103103
rubinius::bug("Fibers not supported on this platform");
104104
#endif
@@ -155,10 +155,15 @@ namespace rubinius {
155155

156156
cur = Fiber::current(state);
157157

158+
// TODO: clean up this and the following conditional.
159+
if(state->vm()->thread_interrupted_p(state)) {
160+
return NULL;
161+
}
162+
158163
if(!cur->exception()->nil_p()) {
159164
state->raise_exception(cur->exception());
160165
cur->exception(state, nil<Exception>());
161-
return 0;
166+
return NULL;
162167
}
163168

164169
Array* ret = cur->value();

Diff for: ‎machine/builtin/fiber.hpp

+2-6
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,12 @@ namespace rubinius {
6969
return data()->machine();
7070
}
7171

72-
void* stack_region() const {
73-
return data()->stack_address();
74-
}
75-
76-
void* stack_end() const {
72+
void* stack_address() const {
7773
return data()->stack_address();
7874
}
7975

8076
void* stack_start() const {
81-
return (void*)((uintptr_t)stack_region() + stack_size());
77+
return (void*)((uintptr_t)stack_address() + stack_size());
8278
}
8379

8480
int stack_size() const {

Diff for: ‎machine/builtin/io.cpp

+5-5
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ namespace rubinius {
288288

289289
if(events == -1) {
290290
if(errno == EAGAIN || errno == EINTR) {
291-
if(!state->check_async(state)) return NULL;
291+
if(state->vm()->thread_interrupted_p(state)) return NULL;
292292

293293
// Recalculate the limit and go again.
294294
if(maybe_limit) {
@@ -678,7 +678,7 @@ namespace rubinius {
678678

679679
if(bytes_read == -1) {
680680
if(errno == EAGAIN || errno == EINTR) {
681-
if(!state->check_async(state)) {
681+
if(state->vm()->thread_interrupted_p(state)) {
682682
if(malloc_buf) free(malloc_buf);
683683
return NULL;
684684
}
@@ -967,7 +967,7 @@ namespace rubinius {
967967

968968
if(bytes_read == -1) {
969969
if(errno == EINTR) {
970-
if(!state->check_async(state)) return NULL;
970+
if(state->vm()->thread_interrupted_p(state)) return NULL;
971971
ensure_open(state);
972972
goto retry;
973973
} else {
@@ -1321,7 +1321,7 @@ namespace rubinius {
13211321

13221322
if(code == -1) {
13231323
if(errno == EAGAIN || errno == EINTR) {
1324-
if(!state->check_async(state)) return NULL;
1324+
if(state->vm()->thread_interrupted_p(state)) return NULL;
13251325
ensure_open(state);
13261326
goto retry;
13271327
}
@@ -1429,7 +1429,7 @@ namespace rubinius {
14291429
break;
14301430
case EAGAIN:
14311431
case EINTR:
1432-
if(!state->check_async(state)) return NULL;
1432+
if(state->vm()->thread_interrupted_p(state)) return NULL;
14331433
io->ensure_open(state);
14341434
goto retry;
14351435
default:

Diff for: ‎machine/builtin/native_function.cpp

+1-9
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,6 @@ namespace rubinius {
308308
FFIData* stub = reinterpret_cast<FFIData*>(user_data);
309309

310310
bool destroy_vm = false;
311-
int stack_address = 0;
312-
313311
if(!env) {
314312
// TODO: fix this, the threads should *always* be set up correctly
315313
// Apparently we're running in a new thread here, setup
@@ -318,13 +316,7 @@ namespace rubinius {
318316

319317
VM* vm = stub->shared->thread_nexus()->new_vm(stub->shared, "ruby.ffi");
320318

321-
// Detect the stack size and set it up in the VM object
322-
size_t stack_size;
323-
pthread_attr_t attrs;
324-
pthread_attr_init(&attrs);
325-
pthread_attr_getstacksize (&attrs, &stack_size);
326-
pthread_attr_destroy(&attrs);
327-
vm->set_root_stack(reinterpret_cast<uintptr_t>(&stack_address), stack_size);
319+
vm->set_stack_bounds(THREAD_STACK_SIZE);
328320

329321
// Setup nativemethod handles into thread local
330322
State state(vm);

Diff for: ‎machine/builtin/native_method.cpp

+8-7
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,9 @@ namespace rubinius {
675675
env->set_current_native_frame(&nmf);
676676

677677
// Register the CallFrame, because we might GC below this.
678-
state->vm()->push_call_frame(call_frame, previous_frame);
678+
if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
679+
return NULL;
680+
}
679681

680682
// Be sure to do this after installing nmf as the current
681683
// native frame.
@@ -706,7 +708,7 @@ namespace rubinius {
706708
} catch(const RubyException& exc) {
707709
LEAVE_CAPI(state);
708710

709-
state->vm()->pop_call_frame(previous_frame);
711+
state->vm()->pop_call_frame(state, previous_frame);
710712
env->set_current_call_frame(saved_frame);
711713
env->set_current_native_frame(nmf.previous());
712714
ep.pop(env);
@@ -716,15 +718,14 @@ namespace rubinius {
716718

717719
LEAVE_CAPI(state);
718720

719-
state->vm()->pop_call_frame(previous_frame);
721+
if(!state->vm()->pop_call_frame(state, previous_frame)) {
722+
value = NULL;
723+
}
724+
720725
env->set_current_call_frame(saved_frame);
721726
env->set_current_native_frame(nmf.previous());
722727
ep.pop(env);
723728

724-
// Handle any signals that occurred while the native method
725-
// was running.
726-
if(!state->check_async(state)) return NULL;
727-
728729
return value;
729730
}
730731

Diff for: ‎machine/builtin/system.cpp

+3-11
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,7 @@ namespace rubinius {
656656
switch(errno) {
657657
case EAGAIN:
658658
case EINTR:
659-
if(!state->check_async(state)) {
659+
if(state->vm()->thread_interrupted_p(state)) {
660660
close(output[0]);
661661
return NULL;
662662
}
@@ -782,7 +782,7 @@ namespace rubinius {
782782
if(pid == -1) {
783783
if(errno == ECHILD) return cFalse;
784784
if(errno == EINTR) {
785-
if(!state->check_async(state)) return NULL;
785+
if(state->vm()->thread_interrupted_p(state)) return NULL;
786786
goto retry;
787787
}
788788

@@ -1029,19 +1029,11 @@ namespace rubinius {
10291029
if(!state->park(state)) return NULL;
10301030
}
10311031

1032-
if(!state->check_async(state)) return NULL;
1032+
if(state->vm()->thread_interrupted_p(state)) return NULL;
10331033

10341034
return Fixnum::from(time(0) - start);
10351035
}
10361036

1037-
Object* System::vm_check_interrupts(STATE) {
1038-
if(state->check_async(state)) {
1039-
return cNil;
1040-
} else {
1041-
return NULL;
1042-
}
1043-
}
1044-
10451037
static inline double tv_to_dbl(struct timeval* tv) {
10461038
return (double)tv->tv_sec + ((double)tv->tv_usec / 1000000.0);
10471039
}

Diff for: ‎machine/builtin/system.hpp

-3
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,6 @@ namespace rubinius {
147147
// Rubinius.primitive :vm_sleep
148148
static Object* vm_sleep(STATE, Object* duration);
149149

150-
// Rubinius.primitive :vm_check_interrupts
151-
static Object* vm_check_interrupts(STATE);
152-
153150
// Rubinius.primitive :vm_times
154151
static Array* vm_times(STATE);
155152

Diff for: ‎machine/builtin/thread.cpp

+1-3
Original file line numberDiff line numberDiff line change
@@ -356,6 +356,7 @@ namespace rubinius {
356356
VM* vm = reinterpret_cast<VM*>(ptr);
357357
State state_obj(vm), *state = &state_obj;
358358

359+
vm->set_stack_bounds(THREAD_STACK_SIZE);
359360
vm->set_current_thread();
360361

361362
RUBINIUS_THREAD_START(
@@ -367,9 +368,6 @@ namespace rubinius {
367368
vm->name().c_str(), vm->thread->pid()->to_native(),
368369
(unsigned int)thread_debug_self());
369370

370-
int stack_address = 0;
371-
vm->set_root_stack(reinterpret_cast<uintptr_t>(&stack_address), THREAD_STACK_SIZE);
372-
373371
NativeMethod::init_thread(state);
374372

375373
state->vm()->become_managed();

Diff for: ‎machine/capi/capi.cpp

+10-10
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,17 @@ namespace rubinius {
5151
return map[type];
5252
}
5353

54-
bool capi_check_interrupts(STATE, void* stack_marker) {
55-
if(!state->check_stack(state, stack_marker)) {
54+
bool capi_check_interrupts(STATE) {
55+
void* stack_address;
56+
57+
if(!state->vm()->check_stack(state, &stack_address)) {
5658
return false;
5759
}
5860

59-
if(unlikely(state->check_local_interrupts())) {
60-
if(!state->process_async(state)) return false;
61+
if(unlikely(state->vm()->check_local_interrupts())) {
62+
return state->vm()->check_thread_raise_or_kill(state);
6163
}
64+
6265
return true;
6366
}
6467

@@ -115,8 +118,7 @@ namespace rubinius {
115118
Object** args, Object* block,
116119
bool allow_private)
117120
{
118-
int stack_marker = 0;
119-
if(!capi_check_interrupts(env->state(), &stack_marker)) {
121+
if(!capi_check_interrupts(env->state())) {
120122
env->current_ep()->return_to(env);
121123
}
122124

@@ -208,8 +210,7 @@ namespace rubinius {
208210
Object* blk,
209211
size_t arg_count, Object** arg_vals)
210212
{
211-
int stack_marker = 0;
212-
if(!capi_check_interrupts(env->state(), &stack_marker)) {
213+
if(!capi_check_interrupts(env->state())) {
213214
env->current_ep()->return_to(env);
214215
}
215216

@@ -258,8 +259,7 @@ namespace rubinius {
258259
VALUE capi_call_super_native(NativeMethodEnvironment* env,
259260
size_t arg_count, Object** args)
260261
{
261-
int stack_marker = 0;
262-
if(!capi_check_interrupts(env->state(), &stack_marker)) {
262+
if(!capi_check_interrupts(env->state())) {
263263
env->current_ep()->return_to(env);
264264
}
265265

Diff for: ‎machine/capi/thread.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ extern "C" {
6363
ret = select(max, read, write, except, tvp);
6464
}
6565

66-
bool ok = env->state()->check_async(env->state());
66+
bool ok = !env->state()->vm()->thread_interrupted_p(env->state());
6767

6868
ENTER_CAPI(env->state());
6969

@@ -199,7 +199,7 @@ extern "C" {
199199
State* state = env->state();
200200
void* ret = NULL;
201201

202-
if(!state->check_async(env->state())) {
202+
if(state->vm()->thread_interrupted_p(state)) {
203203
return ret;
204204
}
205205
if(ubf == RUBY_UBF_IO || ubf == RUBY_UBF_PROCESS) {

Diff for: ‎machine/environment.cpp

+11-6
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
#include <sys/param.h>
6060
#include <sys/stat.h>
6161
#include <sys/types.h>
62+
#include <sys/resource.h>
6263
#include <pwd.h>
6364
#include <dirent.h>
6465

@@ -93,8 +94,6 @@ namespace rubinius {
9394

9495
String::init_hash();
9596

96-
VM::init_stack_size();
97-
9897
copy_argv(argc, argv);
9998
ruby_init_setproctitle(argc, argv);
10099

@@ -108,9 +107,14 @@ namespace rubinius {
108107
root_vm->set_main_thread();
109108
shared->set_root_vm(root_vm);
110109

111-
int stack_address = 0;
112-
root_vm->set_root_stack(
113-
reinterpret_cast<uintptr_t>(&stack_address), VM::cStackDepthMax);
110+
size_t stack_size = THREAD_STACK_SIZE;
111+
struct rlimit rlim;
112+
113+
if(getrlimit(RLIMIT_STACK, &rlim) == 0) {
114+
stack_size = rlim.rlim_cur;
115+
}
116+
117+
root_vm->set_stack_bounds(stack_size);
114118
root_vm->set_current_thread();
115119

116120
state = new State(root_vm);
@@ -818,8 +822,9 @@ namespace rubinius {
818822

819823
// Start signal handling. We don't return until the process is exiting.
820824
VM* vm = SignalThread::new_vm(state);
821-
State main_state(vm);
825+
vm->set_stack_bounds(state->vm()->stack_size());
822826

827+
State main_state(vm);
823828
state->shared().start_signals(&main_state);
824829
}
825830
}

Diff for: ‎machine/instructions.def

+23-6
Original file line numberDiff line numberDiff line change
@@ -1766,8 +1766,6 @@ instruction check_interrupts() [ -- ]
17661766
mcode->call_count++;
17671767
}
17681768

1769-
if(!state->check_async(state)) RUN_EXCEPTION();
1770-
17711769
state->vm()->checkpoint(state);
17721770
end
17731771

@@ -1944,16 +1942,33 @@ instruction zsuper(literal) [ block -- value ]
19441942
}
19451943

19461944
Tuple* tup = Tuple::create(state, arg_count);
1947-
for(int i = 0; i < mc->total_args; i++) {
1948-
tup->put(state, i, scope->get_local(state, i));
1945+
native_int tup_index = 0;
1946+
1947+
native_int fixed_args;
1948+
if(splat) {
1949+
fixed_args = mc->splat_position;
1950+
} else if(mc->keywords) {
1951+
fixed_args = mc->total_args - 1;
1952+
} else {
1953+
fixed_args = mc->total_args;
1954+
}
1955+
for(native_int i = 0; i < fixed_args; i++) {
1956+
tup->put(state, tup_index++, scope->get_local(state, i));
19491957
}
19501958

19511959
if(splat) {
19521960
for(native_int i = 0; i < splat->size(); i++) {
1953-
tup->put(state, i + mc->total_args, splat->get(state, i));
1961+
tup->put(state, tup_index++, splat->get(state, i));
19541962
}
19551963
} else if(splat_obj) {
1956-
tup->put(state, mc->total_args, splat_obj);
1964+
tup->put(state, tup_index++, splat_obj);
1965+
}
1966+
1967+
if(mc->post_args) {
1968+
native_int post_position = mc->splat_position + 1;
1969+
for(native_int i = post_position; i < post_position + mc->post_args; i++) {
1970+
tup->put(state, tup_index++, scope->get_local(state, i));
1971+
}
19571972
}
19581973

19591974
if(mc->keywords) {
@@ -1969,6 +1984,8 @@ instruction zsuper(literal) [ block -- value ]
19691984

19701985
placeholder->send(state, state->symbol("[]="), ary);
19711986
}
1987+
1988+
tup->put(state, tup_index++, scope->get_local(state, placeholder_position));
19721989
}
19731990

19741991
CallSite* call_site = reinterpret_cast<CallSite*>(literal);

Diff for: ‎machine/internal_threads.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ namespace rubinius {
3333
RUBINIUS_THREAD_START(
3434
const_cast<RBX_DTRACE_CHAR_P>(vm->name().c_str()), vm->thread_id(), 1);
3535

36-
int stack_address = 0;
37-
vm->set_root_stack(reinterpret_cast<uintptr_t>(&stack_address), thread->stack_size_);
36+
vm->set_stack_bounds(thread->stack_size_);
3837

3938
NativeMethod::init_thread(state);
4039

Diff for: ‎machine/jit/llvm/util.cpp

+4-14
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ extern "C" {
113113
call_frame->arguments = args;
114114

115115
CallFrame* previous;
116-
state->vm()->push_call_frame(call_frame, previous);
116+
return state->vm()->push_call_frame(state, call_frame, previous);
117117
}
118118

119-
void rbx_block_frame_initialize(STATE,
119+
bool rbx_block_frame_initialize(STATE,
120120
CallFrame* call_frame, StackVariables* scope,
121121
BlockEnvironment* env, Arguments* args, BlockInvocation* invocation)
122122
{
@@ -153,11 +153,11 @@ extern "C" {
153153
| CallFrame::cJITed;
154154

155155
CallFrame* previous;
156-
state->vm()->push_call_frame(call_frame, previous);
156+
return state->vm()->push_call_frame(state, call_frame, previous);
157157
}
158158

159159
void rbx_pop_call_frame(STATE) {
160-
state->vm()->pop_call_frame(state->vm()->call_frame()->previous);
160+
state->vm()->pop_call_frame(state, state->vm()->call_frame()->previous);
161161
}
162162

163163
Object* rbx_splat_send(STATE, CallSite* call_site,
@@ -985,20 +985,10 @@ extern "C" {
985985
}
986986

987987
Object* rbx_prologue_check(STATE) {
988-
if(!state->check_interrupts(state)) return NULL;
989-
990-
// TODO: ensure no stack references exist at this point
991-
// state->vm()->checkpoint(state);
992-
993988
return cTrue;
994989
}
995990

996991
Object* rbx_check_interrupts(STATE) {
997-
if(!state->check_async(state)) return NULL;
998-
999-
// TODO: ensure no stack references exist at this point
1000-
// state->vm()->checkpoint(state);
1001-
1002992
return cTrue;
1003993
}
1004994

Diff for: ‎machine/machine_code.cpp

+15-16
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,9 @@ namespace rubinius {
762762
call_frame->scope = scope;
763763
call_frame->arguments = &args;
764764

765-
state->vm()->push_call_frame(call_frame, previous_frame);
765+
if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
766+
return NULL;
767+
}
766768

767769
#ifdef ENABLE_LLVM
768770
// A negative call_count means we've disabled usage based JIT
@@ -780,13 +782,13 @@ namespace rubinius {
780782

781783
Object* value = 0;
782784

783-
if(state->check_interrupts(state)) {
784-
RUBINIUS_METHOD_ENTRY_HOOK(state, scope->module(), args.name());
785-
value = (*mcode->run)(state, mcode);
786-
RUBINIUS_METHOD_RETURN_HOOK(state, scope->module(), args.name());
787-
}
785+
RUBINIUS_METHOD_ENTRY_HOOK(state, scope->module(), args.name());
786+
value = (*mcode->run)(state, mcode);
787+
RUBINIUS_METHOD_RETURN_HOOK(state, scope->module(), args.name());
788788

789-
state->vm()->pop_call_frame(previous_frame);
789+
if(!state->vm()->pop_call_frame(state, previous_frame)) {
790+
return NULL;
791+
}
790792

791793
return value;
792794
}
@@ -825,14 +827,9 @@ namespace rubinius {
825827
call_frame->scope = scope;
826828
call_frame->arguments = &args;
827829

828-
state->vm()->push_call_frame(call_frame, previous_frame);
829-
830-
// Do NOT check if we should JIT this. We NEVER want to jit a script.
831-
832-
// Check the stack and interrupts here rather than in the interpreter
833-
// loop itself.
834-
835-
if(!state->check_interrupts(state)) return NULL;
830+
if(!state->vm()->push_call_frame(state, call_frame, previous_frame)) {
831+
return NULL;
832+
}
836833

837834
state->vm()->checkpoint(state);
838835

@@ -841,7 +838,9 @@ namespace rubinius {
841838

842839
Object* value = (*mcode->run)(state, mcode);
843840

844-
state->vm()->pop_call_frame(previous_frame);
841+
if(!state->vm()->pop_call_frame(state, previous_frame)) {
842+
return NULL;
843+
}
845844

846845
return value;
847846
}

Diff for: ‎machine/memory/finalizer.cpp

+13-11
Original file line numberDiff line numberDiff line change
@@ -213,22 +213,24 @@ namespace memory {
213213
env->set_current_native_frame(&nmf);
214214

215215
// Register the CallFrame, because we might GC below this.
216-
state->vm()->push_call_frame(call_frame, previous_frame);
216+
if(state->vm()->push_call_frame(state, call_frame, previous_frame)) {
217+
nmf.setup(Qnil, Qnil, Qnil, Qnil);
217218

218-
nmf.setup(Qnil, Qnil, Qnil, Qnil);
219+
PLACE_EXCEPTION_POINT(ep);
219220

220-
PLACE_EXCEPTION_POINT(ep);
221+
if(unlikely(ep.jumped_to())) {
222+
logger::warn(
223+
"finalizer: an exception occurred running a NativeMethod finalizer");
224+
} else {
225+
(*process_item_->finalizer)(state, process_item_->object);
226+
}
221227

222-
if(unlikely(ep.jumped_to())) {
223-
logger::warn(
224-
"finalizer: an exception occurred running a NativeMethod finalizer");
228+
state->vm()->pop_call_frame(state, previous_frame);
229+
env->set_current_call_frame(0);
230+
env->set_current_native_frame(0);
225231
} else {
226-
(*process_item_->finalizer)(state, process_item_->object);
232+
logger::warn("finalizer: stack error");
227233
}
228-
229-
state->vm()->pop_call_frame(previous_frame);
230-
env->set_current_call_frame(0);
231-
env->set_current_native_frame(0);
232234
}
233235
}
234236
process_item_->status = FinalizeObject::eNativeFinalized;

Diff for: ‎machine/park.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
namespace rubinius {
1111
Object* Park::park(STATE) {
12-
if(!state->check_async(state)) return NULL;
12+
if(state->vm()->thread_interrupted_p(state)) return NULL;
1313

1414
utilities::thread::Mutex::LockGuard lg(mutex_);
1515

@@ -25,7 +25,7 @@ namespace rubinius {
2525
cond_.wait(mutex_);
2626
}
2727
mutex_.unlock();
28-
if(!state->check_async(state)) {
28+
if(state->vm()->thread_interrupted_p(state)) {
2929
mutex_.lock();
3030
result = NULL;
3131
break;
@@ -40,7 +40,7 @@ namespace rubinius {
4040

4141
Object* Park::park_timed(STATE, struct timespec* ts) {
4242
utilities::thread::Mutex::LockGuard lg(mutex_);
43-
if(!state->check_async(state)) return NULL;
43+
if(state->vm()->thread_interrupted_p(state)) return NULL;
4444

4545
wake_ = false;
4646
sleeping_ = true;
@@ -59,7 +59,7 @@ namespace rubinius {
5959
}
6060
}
6161
mutex_.unlock();
62-
if(!state->check_async(state)) {
62+
if(state->vm()->thread_interrupted_p(state)) {
6363
mutex_.lock();
6464
timeout = NULL;
6565
break;

Diff for: ‎machine/signal.cpp

+1-4
Original file line numberDiff line numberDiff line change
@@ -165,15 +165,12 @@ namespace rubinius {
165165

166166
State state_obj(vm), *state = &state_obj;
167167

168+
vm->set_stack_bounds(THREAD_STACK_SIZE);
168169
vm->set_current_thread();
169170

170171
RUBINIUS_THREAD_START(
171172
const_cast<RBX_DTRACE_CHAR_P>(vm->name().c_str()), vm->thread_id(), 1);
172173

173-
int stack_address = 0;
174-
vm->set_root_stack(
175-
reinterpret_cast<uintptr_t>(&stack_address), SignalThread::stack_size);
176-
177174
NativeMethod::init_thread(state);
178175

179176
thread->run(state);

Diff for: ‎machine/state.cpp

-56
Original file line numberDiff line numberDiff line change
@@ -19,62 +19,6 @@ namespace rubinius {
1919
vm_->thread_state()->raise_exception(exc);
2020
}
2121

22-
bool State::process_async(STATE) {
23-
utilities::thread::SpinLock::LockGuard guard(vm_->interrupt_lock());
24-
25-
vm_->clear_check_local_interrupts();
26-
27-
Exception* exc = vm_->interrupted_exception_.get();
28-
if(!exc->nil_p()) {
29-
vm_->interrupted_exception_.set(nil<Exception>());
30-
31-
// Only write the locations if there are none.
32-
if(exc->locations()->nil_p() || exc->locations()->size() == 0) {
33-
exc->locations(this, Location::from_call_stack(this));
34-
}
35-
36-
vm_->thread_state_.raise_exception(exc);
37-
return false;
38-
}
39-
if(vm_->interrupt_by_kill()) {
40-
Fiber* fib = vm_->current_fiber.get();
41-
if(fib->nil_p() || fib->root_p()) {
42-
vm_->clear_interrupt_by_kill();
43-
} else {
44-
vm_->set_check_local_interrupts();
45-
}
46-
vm_->thread_state_.raise_thread_kill();
47-
return false;
48-
}
49-
50-
return true;
51-
}
52-
53-
bool State::check_interrupts(STATE) {
54-
// First, we might be here because someone reset the stack_limit_ so that
55-
// we'd fall into here to check interrupts even if the stack is fine,
56-
//
57-
// So fix up the stack_limit_ if thats the case first.
58-
59-
// If this is true, stack_limit_ was just changed to get our attention, reset
60-
// it now.
61-
int stack_marker = 0;
62-
if(!check_stack(state, &stack_marker)) return false;
63-
64-
if(unlikely(check_local_interrupts())) {
65-
if(!process_async(state)) return false;
66-
}
67-
68-
// If the current thread is trying to step, debugger wise, then assist!
69-
if(vm_->thread_step()) {
70-
vm_->clear_thread_step();
71-
if(!Helpers::yield_debugger(this, cNil)) return false;
72-
}
73-
74-
return true;
75-
}
76-
77-
7822
Object* State::park(STATE) {
7923
return vm_->park_->park(this);
8024
}

Diff for: ‎machine/state.hpp

-23
Original file line numberDiff line numberDiff line change
@@ -93,35 +93,12 @@ namespace rubinius {
9393
return shared_;
9494
}
9595

96-
bool detect_stack_condition(void* end) const {
97-
return vm_->detect_stack_condition(end);
98-
}
99-
10096
bool check_local_interrupts() const {
10197
return vm_jit_->check_local_interrupts_;
10298
}
10399

104-
bool check_async(STATE) {
105-
if(vm_->check_local_interrupts()) {
106-
return process_async(state);
107-
}
108-
return true;
109-
}
110-
111100
void raise_stack_error(STATE);
112101

113-
bool check_stack(STATE, void* end) {
114-
// @TODO assumes stack growth direction
115-
if(unlikely(vm_->detect_stack_condition(end))) {
116-
raise_stack_error(state);
117-
return false;
118-
}
119-
return true;
120-
}
121-
122-
bool process_async(STATE);
123-
bool check_interrupts(STATE);
124-
125102
Object* park(STATE);
126103
Object* park_timed(STATE, struct timespec* ts);
127104
};

Diff for: ‎machine/vm.cpp

+67-32
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,17 @@
5757
#define GO(whatever) globals().whatever
5858

5959
namespace rubinius {
60-
61-
unsigned long VM::cStackDepthMax = 655300;
62-
63-
#ifndef RBX_WINDOWS
64-
/**
65-
* Maximum amount of stack space to use.
66-
* getrlimit can report there is 4G of stack (ie, unlimited). Even when
67-
* there is unlimited stack, we clamp the max to this value (currently 128M).
68-
*/
69-
static rlim_t cMaxStack = (1024 * 1024 * 128);
70-
#endif
71-
7260
VM::VM(uint32_t id, SharedState& shared, const char* name)
7361
: memory::ManagedThread(id, shared, memory::ManagedThread::eRuby, name)
7462
, call_frame_(NULL)
7563
, thread_nexus_(shared.thread_nexus())
7664
, saved_call_site_information_(NULL)
7765
, fiber_stacks_(this, shared)
7866
, park_(new Park)
67+
, stack_start_(0)
68+
, stack_size_(0)
69+
, current_stack_start_(0)
70+
, current_stack_size_(0)
7971
, interrupt_lock_()
8072
, method_missing_reason_(eNone)
8173
, constant_missing_reason_(vFound)
@@ -111,10 +103,66 @@ namespace rubinius {
111103
delete vm;
112104
}
113105

114-
void VM::push_call_frame(CallFrame* frame, CallFrame*& previous_frame) {
106+
void VM::set_stack_bounds(size_t size) {
107+
void* stack_address;
108+
109+
stack_size_ = size;
110+
stack_start_ = &stack_address;
111+
112+
set_stack_bounds(stack_start_, stack_size_);
113+
}
114+
115+
void VM::raise_stack_error(STATE) {
116+
state->raise_stack_error(state);
117+
}
118+
119+
bool VM::push_call_frame(STATE, CallFrame* frame, CallFrame*& previous_frame) {
120+
if(!check_stack(state, frame)) return false;
121+
115122
previous_frame = call_frame_;
116123
frame->previous = call_frame_;
117124
call_frame_ = frame;
125+
126+
return true;
127+
}
128+
129+
bool VM::check_thread_raise_or_kill(STATE) {
130+
Exception* exc = interrupted_exception();
131+
132+
if(!exc->nil_p()) {
133+
clear_interrupted_exception();
134+
135+
// Only write the locations if there are none.
136+
if(exc->locations()->nil_p() || exc->locations()->size() == 0) {
137+
exc->locations(this, Location::from_call_stack(state));
138+
}
139+
140+
thread_state_.raise_exception(exc);
141+
142+
return true;
143+
}
144+
145+
if(interrupt_by_kill()) {
146+
Fiber* fib = current_fiber.get();
147+
148+
if(fib->nil_p() || fib->root_p()) {
149+
clear_interrupt_by_kill();
150+
} else {
151+
set_check_local_interrupts();
152+
}
153+
154+
thread_state_.raise_thread_kill();
155+
156+
return true;
157+
}
158+
159+
// If the current thread is trying to step, debugger wise, then assist!
160+
if(thread_step()) {
161+
clear_thread_step();
162+
if(!Helpers::yield_debugger(state, cNil)) return true;
163+
}
164+
165+
return false;
118166
}
119167

120168
CallFrame* VM::get_call_frame(ssize_t up) {
@@ -285,24 +333,6 @@ namespace rubinius {
285333
}
286334
}
287335

288-
void VM::init_stack_size() {
289-
#ifndef RBX_WINDOWS
290-
struct rlimit rlim;
291-
if(getrlimit(RLIMIT_STACK, &rlim) == 0) {
292-
rlim_t space = rlim.rlim_cur/5;
293-
294-
if(space > 1024*1024) space = 1024*1024;
295-
rlim_t adjusted = (rlim.rlim_cur - space);
296-
297-
if(adjusted > cMaxStack) {
298-
cStackDepthMax = cMaxStack;
299-
} else {
300-
cStackDepthMax = adjusted;
301-
}
302-
}
303-
#endif
304-
}
305-
306336
TypeInfo* VM::find_type(int type) {
307337
return memory()->type_info[type];
308338
}
@@ -467,7 +497,12 @@ namespace rubinius {
467497
}
468498

469499
void VM::set_current_fiber(Fiber* fib) {
470-
set_stack_bounds((uintptr_t)fib->stack_start(), fib->stack_size());
500+
if(fib->root_p()) {
501+
restore_stack_bounds();
502+
} else {
503+
set_stack_bounds(fib->stack_start(), fib->stack_size());
504+
}
505+
471506
current_fiber.set(fib);
472507
}
473508

Diff for: ‎machine/vm.hpp

+53-45
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,11 @@ namespace rubinius {
101101
Park* park_;
102102
rbxti::Env* tooling_env_;
103103

104-
uintptr_t root_stack_start_;
105-
uintptr_t root_stack_size_;
104+
void* stack_start_;
105+
size_t stack_size_;
106+
107+
void* current_stack_start_;
108+
size_t current_stack_size_;
106109

107110
utilities::thread::SpinLock interrupt_lock_;
108111

@@ -142,8 +145,6 @@ namespace rubinius {
142145

143146
VMThreadState thread_state_;
144147

145-
static unsigned long cStackDepthMax;
146-
147148
public: /* Inline methods */
148149

149150
UnwindInfoSet& unwinds() {
@@ -206,13 +207,58 @@ namespace rubinius {
206207
return shared.memory();
207208
}
208209

209-
void push_call_frame(CallFrame* frame, CallFrame*& previous_frame);
210+
void raise_stack_error(STATE);
211+
212+
size_t stack_size() {
213+
return current_stack_size_;
214+
}
215+
216+
void restore_stack_bounds() {
217+
current_stack_start_ = stack_start_;
218+
current_stack_size_ = stack_size_;
219+
}
220+
221+
void set_stack_bounds(void* start, size_t size) {
222+
current_stack_start_ = start;
223+
current_stack_size_ = size;
224+
}
225+
226+
void set_stack_bounds(size_t size);
227+
228+
bool check_stack(STATE, void* stack_address) {
229+
ssize_t stack_used =
230+
(reinterpret_cast<intptr_t>(current_stack_start_)
231+
- reinterpret_cast<intptr_t>(stack_address));
210232

211-
void pop_call_frame(CallFrame* frame) {
233+
if(stack_used < 0) stack_used = -stack_used;
234+
235+
if(stack_used > stack_size_) {
236+
raise_stack_error(state);
237+
return false;
238+
}
239+
240+
return true;
241+
}
242+
243+
bool push_call_frame(STATE, CallFrame* frame, CallFrame*& previous_frame);
244+
245+
bool pop_call_frame(STATE, CallFrame* frame) {
212246
call_frame_ = frame;
247+
248+
return !thread_interrupted_p(state);
249+
}
250+
251+
bool thread_interrupted_p(STATE) {
252+
if(check_local_interrupts()) {
253+
return check_thread_raise_or_kill(state);
254+
}
255+
256+
return false;
213257
}
214258

215-
// Do NOT de-deplicate
259+
bool check_thread_raise_or_kill(STATE);
260+
261+
// Do NOT de-duplicate
216262
void set_call_frame(CallFrame* frame) {
217263
call_frame_ = frame;
218264
}
@@ -244,42 +290,6 @@ namespace rubinius {
244290
return shared.globals;
245291
}
246292

247-
void* stack_start() const {
248-
return reinterpret_cast<void*>(vm_jit_.stack_start_);
249-
}
250-
251-
int stack_size() const {
252-
return vm_jit_.stack_size_;
253-
}
254-
255-
void reset_stack_limit() {
256-
// @TODO assumes stack growth direction
257-
vm_jit_.stack_limit_ = (vm_jit_.stack_start_ - vm_jit_.stack_size_) + (4096 * 10);
258-
}
259-
260-
void set_stack_bounds(uintptr_t start, int length) {
261-
if(start == 0) {
262-
start = root_stack_start_;
263-
length = root_stack_size_;
264-
}
265-
266-
vm_jit_.stack_start_ = start;
267-
vm_jit_.stack_size_ = length;
268-
reset_stack_limit();
269-
}
270-
271-
void set_root_stack(uintptr_t start, int length) {
272-
root_stack_start_ = start;
273-
root_stack_size_ = length;
274-
275-
set_stack_bounds(root_stack_start_, root_stack_size_);
276-
}
277-
278-
bool detect_stack_condition(void* end) const {
279-
// @TODO assumes stack growth direction
280-
return reinterpret_cast<uintptr_t>(end) < vm_jit_.stack_limit_;
281-
}
282-
283293
MethodMissingReason method_missing_reason() const {
284294
return method_missing_reason_;
285295
}
@@ -391,8 +401,6 @@ namespace rubinius {
391401
memory::VariableRootBuffers& current_root_buffers();
392402

393403
public:
394-
static void init_stack_size();
395-
396404
static VM* current();
397405

398406
static void discard(STATE, VM*);

Diff for: ‎spec/core/callsite/reset_spec.rb

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
require File.expand_path('../../fixtures/call_site.rb', __FILE__)
2+
3+
describe "Rubinius::CallSite#reset" do
4+
before :each do
5+
@klass = Class.new do
6+
def m(a)
7+
a.to_s
8+
end
9+
end
10+
11+
@call_site = @klass.instance_method(:m).executable.call_sites.first
12+
end
13+
14+
it "clears the caches" do
15+
obj = @klass.new
16+
17+
obj.m 1
18+
obj.m :a
19+
20+
@call_site.depth.should == 1
21+
@call_site.reset
22+
23+
@call_site.depth.should == 0
24+
end
25+
26+
it "sets the invokes to 0" do
27+
obj = @klass.new
28+
29+
obj.m 1
30+
obj.m :a
31+
32+
@call_site.invokes.should == 2
33+
@call_site.reset
34+
35+
@call_site.invokes.should == 0
36+
end
37+
end

Diff for: ‎spec/ruby/language/block_spec.rb

+16
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,12 @@ def m(a) yield a end
196196
var.should == 1
197197
end
198198

199+
it "does not capture a local when the block argument has the same name" do
200+
var = 1
201+
proc { |&var| var[2] }[&proc { |x| x }].should == 2
202+
var.should == 1
203+
end
204+
199205
describe "taking zero arguments" do
200206
it "does not raise an exception when no values are yielded" do
201207
@y.z { 1 }.should == 1
@@ -704,6 +710,16 @@ def m(a) yield a end
704710
glark.should be_nil
705711
end
706712
end
713+
714+
it "are visible in deeper scopes before initialization" do
715+
[1].each {|;glark|
716+
[1].each {
717+
defined?(glark).should_not be_nil
718+
glark = 1
719+
}
720+
glark.should == 1
721+
}
722+
end
707723
end
708724

709725
describe "Post-args" do

Diff for: ‎spec/ruby/language/fixtures/super.rb

+14
Original file line numberDiff line numberDiff line change
@@ -347,4 +347,18 @@ def foo(a:, b: 'b', **)
347347
end
348348
end
349349
end
350+
351+
module SplatAndKeyword
352+
class A
353+
def foo(*args, **options)
354+
[args, options]
355+
end
356+
end
357+
358+
class B < A
359+
def foo(*args, **options)
360+
super
361+
end
362+
end
363+
end
350364
end

Diff for: ‎spec/ruby/language/super_spec.rb

+8
Original file line numberDiff line numberDiff line change
@@ -177,5 +177,13 @@ def a(arg)
177177

178178
b.foo.should == {}
179179
end
180+
181+
describe 'when using splat arguments' do
182+
it 'passes splat arguments and keyword arguments to the parent' do
183+
b = Super::SplatAndKeyword::B.new
184+
185+
b.foo('bar', baz: true).should == [['bar'], {baz: true}]
186+
end
187+
end
180188
end
181189
end

0 commit comments

Comments
 (0)
Please sign in to comment.