From af938896c1accaa88f4af8d134cdd6707631c99c Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Wed, 10 Mar 2010 11:26:56 +0100 Subject: [PATCH] Separate async state switch from the code using goto and labels Fixes bug 602200. --- codegen/valaccodebasemodule.vala | 2 ++ codegen/valaccodemethodcallmodule.vala | 8 ++++--- codegen/valaccodemethodmodule.vala | 30 ++++++++++++++++---------- codegen/valagasyncmodule.vala | 5 ++++- 4 files changed, 30 insertions(+), 15 deletions(-) diff --git a/codegen/valaccodebasemodule.vala b/codegen/valaccodebasemodule.vala index ea136b213..2633f8d03 100644 --- a/codegen/valaccodebasemodule.vala +++ b/codegen/valaccodebasemodule.vala @@ -135,6 +135,8 @@ internal class Vala.CCodeBaseModule : CCodeModule { // code nodes to be inserted before the current statement // used by async method calls in coroutines public CCodeFragment pre_statement_fragment; + // case statements to be inserted for the couroutine state + public CCodeSwitchStatement state_switch_statement; /* all temporary variables */ public ArrayList temp_vars = new ArrayList (); diff --git a/codegen/valaccodemethodcallmodule.vala b/codegen/valaccodemethodcallmodule.vala index 8439beca3..9545c4e84 100644 --- a/codegen/valaccodemethodcallmodule.vala +++ b/codegen/valaccodemethodcallmodule.vala @@ -715,12 +715,14 @@ internal class Vala.CCodeMethodCallModule : CCodeAssignmentModule { // set state before calling async function to support immediate callbacks int state = next_coroutine_state++; - pre_statement_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())))); - pre_statement_fragment.append (new CCodeExpressionStatement (async_call)); + state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ()))); + state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state))); + pre_statement_fragment.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())))); + pre_statement_fragment.append (new CCodeExpressionStatement (async_call)); pre_statement_fragment.append (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); - pre_statement_fragment.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ()))); + pre_statement_fragment.append (new CCodeLabel ("_state_%d".printf (state))); } if (m is ArrayResizeMethod) { diff --git a/codegen/valaccodemethodmodule.vala b/codegen/valaccodemethodmodule.vala index 39f264ac2..35257f1e1 100644 --- a/codegen/valaccodemethodmodule.vala +++ b/codegen/valaccodemethodmodule.vala @@ -268,6 +268,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule { var old_temp_ref_vars = temp_ref_vars; var old_variable_name_map = variable_name_map; var old_try = current_try; + var old_state_switch_statement = state_switch_statement; current_symbol = m; current_method_inner_error = false; next_temp_var_id = 0; @@ -275,6 +276,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule { temp_ref_vars = new ArrayList (); variable_name_map = new HashMap (str_hash, str_equal); current_try = null; + state_switch_statement = null; bool in_gobject_creation_method = false; bool in_fundamental_creation_method = false; @@ -292,6 +294,15 @@ internal class Vala.CCodeMethodModule : CCodeStructModule { } } + if (m.coroutine) { + state_switch_statement = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_")); + + // initial coroutine state + state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant ("0"))); + state_switch_statement.add_statement (new CCodeGotoStatement ("_state_0")); + } + var current_state_switch = state_switch_statement; + var creturn_type = m.return_type; if (m.return_type.is_real_non_null_struct_type ()) { // structs are returned via out parameter @@ -390,6 +401,7 @@ internal class Vala.CCodeMethodModule : CCodeStructModule { temp_ref_vars = old_temp_ref_vars; variable_name_map = old_variable_name_map; current_try = old_try; + state_switch_statement = old_state_switch_statement; // do not declare overriding methods and interface implementations if (m.is_abstract || m.is_virtual @@ -446,23 +458,19 @@ internal class Vala.CCodeMethodModule : CCodeStructModule { co_function.modifiers |= CCodeModifiers.STATIC; source_declarations.add_type_member_declaration (co_function.copy ()); - var cswitch = new CCodeSwitchStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_")); - // let gcc know that this can't happen - cswitch.add_statement (new CCodeLabel ("default")); - cswitch.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached")))); + current_state_switch.add_statement (new CCodeLabel ("default")); + current_state_switch.add_statement (new CCodeExpressionStatement (new CCodeFunctionCall (new CCodeIdentifier ("g_assert_not_reached")))); - // initial coroutine state - cswitch.add_statement (new CCodeCaseStatement (new CCodeConstant ("0"))); + co_function.block = new CCodeBlock (); + co_function.block.add_statement (current_state_switch); // coroutine body - cswitch.add_statement (function.block); + co_function.block.add_statement (new CCodeLabel ("_state_0")); + co_function.block.add_statement (function.block); // epilogue - cswitch.add_statement (complete_async ()); - - co_function.block = new CCodeBlock (); - co_function.block.add_statement (cswitch); + co_function.block.add_statement (complete_async ()); source_type_member_definition.append (co_function); } diff --git a/codegen/valagasyncmodule.vala b/codegen/valagasyncmodule.vala index e6ffb0d6c..c9d9d769f 100644 --- a/codegen/valagasyncmodule.vala +++ b/codegen/valagasyncmodule.vala @@ -519,9 +519,12 @@ internal class Vala.GAsyncModule : GSignalModule { int state = next_coroutine_state++; + state_switch_statement.add_statement (new CCodeCaseStatement (new CCodeConstant (state.to_string ()))); + state_switch_statement.add_statement (new CCodeGotoStatement ("_state_%d".printf (state))); + cfrag.append (new CCodeExpressionStatement (new CCodeAssignment (new CCodeMemberAccess.pointer (new CCodeIdentifier ("data"), "_state_"), new CCodeConstant (state.to_string ())))); cfrag.append (new CCodeReturnStatement (new CCodeConstant ("FALSE"))); - cfrag.append (new CCodeCaseStatement (new CCodeConstant (state.to_string ()))); + cfrag.append (new CCodeLabel ("_state_%d".printf (state))); cfrag.append (new CCodeEmptyStatement ()); return; -- 2.47.3