• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
3  * Description: add ref tracker.
4  * Create: 2020/11/20
5  */
6 
7 #include "tracker.h"
8 
9 #include "ecma-globals.h"
10 #include "ecma-helpers.h"
11 #include "ext-utils.h"
12 #include "heapdump.h"
13 #include "vm.h"
14 
15 #if defined(JERRY_REF_TRACKER)
16 
17 #define BUFFER_SIZE 65536
18 #define LogTracker(...) do { fprintf(gLogTrackerFile, __VA_ARGS__); } while (0)
19 
20 bool gNativeManip = false;
21 // This variable shall be used only in "streaming" mode.
22 bool gRefTrackerEnabled = false;
23 static Storage gStorages[2];
24 static FILE* gLogTrackerFile = NULL;
25 
GetRefTrackerEnabled(void)26 bool GetRefTrackerEnabled(void)
27 {
28   return gRefTrackerEnabled;
29 }
30 
SetRefTrackerEnabled(bool flag)31 void SetRefTrackerEnabled(bool flag)
32 {
33   gRefTrackerEnabled = flag;
34 }
35 
LogTrackerInit(const char * filepath)36 void LogTrackerInit(const char* filepath)
37 {
38   gLogTrackerFile = fopen(filepath, "w+");
39 }
40 
LogTrackerClose(void)41 void LogTrackerClose(void)
42 {
43   fclose(gLogTrackerFile);
44 }
45 
RefInfoResetFn(IStorageItem * item)46 void RefInfoResetFn(IStorageItem* item)
47 {
48   RefInfoItem* ref_item = (RefInfoItem*)item;
49   JerryExtFree(ref_item->stacktrace);
50   JerryExtFree(ref_item);
51 }
52 
InitTracker(void)53 void InitTracker(void)
54 {
55   StorageInit(&gStorages[kObjectRefInfo], BUFFER_SIZE);
56   StorageInit(&gStorages[kStringRefInfo], BUFFER_SIZE);
57 }
58 
StorageInit(Storage * storage,size_t size)59 void StorageInit(Storage* storage, size_t size)
60 {
61   storage->size = size;
62   storage->data = JerryExtAllocStorageData(size);
63 }
64 
StoragePut(Storage * storage,size_t key,size_t value)65 void StoragePut(Storage* storage, size_t key, size_t value)
66 {
67   if (storage->data[key] == 0) {
68     storage->data[key] = value;
69     return;
70   }
71 
72   IStorageItem* item = (IStorageItem*)storage->data[key];
73   storage->data[key] = value;
74 
75   IStorageItem* new_item = (IStorageItem*)value;
76   new_item->next = item;
77 }
78 
StorageGet(Storage * storage,size_t key)79 size_t StorageGet(Storage* storage, size_t key)
80 {
81   return storage->data[key];
82 }
83 
StorageReset(Storage * storage,size_t key,void (* reset_fn)(IStorageItem *))84 void StorageReset(Storage* storage, size_t key, void(*reset_fn)(IStorageItem*))
85 {
86   if (storage->data[key] == 0) {
87     // Nothing to reset.
88     return;
89   }
90 
91   IStorageItem* item = (IStorageItem*)storage->data[key];
92   storage->data[key] = 0;
93   while (item != NULL) {
94     IStorageItem* next = item->next;
95     reset_fn(item);
96     item = next;
97   }
98 }
99 
GetStacktraceString(ecma_string_t * stack)100 char* GetStacktraceString(ecma_string_t* stack)
101 {
102   if (stack == NULL) {
103     return NULL;
104   }
105   // Copy string to jsheap-independent storage.
106   ECMA_STRING_TO_UTF8_STRING(stack, data, data_size);
107   char* dst = JerryExtAllocStr(data_size + 1);
108   memcpy(dst, data, data_size);
109   dst[data_size] = '\0';
110   return dst;
111 }
112 
CreateRefInfoItem(RefInfoItemFlags flags,char * stack_str)113 RefInfoItem* CreateRefInfoItem(RefInfoItemFlags flags, char* stack_str)
114 {
115   RefInfoItem* item = JerryExtAlloc(sizeof(RefInfoItem));
116   item->next = NULL;
117   item->stacktrace = stack_str;
118   item->flags = flags;
119   return item;
120 }
121 
ReportObjRefManip(ecma_object_t * obj,RefInfoItemFlags flags)122 void ReportObjRefManip(ecma_object_t* obj, RefInfoItemFlags flags)
123 {
124   if (!gRefTrackerEnabled) {
125     return;
126   }
127 
128   if (gNativeManip) {
129     flags &= kRefNative;
130   }
131 
132   // XXX: For now don't do anything regarding within-gc ops.
133   if (flags & (kRefMark | kRefUnmark)) {
134     return;
135   }
136 
137   const char* native_str = "    native";
138   const char* init_str   = "      init";
139   const char* inc_str    = " increment";
140   const char* dec_str    = " decrement";
141 
142   uint32_t refcnt = obj->type_flags_refs >> REF_CNT_SHIFT;
143 
144   LogTracker("Object %p%s%s%s%s: refcount = %u\n", (void*)obj,
145       (flags & kRefNative) ? native_str : "",
146       (flags & kRefInit) ? init_str : "",
147       (flags & kRefRef) ? inc_str : "",
148       (flags & kRefDeref) ? dec_str : "",
149       refcnt);
150   LogTracker("\n");
151 }
152 
ReportObjDelete(ecma_object_t * obj)153 void ReportObjDelete(ecma_object_t* obj)
154 {
155   if (!gRefTrackerEnabled) {
156     return;
157   }
158 
159   LogTracker("Object %p deleted\n", (void*)obj);
160   LogTracker("\n");
161 }
162 
DumpTracker(void)163 void DumpTracker(void)
164 {
165   Storage* storage = &gStorages[kObjectRefInfo];
166   for (int i = 0; i < (int)storage->size; ++i) {
167     if (storage->data[i] != 0) {
168       RefInfoItem* item = (RefInfoItem*)storage->data[i];
169       printf("--== %p ==--:\n", (void*)ECMA_OBJECT_FROM_STORAGE_KEY(i));
170       while (item != NULL) {
171         printf("flags = %d\nStacktrace:\n%s\n", item->flags, item->stacktrace);
172         item = item->next;
173       }
174     }
175   }
176 }
177 
178 #endif
179