* OPT: Use the Gambas stack to store GoSub data instead of allocating
  new arrays all the time. Up to 10 times faster!


git-svn-id: svn://localhost/gambas/trunk@4937 867c0c6c-44f3-4631-809d-bfa615b0a4ec
This commit is contained in:
Emil Lenngren 2012-07-10 19:35:36 +00:00
parent e938c9190d
commit c3742b189a
3 changed files with 62 additions and 7 deletions

View File

@ -53,6 +53,8 @@ extern "C" {
#define TARGET_BITS 32
#endif
#define GOSUB_ON_STACK
#define llvmType(t) llvm::Type::t(llvm_context)
#define pointer_t(type) llvm::PointerType::get((type), 0)
#define charPP llvm::PointerType::get(llvmType(getInt8PtrTy), 0)
@ -101,6 +103,7 @@ static llvm::Value* temp_got_error;
static llvm::Value* temp_got_error2;
//static llvm::Value* temp_gosub_stack;
//static llvm::Value* temp_num_gosubs_on_stack;
static llvm::Value* gp;
static llvm::Value* gosub_return_point;
static std::vector<llvm::BasicBlock*> return_points;
@ -3204,7 +3207,8 @@ void GosubExpression::codegen(){
index = builder->CreateAdd(index, getInteger(32, 1));
builder->CreateStore(index, temp_num_gosubs_on_stack);*/
#ifndef GOSUB_ON_STACK
llvm::Value* gosub_stack_node = builder->CreateBitCast(builder->CreateCall(get_global_function(GB.Add, 'p', "p"), get_global(&GP, llvmType(getInt8Ty))), pointer_t(gosub_stack_node_type));
/*builder->CreateStore(builder->CreateLoad(gosub_return_point), create_gep(gosub_stack_node, TARGET_BITS, 0, 32, 0));
@ -3212,13 +3216,30 @@ void GosubExpression::codegen(){
unsigned int gosub_return_id = gosub_continue_points.size() + 1;
builder->CreateStore(builder->CreateLoad(gosub_return_point), create_gep(gosub_stack_node, TARGET_BITS, 0, 32, 0));
builder->CreateStore(getInteger(16, gosub_return_id), gosub_return_point);
#else
llvm::Value* stack_addr = builder->CreateLoad(gp);
unsigned int gosub_return_id = gosub_continue_points.size() + 1;
store_value(stack_addr, builder->CreateLoad(gosub_return_point), T_SHORT);
builder->CreateStore(getInteger(16, gosub_return_id), gosub_return_point);
int diff = 1 + end_ctrl - FP->n_local;
llvm::Value* new_gp = builder->CreateGEP(stack_addr, getInteger(TARGET_BITS, diff));
builder->CreateStore(new_gp, gp);
//c_SP(diff);
builder->CreateStore(new_gp, get_global(&SP, pointer_t(value_type)));
#endif
if (FP->n_ctrl){
#ifndef GOSUB_ON_STACK
llvm::Value* gp_ctrl_addr = create_gep(gosub_stack_node, TARGET_BITS, 0, 32, 1);
builder->CreateCall2(get_global_function(GB.Alloc, 'v', "pj"), builder->CreateBitCast(gp_ctrl_addr, llvmType(getInt8PtrTy)), getInteger(TARGET_BITS, sizeof(VALUE) * FP->n_ctrl));
llvm::Value* gp_ctrl = builder->CreateLoad(gp_ctrl_addr);
#else
llvm::Value* gp_ctrl = builder->CreateGEP(stack_addr, getInteger(TARGET_BITS, 1));
#endif
for(int i=FP->n_local; i<end_ctrl; i++){
@ -3272,6 +3293,7 @@ void GosubExpression::codegen(){
builder->SetInsertPoint(contpoint);
//On return:
#ifndef GOSUB_ON_STACK
llvm::Value* gp = read_global(&GP, pointer_t(gosub_stack_node_type));
llvm::Value* gp_array = builder->CreateBitCast(gp, llvmType(getInt32PtrTy));
llvm::Value* count_addr = builder->CreateGEP(gp_array, getInteger(TARGET_BITS, -4)); //((int*)GP)[-4] == ARRAY_count(GP)
@ -3281,10 +3303,26 @@ void GosubExpression::codegen(){
llvm::Value* old_return_point = builder->CreateLoad(create_gep(gosub_stack_node, TARGET_BITS, 0, 32, 0));
builder->CreateStore(old_return_point, gosub_return_point);
#else
int diff = 1 + end_ctrl - FP->n_local;
llvm::Value* new_gp = builder->CreateGEP(builder->CreateLoad(gp), getInteger(TARGET_BITS, -diff));
builder->CreateStore(new_gp, gp);
//c_SP(-diff)
builder->CreateStore(new_gp, get_global(&SP, pointer_t(value_type)));
llvm::Value* old_return_point = read_value(new_gp, T_SHORT);
builder->CreateStore(old_return_point, gosub_return_point);
#endif
if (FP->n_ctrl){
#ifndef GOSUB_ON_STACK
llvm::Value* gp_ctrl_addr = create_gep(gosub_stack_node, TARGET_BITS, 0, 32, 1);
llvm::Value* gp_ctrl = builder->CreateLoad(gp_ctrl_addr);
#else
llvm::Value* gp_ctrl = builder->CreateGEP(new_gp, getInteger(TARGET_BITS, 1));
#endif
for(int i=FP->n_local; i<end_ctrl; i++){
llvm::Value* val = read_value(i == FP->n_local ? gp_ctrl : builder->CreateGEP(gp_ctrl, getInteger(TARGET_BITS, i - FP->n_local)), get_ctrl_type(i));
@ -3299,8 +3337,10 @@ void GosubExpression::codegen(){
for(int i=end_ctrl; i<FP->n_local+FP->n_ctrl; i++){
builder->CreateStore(getInteger(32, 0), current_ctrl_types[i - FP->n_local]);
}
#ifndef GOSUB_ON_STACK
builder->CreateCall(get_global_function(GB.Free, 'v', "p"), builder->CreateBitCast(gp_ctrl_addr, llvmType(getInt8PtrTy)));
#endif
}
}
@ -3568,7 +3608,7 @@ void TryExpression::codegen(){
llvm::Value* second_time = builder->CreateICmpNE(setjmp_return, getInteger(32, 0));
gen_if_else(second_time, [&](){
builder->CreateCall(get_global_function(JR_try_unwind, 'v', ""));
builder->CreateCall(get_global_function(JR_try_unwind, 'v', "p"), builder->CreateBitCast(builder->CreateLoad(gp), llvmType(getInt8PtrTy)));
builder->CreateStore(getInteger(1, true), temp_got_error);
}, [&](){
builder->CreateStore(getInteger(1, false), temp_got_error);
@ -3608,7 +3648,7 @@ void LargeTryExpression::codegen(){
llvm::Value* second_time = builder->CreateICmpNE(setjmp_return, getInteger(32, 0));
gen_if_else(second_time, [&](){
builder->CreateCall(get_global_function(JR_try_unwind, 'v', ""));
builder->CreateCall(get_global_function(JR_try_unwind, 'v', "p"), builder->CreateBitCast(builder->CreateLoad(gp), llvmType(getInt8PtrTy)));
builder->CreateCall(get_global_function(JR_end_try, 'v', "p"),
create_gep(temp_errcontext2, TARGET_BITS, 0, TARGET_BITS, 0));
builder->CreateStore(get_nullptr(), get_global((void*)&EC));
@ -6344,9 +6384,14 @@ void NopExpression::codegen(){
read_global((void*)&BP));*/
if (test_stack){
#ifndef GOSUB_ON_STACK
llvm::Value* sp = read_global((void*)&SP);
llvm::Value* bp = read_global((void*)&BP);
bp = builder->CreateGEP(bp, getInteger(TARGET_BITS, sizeof(VALUE)*(FP->n_local+FP->n_ctrl)));
#else
llvm::Value* sp = builder->CreateBitCast(read_global((void*)&SP), pointer_t(value_type));
llvm::Value* bp = builder->CreateLoad(gp);
#endif
gen_if_noreturn(builder->CreateICmpNE(bp, sp), [&](){
builder->CreateCall(get_global_function(stack_corrupted_abort, 'v', ""));
builder->CreateUnreachable();
@ -6714,14 +6759,24 @@ void JIT_codegen(){
/*temp_num_gosubs_on_stack = builder->CreateAlloca(llvmType(getInt32Ty));
builder->CreateStore(getInteger(32, 0), temp_num_gosubs_on_stack);*/
#ifndef GOSUB_ON_STACK
builder->CreateCall3(get_global_function(GB.NewArray, 'v', "pii"),
get_global(&GP, llvmType(getInt8Ty)), getInteger(32, sizeof(STACK_GOSUB)), getInteger(32, 0));
#else
gp = builder->CreateAlloca(pointer_t(value_type));
builder->CreateStore(builder->CreateGEP(read_global((void*)&BP, pointer_t(value_type)), getInteger(TARGET_BITS, FP->n_local + FP->n_ctrl)), gp);
#endif
/*gosub_return_point = builder->CreateAlloca(llvmType(getInt8PtrTy));
builder->CreateStore(get_nullptr(), gosub_return_point);*/
gosub_return_point = builder->CreateAlloca(llvmType(getInt16Ty));
builder->CreateStore(getInteger(16, 0), gosub_return_point);
}
#ifndef GOSUB_ON_STACK
//For JR_try_unwind
gp = builder->CreateAlloca(pointer_t(value_type));
builder->CreateStore(builder->CreateGEP(read_global((void*)&BP, pointer_t(value_type)), getInteger(TARGET_BITS, FP->n_local + FP->n_ctrl)), gp);
#endif
init_locals();
codegen_statements();

View File

@ -1073,14 +1073,14 @@ void JR_end_try(ERROR_CONTEXT* err){
//FIXME Can this happen: Try native_call -> do non_native call -> non_native throw, directly back to first try?
//FIXME FIXME exec_function_keep måste ju sätta upp en try catch .. väl ..
void JR_try_unwind(){
void JR_try_unwind(VALUE* stack_start){
JIF.F_ERROR_set_last(EP != NULL ? FALSE : TRUE);
JIF.F_ERROR_lock();
while(EC == NULL){
JIF.F_EXEC_leave_drop();
}
while(SP > BP + FP->n_local + FP->n_ctrl){
while(SP > stack_start){
SP--;
JR_RELEASE(SP);
}

View File

@ -54,7 +54,7 @@ void JR_EXEC_jit_execute_function(void);
void* JR_try(ERROR_CONTEXT* err);
void JR_end_try(ERROR_CONTEXT* err);
void JR_try_unwind(void);
void JR_try_unwind(VALUE* stack_start);
CLASS_DESC_METHOD *JR_CLASS_get_special_desc(CLASS *klass, int spec);
#ifdef __cplusplus