1425bb815Sopenharmony_ci/* 2425bb815Sopenharmony_ci * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. 3425bb815Sopenharmony_ci * Description: add ref tracker. 4425bb815Sopenharmony_ci * Create: 2020/11/20 5425bb815Sopenharmony_ci */ 6425bb815Sopenharmony_ci 7425bb815Sopenharmony_ci#include "tracker.h" 8425bb815Sopenharmony_ci 9425bb815Sopenharmony_ci#include "ecma-globals.h" 10425bb815Sopenharmony_ci#include "ecma-helpers.h" 11425bb815Sopenharmony_ci#include "ext-utils.h" 12425bb815Sopenharmony_ci#include "heapdump.h" 13425bb815Sopenharmony_ci#include "vm.h" 14425bb815Sopenharmony_ci 15425bb815Sopenharmony_ci#if defined(JERRY_REF_TRACKER) 16425bb815Sopenharmony_ci 17425bb815Sopenharmony_ci#define BUFFER_SIZE 65536 18425bb815Sopenharmony_ci#define LogTracker(...) do { fprintf(gLogTrackerFile, __VA_ARGS__); } while (0) 19425bb815Sopenharmony_ci 20425bb815Sopenharmony_cibool gNativeManip = false; 21425bb815Sopenharmony_ci// This variable shall be used only in "streaming" mode. 22425bb815Sopenharmony_cibool gRefTrackerEnabled = false; 23425bb815Sopenharmony_cistatic Storage gStorages[2]; 24425bb815Sopenharmony_cistatic FILE* gLogTrackerFile = NULL; 25425bb815Sopenharmony_ci 26425bb815Sopenharmony_cibool GetRefTrackerEnabled(void) 27425bb815Sopenharmony_ci{ 28425bb815Sopenharmony_ci return gRefTrackerEnabled; 29425bb815Sopenharmony_ci} 30425bb815Sopenharmony_ci 31425bb815Sopenharmony_civoid SetRefTrackerEnabled(bool flag) 32425bb815Sopenharmony_ci{ 33425bb815Sopenharmony_ci gRefTrackerEnabled = flag; 34425bb815Sopenharmony_ci} 35425bb815Sopenharmony_ci 36425bb815Sopenharmony_civoid LogTrackerInit(const char* filepath) 37425bb815Sopenharmony_ci{ 38425bb815Sopenharmony_ci gLogTrackerFile = fopen(filepath, "w+"); 39425bb815Sopenharmony_ci} 40425bb815Sopenharmony_ci 41425bb815Sopenharmony_civoid LogTrackerClose(void) 42425bb815Sopenharmony_ci{ 43425bb815Sopenharmony_ci fclose(gLogTrackerFile); 44425bb815Sopenharmony_ci} 45425bb815Sopenharmony_ci 46425bb815Sopenharmony_civoid RefInfoResetFn(IStorageItem* item) 47425bb815Sopenharmony_ci{ 48425bb815Sopenharmony_ci RefInfoItem* ref_item = (RefInfoItem*)item; 49425bb815Sopenharmony_ci JerryExtFree(ref_item->stacktrace); 50425bb815Sopenharmony_ci JerryExtFree(ref_item); 51425bb815Sopenharmony_ci} 52425bb815Sopenharmony_ci 53425bb815Sopenharmony_civoid InitTracker(void) 54425bb815Sopenharmony_ci{ 55425bb815Sopenharmony_ci StorageInit(&gStorages[kObjectRefInfo], BUFFER_SIZE); 56425bb815Sopenharmony_ci StorageInit(&gStorages[kStringRefInfo], BUFFER_SIZE); 57425bb815Sopenharmony_ci} 58425bb815Sopenharmony_ci 59425bb815Sopenharmony_civoid StorageInit(Storage* storage, size_t size) 60425bb815Sopenharmony_ci{ 61425bb815Sopenharmony_ci storage->size = size; 62425bb815Sopenharmony_ci storage->data = JerryExtAllocStorageData(size); 63425bb815Sopenharmony_ci} 64425bb815Sopenharmony_ci 65425bb815Sopenharmony_civoid StoragePut(Storage* storage, size_t key, size_t value) 66425bb815Sopenharmony_ci{ 67425bb815Sopenharmony_ci if (storage->data[key] == 0) { 68425bb815Sopenharmony_ci storage->data[key] = value; 69425bb815Sopenharmony_ci return; 70425bb815Sopenharmony_ci } 71425bb815Sopenharmony_ci 72425bb815Sopenharmony_ci IStorageItem* item = (IStorageItem*)storage->data[key]; 73425bb815Sopenharmony_ci storage->data[key] = value; 74425bb815Sopenharmony_ci 75425bb815Sopenharmony_ci IStorageItem* new_item = (IStorageItem*)value; 76425bb815Sopenharmony_ci new_item->next = item; 77425bb815Sopenharmony_ci} 78425bb815Sopenharmony_ci 79425bb815Sopenharmony_cisize_t StorageGet(Storage* storage, size_t key) 80425bb815Sopenharmony_ci{ 81425bb815Sopenharmony_ci return storage->data[key]; 82425bb815Sopenharmony_ci} 83425bb815Sopenharmony_ci 84425bb815Sopenharmony_civoid StorageReset(Storage* storage, size_t key, void(*reset_fn)(IStorageItem*)) 85425bb815Sopenharmony_ci{ 86425bb815Sopenharmony_ci if (storage->data[key] == 0) { 87425bb815Sopenharmony_ci // Nothing to reset. 88425bb815Sopenharmony_ci return; 89425bb815Sopenharmony_ci } 90425bb815Sopenharmony_ci 91425bb815Sopenharmony_ci IStorageItem* item = (IStorageItem*)storage->data[key]; 92425bb815Sopenharmony_ci storage->data[key] = 0; 93425bb815Sopenharmony_ci while (item != NULL) { 94425bb815Sopenharmony_ci IStorageItem* next = item->next; 95425bb815Sopenharmony_ci reset_fn(item); 96425bb815Sopenharmony_ci item = next; 97425bb815Sopenharmony_ci } 98425bb815Sopenharmony_ci} 99425bb815Sopenharmony_ci 100425bb815Sopenharmony_cichar* GetStacktraceString(ecma_string_t* stack) 101425bb815Sopenharmony_ci{ 102425bb815Sopenharmony_ci if (stack == NULL) { 103425bb815Sopenharmony_ci return NULL; 104425bb815Sopenharmony_ci } 105425bb815Sopenharmony_ci // Copy string to jsheap-independent storage. 106425bb815Sopenharmony_ci ECMA_STRING_TO_UTF8_STRING(stack, data, data_size); 107425bb815Sopenharmony_ci char* dst = JerryExtAllocStr(data_size + 1); 108425bb815Sopenharmony_ci memcpy(dst, data, data_size); 109425bb815Sopenharmony_ci dst[data_size] = '\0'; 110425bb815Sopenharmony_ci return dst; 111425bb815Sopenharmony_ci} 112425bb815Sopenharmony_ci 113425bb815Sopenharmony_ciRefInfoItem* CreateRefInfoItem(RefInfoItemFlags flags, char* stack_str) 114425bb815Sopenharmony_ci{ 115425bb815Sopenharmony_ci RefInfoItem* item = JerryExtAlloc(sizeof(RefInfoItem)); 116425bb815Sopenharmony_ci item->next = NULL; 117425bb815Sopenharmony_ci item->stacktrace = stack_str; 118425bb815Sopenharmony_ci item->flags = flags; 119425bb815Sopenharmony_ci return item; 120425bb815Sopenharmony_ci} 121425bb815Sopenharmony_ci 122425bb815Sopenharmony_civoid ReportObjRefManip(ecma_object_t* obj, RefInfoItemFlags flags) 123425bb815Sopenharmony_ci{ 124425bb815Sopenharmony_ci if (!gRefTrackerEnabled) { 125425bb815Sopenharmony_ci return; 126425bb815Sopenharmony_ci } 127425bb815Sopenharmony_ci 128425bb815Sopenharmony_ci if (gNativeManip) { 129425bb815Sopenharmony_ci flags &= kRefNative; 130425bb815Sopenharmony_ci } 131425bb815Sopenharmony_ci 132425bb815Sopenharmony_ci // XXX: For now don't do anything regarding within-gc ops. 133425bb815Sopenharmony_ci if (flags & (kRefMark | kRefUnmark)) { 134425bb815Sopenharmony_ci return; 135425bb815Sopenharmony_ci } 136425bb815Sopenharmony_ci 137425bb815Sopenharmony_ci const char* native_str = " native"; 138425bb815Sopenharmony_ci const char* init_str = " init"; 139425bb815Sopenharmony_ci const char* inc_str = " increment"; 140425bb815Sopenharmony_ci const char* dec_str = " decrement"; 141425bb815Sopenharmony_ci 142425bb815Sopenharmony_ci uint32_t refcnt = obj->type_flags_refs >> REF_CNT_SHIFT; 143425bb815Sopenharmony_ci 144425bb815Sopenharmony_ci LogTracker("Object %p%s%s%s%s: refcount = %u\n", (void*)obj, 145425bb815Sopenharmony_ci (flags & kRefNative) ? native_str : "", 146425bb815Sopenharmony_ci (flags & kRefInit) ? init_str : "", 147425bb815Sopenharmony_ci (flags & kRefRef) ? inc_str : "", 148425bb815Sopenharmony_ci (flags & kRefDeref) ? dec_str : "", 149425bb815Sopenharmony_ci refcnt); 150425bb815Sopenharmony_ci LogTracker("\n"); 151425bb815Sopenharmony_ci} 152425bb815Sopenharmony_ci 153425bb815Sopenharmony_civoid ReportObjDelete(ecma_object_t* obj) 154425bb815Sopenharmony_ci{ 155425bb815Sopenharmony_ci if (!gRefTrackerEnabled) { 156425bb815Sopenharmony_ci return; 157425bb815Sopenharmony_ci } 158425bb815Sopenharmony_ci 159425bb815Sopenharmony_ci LogTracker("Object %p deleted\n", (void*)obj); 160425bb815Sopenharmony_ci LogTracker("\n"); 161425bb815Sopenharmony_ci} 162425bb815Sopenharmony_ci 163425bb815Sopenharmony_civoid DumpTracker(void) 164425bb815Sopenharmony_ci{ 165425bb815Sopenharmony_ci Storage* storage = &gStorages[kObjectRefInfo]; 166425bb815Sopenharmony_ci for (int i = 0; i < (int)storage->size; ++i) { 167425bb815Sopenharmony_ci if (storage->data[i] != 0) { 168425bb815Sopenharmony_ci RefInfoItem* item = (RefInfoItem*)storage->data[i]; 169425bb815Sopenharmony_ci printf("--== %p ==--:\n", (void*)ECMA_OBJECT_FROM_STORAGE_KEY(i)); 170425bb815Sopenharmony_ci while (item != NULL) { 171425bb815Sopenharmony_ci printf("flags = %d\nStacktrace:\n%s\n", item->flags, item->stacktrace); 172425bb815Sopenharmony_ci item = item->next; 173425bb815Sopenharmony_ci } 174425bb815Sopenharmony_ci } 175425bb815Sopenharmony_ci } 176425bb815Sopenharmony_ci} 177425bb815Sopenharmony_ci 178425bb815Sopenharmony_ci#endif 179