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 20bool gNativeManip = false; 21// This variable shall be used only in "streaming" mode. 22bool gRefTrackerEnabled = false; 23static Storage gStorages[2]; 24static FILE* gLogTrackerFile = NULL; 25 26bool GetRefTrackerEnabled(void) 27{ 28 return gRefTrackerEnabled; 29} 30 31void SetRefTrackerEnabled(bool flag) 32{ 33 gRefTrackerEnabled = flag; 34} 35 36void LogTrackerInit(const char* filepath) 37{ 38 gLogTrackerFile = fopen(filepath, "w+"); 39} 40 41void LogTrackerClose(void) 42{ 43 fclose(gLogTrackerFile); 44} 45 46void RefInfoResetFn(IStorageItem* item) 47{ 48 RefInfoItem* ref_item = (RefInfoItem*)item; 49 JerryExtFree(ref_item->stacktrace); 50 JerryExtFree(ref_item); 51} 52 53void InitTracker(void) 54{ 55 StorageInit(&gStorages[kObjectRefInfo], BUFFER_SIZE); 56 StorageInit(&gStorages[kStringRefInfo], BUFFER_SIZE); 57} 58 59void StorageInit(Storage* storage, size_t size) 60{ 61 storage->size = size; 62 storage->data = JerryExtAllocStorageData(size); 63} 64 65void 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 79size_t StorageGet(Storage* storage, size_t key) 80{ 81 return storage->data[key]; 82} 83 84void 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 100char* 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 113RefInfoItem* 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 122void 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 153void 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 163void 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