Exemplo n.º 1
0
static void
method_jit_result (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) {
	if (result == MONO_PROFILE_OK) {
		int i;
		MonoDebugSourceLocation *sourceLoc;
		MonoDebugMethodJitInfo *dmji;
		MonoClass *klass = mono_method_get_class (method);
		char *signature = mono_signature_get_desc (mono_method_signature (method), TRUE);
		char *name = g_strdup_printf ("%s(%s)", mono_method_get_name (method), signature);
		char *classname = g_strdup_printf ("%s%s%s", mono_class_get_namespace (klass), mono_class_get_namespace (klass)[0] != 0 ? "::" : "", mono_class_get_name (klass));
		gpointer code_start = mono_jit_info_get_code_start (jinfo);
		int code_size = mono_jit_info_get_code_size (jinfo);
		
		iJIT_Method_Load vtuneMethod;
		memset(&vtuneMethod, 0, sizeof(vtuneMethod));
		vtuneMethod.method_id = iJIT_GetNewMethodID();
		vtuneMethod.method_name = name;
		vtuneMethod.method_load_address = code_start;
		vtuneMethod.method_size = code_size;
		vtuneMethod.class_file_name = classname;

		dmji = mono_debug_find_method (method, mono_domain_get());

		if (dmji != NULL)
		{
			vtuneMethod.line_number_size = dmji->num_line_numbers;
			vtuneMethod.line_number_table = (vtuneMethod.line_number_size != 0) ?
				(LineNumberInfo*)malloc(sizeof(LineNumberInfo) * vtuneMethod.line_number_size) : NULL;

			for (i = 0; i < dmji->num_line_numbers; ++i)
			{
				sourceLoc = mono_debug_lookup_source_location (method, dmji->line_numbers[i].native_offset, mono_domain_get());
				if (sourceLoc == NULL)
				{
					g_free (vtuneMethod.line_number_table);
					vtuneMethod.line_number_table = NULL;
					vtuneMethod.line_number_size = 0;
					break;
				}
				if (i == 0)
					vtuneMethod.source_file_name = strdup(sourceLoc->source_file);
				vtuneMethod.line_number_table[i].Offset = dmji->line_numbers[i].native_offset;
				vtuneMethod.line_number_table[i].LineNumber = sourceLoc->row;
				mono_debug_free_source_location (sourceLoc);
			}
			mono_debug_free_method_jit_info (dmji);
		}

		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);

		if (vtuneMethod.source_file_name != NULL)
			g_free (vtuneMethod.source_file_name);
		if (vtuneMethod.line_number_table != NULL)
			g_free (vtuneMethod.line_number_table);
	
		g_free (signature);
		g_free (name);
		g_free (classname);
	}
}
Exemplo n.º 2
0
void RegisterV(const void* base_address, u32 code_size,
	const char* format, va_list args)
{
#if !(defined USE_OPROFILE && USE_OPROFILE) && !defined(USE_VTUNE)
	if (!s_perf_map_file.IsOpen())
		return;
#endif

	std::string symbol_name = StringFromFormatV(format, args);

#if defined USE_OPROFILE && USE_OPROFILE
	op_write_native_code(s_agent, symbol_name.data(), (u64)base_address,
		base_address, code_size);
#endif

#ifdef USE_VTUNE
	iJIT_Method_Load jmethod = {0};
	jmethod.method_id = iJIT_GetNewMethodID();
	jmethod.method_load_address = const_cast<void*>(base_address);
	jmethod.method_size = code_size;
	jmethod.method_name = const_cast<char*>(symbol_name.data());
	iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
#endif

	// Linux perf /tmp/perf-$pid.map:
	if (s_perf_map_file.IsOpen())
	{
		std::string entry = StringFromFormat(
			"%llx %x %s\n",
			(u64)base_address, code_size, symbol_name.data());
		s_perf_map_file.WriteBytes(entry.data(), entry.size());
	}
}
Exemplo n.º 3
0
void JitBlockCache::FinalizeBlock(int block_num, bool block_link) {
    JitBlock &b = blocks_[block_num];

    b.originalFirstOpcode = Memory::Read_Opcode_JIT(b.originalAddress);
    MIPSOpcode opcode = GetEmuHackOpForBlock(block_num);
    Memory::Write_Opcode_JIT(b.originalAddress, opcode);

    AddBlockMap(block_num);

    u32 latestExit = 0;
    if (block_link) {
        for (int i = 0; i < MAX_JIT_BLOCK_EXITS; i++) {
            if (b.exitAddress[i] != INVALID_EXIT) {
                links_to_.insert(std::make_pair(b.exitAddress[i], block_num));
                latestExit = std::max(latestExit, b.exitAddress[i]);
            }
        }

        LinkBlock(block_num);
        LinkBlockExits(block_num);
    }

    if (Memory::IsScratchpadAddress(b.originalAddress)) {
        ExpandRange(blockMemRanges_[JITBLOCK_RANGE_SCRATCH], b.originalAddress, latestExit);
    }
    const u32 halfUserMemory = (PSP_GetUserMemoryEnd() - PSP_GetUserMemoryBase()) / 2;
    if (b.originalAddress < PSP_GetUserMemoryBase() + halfUserMemory) {
        ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMBOTTOM], b.originalAddress, latestExit);
    }
    if (latestExit > PSP_GetUserMemoryBase() + halfUserMemory) {
        ExpandRange(blockMemRanges_[JITBLOCK_RANGE_RAMTOP], b.originalAddress, latestExit);
    }

#if defined USE_OPROFILE && USE_OPROFILE
    char buf[100];
    sprintf(buf, "EmuCode%x", b.originalAddress);
    const u8* blockStart = blocks_[block_num].checkedEntry;
    op_write_native_code(agent, buf, (uint64_t)blockStart, blockStart, b.normalEntry + b.codeSize - b.checkedEntry);
#endif

#ifdef USE_VTUNE
    sprintf(b.blockName, "EmuCode_0x%08x", b.originalAddress);

    iJIT_Method_Load jmethod = {0};
    jmethod.method_id = iJIT_GetNewMethodID();
    jmethod.class_file_name = "";
    jmethod.source_file_name = __FILE__;
    jmethod.method_load_address = (void*)blocks_[block_num].checkedEntry;
    jmethod.method_size = b.normalEntry + b.codeSize - b.checkedEntry;
    jmethod.line_number_size = 0;
    jmethod.method_name = b.blockName;
    iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod);
#endif
}
Exemplo n.º 4
0
static void
code_buffer_new (MonoProfiler *prof, void *buffer, int size, MonoProfilerCodeBufferType type, void *data)
{
	char *name;
	iJIT_Method_Load vtuneMethod;

	if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE)
		name = g_strdup_printf ("code_buffer_specific_trampoline_%s", (char*) data);
	else
		name = (char*) code_buffer_desc (type);

	memset (&vtuneMethod, 0, sizeof (vtuneMethod));
	vtuneMethod.method_id = iJIT_GetNewMethodID ();
	vtuneMethod.method_name = name;
	vtuneMethod.method_load_address = buffer;
	vtuneMethod.method_size = size;

	iJIT_NotifyEvent (iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &vtuneMethod);

	if (type == MONO_PROFILER_CODE_BUFFER_SPECIFIC_TRAMPOLINE) {
		g_free (name);
	}
}
Exemplo n.º 5
0
//
// Log loop body load event to VTune 
//
void VTuneChakraProfile::LogLoopBodyLoadEvent(Js::FunctionBody* body, Js::LoopHeader* loopHeader, Js::LoopEntryPointInfo* entryPoint, uint16 loopNumber)
{
#if ENABLE_NATIVE_CODEGEN
    if (isJitProfilingActive)
    {
        iJIT_Method_Load methodInfo;
        memset(&methodInfo, 0, sizeof(iJIT_Method_Load));
        const char16* methodName = body->GetExternalDisplayName();
        size_t methodLength = wcslen(methodName);
        methodLength = min(methodLength, (size_t)UINT_MAX); // Just truncate if it is too big
        size_t length = methodLength * 3 + /* spaces */ 2 + _countof(LoopStr) + /*size of loop number*/ 10 + /*NULL*/ 1;
        utf8char_t* utf8MethodName = HeapNewNoThrowArray(utf8char_t, length);
        if(utf8MethodName)
        {
            methodInfo.method_id = iJIT_GetNewMethodID();
            size_t len = utf8::EncodeInto(utf8MethodName, methodName, (charcount_t)methodLength);
            sprintf_s((char*)(utf8MethodName + len), length - len," %s %d", LoopStr, loopNumber + 1);
            methodInfo.method_name = (char*)utf8MethodName;
            methodInfo.method_load_address = (void*)entryPoint->GetNativeAddress();
            methodInfo.method_size = (uint)entryPoint->GetCodeSize();        // Size in memory - Must be exact

            size_t urlLength  = 0;
            utf8char_t* utf8Url = GetUrl(body, &urlLength);
            methodInfo.source_file_name = (char*)utf8Url;

            iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &methodInfo);
            OUTPUT_TRACE(Js::ProfilerPhase, _u("Loop body load event: %s Loop %d\n"), methodName, loopNumber + 1);

            if(urlLength > 0)
            {
                HeapDeleteArray(urlLength, utf8Url);
            }
            HeapDeleteArray(length, utf8MethodName);
        }
    }
#endif
}
Exemplo n.º 6
0
void CBasicBlock::Compile()
{
#ifndef AOT_USE_CACHE

	Framework::CMemStream stream;
	{
		static
#ifdef AOT_BUILD_CACHE
		    __declspec(thread)
#endif
		        CMipsJitter* jitter = nullptr;
		if(jitter == nullptr)
		{
			Jitter::CCodeGen* codeGen = Jitter::CreateCodeGen();
			jitter = new CMipsJitter(codeGen);

			for(unsigned int i = 0; i < 4; i++)
			{
				jitter->SetVariableAsConstant(
				    offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]),
				    0);
			}
		}

		jitter->SetStream(&stream);
		jitter->Begin();
		CompileRange(jitter);
		//		codeGen.DumpVariables(0);
		//		codeGen.EndQuota();
		jitter->End();
	}

	m_function = CMemoryFunction(stream.GetBuffer(), stream.GetSize());

#ifdef VTUNE_ENABLED
	if(iJIT_IsProfilingActive() == iJIT_SAMPLING_ON)
	{
		iJIT_Method_Load jmethod = {};
		jmethod.method_id = iJIT_GetNewMethodID();
		jmethod.class_file_name = "";
		jmethod.source_file_name = __FILE__;

		jmethod.method_load_address = m_function.GetCode();
		jmethod.method_size = m_function.GetSize();
		jmethod.line_number_size = 0;

		auto functionName = string_format("BasicBlock_0x%08X_0x%08X", m_begin, m_end);

		jmethod.method_name = const_cast<char*>(functionName.c_str());
		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, reinterpret_cast<void*>(&jmethod));
	}
#endif

#endif

#ifdef AOT_ENABLED

	size_t blockSize = ((m_end - m_begin) / 4) + 1;
	auto blockData = new uint32[blockSize];

	for(uint32 i = 0; i < blockSize; i++)
	{
		blockData[i] = m_context.m_pMemoryMap->GetWord(m_begin + (i * 4));
	}

	uint32 blockChecksum = crc32(0, reinterpret_cast<Bytef*>(blockData), blockSize * 4);

#endif

#ifdef AOT_USE_CACHE

	AOT_BLOCK* blocksBegin = &_aot_firstBlock;
	AOT_BLOCK* blocksEnd = blocksBegin + _aot_blockCount;

	AOT_BLOCK blockRef = {blockChecksum, m_begin, m_end, nullptr};

	static const auto blockComparer =
	    [](const AOT_BLOCK& item1, const AOT_BLOCK& item2) {
		    return item1.key < item2.key;
	    };

	//	assert(std::is_sorted(blocksBegin, blocksEnd, blockComparer));

	bool blockExists = std::binary_search(blocksBegin, blocksEnd, blockRef, blockComparer);
	auto blockIterator = std::lower_bound(blocksBegin, blocksEnd, blockRef, blockComparer);

	assert(blockExists);
	assert(blockIterator != blocksEnd);
	assert(blockIterator->key.crc == blockChecksum);
	assert(blockIterator->key.begin == m_begin);
	assert(blockIterator->key.end == m_end);

	m_function = reinterpret_cast<void (*)(void*)>(blockIterator->fct);

#endif

#ifdef AOT_BUILD_CACHE
	{
		std::lock_guard<std::mutex> lock(m_aotBlockOutputStreamMutex);

		m_aotBlockOutputStream->Write32(blockChecksum);
		m_aotBlockOutputStream->Write32(m_begin);
		m_aotBlockOutputStream->Write32(m_end);
		m_aotBlockOutputStream->Write(blockData, blockSize * 4);
	}
#endif
}
Exemplo n.º 7
0
   void VTune_RegisterMethod(AvmCore* core, JITCodeInfo* inf) 
   {       
		// assume no method inlining so start/end of JIT code gen = method start/end
       uintptr startAt = inf->startAddr;
       uintptr endAt = inf->endAddr;
		uint32 methodSize = endAt - startAt;

       Stringp name = inf->method->format(core);
       int idx[4];
       bool hasClass = locateNames(core, name, idx);

		// register the method
		iJIT_Method_Load ML;
       Stringp mname = name->substring(idx[2],idx[3]);
		VMPI_memset(&ML, 0, sizeof(iJIT_Method_Load));
       ML.method_id = (inf->vtune) ? inf->vtune->method_id : iJIT_GetNewMethodID();
       ML.method_name = string2char(core, mname);
		ML.method_load_address = (void *)startAt;	// virtual address of that method  - This determines the method range for the iJVM_EVENT_TYPE_ENTER/LEAVE_METHOD_ADDR events
		ML.method_size = methodSize;	// Size in memory - Must be exact

		// md position / line number table
       SortedIntMap<LineNumberRecord*>* tbl = &inf->lineNumTable;
		int size = tbl->size();
		LineNumberInfo* lines = 0;
		if (size)
		{
			int bsz = size*sizeof(LineNumberInfo);
			lines = (LineNumberInfo*) malloc(bsz);
			VMPI_memset(lines, 0, bsz);
		}

       String* fileName = 0;
       int at = 0;
       for(int i=0; i<size; i++) 
		{
			sintptr mdPos = tbl->keyAt(i);
			LineNumberRecord* entry = tbl->at(i);
           if (entry->filename && entry->lineno)
           {
               if (!fileName) fileName = entry->filename;

               // @todo file name should be part of the lines[] record, no?
               lines[at].LineNumber = entry->lineno;
               lines[at].Offset = mdPos - startAt;
               at++;
           }
       }

       // @todo hack for vtune since it can't process multiple records with the same method name 
       if (inf->sid>0 && at>0) {
           mname = core->concatStrings(mname,core->newString("_L"));
           mname = core->concatStrings(mname,core->intToString(lines[0].LineNumber));
           mname = core->concatStrings(mname,core->newString("_"));
           mname = core->concatStrings(mname,core->intToString(inf->sid));
           if (ML.method_name) free(ML.method_name);
           ML.method_name = string2char(core,mname);
       }

       ML.line_number_table = lines;   // Pointer to the begining of the line numbers info array
       ML.line_number_size = at;       // Line Table size in number of entries - Zero if none

       UTF8String* utf = ( fileName ) ? fileName->toUTF8String() : core->kEmptyString->toUTF8String();
		
		ML.class_id = 0;                // uniq class ID
       ML.class_file_name = (hasClass) ? string2char(core,name->substring(idx[0],idx[1])) : 0;     // class file name 
		ML.source_file_name = (char *)(malloc((utf->length()+3)*sizeof(char)));   // +1 for \0 and +2 for wtoc's ()
		wtoc(ML.source_file_name, utf->c_str(), 0);	// source file name 

		ML.user_data = NULL;            // bits supplied by the user for saving in the JIT file...
		ML.user_data_size = 0;          // the size of the user data buffer
		ML.env = iJDE_JittingAPI;

		// DumpVTuneMethodInfo(core, &ML); // Uncommented to debug VTune
		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &ML);

       if (inf->vtune && core->VTuneStatus == iJIT_CALLGRAPH_ON) 
		{
			MMgc::GCHeap* heap = core->GetGC()->GetGCHeap();
           heap->SetPageProtection(inf->vtune, sizeof (iJIT_Method_NIDS), false, true);   
       }

		// free everything we alloc'd  ( @todo did vtune really copy all the strings?!? )
		if (ML.line_number_table) free(ML.line_number_table);
       if (ML.class_file_name && hasClass) free(ML.class_file_name);
		if (ML.method_name) free(ML.method_name);
		if (ML.source_file_name) free(ML.source_file_name);
	}	
Exemplo n.º 8
0
//
// Log JIT method native load event to VTune 
//
void VTuneChakraProfile::LogMethodNativeLoadEvent(Js::FunctionBody* body, Js::FunctionEntryPointInfo* entryPoint)
{
#if ENABLE_NATIVE_CODEGEN
    if (isJitProfilingActive)
    {
        iJIT_Method_Load methodInfo;
        memset(&methodInfo, 0, sizeof(iJIT_Method_Load));
        const char16* methodName = body->GetExternalDisplayName();
        // Append function line number info to method name so that VTune can distinguish between polymorphic methods
        char16 methodNameBuffer[_MAX_PATH];
        ULONG lineNumber = body->GetLineNumber();
        char16 numberBuffer[20];
        _ltow_s(lineNumber, numberBuffer, 10);
        wcscpy_s(methodNameBuffer, methodName);
        if (entryPoint->GetJitMode() == ExecutionMode::SimpleJit)
        {
            wcscat_s(methodNameBuffer, _u(" Simple"));
        }
        wcscat_s(methodNameBuffer, _u(" {line:"));
        wcscat_s(methodNameBuffer, numberBuffer);
        wcscat_s(methodNameBuffer, _u("}"));

        size_t methodLength = wcslen(methodNameBuffer);
        Assert(methodLength < _MAX_PATH);
        size_t length = methodLength * 3 + 1;
        utf8char_t* utf8MethodName = HeapNewNoThrowArray(utf8char_t, length);
        if (utf8MethodName)
        {
            methodInfo.method_id = iJIT_GetNewMethodID();
            utf8::EncodeIntoAndNullTerminate(utf8MethodName, methodNameBuffer, (charcount_t)methodLength);
            methodInfo.method_name = (char*)utf8MethodName;
            methodInfo.method_load_address = (void*)entryPoint->GetNativeAddress();
            methodInfo.method_size = (uint)entryPoint->GetCodeSize();        // Size in memory - Must be exact

            LineNumberInfo numberInfo[1];

            uint lineCount = (entryPoint->GetNativeOffsetMapCount()) * 2 + 1; // may need to record both .begin and .end for all elements
            LineNumberInfo* pLineInfo = HeapNewNoThrowArray(LineNumberInfo, lineCount);

            if (pLineInfo == NULL || Js::Configuration::Global.flags.DisableVTuneSourceLineInfo)
            {
                // resort to original implementation, attribute all samples to first line
                numberInfo[0].LineNumber = lineNumber;
                numberInfo[0].Offset = 0;
                methodInfo.line_number_size = 1;
                methodInfo.line_number_table = numberInfo;
            }
            else
            {
                int size = entryPoint->PopulateLineInfo(pLineInfo, body);
                methodInfo.line_number_size = size;
                methodInfo.line_number_table = pLineInfo;
            }

            size_t urlLength = 0;
            utf8char_t* utf8Url = GetUrl(body, &urlLength);
            methodInfo.source_file_name = (char*)utf8Url;
            OUTPUT_TRACE(Js::ProfilerPhase, _u("Method load event: %s\n"), methodNameBuffer);
            iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, &methodInfo);

            HeapDeleteArray(lineCount, pLineInfo);

            if (urlLength > 0)
            {
                HeapDeleteArray(urlLength, utf8Url);
            }

            HeapDeleteArray(length, utf8MethodName);
        }
    }
#endif
}