* 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);
oldflowcontrol:=flowcontrol;
flowcontrol:=flowcontrol*[fc_unwind]+[fc_inflowcontrol];
flowcontrol:=[fc_inflowcontrol];
{ RTL will put exceptobject into EAX when jumping here }
cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);

View File

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

View File

@ -36,7 +36,8 @@ uses
fc_inflowcontrol,
fc_gotolabel,
{ 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
not allowed to do ssl }
fc_lefthandled);

View File

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