// // Get URL from source context, called by LogMethodNativeLoadEvent and LogLoopBodyLoadEvent // utf8char_t* VTuneChakraProfile::GetUrl(Js::FunctionBody* body, size_t* urlBufferLength ) { utf8char_t* utf8Url = NULL; if (!body->GetSourceContextInfo()->IsDynamic()) { const wchar* url = body->GetSourceContextInfo()->url; if (url) { size_t urlCharLength = wcslen(url); urlCharLength = min(urlCharLength, (size_t)UINT_MAX); // Just truncate if it is too big *urlBufferLength = urlCharLength * 3 + 1; utf8Url = HeapNewNoThrowArray(utf8char_t, *urlBufferLength); if (utf8Url) { utf8::EncodeIntoAndNullTerminate(utf8Url, url, (charcount_t)urlCharLength); } } } else { utf8Url = (utf8char_t*)VTuneChakraProfile::DynamicCode; } return utf8Url; }
BYTE* WebAssemblySharedArrayBuffer::AllocBuffer(uint32 length, uint32 maxLength) { #if ENABLE_FAST_ARRAYBUFFER if (CONFIG_FLAG(WasmFastArray)) { return (BYTE*)WasmVirtualAllocator(length); } #endif #ifdef _WIN32 if (CONFIG_FLAG(WasmSharedArrayVirtualBuffer)) { return (BYTE*)AllocWrapper(length, maxLength); } #endif AssertOrFailFast(maxLength >= length); uint32 additionalSize = maxLength - length; if (additionalSize > 0) { // SharedArrayBuffer::Init already requested External Memory for `length`, we need to request the balance if (!this->GetRecycler()->RequestExternalMemoryAllocation(additionalSize)) { // Failed to request for more memory return nullptr; } } // Allocate the full size of the buffer if we can't do VirtualAlloc return HeapNewNoThrowArray(BYTE, maxLength); }
BYTE* SharedArrayBuffer::AllocBuffer(uint32 length, uint32 maxLength) { Unused(maxLength); // WebAssembly only #if ENABLE_FAST_ARRAYBUFFER if (this->IsValidVirtualBufferLength(length)) { return (BYTE*)AsmJsVirtualAllocator(length); } else #endif { return HeapNewNoThrowArray(BYTE, length); } }
void JsrtDebugUtils::AddSouceToObject(Js::DynamicObject * object, Js::Utf8SourceInfo * utf8SourceInfo) { int32 cchLength = utf8SourceInfo->GetCchLength(); AutoArrayPtr<char16> sourceContent(HeapNewNoThrowArray(char16, cchLength + 1), cchLength + 1); if (sourceContent != nullptr) { utf8::DecodeOptions options = utf8SourceInfo->IsCesu8() ? utf8::doAllowThreeByteSurrogates : utf8::doDefault; utf8::DecodeIntoAndNullTerminate(sourceContent, utf8SourceInfo->GetSource(), cchLength, options); JsrtDebugUtils::AddPropertyToObject(object, JsrtDebugPropertyId::source, sourceContent, cchLength, utf8SourceInfo->GetScriptContext()); } else { JsrtDebugUtils::AddPropertyToObject(object, JsrtDebugPropertyId::source, _u(""), 1, utf8SourceInfo->GetScriptContext()); } }
// // 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 }
void JsrtDebugUtils::AddSourceLengthAndTextToObject(Js::DynamicObject* object, Js::FunctionBody* functionBody, int byteCodeOffset) { Js::FunctionBody::StatementMap* statementMap = functionBody->GetEnclosingStatementMapFromByteCode(byteCodeOffset); Assert(statementMap != nullptr); LPCUTF8 source = functionBody->GetStartOfDocument(_u("Source for debugging")); size_t startByte = utf8::CharacterIndexToByteIndex(source, functionBody->GetUtf8SourceInfo()->GetCbLength(), (const charcount_t)statementMap->sourceSpan.begin); int byteLength = statementMap->sourceSpan.end - statementMap->sourceSpan.begin; JsrtDebugUtils::AddPropertyToObject(object, JsrtDebugPropertyId::sourceLength, (double)byteLength, functionBody->GetScriptContext()); AutoArrayPtr<char16> sourceContent(HeapNewNoThrowArray(char16, byteLength + 1), byteLength + 1); if (sourceContent != nullptr) { utf8::DecodeOptions options = functionBody->GetUtf8SourceInfo()->IsCesu8() ? utf8::doAllowThreeByteSurrogates : utf8::doDefault; utf8::DecodeIntoAndNullTerminate(sourceContent, source + startByte, byteLength, options); JsrtDebugUtils::AddPropertyToObject(object, JsrtDebugPropertyId::sourceText, sourceContent, byteLength, functionBody->GetScriptContext()); } else { JsrtDebugUtils::AddPropertyToObject(object, JsrtDebugPropertyId::sourceText, _u(""), 1, functionBody->GetScriptContext()); } }
// // 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 }