anchor.diff:      end;
   validate_instrs([I|Is], MFA, Offset, Vst0) ->
       validate_instrs(Is, MFA, Offset+1,
  -	   try
  -	       Vst = validate_mutation(I, Vst0),
  -	       vi_safe(I, Vst)
  -	   catch Error ->
  -		   error({MFA,{I,Offset,Error}})
  -	   end).
  -
  -%%%
  -%%% vi_safe/2 handles instructions that will never throw an exception, and can
  -%%% thus be used when the state is undecided in some way.
  -%%%
  -vi_safe({label,Lbl}, #vst{current=St0,
  +                    try
  +                        Vst = validate_mutation(I, Vst0),
  +                        vi(I, Vst)
  +                    catch Error ->
  +                       error({MFA,{I,Offset,Error}})
  +                    end).
  +
  +vi({label,Lbl}, #vst{current=St0,
                             ref_ctr=Counter0,
                             branched=Branched0,
                             labels=Labels0}=Vst) ->
  
positive.code:     St = St0#st{ct=[Tag|Tags]},
   
      Vst#vst{current=St}.
  
  %% Handle the remaining floating point instructions here.
  vi_float({fconv,Src,{fr,_}=Dst}, Vst) ->
      assert_term(Src, Vst),
  
      branch(?EXCEPTION_LABEL, Vst,
             fun(FailVst) ->
                     %% This is a hack to supress assert_float_checked/1 in
                     %% fork_state/2, since this instruction is legal even when
                     %% the state is unchecked.
                     set_fls(checked, FailVst)
             end,
             fun(SuccVst0) ->
                     SuccVst = update_type(fun meet/2, number, Src, SuccVst0),
                     set_freg(Dst, SuccVst)
             end);
  vi_float(fclearerror, Vst) ->
      case get_fls(Vst) of
          undefined -> ok;
          checked -> ok;
          Fls -> error({bad_floating_point_state,Fls})
      end,
      set_fls(cleared, Vst);
  vi_float({fcheckerror,_}, Vst0) ->
      assert_fls(cleared, Vst0),
      Vst = set_fls(checked, Vst0),
  
      branch(?EXCEPTION_LABEL, Vst);
  vi_float(I, Vst) ->
      vi_throwing(I, Vst).
  
  %%%
  %%% vi_throwing/2 handles instructions that can cause exceptions.
  %%%
  vi_throwing({badmatch,Src}, Vst) ->
      assert_durable_term(Src, Vst),
      branch(?EXCEPTION_LABEL, Vst, fun kill_state/1);
  vi_throwing({case_end,Src}, Vst) ->
      assert_durable_term(Src, Vst),
      branch(?EXCEPTION_LABEL, Vst, fun kill_state/1);
  vi_throwing(if_end, Vst) ->
      branch(?EXCEPTION_LABEL, Vst, fun kill_state/1);
  vi_throwing({try_case_end,Src}, Vst) ->
      assert_durable_term(Src, Vst),
      branch(?EXCEPTION_LABEL, Vst, fun kill_state/1);
  vi_throwing({call_fun,Live}, Vst) ->
      Fun = {x,Live},
      assert_term(Fun, Vst),
  
      branch(?EXCEPTION_LABEL, Vst,
             fun(SuccVst0) ->
                     SuccVst = update_type(fun meet/2, #t_fun{arity=Live},
                                           Fun, SuccVst0),
                     validate_body_call('fun', Live+1, SuccVst)
             end);
  vi_throwing({make_fun2,{f,Lbl},_,_,NumFree}, #vst{ft=Ft}=Vst0) ->
      #{ arity := Arity0 } = map_get(Lbl, Ft),
      Arity = Arity0 - NumFree,
  
      true = Arity >= 0,                          %Assertion.
  
      Vst = prune_x_regs(NumFree, Vst0),
      verify_call_args(make_fun, NumFree, Vst),
      verify_y_init(Vst),
  
      branch(?EXCEPTION_LABEL, Vst,
             fun(SuccVst) ->
                     Type = #t_fun{arity=Arity},
                     create_term(Type, make_fun, [], {x,0}, SuccVst)
             end);
  vi_throwing(raw_raise=I, Vst) ->
      validate_body_call(I, 3, Vst);
  vi_throwing({wait_timeout,{f,Lbl},Src}, Vst0) ->
      assert_no_exception(Lbl),
  
      %% Note that the receive marker is not cleared since we may re-enter the
      %% loop while waiting. If we time out we'll be transferred to a timeout
      %% instruction that clears the marker.
      assert_term(Src, Vst0),
      verify_y_init(Vst0),
  
      Vst = branch(Lbl, prune_x_regs(0, Vst0)),
      branch(?EXCEPTION_LABEL, Vst);
  vi_throwing(send, Vst) ->
      validate_body_call(send, 2, Vst);
  vi_throwing({bs_add,{f,Fail},[A,B,_],Dst}, Vst) ->
      assert_term(A, Vst),
      assert_term(B, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     create_term(#t_integer{}, bs_add, [A, B], Dst, SuccVst)
             end);
  vi_throwing({bs_utf8_size,{f,Fail},A,Dst}, Vst) ->
      assert_term(A, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     create_term(#t_integer{}, bs_utf8_size, [A], Dst, SuccVst)
             end);
  vi_throwing({bs_utf16_size,{f,Fail},A,Dst}, Vst) ->
      assert_term(A, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     create_term(#t_integer{}, bs_utf16_size, [A], Dst, SuccVst)
             end);
  vi_throwing({bs_init2,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
      verify_live(Live, Vst0),
      verify_y_init(Vst0),
      if
          is_integer(Sz) -> ok;
          true -> assert_term(Sz, Vst0)
      end,
      Vst = heap_alloc(Heap, Vst0),
      branch(Fail, Vst,
             fun(SuccVst0) ->
                     SuccVst = prune_x_regs(Live, SuccVst0),
                     create_term(#t_bitstring{size_unit=8}, bs_init2, [], Dst,
                                 SuccVst, SuccVst0)
             end);
  vi_throwing({bs_init_bits,{f,Fail},Sz,Heap,Live,_,Dst}, Vst0) ->
      verify_live(Live, Vst0),
      verify_y_init(Vst0),
      if
          is_integer(Sz) -> ok;
          true -> assert_term(Sz, Vst0)
      end,
      Vst = heap_alloc(Heap, Vst0),
      branch(Fail, Vst,
             fun(SuccVst0) ->
                     SuccVst = prune_x_regs(Live, SuccVst0),
                     create_term(#t_bitstring{}, bs_init_bits, [], Dst, SuccVst)
             end);
  vi_throwing({bs_append,{f,Fail},Bits,Heap,Live,Unit,Bin,_Flags,Dst}, Vst0) ->
      verify_live(Live, Vst0),
      verify_y_init(Vst0),
      assert_term(Bits, Vst0),
      assert_term(Bin, Vst0),
      Vst = heap_alloc(Heap, Vst0),
      branch(Fail, Vst,
             fun(SuccVst0) ->
                     SuccVst = prune_x_regs(Live, SuccVst0),
                     create_term(#t_bitstring{size_unit=Unit}, bs_append,
                                 [Bin], Dst, SuccVst, SuccVst0)
             end);
  vi_throwing({bs_private_append,{f,Fail},Bits,Unit,Bin,_Flags,Dst}, Vst) ->
      assert_term(Bits, Vst),
      assert_term(Bin, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     create_term(#t_bitstring{size_unit=Unit}, bs_private_append,
                                 [Bin], Dst, SuccVst)
             end);
  vi_throwing({bs_put_string,Sz,_}, Vst) when is_integer(Sz) ->
      Vst;
  vi_throwing({bs_put_binary,{f,Fail},Sz,_,_,Src}, Vst) ->
      assert_term(Sz, Vst),
      assert_term(Src, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     update_type(fun meet/2, #t_bitstring{}, Src, SuccVst)
             end);
  vi_throwing({bs_put_float,{f,Fail},Sz,_,_,Src}, Vst) ->
      assert_term(Sz, Vst),
      assert_term(Src, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     update_type(fun meet/2, #t_float{}, Src, SuccVst)
             end);
  vi_throwing({bs_put_integer,{f,Fail},Sz,_,_,Src}, Vst) ->
      assert_term(Sz, Vst),
      assert_term(Src, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     update_type(fun meet/2, #t_integer{}, Src, SuccVst)
             end);
  vi_throwing({bs_put_utf8,{f,Fail},_,Src}, Vst) ->
      assert_term(Src, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     update_type(fun meet/2, #t_integer{}, Src, SuccVst)
             end);
  vi_throwing({bs_put_utf16,{f,Fail},_,Src}, Vst) ->
      assert_term(Src, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     update_type(fun meet/2, #t_integer{}, Src, SuccVst)
             end);
  vi_throwing({bs_put_utf32,{f,Fail},_,Src}, Vst) ->
      assert_term(Src, Vst),
      branch(Fail, Vst,
             fun(SuccVst) ->
                     update_type(fun meet/2, #t_integer{}, Src, SuccVst)
             end);
  %% Map instructions.
  vi_throwing({put_map_exact=Op,{f,Fail},Src,Dst,Live,{list,List}}, Vst) ->
      verify_put_map(Op, Fail, Src, Dst, Live, List, Vst);
  vi_throwing(_, _) ->
      error(unknown_instruction).
  
  verify_has_map_fields(Lbl, Src, List, Vst) ->
      assert_type(#t_map{}, Src, Vst),
  
negative.code: 
  verify_call_args(_, 0, #vst{}) ->
      ok;
  verify_call_args({f,Lbl}, Live, #vst{ft=Ft}=Vst) ->
      case Ft of
          #{ Lbl := FuncInfo } ->
              #{ arity := Live,
  