diff paraspace/injection.py @ 135:b488ca519709

Make sure elements are absolute incremental for sorted arrays when injecting. - All sorted array of DEXFile must be absolute incremental. - If injected one is the same order as one already in the array, the one in array are used to replace injected one. - All references to clone and injected one refer to ones already in array instead.
author Thinker K.F. Li <thinker@codemud.net>
date Tue, 09 Aug 2011 21:28:13 +0800
parents 3dee4d929e1f
children 987fead83ce3
line wrap: on
line diff
--- a/paraspace/injection.py	Tue Aug 09 17:23:01 2011 +0800
+++ b/paraspace/injection.py	Tue Aug 09 21:28:13 2011 +0800
@@ -77,6 +77,7 @@
     from paraspace.dex_deptracker import _dex_tree_get_child
     from paraspace.dex_deptracker import _dex_tree_set_child
     from paraspace.dexfile import _DEX_TypeList, _DEX_TypeList_align
+    from paraspace.dexfile import array_sorted
 
     if isinstance(obj, _DEX_TypeList):
         wrapper = _DEX_TypeList_align()
@@ -91,6 +92,13 @@
         return
 
     array = getattr(dex, attr)
+    
+    if isinstance(array, array_sorted):
+        if obj in array.items:
+            idx = array.items.index(obj)
+            return array.items[idx]
+        pass
+
     array.items.append(obj)
     
     count_name = array.count_name
@@ -98,7 +106,8 @@
         count = _dex_tree_get_child(dex, count_name)
         _dex_tree_set_child(dex, count_name, count + 1)
         pass
-    pass
+
+    return obj
 
 
 ## \brief Clone a composite object.
@@ -188,13 +197,26 @@
     merge_unique_strid()
     merge_unique_typeid()
     
-    for obj in visit_log.values():
+    relink_list = []
+    for key, obj in visit_log.items():
+        if isinstance(obj, (_DEX_StringDataItem,
+                            _DEX_StringId,
+                            _DEX_TypeId)):
+            continue
+        r = dex_append_obj_list(dex, obj)
+        if r and r is not obj:
+            visit_log[key] = r
+        else:
+            relink_list.append(obj)
+            pass
+        pass
+    
+    for obj in relink_list:
         if isinstance(obj, (_DEX_StringDataItem,
                             _DEX_StringId,
                             _DEX_TypeId)):
             continue
         relink_dependencies(obj)
-        dex_append_obj_list(dex, obj)
         pass
     
     clone = visit_log[id(comobj)]
@@ -660,11 +682,8 @@
 # and redirect all invoking of type, given by redir_classname, to
 # the injected one.
 #
-def inject_redir(src_linked, inj_classname,
-                 dst_linked, redir_classname, decls):
-    from paraspace.dex_deptracker import dex_sort_sorted_arrays
-    from paraspace.dex_deptracker import restore_dependencies
-    
+def inject_redir_no_restore(src_linked, inj_classname,
+                            dst_linked, redir_classname, decls):
     inj_classdef = src_linked.find_class_name(inj_classname)
     injected_classdefs = inject_classdefs(dst_linked, src_linked,
                                           [inj_classdef])
@@ -682,7 +701,22 @@
                          for classdef in injected_classdefs]
     dexfile_redirect_types(dst_linked, typeidxs_redir, methodidxs_redir,
                            excludes=injected_typeidxs)
+    pass
+
+
+## \brief Inject and redirect a _DEX_ClassDef from one linked to another.
+#
+# The _DEX_ClassDef given by inj_classname would be inserted to dst_linked,
+# and redirect all invoking of type, given by redir_classname, to
+# the injected one.
+#
+def inject_redir(src_linked, inj_classname,
+                 dst_linked, redir_classname, decls):
+    from paraspace.dex_deptracker import dex_sort_sorted_arrays
+    from paraspace.dex_deptracker import restore_dependencies
     
+    inject_redir_no_restore(src_linked, inj_classname,
+                            dst_linked, redir_classname, decls)
     dex_sort_sorted_arrays(dst_linked)
     restore_dependencies(dst_linked, decls)
     pass