[m-rev.] for review: fix stm expansion of or_else alternatives
Peter Wang
novalazy at gmail.com
Mon Nov 16 12:20:58 AEDT 2009
Branches: main
Fix a problem with the STM transformation of or_else alternatives. Input
variables which are needed for later alternatives but not the "main" atomic
goal weren't being passed down through the generated predicates.
compiler/stm_expand.m:
As above.
Add a missing call to stm_discard_transaction_log in the generated
code.
Fix some typos.
library/stm_builtin.m:
Fix a branch of branch of or_else/5 which called stm_unlock when the
STM lock would not be acquired in that code path.
tests/stm/Mmakefile:
tests/stm/atomic_or_else2.exp:
tests/stm/atomic_or_else2.m:
Add test case for the main fix.
diff --git a/compiler/stm_expand.m b/compiler/stm_expand.m
index d8a61c3..8dce332 100644
--- a/compiler/stm_expand.m
+++ b/compiler/stm_expand.m
@@ -39,8 +39,8 @@
% IO0 = IO.
%
%
-% :- pred 'StmExpaded_rollback_0_0_0'(int::in, int::out) is cc_multi.
-% 'StmExpaded_rollback_0_0_0'(X, Y) :-
+% :- pred 'StmExpanded_rollback_0_0_0'(int::in, int::out) is cc_multi.
+% 'StmExpanded_rollback_0_0_0'(X, Y) :-
% promise_pure (
% impure stm_create_trasaction_log(STM0),
% Closure = 'StmExpanded_wrapper_0_0_0'(X),
@@ -548,6 +548,13 @@ order_vars_into_groups_2(ModuleInfo, [Var|Vars], InitInstmap, FinalInstmap,
order_vars_into_groups_2(ModuleInfo, Vars, InitInstmap, FinalInstmap,
!LocalVars, !InputVars, !OutputVars).
+ % Return the var sets for the first atomic goal in the list, taking the
+ % union of the input var sets of all the goals. If the first atomic goal
+ % does not succeed, we will try the later goals, so inputs to the later
+ % goals must also be inputs of the first goal.
+ %
+ % XXX This probably could done directly in calc_pred_variables_list.
+ %
:- pred common_goal_vars_from_list(list(stm_goal_vars)::in, stm_goal_vars::out)
is det.
@@ -817,11 +824,10 @@ create_top_level_goal(InitInstmap, FinalInstmap, OuterDI, OuterUO,
create_top_level_pred(AtomicGoalVarList, OuterDI, OuterUO, AtomicGoal,
OrElseGoals, HldsGoal, !StmInfo) :-
- AtomicGoalVars = list.det_head(AtomicGoalVarList),
-
create_rollback_pred(AtomicGoalVarList, WrapperCall, AtomicGoal,
OrElseGoals, !StmInfo),
+ common_goal_vars_from_list(AtomicGoalVarList, AtomicGoalVars),
get_input_output_varlist(AtomicGoalVars, InputVars, OutputVars),
get_input_output_types(AtomicGoalVars, !.StmInfo, InputTypes, OutputTypes),
get_input_output_modes(AtomicGoalVars, InputModes, OutputModes),
@@ -1036,7 +1042,12 @@ create_validate_exception_goal(StmVar, ExceptionVar, ReturnType, RecursiveCall,
HldsGoal_ExceptionThrow_Call, !NewPredInfo),
create_plain_conj(CreateTypeInfoGoals ++ [HldsGoal_ExceptionThrow_Call],
HldsGoal_ValidBranch),
- create_plain_conj([RecursiveCall], HldsGoal_InvalidBranch),
+ create_simple_call(mercury_stm_builtin_module,
+ "stm_discard_transaction_log",
+ pf_predicate, only_mode, detism_det, purity_impure, [StmVar], [],
+ instmap_delta_from_assoc_list([StmVar - ground(clobbered, none)]),
+ DropStateCall, !NewPredInfo),
+ create_plain_conj([DropStateCall, RecursiveCall], HldsGoal_InvalidBranch),
template_lock_and_validate(StmVar, yes, HldsGoal_ValidBranch,
HldsGoal_InvalidBranch, HldsGoals, !NewPredInfo),
create_plain_conj(HldsGoals, HldsGoal).
@@ -1183,8 +1194,7 @@ create_rollback_handler_goal(AtomicGoalVars, ReturnType, StmVarDI, StmVarUO,
create_rollback_pred(AtomicGoalVarList, CallGoal, AtomicGoal, OrElseGoals,
!StmInfo) :-
- AtomicGoalVars = list.det_head(AtomicGoalVarList),
-
+ common_goal_vars_from_list(AtomicGoalVarList, AtomicGoalVars),
get_input_output_varlist(AtomicGoalVars, InputVars, OutputVars),
get_input_output_types(AtomicGoalVars, !.StmInfo, InputTypes, OutputTypes),
get_input_output_modes(AtomicGoalVars, InputModes, OutputModes),
@@ -1203,11 +1213,11 @@ create_rollback_pred(AtomicGoalVarList, CallGoal, AtomicGoal, OrElseGoals,
create_rollback_pred_2(AtomicGoalVarList, RecCallGoal, AtomicGoal, OrElseGoals,
!NewPredInfo, !StmInfo) :-
- AtomicGoalVars = list.det_head(AtomicGoalVarList),
+ common_goal_vars_from_list(AtomicGoalVarList, AtomicGoalVars),
get_input_output_types(AtomicGoalVars, !.StmInfo, _, OutputTypes),
make_return_type(OutputTypes, ResultType),
- create_aux_variable(ResultType, yes("ResltVar"), ResultVar, !NewPredInfo),
+ create_aux_variable(ResultType, yes("ResultVar"), ResultVar, !NewPredInfo),
create_aux_variable(stm_state_type, yes("STM0"), InnerDI, !NewPredInfo),
create_aux_variable(stm_state_type, yes("STM"), InnerUO, !NewPredInfo),
diff --git a/library/stm_builtin.m b/library/stm_builtin.m
index 6a2f126..fc504da 100644
--- a/library/stm_builtin.m
+++ b/library/stm_builtin.m
@@ -530,7 +530,7 @@ or_else(TransA, TransB, Result, OuterSTM0, OuterSTM) :-
throw(rollback_invalid_transaction)
)
;
- impure stm_unlock,
+ impure stm_discard_transaction_log(InnerSTM_B),
rethrow(ResultB)
)
)
diff --git a/tests/stm/Mmakefile b/tests/stm/Mmakefile
index 8b3f149..ff0b0b3 100644
--- a/tests/stm/Mmakefile
+++ b/tests/stm/Mmakefile
@@ -12,6 +12,7 @@ VALID_PROGS = \
nested \
nested_or_else \
atomic_or_else \
+ atomic_or_else2 \
atomic_conj \
atomic_ite \
atomic_mvar \
diff --git a/tests/stm/atomic_or_else2.exp b/tests/stm/atomic_or_else2.exp
new file mode 100644
index 0000000..27c65ac
--- /dev/null
+++ b/tests/stm/atomic_or_else2.exp
@@ -0,0 +1 @@
+TVar2 is non-zero
diff --git a/tests/stm/atomic_or_else2.m b/tests/stm/atomic_or_else2.m
new file mode 100644
index 0000000..82e3494
--- /dev/null
+++ b/tests/stm/atomic_or_else2.m
@@ -0,0 +1,43 @@
+%-----------------------------------------------------------------------------%
+
+:- module atomic_or_else2.
+:- interface.
+
+:- import_module io.
+
+:- pred main(io::di, io::uo) is cc_multi.
+
+%-----------------------------------------------------------------------------%
+%-----------------------------------------------------------------------------%
+
+:- implementation.
+
+:- import_module stm_builtin.
+
+%-----------------------------------------------------------------------------%
+
+main(!IO) :-
+ new_stm_var(0, TVar1, !IO),
+ new_stm_var(1, TVar2, !IO),
+ atomic [outer(!IO), inner(!STM)] (
+ nonzero(TVar1, !STM),
+ Msg = "TVar1 is non-zero"
+ or_else
+ nonzero(TVar2, !STM),
+ Msg = "TVar2 is non-zero"
+ ),
+ io.write_string(Msg, !IO),
+ io.nl(!IO).
+
+:- pred nonzero(stm_var(int)::in, stm::di, stm::uo) is det.
+
+nonzero(TVar, !STM) :-
+ read_stm_var(TVar, X, !STM),
+ ( X = 0 ->
+ retry(!.STM)
+ ;
+ true
+ ).
+
+%-----------------------------------------------------------------------------%
+% vim: ft=mercury ts=8 sts=4 sw=4 et
--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to: mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions: mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------
More information about the reviews
mailing list