diff --git a/matlab/build_two_dim_hessian.m b/matlab/build_two_dim_hessian.m
new file mode 100644
index 0000000000000000000000000000000000000000..802c7c1fc1f6b07aeb82030ea6255955c1e0b5ef
--- /dev/null
+++ b/matlab/build_two_dim_hessian.m
@@ -0,0 +1,58 @@
+function H = build_two_dim_hessian(sparse_indices, g2_v, neq, nvar)
+% Creates a 2D Hessian (equations in rows, pairs of variables in columns),
+% given the output from the sparse {static,dynamic}_g2.m
+%
+% – sparse_indices is typically equal to M_.{static,dynamic}_g2_sparse_indices
+% – g2_v is the vector of non zero values returned by {static,dynamic}_g2.m
+% – neq is the number of equations (equal to number of rows of the output matrix)
+% – nvar is the number of variables (the output matrix will have nvar² columns)
+
+% Copyright © 2024 Dynare Team
+%
+% This file is part of Dynare.
+%
+% Dynare is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+%
+% Dynare is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+%
+% You should have received a copy of the GNU General Public License
+% along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
+
+nnz = size(sparse_indices, 1);
+
+%% The g2_* arrays may be expanded if there are symmetric elements added
+g2_i = int32(zeros(nnz, 1));
+g2_j = int32(zeros(nnz, 1));
+
+next_sym_idx = nnz + 1; % Index of next symmetric element to be added
+
+for k = 1:length(g2_v)
+    eq = sparse_indices(k, 1);
+    var1 = sparse_indices(k, 2)-1;
+    var2 = sparse_indices(k, 3)-1;
+
+    g2_i(k) = eq;
+    g2_j(k) = var1 * nvar + var2 + 1;
+
+    %% Add symmetric elements, which are not included by sparse {static,dynamic}_g2.m
+    if var1 ~= var2
+        g2_i(next_sym_idx) = eq;
+        g2_j(next_sym_idx) = var2 * nvar + var1 + 1;
+        g2_v(next_sym_idx) = g2_v(k);
+        next_sym_idx = next_sym_idx + 1;
+    end
+end
+
+%% On MATLAB < R2020a, sparse() does not accept int32 indices
+if ~isoctave && matlab_ver_less_than('9.8')
+    g2_i = double(g2_i);
+    g2_j = double(g2_j);
+end
+
+H = sparse(g2_i, g2_j, g2_v, neq, nvar*nvar);
diff --git a/matlab/discretionary_policy/discretionary_policy_1.m b/matlab/discretionary_policy/discretionary_policy_1.m
index 30f7ca0480c634c2134cbf561b76f1b20b8872a9..440b74f6a865fd81a68319ad5a895cc396b228c0 100644
--- a/matlab/discretionary_policy/discretionary_policy_1.m
+++ b/matlab/discretionary_policy/discretionary_policy_1.m
@@ -13,7 +13,7 @@ function [dr, info, params]=discretionary_policy_1(M_, options_, dr, endo_steady
 % - info          [integer]       scalar or vector, error code.
 % - params        [double]        vector of potentially updated parameters
 
-% Copyright © 2007-2020 Dynare Team
+% Copyright © 2007-2024 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -49,7 +49,9 @@ else
 end
 params=M_.params;
 
-[~,Uy,W] = feval([M_.fname,'.objective.static'],zeros(M_.endo_nbr,1),[], M_.params);
+y = zeros(M_.endo_nbr,1);
+[Uy, T_order, T] = feval([M_.fname,'.objective.sparse.static_g1'], y, [], params, M_.objective_g1_sparse_rowval, M_.objective_g1_sparse_colval, M_.objective_g1_sparse_colptr);
+
 if any(any(isnan(Uy)))
     info = 64 ; %the derivatives of the objective function contain NaN
     return;
@@ -70,6 +72,8 @@ if any(any(Uy~=0))
     return;
 end
 
+g2_v = feval([M_.fname,'.objective.sparse.static_g2'], y, [], params, T_order, T);
+W = build_two_dim_hessian(M_.objective_g2_sparse_indices, g2_v, 1, M_.endo_nbr);
 W=reshape(W,M_.endo_nbr,M_.endo_nbr);
 
 klen = M_.maximum_lag + M_.maximum_lead + 1;
@@ -122,4 +126,4 @@ dr.ghu=G(dr.order_var,:);
 if M_.maximum_endo_lag
     Selection=M_.lead_lag_incidence(1,dr.order_var)>0;%select state variables
 end
-dr.ghx=T(:,Selection);
\ No newline at end of file
+dr.ghx=T(:,Selection);
diff --git a/preprocessor b/preprocessor
index b134dba32c9bfc8e0ee25c4977e37558721d7737..db1bad652209c2d6de9d42143bb2b51a0f507b5e 160000
--- a/preprocessor
+++ b/preprocessor
@@ -1 +1 @@
-Subproject commit b134dba32c9bfc8e0ee25c4977e37558721d7737
+Subproject commit db1bad652209c2d6de9d42143bb2b51a0f507b5e