* Win64 SEH: Track control flow out of unwind-protected regions in a more precise way and don't generate expensive calls to __fpc_local_unwind when not necessary.

git-svn-id: trunk@31582 -
This commit is contained in:
sergei 2015-09-09 18:43:46 +00:00
parent 5f3c45d370
commit e542800ea9
4 changed files with 16 additions and 19 deletions

View File

@ -100,7 +100,7 @@ procedure ti386onnode.pass_generate_code;
location_reset(location,LOC_VOID,OS_NO); location_reset(location,LOC_VOID,OS_NO);
oldflowcontrol:=flowcontrol; oldflowcontrol:=flowcontrol;
flowcontrol:=flowcontrol*[fc_unwind]+[fc_inflowcontrol]; flowcontrol:=[fc_inflowcontrol];
{ RTL will put exceptobject into EAX when jumping here } { RTL will put exceptobject into EAX when jumping here }
cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG); cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);

View File

@ -148,6 +148,7 @@ implementation
oldclabel:=current_procinfo.CurrContinueLabel; oldclabel:=current_procinfo.CurrContinueLabel;
oldblabel:=current_procinfo.CurrBreakLabel; oldblabel:=current_procinfo.CurrBreakLabel;
include(flowcontrol,fc_inflowcontrol); include(flowcontrol,fc_inflowcontrol);
exclude(flowcontrol,fc_unwind_loop);
sync_regvars(true); sync_regvars(true);
{$ifdef OLDREGVARS} {$ifdef OLDREGVARS}
@ -470,6 +471,7 @@ implementation
hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false); hlcg.maybe_change_load_node_reg(current_asmdata.CurrAsmList,left,false);
oldflowcontrol:=flowcontrol; oldflowcontrol:=flowcontrol;
include(flowcontrol,fc_inflowcontrol); include(flowcontrol,fc_inflowcontrol);
exclude(flowcontrol,fc_unwind_loop);
{ produce start assignment } { produce start assignment }
case left.location.loc of case left.location.loc of
LOC_REFERENCE, LOC_REFERENCE,
@ -816,7 +818,7 @@ implementation
if assigned(left) then if assigned(left) then
secondpass(left); secondpass(left);
if (fc_unwind in flowcontrol) then if (fc_unwind_exit in flowcontrol) then
hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel) hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel)
else else
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel); hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrExitLabel);
@ -837,7 +839,7 @@ implementation
{$ifdef OLDREGVARS} {$ifdef OLDREGVARS}
load_all_regvars(current_asmdata.CurrAsmList); load_all_regvars(current_asmdata.CurrAsmList);
{$endif OLDREGVARS} {$endif OLDREGVARS}
if (fc_unwind in flowcontrol) then if (fc_unwind_loop in flowcontrol) then
hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel) hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel)
else else
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel) hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrBreakLabel)
@ -861,7 +863,7 @@ implementation
{$ifdef OLDREGVARS} {$ifdef OLDREGVARS}
load_all_regvars(current_asmdata.CurrAsmList); load_all_regvars(current_asmdata.CurrAsmList);
{$endif OLDREGVARS} {$endif OLDREGVARS}
if (fc_unwind in flowcontrol) then if (fc_unwind_loop in flowcontrol) then
hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel) hlcg.g_local_unwind(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel)
else else
hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel) hlcg.a_jmp_always(current_asmdata.CurrAsmList,current_procinfo.CurrContinueLabel)

View File

@ -36,7 +36,8 @@ uses
fc_inflowcontrol, fc_inflowcontrol,
fc_gotolabel, fc_gotolabel,
{ in try block of try..finally } { in try block of try..finally }
fc_unwind, fc_unwind_exit,
fc_unwind_loop,
{ the left side of an expression is already handled, so we are { the left side of an expression is already handled, so we are
not allowed to do ssl } not allowed to do ssl }
fc_lefthandled); fc_lefthandled);

View File

@ -87,7 +87,6 @@ end;
procedure tx64onnode.pass_generate_code; procedure tx64onnode.pass_generate_code;
var var
oldflowcontrol : tflowcontrol;
exceptvarsym : tlocalvarsym; exceptvarsym : tlocalvarsym;
begin begin
if (target_info.system<>system_x86_64_win64) then if (target_info.system<>system_x86_64_win64) then
@ -98,9 +97,6 @@ procedure tx64onnode.pass_generate_code;
location_reset(location,LOC_VOID,OS_NO); location_reset(location,LOC_VOID,OS_NO);
oldflowcontrol:=flowcontrol;
flowcontrol:=flowcontrol*[fc_unwind]+[fc_inflowcontrol];
{ RTL will put exceptobject into RAX when jumping here } { RTL will put exceptobject into RAX when jumping here }
cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG); cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
@ -130,8 +126,6 @@ procedure tx64onnode.pass_generate_code;
end; end;
cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION'); cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel); cg.a_jmp_always(current_asmdata.CurrAsmList,endexceptlabel);
flowcontrol:=oldflowcontrol+(flowcontrol-[fc_inflowcontrol]);
end; end;
{ tx64tryfinallynode } { tx64tryfinallynode }
@ -299,12 +293,12 @@ procedure tx64tryfinallynode.pass_generate_code;
{ try code } { try code }
if assigned(left) then if assigned(left) then
begin begin
{ fc_unwind tells exit/continue/break statements to emit special { fc_unwind_xx tells exit/continue/break statements to emit special
unwind code instead of just JMP } unwind code instead of just JMP }
if not implicitframe then if not implicitframe then
include(flowcontrol,fc_unwind); flowcontrol:=flowcontrol+[fc_unwind_exit,fc_unwind_loop];
secondpass(left); secondpass(left);
exclude(flowcontrol,fc_unwind); flowcontrol:=flowcontrol-[fc_unwind_exit,fc_unwind_loop];
if codegenerror then if codegenerror then
exit; exit;
end; end;
@ -393,7 +387,7 @@ procedure tx64tryexceptnode.pass_generate_code;
continueexceptlabel:=nil; continueexceptlabel:=nil;
breakexceptlabel:=nil; breakexceptlabel:=nil;
flowcontrol:=flowcontrol*[fc_unwind]+[fc_inflowcontrol]; include(flowcontrol,fc_inflowcontrol);
{ this can be called recursivly } { this can be called recursivly }
oldBreakLabel:=nil; oldBreakLabel:=nil;
oldContinueLabel:=nil; oldContinueLabel:=nil;
@ -442,7 +436,7 @@ procedure tx64tryexceptnode.pass_generate_code;
current_procinfo.CurrBreakLabel:=breakexceptlabel; current_procinfo.CurrBreakLabel:=breakexceptlabel;
end; end;
flowcontrol:=flowcontrol*[fc_unwind]+[fc_inflowcontrol]; flowcontrol:=[fc_inflowcontrol];
{ on statements } { on statements }
if assigned(right) then if assigned(right) then
begin begin
@ -496,7 +490,7 @@ procedure tx64tryexceptnode.pass_generate_code;
{ do some magic for exit in the try block } { do some magic for exit in the try block }
cg.a_label(current_asmdata.CurrAsmList,exitexceptlabel); cg.a_label(current_asmdata.CurrAsmList,exitexceptlabel);
cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION'); cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
if (fc_unwind in flowcontrol) then if (fc_unwind_exit in oldflowcontrol) then
cg.g_local_unwind(current_asmdata.CurrAsmList,oldCurrExitLabel) cg.g_local_unwind(current_asmdata.CurrAsmList,oldCurrExitLabel)
else else
cg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel); cg.a_jmp_always(current_asmdata.CurrAsmList,oldCurrExitLabel);
@ -506,7 +500,7 @@ procedure tx64tryexceptnode.pass_generate_code;
begin begin
cg.a_label(current_asmdata.CurrAsmList,breakexceptlabel); cg.a_label(current_asmdata.CurrAsmList,breakexceptlabel);
cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION'); cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
if (fc_unwind in flowcontrol) then if (fc_unwind_loop in oldflowcontrol) then
cg.g_local_unwind(current_asmdata.CurrAsmList,oldBreakLabel) cg.g_local_unwind(current_asmdata.CurrAsmList,oldBreakLabel)
else else
cg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel); cg.a_jmp_always(current_asmdata.CurrAsmList,oldBreakLabel);
@ -516,7 +510,7 @@ procedure tx64tryexceptnode.pass_generate_code;
begin begin
cg.a_label(current_asmdata.CurrAsmList,continueexceptlabel); cg.a_label(current_asmdata.CurrAsmList,continueexceptlabel);
cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION'); cg.g_call(current_asmdata.CurrAsmList,'FPC_DONEEXCEPTION');
if (fc_unwind in flowcontrol) then if (fc_unwind_loop in oldflowcontrol) then
cg.g_local_unwind(current_asmdata.CurrAsmList,oldContinueLabel) cg.g_local_unwind(current_asmdata.CurrAsmList,oldContinueLabel)
else else
cg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel); cg.a_jmp_always(current_asmdata.CurrAsmList,oldContinueLabel);