Permalink
Browse files

Setup new unwinds structure that allows dynamic growth

We allocate a small static space for unwinds and allow for growth
instead of large static sized area. The size of the small space is based
currently on CI runs that have enough head room with a size of 4.

This reduces the size of a call frame in the interpreter by around 180
bytes.
  • Loading branch information...
1 parent 89edef7 commit 79209c9601e283c405c2c7f7e769cadd13e16d08 @dbussink dbussink committed Nov 25, 2012
Showing with 197 additions and 89 deletions.
  1. +64 −69 vm/instructions.cpp
  2. +3 −7 vm/instructions.def
  3. +5 −6 vm/llvm/jit_util.cpp
  4. +2 −3 vm/machine_code.hpp
  5. +40 −0 vm/unwind_info.cpp
  6. +81 −2 vm/unwind_info.hpp
  7. +2 −2 vm/vm.hpp
View
@@ -64,7 +64,7 @@ using namespace rubinius;
#define JUMP_DEBUGGING \
return MachineCode::debugger_interpreter_continue(state, mcode, call_frame, \
- stack_calculate_sp(), is, current_unwind, unwinds)
+ stack_calculate_sp(), is, unwinds)
#define CHECK_AND_PUSH(val) \
if(val == NULL) { goto exception; } \
@@ -94,8 +94,7 @@ Object* MachineCode::interpreter(STATE,
Object** stack_ptr = call_frame->stk - 1;
- int current_unwind = 0;
- UnwindInfo unwinds[kMaxUnwindInfos];
+ UnwindInfoSet unwinds;
continue_to_run:
try {
@@ -137,11 +136,11 @@ Object* MachineCode::interpreter(STATE,
//
switch(th->raise_reason()) {
case cException:
- if(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ if(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
goto continue_to_run;
} else {
call_frame->scope->flush_to_heap(state);
@@ -164,12 +163,12 @@ Object* MachineCode::interpreter(STATE,
case cThreadKill:
// Otherwise, we're doing a long return/break unwind through
// here. We need to run ensure blocks.
- while(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- if(info->for_ensure()) {
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ while(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ if(info.for_ensure()) {
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
// Don't reset ep here, we're still handling the return/break.
goto continue_to_run;
@@ -214,8 +213,7 @@ Object* MachineCode::uncommon_interpreter(STATE,
native_int sp,
CallFrame* const method_call_frame,
jit::RuntimeDataHolder* rd,
- int current_unwind,
- UnwindInfo* unwinds)
+ UnwindInfoSet& unwinds)
{
MachineCode* mc = method_call_frame->compiled_code->machine_code();
@@ -281,11 +279,11 @@ Object* MachineCode::uncommon_interpreter(STATE,
//
switch(th->raise_reason()) {
case cException:
- if(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ if(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
goto continue_to_run;
} else {
call_frame->scope->flush_to_heap(state);
@@ -308,12 +306,12 @@ Object* MachineCode::uncommon_interpreter(STATE,
case cThreadKill:
// Otherwise, we're doing a long return/break unwind through
// here. We need to run ensure blocks.
- while(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- if(info->for_ensure()) {
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ while(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ if(info.for_ensure()) {
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
// Don't reset ep here, we're still handling the return/break.
goto continue_to_run;
@@ -372,8 +370,7 @@ Object* MachineCode::debugger_interpreter(STATE,
InterpreterState is;
GCTokenImpl gct;
- int current_unwind = 0;
- UnwindInfo unwinds[kMaxUnwindInfos];
+ UnwindInfoSet unwinds;
// TODO: ug, cut and paste of the whole interpreter above. Needs to be fast,
// maybe could use a function template?
@@ -428,11 +425,11 @@ Object* MachineCode::debugger_interpreter(STATE,
//
switch(th->raise_reason()) {
case cException:
- if(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ if(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
goto continue_to_run;
} else {
call_frame->scope->flush_to_heap(state);
@@ -455,14 +452,14 @@ Object* MachineCode::debugger_interpreter(STATE,
case cThreadKill:
// Otherwise, we're doing a long return/break unwind through
// here. We need to run ensure blocks.
- while(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
+ while(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
- if(info->for_ensure()) {
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ if(info.for_ensure()) {
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
// Don't reset ep here, we're still handling the return/break.
goto continue_to_run;
@@ -505,8 +502,7 @@ Object* MachineCode::debugger_interpreter_continue(STATE,
CallFrame* const call_frame,
int sp,
InterpreterState& is,
- int current_unwind,
- UnwindInfo* unwinds)
+ UnwindInfoSet& unwinds)
{
#include "vm/gen/instruction_locations.hpp"
@@ -560,11 +556,11 @@ Object* MachineCode::debugger_interpreter_continue(STATE,
//
switch(th->raise_reason()) {
case cException:
- if(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ if(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
goto continue_to_run;
} else {
call_frame->scope->flush_to_heap(state);
@@ -587,12 +583,12 @@ Object* MachineCode::debugger_interpreter_continue(STATE,
case cThreadKill:
// Otherwise, we're doing a long return/break unwind through
// here. We need to run ensure blocks.
- while(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- if(info->for_ensure()) {
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ while(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ if(info.for_ensure()) {
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
// Don't reset ep here, we're still handling the return/break.
goto continue_to_run;
@@ -645,8 +641,7 @@ Object* MachineCode::tooling_interpreter(STATE,
InterpreterState is;
GCTokenImpl gct;
- int current_unwind = 0;
- UnwindInfo unwinds[kMaxUnwindInfos];
+ UnwindInfoSet unwinds;
Object** stack_ptr = call_frame->stk - 1;
@@ -693,11 +688,11 @@ Object* MachineCode::tooling_interpreter(STATE,
//
switch(th->raise_reason()) {
case cException:
- if(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ if(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
goto continue_to_run;
} else {
call_frame->scope->flush_to_heap(state);
@@ -719,14 +714,14 @@ Object* MachineCode::tooling_interpreter(STATE,
case cCatchThrow:
// Otherwise, we're doing a long return/break unwind through
// here. We need to run ensure blocks.
- while(current_unwind > 0) {
- UnwindInfo* info = &unwinds[--current_unwind];
- stack_position(info->stack_depth);
-
- if(info->for_ensure()) {
- stack_position(info->stack_depth);
- call_frame->set_ip(info->target_ip);
- cache_ip(info->target_ip);
+ while(unwinds.has_unwinds()) {
+ UnwindInfo info = unwinds.pop();
+ stack_position(info.stack_depth);
+
+ if(info.for_ensure()) {
+ stack_position(info.stack_depth);
+ call_frame->set_ip(info.target_ip);
+ cache_ip(info.target_ip);
// Don't reset ep here, we're still handling the return/break.
goto continue_to_run;
View
@@ -496,11 +496,7 @@ end
# pop_unwind
instruction setup_unwind(ip type) [ -- ] => handler
- interp_assert(current_unwind < kMaxUnwindInfos);
- UnwindInfo& info = unwinds[current_unwind++];
- info.target_ip = ip;
- info.stack_depth = stack_calculate_sp();
- info.type = (UnwindType)type;
+ unwinds.push(ip, stack_calculate_sp(), (UnwindType)type);
end
# [Description]
@@ -512,11 +508,11 @@ end
# setup_unwind
instruction pop_unwind() [ -- ]
- if(current_unwind <= 0) {
+ if(!unwinds.has_unwinds()) {
Exception::internal_error(state, call_frame, "unbalanced pop_unwind");
RUN_EXCEPTION();
}
- --current_unwind;
+ unwinds.drop();
end
# [Description]
View
@@ -1268,10 +1268,7 @@ extern "C" {
}
void rbx_setup_unwind(STATE, int count, uint32_t target_ip, int stack_depth, UnwindType type) {
- UnwindInfo& uw = state->vm()->unwinds()[count];
- uw.target_ip = target_ip;
- uw.stack_depth = stack_depth;
- uw.type = type;
+ state->vm()->unwinds().set_unwind_info(count, target_ip, stack_depth, type);
}
Object* rbx_continue_uncommon(STATE, CallFrame* call_frame,
@@ -1316,10 +1313,11 @@ extern "C" {
}
}
+ state->vm()->unwinds().set_current(unwind_count);
return MachineCode::uncommon_interpreter(state, mcode, call_frame,
entry_ip, sp,
method_call_frame, rd,
- unwind_count, state->vm()->unwinds());
+ state->vm()->unwinds());
}
Object* rbx_restart_interp(STATE, CallFrame* call_frame, Executable* exec, Module* mod, Arguments& args) {
@@ -1359,8 +1357,9 @@ extern "C" {
call_frame->stk[++sp] = top_of_stack;
}
+ state->vm()->unwinds().set_current(unwind_count);
return MachineCode::debugger_interpreter_continue(state, mcode, call_frame,
- sp, is, unwind_count, state->vm()->unwinds());
+ sp, is, state->vm()->unwinds());
}
Object* rbx_flush_scope(STATE, StackVariables* vars) {
View
@@ -184,13 +184,12 @@ namespace rubinius {
CallFrame* const call_frame,
int sp,
InterpreterState& is,
- int current_unwind,
- UnwindInfo* unwinds);
+ UnwindInfoSet& unwinds);
static Object* uncommon_interpreter(STATE, MachineCode* const mcode,
CallFrame* const call_frame, int32_t entry_ip, native_int sp,
CallFrame* const method_call_frame, jit::RuntimeDataHolder* rd,
- int current_unwind, UnwindInfo* unwinds);
+ UnwindInfoSet& unwinds);
static Object* tooling_interpreter(STATE,
MachineCode* const mcode,
View
@@ -0,0 +1,40 @@
+#include "unwind_info.hpp"
+
+namespace rubinius {
+
+ void UnwindInfoSet::overflow_set_unwind_info(int i, uint32_t target_ip, int stack_depth, UnwindType type) {
+ if(!overflow_) {
+ overflow_ = new UnwindOverflow();
+ }
+
+ UnwindInfo info;
+ info.target_ip = target_ip;
+ info.stack_depth = stack_depth;
+ info.type = type;
+ (*overflow_)[i - kMaxUnwindInfos] = info;
+ }
+
+ void UnwindInfoSet::overflow_push(uint32_t target_ip, int stack_depth, UnwindType type) {
+ if(!overflow_) {
+ overflow_ = new UnwindOverflow();
+ }
+ current_++;
+ UnwindInfo info;
+ info.target_ip = target_ip;
+ info.stack_depth = stack_depth;
+ info.type = type;
+ overflow_->push_back(info);
+ }
+
+ UnwindInfo UnwindInfoSet::overflow_pop() {
+ current_--;
+ UnwindInfo info = overflow_->back();
+ overflow_->pop_back();
+ return info;
+ }
+
+ void UnwindInfoSet::overflow_drop() {
+ current_--;
+ overflow_->pop_back();
+ }
+}
Oops, something went wrong.

0 comments on commit 79209c9

Please sign in to comment.