Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Memoryprofiler] Exposing required mono API for backend migration #1206

Merged
merged 8 commits into from
Jul 29, 2019
283 changes: 283 additions & 0 deletions mono/metadata/class.c
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,289 @@ mono_type_get_name (MonoType *type)
return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
}

static char *
mono_identifier_escape_type_append(char *bufferPtr, const char *identifier)
{
for (const char *s = identifier; *s != 0; ++s) {
switch (*s) {
case ',':
case '+':
case '&':
case '*':
case '[':
case ']':
case '\\':
*bufferPtr++ = '\\';
*bufferPtr++ = *s;

return bufferPtr;
default:
*bufferPtr++ = *s;

return bufferPtr;
}
}

return bufferPtr;
}

enum {
//max digits on uint16 is 5(used to convert the number of generic args) + max 3 other slots taken;
kNameChunkBufferSize = 8
};

static inline char *
flush_name_buffer(char *buffer, GFunc callback, void *userData)
{
callback(buffer, userData);
memset(buffer, 0x00, kNameChunkBufferSize);

return buffer;
}

static void
mono_type_get_name_foreach_name_chunk_recurse(MonoType *type, gboolean is_recursed, MonoTypeNameFormat format, GFunc nameChunkReport, void *userData)
{
MonoClass *klass = NULL;
char buffer[kNameChunkBufferSize + 1]; //null terminate the buffer
memset(buffer, 0x00, kNameChunkBufferSize + 1);
char *bufferPtr = buffer;
char *bufferIter = buffer;

switch (type->type) {
case MONO_TYPE_ARRAY: {
int i, rank = type->data.array->rank;
MonoTypeNameFormat nested_format;

nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? MONO_TYPE_NAME_FORMAT_FULL_NAME : format;

mono_type_get_name_foreach_name_chunk_recurse(
&type->data.array->eklass->byval_arg, FALSE, nested_format, nameChunkReport, userData);

*bufferIter++ = '[';

if (rank == 1) {
*bufferIter++ = '*';
}

for (i = 1; i < rank; i++) {

*bufferIter++ = ',';

if (kNameChunkBufferSize - (bufferIter - bufferPtr) < 2) {
bufferIter = flush_name_buffer(bufferPtr, nameChunkReport, userData);
}
}

*bufferIter++ = ']';

if (type->byref) {
*bufferIter++ = '&';
}

nameChunkReport(bufferPtr, userData);

if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) {
MonoClass *klass = mono_class_from_mono_type(type);
MonoImage *klassImg = mono_class_get_image(klass);
char *imgName = mono_image_get_name(klassImg);
nameChunkReport(imgName, userData);
}
break;
}
case MONO_TYPE_SZARRAY: {
MonoTypeNameFormat nested_format;

nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? MONO_TYPE_NAME_FORMAT_FULL_NAME : format;

mono_type_get_name_foreach_name_chunk_recurse(&type->data.klass->byval_arg, FALSE, nested_format, nameChunkReport, userData);

*bufferIter++ = '[';
*bufferIter++ = ']';

if (type->byref)
*bufferIter++ = '&';

nameChunkReport(bufferPtr, userData);

if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) {
MonoClass *klass = mono_class_from_mono_type(type);
MonoImage *klassImg = mono_class_get_image(klass);
char *imgName = mono_image_get_name(klassImg);
nameChunkReport(imgName, userData);
}
break;
}
case MONO_TYPE_PTR: {
MonoTypeNameFormat nested_format;

nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ? MONO_TYPE_NAME_FORMAT_FULL_NAME : format;

mono_type_get_name_foreach_name_chunk_recurse(type->data.type, FALSE, nested_format, nameChunkReport, userData);
*bufferIter++ = '*';

if (type->byref)
*bufferIter++ = '&';

nameChunkReport(bufferPtr, userData);

if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) {
MonoClass *klass = mono_class_from_mono_type(type);
MonoImage *klassImg = mono_class_get_image(klass);
char *imgName = mono_image_get_name(klassImg);
nameChunkReport(imgName, userData);
}
break;
}
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
if (!mono_generic_param_info(type->data.generic_param)) {

if (type->type == MONO_TYPE_VAR) {
*bufferIter++ = '!';
}
else {
*bufferIter++ = '!';
*bufferIter++ = '!';
}
sprintf(bufferIter, "%d", type->data.generic_param->num);
}
else
nameChunkReport(mono_generic_param_info(type->data.generic_param)->name, userData);

if (type->byref)
*bufferIter++ = '&';

nameChunkReport(bufferPtr, userData);
break;
default:
klass = mono_class_from_mono_type(type);
if (klass->nested_in) {
mono_type_get_name_foreach_name_chunk_recurse(&klass->nested_in->byval_arg, TRUE, format, nameChunkReport, userData);
if (format == MONO_TYPE_NAME_FORMAT_IL)
*bufferIter++ = '.';
else
*bufferIter++ = '+';
}
else if (*klass->name_space) {
if (format == MONO_TYPE_NAME_FORMAT_IL)
nameChunkReport(klass->name_space, userData);
else
bufferIter = mono_identifier_escape_type_append(bufferIter, klass->name_space);

*bufferIter++ = '.';
}

if (format == MONO_TYPE_NAME_FORMAT_IL) {
char *s = strchr(klass->name, '`');
int len = s ? s - klass->name : strlen(klass->name);

for (int i = 0; i < len; ++i) {

*bufferIter++ = *(klass->name + i);
if (kNameChunkBufferSize - (bufferIter - bufferPtr) == 0) {
bufferIter = flush_name_buffer(bufferPtr, nameChunkReport, userData);
}
}

if (bufferPtr != bufferIter) {
bufferIter = flush_name_buffer(bufferPtr, nameChunkReport, userData);
}

}
else {
bufferIter = mono_identifier_escape_type_append(bufferIter, klass->name);
}

if (!is_recursed) {
if (bufferIter != bufferPtr)
bufferIter = flush_name_buffer(bufferPtr, nameChunkReport, userData);

if (mono_class_is_ginst(klass)) {
MonoGenericClass *gclass = mono_class_get_generic_class(klass);
MonoGenericInst *inst = gclass->context.class_inst;
MonoTypeNameFormat nested_format;
int i;

nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ? MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;

if (format == MONO_TYPE_NAME_FORMAT_IL)
*bufferIter++ = '<';
else
*bufferIter++ = '[';

for (i = 0; i < inst->type_argc; i++) {
MonoType *t = inst->type_argv[i];

if (i)
*bufferIter++ = ',';
if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
(t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
*bufferIter++ = '[';

//flush the buffer before recursing
bufferIter = flush_name_buffer(bufferPtr, nameChunkReport, userData);
mono_type_get_name_foreach_name_chunk_recurse(inst->type_argv[i], FALSE, nested_format, nameChunkReport, userData);

if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
(t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
*bufferIter++ = ']';
}
if (format == MONO_TYPE_NAME_FORMAT_IL)
*bufferIter++ = '>';
else
*bufferIter++ = ']';
}
else if (mono_class_is_gtd(klass) &&
(format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
(format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
int i;

if (format == MONO_TYPE_NAME_FORMAT_IL)
*bufferIter++ = '<';
else
*bufferIter++ = '[';

bufferIter = flush_name_buffer(bufferPtr, nameChunkReport, userData);

for (i = 0; i < mono_class_get_generic_container(klass)->type_argc; i++) {
if (i)
nameChunkReport(",", userData);
nameChunkReport(mono_generic_container_get_param_info(mono_class_get_generic_container(klass), i)->name, userData);
}
if (format == MONO_TYPE_NAME_FORMAT_IL)
*bufferIter++ = '>';
else
*bufferIter++ = ']';
}

if (type->byref)
*bufferIter++ = '&';
}

if (bufferPtr != bufferIter)
nameChunkReport(bufferPtr, userData);

if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
(type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
MonoImage *klassImg = mono_class_get_image(klass);
char *imgName = mono_image_get_name(klassImg);
nameChunkReport(imgName, userData);
}
break;
}
}

/**
* mono_type_get_name_chunked:
* \param type a type
* \reports chunks null terminated of a type's name via a callback.
*/
void mono_type_get_name_chunked(MonoType * type, uint32_t format, void(*namePieceReportCallback)(void *data, void *userData), void * userData)
{
mono_type_get_name_foreach_name_chunk_recurse(type, FALSE, format, namePieceReportCallback, userData);
}

/**
* mono_type_get_underlying_type:
* \param type a type
Expand Down
3 changes: 3 additions & 0 deletions mono/metadata/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ mono_ldtoken (MonoImage *image, uint32_t token, MonoClass **retcla
MONO_API char*
mono_type_get_name (MonoType *type);

MONO_API void
mono_type_get_name_chunked(MonoType *type, uint32_t format, void(*namePieceReportCallback)(void* data, void* userData), void* userData);

MONO_API MonoType*
mono_type_get_underlying_type (MonoType *type);

Expand Down
4 changes: 1 addition & 3 deletions mono/metadata/mempool.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,8 @@ mono_mempool_foreach_block(MonoMemPool* pool, mono_mempool_block_proc callback,

while (current)
{
gpointer start = (guint8*)current + SIZEOF_MEM_POOL;
gpointer end = (guint8*)current + current->size;

callback(start, end, user_data);
callback(current, end, user_data);
current = current->next;
}
}
Expand Down
Loading