]> granicus.if.org Git - fribidi/commitdiff
Reduce dynamic allocations by using arrays for all small arrays.
authorDov Grobgeld <dov.grobgeld@gmail.com>
Sat, 30 Jun 2018 20:15:21 +0000 (23:15 +0300)
committerDov Grobgeld <dov.grobgeld@gmail.com>
Sat, 30 Jun 2018 20:15:21 +0000 (23:15 +0300)
lib/fribidi-bidi.c
lib/fribidi-deprecated.c

index 671fe808f700356d80817c86213bad2bc4f4b087..9d700d3bea4f82c0a8de20ef1998e57af63ba1f9 100644 (file)
@@ -56,6 +56,8 @@
 #define RL_BRACKET_TYPE(list) ((list)->bracket_type)
 #define RL_ISOLATE_LEVEL(list) ((list)->isolate_level)
 
+#define LOCAL_BRACKET_SIZE 16
+
 /* Pairing nodes are used for holding a pair of open/close brackets as
    described in BD16. */
 struct _FriBidiPairingNodeStruct {
@@ -504,7 +506,8 @@ fribidi_get_par_embedding_levels_ex (
   FriBidiLevel *embedding_levels
 )
 {
-  FriBidiLevel base_level, *base_level_per_iso_level = NULL, max_level = 0;
+  FriBidiLevel base_level_per_iso_level[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
+  FriBidiLevel base_level, max_level = 0;
   FriBidiParType base_dir;
   FriBidiRun *main_run_list = NULL, *explicits_list = NULL, *pp;
   fribidi_boolean status = false;
@@ -562,8 +565,6 @@ fribidi_get_par_embedding_levels_ex (
   DBG2 ("  base level : %c", fribidi_char_from_level (base_level));
   DBG2 ("  base dir   : %s", fribidi_get_bidi_type_name (base_dir));
 
-  base_level_per_iso_level = fribidi_malloc(sizeof(base_level_per_iso_level[0]) *
-                                            FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL);
   base_level_per_iso_level[0] = base_level;
 
 # if DEBUG
@@ -591,12 +592,10 @@ fribidi_get_par_embedding_levels_ex (
       FriBidiLevel level;
       int isolate;
       int isolate_level;
-    } *status_stack;
+    } status_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
     FriBidiRun temp_link;
-    FriBidiRun **run_per_isolate_level; /* Connect the isolate levels */
+    FriBidiRun *run_per_isolate_level[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
 
-    run_per_isolate_level = fribidi_malloc(sizeof(run_per_isolate_level[0])
-                                           * FRIBIDI_BIDI_MAX_RESOLVED_LEVELS);
     memset(run_per_isolate_level, 0, sizeof(run_per_isolate_level[0])
            * FRIBIDI_BIDI_MAX_RESOLVED_LEVELS);
 
@@ -623,8 +622,6 @@ fribidi_get_par_embedding_levels_ex (
     first_interval = 0;
     valid_isolate_count = 0;
     isolate_overflow = 0;
-    status_stack = fribidi_malloc (sizeof (status_stack[0]) *
-                                  FRIBIDI_BIDI_MAX_RESOLVED_LEVELS);
 
     for_run_list (pp, main_run_list)
     {
@@ -803,9 +800,6 @@ fribidi_get_par_embedding_levels_ex (
     override = FRIBIDI_TYPE_ON;
     stack_size = 0;
     over_pushed = 0;
-
-    fribidi_free (status_stack);
-    fribidi_free (run_per_isolate_level);
   }
   /* X10. The remaining rules are applied to each run of characters at the
      same level. For each run, determine the start-of-level-run (sor) and
@@ -834,12 +828,10 @@ fribidi_get_par_embedding_levels_ex (
   max_iso_level = 0;
   DBG ("resolving weak types");
   {
-    int *last_strong_stack;
+    int last_strong_stack[FRIBIDI_BIDI_MAX_RESOLVED_LEVELS];
     FriBidiCharType prev_type_orig;
     fribidi_boolean w4;
 
-    last_strong_stack = fribidi_malloc (sizeof (int)
-                                        * FRIBIDI_BIDI_MAX_RESOLVED_LEVELS);
     last_strong_stack[0] = base_dir;
 
     for_run_list (pp, main_run_list)
@@ -1001,8 +993,6 @@ fribidi_get_par_embedding_levels_ex (
       else
        prev_type_orig = PREV_TYPE_OR_SOR (pp->next);
     }
-
-    fribidi_free (last_strong_stack);
   }
 
   compact_neutrals (main_run_list);
@@ -1023,16 +1013,28 @@ fribidi_get_par_embedding_levels_ex (
     /*  BD16 - Build list of all pairs*/
     int num_iso_levels = max_iso_level + 1;
     FriBidiPairingNode *pairing_nodes = NULL;
-    FriBidiRun ***bracket_stack = fribidi_malloc(sizeof(bracket_stack[0])
-                                                 * num_iso_levels);
-    int *bracket_stack_size = fribidi_malloc(sizeof(bracket_stack_size[0])
-                                             * num_iso_levels);
+    FriBidiRun *local_bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL][LOCAL_BRACKET_SIZE];
+    FriBidiRun **bracket_stack[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
+    int bracket_stack_size[FRIBIDI_BIDI_MAX_EXPLICIT_LEVEL];
     int last_level = RL_LEVEL(main_run_list);
     int last_iso_level = 0;
 
     memset(bracket_stack, 0, sizeof(bracket_stack[0])*num_iso_levels);
     memset(bracket_stack_size, 0, sizeof(bracket_stack_size[0])*num_iso_levels);
 
+    /* populate the bracket_size. The first LOCAL_BRACKET_SIZE entries
+       of the stack are one the stack. Allocate the rest of the entries.
+     */
+    {
+      int iso_level;
+      for (iso_level=0; iso_level < LOCAL_BRACKET_SIZE; iso_level++)
+        bracket_stack[iso_level] = local_bracket_stack[iso_level];
+
+      for (iso_level=LOCAL_BRACKET_SIZE; iso_level < num_iso_levels; iso_level++)
+        bracket_stack[iso_level] = fribidi_malloc (sizeof (bracket_stack[0])
+                                                       * FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS);
+    }
+
     /* Build the bd16 pair stack. */
     for_run_list (pp, main_run_list)
       {
@@ -1046,9 +1048,6 @@ fribidi_get_par_embedding_levels_ex (
         if (level != last_level && last_iso_level == iso_level)
           bracket_stack_size[last_iso_level] = 0;
 
-        if (!bracket_stack[iso_level])
-          bracket_stack[iso_level] = fribidi_malloc (sizeof (bracket_stack[0])
-                                                     * FRIBIDI_BIDI_MAX_NESTED_BRACKET_PAIRS);
         if (brack_prop!= FRIBIDI_NO_BRACKET)
           {
             if (FRIBIDI_IS_BRACKET_OPEN(brack_prop))
@@ -1162,13 +1161,14 @@ fribidi_get_par_embedding_levels_ex (
         }
 
       free_pairing_nodes(pairing_nodes);
-      {
-        int i;
-        for (i=0; i<num_iso_levels; i++)
-          fribidi_free(bracket_stack[i]);
-      }
-      fribidi_free(bracket_stack);
-      fribidi_free(bracket_stack_size);
+
+      if (num_iso_levels >= LOCAL_BRACKET_SIZE)
+        {
+          int i;
+          /* Only need to free the non static members */
+          for (i=LOCAL_BRACKET_SIZE; i<num_iso_levels; i++)
+            fribidi_free(bracket_stack[i]);
+        }
 
       /* Remove the bracket property and re-compact */
       {
@@ -1388,8 +1388,6 @@ out:
     free_run_list (main_run_list);
   if UNLIKELY
     (explicits_list) free_run_list (explicits_list);
-  if (base_level_per_iso_level)
-    fribidi_free (base_level_per_iso_level);
 
   return status ? max_level + 1 : 0;
 }
index 862e51e4c2358b268a9cc1c765bf50b94d8b3470..12a13d2ca9fc835244f742a3ebb8f6bea869829d 100644 (file)
@@ -177,7 +177,8 @@ out:
   return status ? j : -1;
 }
 
-
+/* Local array size, used for stack-based local arrays */
+#define LOCAL_LIST_SIZE 128
 
 FRIBIDI_ENTRY FriBidiLevel
 fribidi_log2vis (
@@ -198,9 +199,14 @@ fribidi_log2vis (
   fribidi_boolean private_V_to_L = false;
   fribidi_boolean private_embedding_levels = false;
   fribidi_boolean status = false;
+  FriBidiArabicProp local_ar_props[LOCAL_LIST_SIZE];
   FriBidiArabicProp *ar_props = NULL;
+  FriBidiLevel local_embedding_levels[LOCAL_LIST_SIZE];
+  FriBidiCharType local_bidi_types[LOCAL_LIST_SIZE];
   FriBidiCharType *bidi_types = NULL;
+  FriBidiBracketType local_bracket_types[LOCAL_LIST_SIZE];
   FriBidiBracketType *bracket_types = NULL;
+  FriBidiStrIndex local_positions_V_to_L[LOCAL_LIST_SIZE];
 
   if UNLIKELY
     (len == 0)
@@ -214,13 +220,20 @@ fribidi_log2vis (
   fribidi_assert (str);
   fribidi_assert (pbase_dir);
 
-  bidi_types = fribidi_malloc (len * sizeof bidi_types[0]);
+  if (len < LOCAL_LIST_SIZE)
+    bidi_types = local_bidi_types;
+  else
+    bidi_types = fribidi_malloc (len * sizeof bidi_types[0]);
   if (!bidi_types)
     goto out;
 
   fribidi_get_bidi_types (str, len, bidi_types);
 
-  bracket_types = fribidi_malloc (len * sizeof bracket_types[0]);
+  if (len < LOCAL_LIST_SIZE)
+    bracket_types = local_bracket_types;
+  else
+    bracket_types = fribidi_malloc (len * sizeof bracket_types[0]);
+    
   if (!bracket_types)
     goto out;
 
@@ -229,7 +242,10 @@ fribidi_log2vis (
                              bracket_types);
   if (!embedding_levels)
     {
-      embedding_levels = fribidi_malloc (len * sizeof embedding_levels[0]);
+      if (len < LOCAL_LIST_SIZE)
+        embedding_levels = local_embedding_levels;
+      else
+        embedding_levels = fribidi_malloc (len * sizeof embedding_levels[0]);
       if (!embedding_levels)
        goto out;
       private_embedding_levels = true;
@@ -247,7 +263,10 @@ fribidi_log2vis (
      given by the caller, we have to make a private instance of it. */
   if (positions_L_to_V && !positions_V_to_L)
     {
-      positions_V_to_L =
+      if (len < LOCAL_LIST_SIZE)
+        positions_V_to_L = local_positions_V_to_L;
+      else
+        positions_V_to_L =
        (FriBidiStrIndex *) fribidi_malloc (sizeof (FriBidiStrIndex) * len);
       if (!positions_V_to_L)
        goto out;
@@ -271,7 +290,10 @@ fribidi_log2vis (
       memcpy (visual_str, str, len * sizeof (*visual_str));
 
       /* Arabic joining */
-      ar_props = fribidi_malloc (len * sizeof ar_props[0]);
+      if (len < LOCAL_LIST_SIZE)
+        ar_props = local_ar_props;
+      else
+        ar_props = fribidi_malloc (len * sizeof ar_props[0]);
       fribidi_get_joining_types (str, len, ar_props);
       fribidi_join_arabic (bidi_types, len, embedding_levels, ar_props);
 
@@ -298,19 +320,19 @@ fribidi_log2vis (
 
 out:
 
-  if (private_V_to_L)
+  if (private_V_to_L && positions_V_to_L != local_positions_V_to_L)
     fribidi_free (positions_V_to_L);
 
-  if (private_embedding_levels)
+  if (private_embedding_levels && embedding_levels != local_embedding_levels)
     fribidi_free (embedding_levels);
 
-  if (ar_props)
+  if (ar_props && ar_props != local_ar_props)
     fribidi_free (ar_props);
 
-  if (bidi_types)
+  if (bidi_types && bidi_types != local_bidi_types)
     fribidi_free (bidi_types);
 
-  if (bracket_types)
+  if (bracket_types && bracket_types != local_bracket_types)
     fribidi_free (bracket_types);
 
   return status ? max_level + 1 : 0;