Răsfoiți Sursa

fix: move the whole typed dispatch out of from_element (try_set_node_from_element) — the remaining inlined element.as<T> chain still hit the layout-dependent stack-slot bug and segfaulted slot signing

clanker 5 zile în urmă
părinte
comite
45dc923e61
1 a modificat fișierele cu 43 adăugiri și 33 ștergeri
  1. 43 33
      src/lib/Json.vala

+ 43 - 33
src/lib/Json.vala

@@ -80,101 +80,111 @@ namespace InvercargillJson {
 
             node = new Json.Node (Json.NodeType.VALUE);
 
-            // For ValueElement scalars, read the underlying GValue directly
-            // through a dedicated helper instead of inlining every branch
-            // here: the fully inlined version produced a single ~13KB
-            // function whose optimised stack-slot reuse read a stale cached
-            // GValue pointer on some layouts (deterministic SIGSEGV in the
-            // double/int64 paths during Statum slot signing). Keeping the
-            // scalar dispatch out of line sidesteps that codegen bug.
-            if (element is Invercargill.ValueElement) {
-                if (set_node_from_value(node, ((Invercargill.ValueElement) element).get_value())) {
-                    return;
-                }
-                // Non-fundamental held types (DateTime, BinaryData, objects,
-                // ...) fall through to the dispatch below.
+            // Everything scalar lives in out-of-line helpers: the fully
+            // inlined version produced a single ~13KB function whose
+            // optimised stack-slot reuse read stale pointers on some
+            // layouts (intermittent SIGSEGV during Statum slot signing —
+            // first the double/int64 GValue paths, then the generic
+            // element.as<T> dispatch). Keeping this function small
+            // sidesteps that codegen bug entirely.
+            if (element is Invercargill.ValueElement
+                    && set_node_from_value(node, ((Invercargill.ValueElement) element).get_value())) {
+                return;
+            }
+            if (try_set_node_from_element(node, element)) {
+                return;
             }
 
+            // Could not convert
+            var type = element.type();
+            throw new Invercargill.ElementError.INVALID_CONVERSION(@"No way to convert element $(element.get_type ().name()) containing type $(type.name()) to a type suitable for a JsonElement.");
+        }
+
+        /**
+         * Out-of-line typed dispatch for {@link JsonElement.from_element}:
+         * known element types first, then the element's native
+         * conversions. Returns true when `node` was filled.
+         */
+        private static bool try_set_node_from_element(Json.Node node, Invercargill.Element element) throws Invercargill.ElementError {
             var type = element.type();
 
             // Third priority is conversion of known types
             if(type == typeof(DateTime)) {
                 node.set_string (element.as<DateTime>().format_iso8601());
-                return;
+                return true;
             }
             if(type == typeof(Invercargill.BinaryData)) {
                 node.set_string (element.as<Invercargill.BinaryData>().to_base64());
-                return;
+                return true;
             }
             if(type == typeof(string)) {
                 node.set_string (element.as<string>());
-                return;
+                return true;
             }
             if(type == typeof(bool)) {
                 node.set_boolean (element.as<bool>());
-                return;
+                return true;
             }
             if(type == typeof(double)) {
                 node.set_double (element.as<double?>());
-                return;
+                return true;
             }
             if(type == typeof(int64)) {
                 node.set_int (element.as<int64?>());
-                return;
+                return true;
             }
             if(type == typeof(uint8)) {
                 node.set_int (element.as<uint>());
-                return;
+                return true;
             }
             if(type == typeof(int8)) {
                 node.set_int (element.as<int>());
-                return;
+                return true;
             }
             if(type == typeof(uint16)) {
                 node.set_int (element.as<uint16>());
-                return;
+                return true;
             }
             if(type == typeof(int16)) {
                 node.set_int (element.as<int16>());
-                return;
+                return true;
             }
             if(type == typeof(uint32)) {
                 node.set_int (element.as<uint32>());
-                return;
+                return true;
             }
             if(type == typeof(int32)) {
                 node.set_int (element.as<int32>());
-                return;
+                return true;
             }
             if(type == typeof(uint64?)) {
                 node.set_int ((int64)element.as<uint64?>());
-                return;
+                return true;
             }
             if(type == typeof(float?)) {
                 node.set_double (element.as<float?>());
-                return;
+                return true;
             }            
 
             // Last priority is the element's native conversions
             if(element.assignable_to<string>()) {
                 node.set_string (element.as<string>());
-                return;
+                return true;
             }
             if(element.assignable_to<bool> ()) {
                 node.set_boolean(element.as<bool>());
-                return;
+                return true;
             }
             if(element.assignable_to<double?>()) {
                 node.set_double(element.as<double?>());
-                return;
+                return true;
             }
             if(element.assignable_to<int64?>()) {
                 node.set_int(element.as<int64?>());
-                return;
+                return true;
             }
 
-            // Could not convert
-            throw new Invercargill.ElementError.INVALID_CONVERSION(@"No way to convert element $(element.get_type ().name()) containing type $(type.name()) to a type suitable for a JsonElement.");
+            return false;
         }
 
         /**