MemoryLogger* MemoryLogger::Create(TAllocator* alloc, ULONG count) { #ifdef EXCEPTION_CHECK AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck); #endif return Anew(alloc, MemoryLogger, alloc, count); }
StackTraceHelper* StackTraceHelper::Create(TAllocator* alloc) { #ifdef EXCEPTION_CHECK AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck); #endif return Anew(alloc, StackTraceHelper, alloc); }
void Profiler::MergeTree(TypeNode * toNode, TypeNode * fromNode) { UnitData * toData = toNode->GetValue(); const UnitData * fromData = fromNode->GetValue(); toData->count += fromData->count; toData->incl += fromData->incl; toData->excl += fromData->excl; if (fromData->max > toData->max) { toData->max = fromData->max; } for (int i = 0; i < PhaseCount; i++) { if (fromNode->ChildExistsAt(i)) { TypeNode * fromChild = fromNode->GetChildAt(i); TypeNode * toChild; if (!toNode->ChildExistsAt(i)) { toChild = Anew(this->alloc, TypeNode, toNode); toNode->SetChildAt(i, toChild); } else { toChild = toNode->GetChildAt(i); } MergeTree(toChild, fromChild); } } }
void FuncInfo::AddCapturedSym(Symbol *sym) { if (this->capturedSyms == nullptr) { this->capturedSyms = Anew(alloc, SymbolTable, alloc); } this->capturedSyms->AddNew(sym); }
CapturedSymMap *FuncInfo::EnsureCapturedSymMap() { if (this->capturedSymMap == nullptr) { this->capturedSymMap = Anew(alloc, CapturedSymMap, alloc); } return this->capturedSymMap; }
CharSet<char16>* StandardChars<char16>::GetFullSet() { if (fullSet == 0) { fullSet = Anew(allocator, UnicodeCharSet); fullSet->SetRange(allocator, MinChar, MaxChar); } return fullSet; }
CharSet<char16>* StandardChars<char16>::GetWhitespaceSet() { if (whitespaceSet == 0) { whitespaceSet = Anew(allocator, UnicodeCharSet); whitespaceSet->SetRanges(allocator, numWhitespacePairs, whitespaceStr); } return whitespaceSet; }
CharSet<char16>* StandardChars<char16>::GetNewlineSet() { if (newlineSet == 0) { newlineSet = Anew(allocator, UnicodeCharSet); newlineSet->SetRanges(allocator, numNewlinePairs, newlineStr); } return newlineSet; }
CharSet<char16>* StandardChars<char16>::GetNonWordSet() { if (nonWordSet == 0) { nonWordSet = Anew(allocator, UnicodeCharSet); nonWordSet->SetNotRanges(allocator, numWordPairs, wordStr); } return nonWordSet; }
CharSet<char16>* StandardChars<char16>::GetEmptySet() { if (emptySet == 0) { emptySet = Anew(allocator, UnicodeCharSet); // leave empty } return emptySet; }
CharSet<char16>* StandardChars<char16>::GetSurrogateUpperRange() { if (surrogateUpperRange == 0) { surrogateUpperRange = Anew(allocator, UnicodeCharSet); surrogateUpperRange->SetRange(allocator, (char16)0xDC00u, (char16)0xDFFFu); } return surrogateUpperRange; }
BreakpointProbe* DebugDocument::SetBreakPoint_TTDWbpId(int64 bpId, StatementLocation statement) { ScriptContext* scriptContext = this->utf8SourceInfo->GetScriptContext(); BreakpointProbe* pProbe = Anew(scriptContext->AllocatorForDiagnostics(), BreakpointProbe, this, statement, (uint32)bpId); scriptContext->GetDebugContext()->GetProbeContainer()->AddProbe(pProbe); BreakpointProbeList* pBreakpointList = this->GetBreakpointList(); pBreakpointList->Add(pProbe); return pProbe; }
BreakpointProbe* DebugDocument::SetBreakPoint(StatementLocation statement, BREAKPOINT_STATE bps) { ScriptContext* scriptContext = this->utf8SourceInfo->GetScriptContext(); if (scriptContext == nullptr || scriptContext->IsClosed()) { return nullptr; } switch (bps) { default: AssertMsg(FALSE, "Bad breakpoint state"); // Fall thru case BREAKPOINT_DISABLED: case BREAKPOINT_DELETED: { BreakpointProbeList* pBreakpointList = this->GetBreakpointList(); if (pBreakpointList) { ArenaAllocator arena(_u("TemporaryBreakpointList"), scriptContext->GetThreadContext()->GetDebugManager()->GetDiagnosticPageAllocator(), Throw::OutOfMemory); BreakpointProbeList* pDeleteList = this->NewBreakpointList(&arena); pBreakpointList->Map([&statement, scriptContext, pDeleteList](int index, BreakpointProbe * breakpointProbe) { if (breakpointProbe->Matches(statement.function, statement.statement.begin)) { scriptContext->GetDebugContext()->GetProbeContainer()->RemoveProbe(breakpointProbe); pDeleteList->Add(breakpointProbe); } }); pDeleteList->Map([pBreakpointList](int index, BreakpointProbe * breakpointProbe) { pBreakpointList->Remove(breakpointProbe); }); pDeleteList->Clear(); } break; } case BREAKPOINT_ENABLED: { BreakpointProbe* pProbe = Anew(scriptContext->AllocatorForDiagnostics(), BreakpointProbe, this, statement, scriptContext->GetThreadContext()->GetDebugManager()->GetNextBreakpointId()); scriptContext->GetDebugContext()->GetProbeContainer()->AddProbe(pProbe); BreakpointProbeList* pBreakpointList = this->GetBreakpointList(); pBreakpointList->Add(pProbe); return pProbe; break; } } return nullptr; }
RegexStats* RegexStatsDatabase::GetRegexStats(RegexPattern* pattern) { Js::InternalString str = pattern->GetSource(); RegexStats *res; if (!map->TryGetValue(str, &res)) { res = Anew(allocator, RegexStats, pattern); map->Add(str, res); } return res; }
// This will make a copy of the entire buffer InternalString *InternalString::New(ArenaAllocator* alloc, const char16* content, charcount_t length) { size_t bytelength = sizeof(char16) * length; DWORD* allocbuffer = (DWORD*)alloc->Alloc(sizeof(DWORD) + bytelength + sizeof(char16)); allocbuffer[0] = (DWORD) bytelength; char16* buffer = (char16*)(allocbuffer+1); js_memcpy_s(buffer, bytelength, content, bytelength); buffer[length] = L'\0'; InternalString* newInstance = Anew(alloc, InternalString, buffer, length); return newInstance; }
JSONScanner::RangeCharacterPairList* JSONScanner::GetCurrentRangeCharacterPairList(void) { if (this->currentRangeCharacterPairList == nullptr) { if (this->allocator == nullptr) { this->allocatorObject = this->scriptContext->GetTemporaryGuestAllocator(_u("JSONScanner")); this->allocator = this->allocatorObject->GetAllocator(); } this->currentRangeCharacterPairList = Anew(this->allocator, RangeCharacterPairList, this->allocator, 4); } return this->currentRangeCharacterPairList; }
bool ProbeContainer::InitializeLocation(InterpreterHaltState* pHaltState, bool fMatchWithCurrentScriptContext) { Assert(debugManager); debugManager->SetCurrentInterpreterLocation(pHaltState); ArenaAllocator* pDiagArena = debugManager->GetDiagnosticArena()->Arena(); UpdateFramePointers(fMatchWithCurrentScriptContext); pHaltState->framePointers = framePointers; pHaltState->stringBuilder = Anew(pDiagArena, StringBuilder<ArenaAllocator>, pDiagArena); if (pHaltState->framePointers->Count() > 0) { pHaltState->topFrame = pHaltState->framePointers->Peek(0); } OUTPUT_TRACE(Js::DebuggerPhase, _u("ProbeContainer::InitializeLocation (end): this=%p, pHaltState=%p, fMatch=%d, topFrame=%p\n"), this, pHaltState, fMatchWithCurrentScriptContext, pHaltState->topFrame); return true; }
PropertyString* PropertyString::New(StaticType* type, const Js::PropertyRecord* propertyRecord, ArenaAllocator *arena) { PropertyString * propertyString = (PropertyString *)Anew(arena, ArenaAllocPropertyString, type, propertyRecord); propertyString->propCache = AllocatorNewStructZ(InlineCacheAllocator, type->GetScriptContext()->GetInlineCacheAllocator(), PropertyCache); return propertyString; }
double ppm( const Matrix<T,N,1> & Delta, const Matrix<T,N,1> & Vmax, const Matrix<T,N,1> & Amax, Matrix<T,N,1> & Vnew, Matrix<T,N,1> & Anew, Matrix<T,N,1> & Dnew, T requestedMotionTime = 0 ) { Matrix<T,N,3> Times; // Iterate over axes for(unsigned int l = 0; l < N; ++l) { const T delta = Delta(l,0), // motor position delta vmax = Vmax(l,0), // maximal velocity amax = Amax(l,0), // maximal acceleration dmax = -Amax(l,0); // maximal deceleration // Velocity value, when the velocity profile is triangular (eq. 3.32) const T VTriangle = amax*std::sqrt(2*delta*dmax/(amax*(dmax-amax))); //const T VTriangle = std::sqrt(2*delta*amax*dmax/(dmax-amax)); #if 0 std::cout << "VTriangle(" << l << ") = " << VTriangle << std::endl; #endif const bool TriangularProfile = (VTriangle <= vmax); if(TriangularProfile) { // tt: total motion time (eq. 3.33) Times(l,2) = std::sqrt(2*delta*(dmax-amax)/(amax*dmax)); // acceleration and deceleration phase treated as a half of the total motion time Times(l,0) = Times(l,1) = Times(l,2)/2; } else { // ta: time to stop accelerate (eq. 3.35) Times(l,0) = vmax/amax; // td: time to start deceleration (eq. 3.42) Times(l,1) = delta/vmax + vmax/(2*amax) + vmax/(2*dmax); // Numerically stable version: //Time(l,1) = (2*delta*amax*dmax+vmax*vmax*amax+vmax*vmax*dmax)/(2*vmax*amax*dmax); // tt: total motion time (eq. 3.40) Times(l,2) = delta/vmax + vmax/(2*amax) - vmax/(2*dmax); // Numerically stable version: //Time(l,2) = (2*delta*amax*dmax+vmax*vmax*dmax-vmax*vmax*amax)/(2*vmax*amax*dmax); } // std::cerr << "VLimit[" << l << "]: " << VTriangle << // " => " << (TriangularProfile ? "triangular" : "trapezoidal") << std::endl << // "Time[" << l << "]: " << Times(l,0) << " " << Times(l,1) << " " << Times(l,2) << // std::endl; } Matrix<T,1,3> maxTimes = Times.colwise().maxCoeff(); // std::cerr << "maxTimes: " << maxTimes << std::endl; // max of acceleration intervals const T ta = maxTimes(0); // max of constant velocity intervals const T tV = (Times.col(1)-Times.col(0)).maxCoeff(); // max of deceleration intervals const T tD = (Times.col(2)-Times.col(1)).maxCoeff(); // deceleration interval const T td = ta + tV; T tt = ta + tV + tD; if (ta > td) { tt += (ta - td); } // Make the motion longer if(requestedMotionTime > 0) { if(tt > requestedMotionTime) { throw std::runtime_error("requested motion time too short"); } tt = requestedMotionTime; } // std::cout // << "ta: " << ta << "\t" // << "td: " << td << "\t" // << "tt: " << tt // << std::endl; // If the total time is zero there will be no motion if(tt > 0) { // I guess this can be implemented as a single matrix calculation for(unsigned int l = 0; l < N; ++l) { const T delta = Delta(l,0); // Calculate new parameters if there is motion along an axis if(delta) { Anew(l,0) = 2*delta/(ta*(tt+td-ta)); Dnew(l,0) = - (-2*delta/((tt+td-ta)*(tt-td))); // deceleration value (without sign) //Dnew(l,0) = (2*delta)/(tt*tt-tt*ta+td*ta-td*td); // Numerically stable (?) version Vnew(l,0) = Anew(l,0)*ta; //Vnew(l,0) = (2*delta)/(tt+td-ta); // Numerically stable (?) version } else { Anew(l,0) = Amax(l,0); Dnew(l,0) = Amax(l,0); Vnew(l,0) = Vmax(l,0); } } } else { Vnew = Vmax; Anew = Dnew = Amax; } // These assertions fail because of floating point inequalities //assert(Dnew(l,0)<=Amax(l,0)); //assert(Anew(l,0)<=Amax(l,0)); //assert(Vnew(l,0)<=Vmax(l,0));; // std::cerr << // "Vnew:\n" << Vnew << std::endl << // "Anew:\n" << Anew << std::endl << // "Dnew:\n" << Dnew << std::endl << // std::endl; // std::cerr << "tt: " << tt << std::endl; return tt; }
HRESULT ServerRemoteCodeGen( /* [in] */ handle_t binding, /* [in] */ intptr_t scriptContextInfoAddress, /* [in] */ __RPC__in CodeGenWorkItemIDL *workItemData, /* [out] */ __RPC__out JITOutputIDL *jitData) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); LARGE_INTEGER start_time = { 0 }; if (PHASE_TRACE1(Js::BackEndPhase)) { QueryPerformanceCounter(&start_time); } memset(jitData, 0, sizeof(JITOutputIDL)); ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress); if (scriptContextInfo == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsScriptContextAlive(scriptContextInfo)) { Assert(false); return E_ACCESSDENIED; } AutoReleaseContext<ServerScriptContext> autoScriptContext(scriptContextInfo); return ServerCallWrapper(scriptContextInfo, [&]() ->HRESULT { scriptContextInfo->UpdateGlobalObjectThisAddr(workItemData->globalThisAddr); ServerThreadContext * threadContextInfo = scriptContextInfo->GetThreadContext(); NoRecoverMemoryJitArenaAllocator jitArena(L"JITArena", threadContextInfo->GetPageAllocator(), Js::Throw::OutOfMemory); JITTimeWorkItem * jitWorkItem = Anew(&jitArena, JITTimeWorkItem, workItemData); if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId())) { LARGE_INTEGER freq; LARGE_INTEGER end_time; QueryPerformanceCounter(&end_time); QueryPerformanceFrequency(&freq); Output::Print( L"BackendMarshalIn - function: %s time:%8.6f mSec\r\n", jitWorkItem->GetJITFunctionBody()->GetDisplayName(), (((double)((end_time.QuadPart - workItemData->startTime)* (double)1000.0 / (double)freq.QuadPart))) / (1)); Output::Flush(); } auto profiler = scriptContextInfo->GetCodeGenProfiler(); #ifdef PROFILE_EXEC if (profiler && !profiler->IsInitialized()) { profiler->Initialize(threadContextInfo->GetPageAllocator(), nullptr); } #endif if (jitWorkItem->GetWorkItemData()->xProcNumberPageSegment) { jitData->numberPageSegments = (XProcNumberPageSegment*)midl_user_allocate(sizeof(XProcNumberPageSegment)); if (!jitData->numberPageSegments) { return E_OUTOFMEMORY; } __analysis_assume(jitData->numberPageSegments); memcpy_s(jitData->numberPageSegments, sizeof(XProcNumberPageSegment), jitWorkItem->GetWorkItemData()->xProcNumberPageSegment, sizeof(XProcNumberPageSegment)); } Func::Codegen( &jitArena, jitWorkItem, threadContextInfo, scriptContextInfo, jitData, nullptr, nullptr, jitWorkItem->GetPolymorphicInlineCacheInfo(), threadContextInfo->GetCodeGenAllocators(), #if !FLOATVAR nullptr, // number allocator #endif profiler, true); #ifdef PROFILE_EXEC if (profiler && profiler->IsInitialized()) { profiler->ProfilePrint(Js::Configuration::Global.flags.Profile.GetFirstPhase()); } #endif if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId())) { LARGE_INTEGER freq; LARGE_INTEGER end_time; QueryPerformanceCounter(&end_time); QueryPerformanceFrequency(&freq); Output::Print( L"EndBackEndInner - function: %s time:%8.6f mSec\r\n", jitWorkItem->GetJITFunctionBody()->GetDisplayName(), (((double)((end_time.QuadPart - start_time.QuadPart)* (double)1000.0 / (double)freq.QuadPart))) / (1)); Output::Flush(); } LARGE_INTEGER out_time = { 0 }; if (PHASE_TRACE1(Js::BackEndPhase)) { QueryPerformanceCounter(&out_time); jitData->startTime = out_time.QuadPart; } return S_OK; }); }
Js::Var JSONParser::ParseObject() { PROBE_STACK(scriptContext, Js::Constants::MinStackDefault); Js::Var retVal; switch (m_token.tk) { case tkFltCon: retVal = Js::JavascriptNumber::ToVarIntCheck(m_token.GetDouble(), scriptContext); Scan(); return retVal; case tkStrCon: { // will auto-null-terminate the string (as length=len+1) uint len = m_scanner.GetCurrentStringLen(); retVal = Js::JavascriptString::NewCopyBuffer(m_scanner.GetCurrentString(), len, scriptContext); Scan(); return retVal; } case tkTRUE: retVal = scriptContext->GetLibrary()->GetTrue(); Scan(); return retVal; case tkFALSE: retVal = scriptContext->GetLibrary()->GetFalse(); Scan(); return retVal; case tkNULL: retVal = scriptContext->GetLibrary()->GetNull(); Scan(); return retVal; case tkSub: // unary minus if (Scan() == tkFltCon) { retVal = Js::JavascriptNumber::ToVarIntCheck(-m_token.GetDouble(), scriptContext); Scan(); return retVal; } else { m_scanner.ThrowSyntaxError(JSERR_JsonBadNumber); } case tkLBrack: { Js::JavascriptArray* arrayObj = scriptContext->GetLibrary()->CreateArray(0); //skip '[' Scan(); //iterate over the array members, get JSON objects and add them in the pArrayMemberList uint k = 0; while (true) { if(tkRBrack == m_token.tk) { break; } Js::Var value = ParseObject(); arrayObj->SetItem(k++, value, Js::PropertyOperation_None); // if next token is not a comma consider the end of the array member list. if (tkComma != m_token.tk) break; Scan(); if(tkRBrack == m_token.tk) { m_scanner.ThrowSyntaxError(JSERR_JsonIllegalChar); } } //check and consume the ending ']' CheckCurrentToken(tkRBrack, JSERR_JsonNoRbrack); return arrayObj; } case tkLCurly: { // Parse an object, "{"name1" : ObjMember1, "name2" : ObjMember2, ...} " if(IsCaching()) { if(!typeCacheList) { typeCacheList = Anew(this->arenaAllocator, JsonTypeCacheList, this->arenaAllocator, 8); } } // first, create the object Js::DynamicObject* object = scriptContext->GetLibrary()->CreateObject(); JS_ETW(EventWriteJSCRIPT_RECYCLER_ALLOCATE_OBJECT(object)); #if ENABLE_DEBUG_CONFIG_OPTIONS if (Js::Configuration::Global.flags.IsEnabled(Js::autoProxyFlag)) { object = DynamicObject::FromVar(JavascriptProxy::AutoProxyWrapper(object)); } #endif //next token after '{' Scan(); //if empty object "{}" return; if(tkRCurly == m_token.tk) { Scan(); return object; } JsonTypeCache* previousCache = nullptr; JsonTypeCache* currentCache = nullptr; //parse the list of members while(true) { // parse a list member: "name" : ObjMember // and add it to the object. //pick "name" if(tkStrCon != m_token.tk) { m_scanner.ThrowSyntaxError(JSERR_JsonIllegalChar); } // currentStrLength = length w/o null-termination WCHAR* currentStr = m_scanner.GetCurrentString(); uint currentStrLength = m_scanner.GetCurrentStringLen(); DynamicType* typeWithoutProperty = object->GetDynamicType(); if(IsCaching()) { if(!previousCache) { // This is the first property in the list - see if we have an existing cache for it. currentCache = typeCacheList->LookupWithKey(Js::HashedCharacterBuffer<WCHAR>(currentStr, currentStrLength), nullptr); } if(currentCache && currentCache->typeWithoutProperty == typeWithoutProperty && currentCache->propertyRecord->Equals(JsUtil::CharacterBuffer<WCHAR>(currentStr, currentStrLength))) { //check and consume ":" if(Scan() != tkColon ) { m_scanner.ThrowSyntaxError(JSERR_JsonNoColon); } Scan(); // Cache all values from currentCache as there is a chance that ParseObject might change the cache DynamicType* typeWithProperty = currentCache->typeWithProperty; PropertyId propertyId = currentCache->propertyRecord->GetPropertyId(); PropertyIndex propertyIndex = currentCache->propertyIndex; previousCache = currentCache; currentCache = currentCache->next; // fast path for type transition and property set object->EnsureSlots(typeWithoutProperty->GetTypeHandler()->GetSlotCapacity(), typeWithProperty->GetTypeHandler()->GetSlotCapacity(), scriptContext, typeWithProperty->GetTypeHandler()); object->ReplaceType(typeWithProperty); Js::Var value = ParseObject(); object->SetSlot(SetSlotArguments(propertyId, propertyIndex, value)); // if the next token is not a comma consider the list of members done. if (tkComma != m_token.tk) break; Scan(); continue; } } // slow path Js::PropertyRecord const * propertyRecord; scriptContext->GetOrAddPropertyRecord(currentStr, currentStrLength, &propertyRecord); //check and consume ":" if(Scan() != tkColon ) { m_scanner.ThrowSyntaxError(JSERR_JsonNoColon); } Scan(); Js::Var value = ParseObject(); PropertyValueInfo info; object->SetProperty(propertyRecord->GetPropertyId(), value, PropertyOperation_None, &info); DynamicType* typeWithProperty = object->GetDynamicType(); if(IsCaching() && !propertyRecord->IsNumeric() && !info.IsNoCache() && typeWithProperty->GetIsShared() && typeWithProperty->GetTypeHandler()->IsPathTypeHandler()) { PropertyIndex propertyIndex = info.GetPropertyIndex(); if(!previousCache) { // This is the first property in the set add it to the dictionary. currentCache = JsonTypeCache::New(this->arenaAllocator, propertyRecord, typeWithoutProperty, typeWithProperty, propertyIndex); typeCacheList->AddNew(propertyRecord, currentCache); } else if(!currentCache) { currentCache = JsonTypeCache::New(this->arenaAllocator, propertyRecord, typeWithoutProperty, typeWithProperty, propertyIndex); previousCache->next = currentCache; } else { // cache miss!! currentCache->Update(propertyRecord, typeWithoutProperty, typeWithProperty, propertyIndex); } previousCache = currentCache; currentCache = currentCache->next; } // if the next token is not a comma consider the list of members done. if (tkComma != m_token.tk) break; Scan(); } // check and consume the ending '}" CheckCurrentToken(tkRCurly, JSERR_JsonNoRcurly); return object; } default: m_scanner.ThrowSyntaxError(JSERR_JsonSyntax); } }
RegexStatsDatabase::RegexStatsDatabase(ArenaAllocator* allocator) : start(0), allocator(allocator) { ticksPerMillisecond = Freq(); map = Anew(allocator, RegexStatsMap, allocator, 17); }
// // Load persisted scope info. // void ScopeInfo::GetScopeInfo(Parser *parser, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo, Scope* scope) { ScriptContext* scriptContext; ArenaAllocator* alloc; // Load scope attributes and push onto scope stack. scope->SetIsDynamic(this->isDynamic); if (this->isObject) { scope->SetIsObject(); } scope->SetMustInstantiate(this->mustInstantiate); if (!this->GetCanMergeWithBodyScope()) { scope->SetCannotMergeWithBodyScope(); } scope->SetHasOwnLocalInClosure(this->hasLocalInClosure); if (parser) { scriptContext = parser->GetScriptContext(); alloc = parser->GetAllocator(); } else { TRACE_BYTECODE(_u("\nRestore ScopeInfo: %s #symbols: %d %s\n"), funcInfo->name, symbolCount, isObject ? _u("isObject") : _u("")); Assert(!this->isCached || scope == funcInfo->GetBodyScope()); funcInfo->SetHasCachedScope(this->isCached); byteCodeGenerator->PushScope(scope); // The scope is already populated, so we're done. return; } // Load scope symbols // On first access to the scopeinfo, replace the ID's with PropertyRecord*'s to save the dictionary lookup // on later accesses. Replace them all before allocating Symbol's to prevent inconsistency on OOM. if (!this->areNamesCached && !PHASE_OFF1(Js::CacheScopeInfoNamesPhase)) { for (int i = 0; i < symbolCount; i++) { PropertyId propertyId = GetSymbolId(i); if (propertyId != 0) // There may be empty slots, e.g. "arguments" may have no slot { PropertyRecord const* name = scriptContext->GetPropertyName(propertyId); this->SetPropertyName(i, name); } } this->areNamesCached = true; } for (int i = 0; i < symbolCount; i++) { PropertyRecord const* name = nullptr; if (this->areNamesCached) { name = this->GetPropertyName(i); } else { PropertyId propertyId = GetSymbolId(i); if (propertyId != 0) // There may be empty slots, e.g. "arguments" may have no slot { name = scriptContext->GetPropertyName(propertyId); } } if (name != nullptr) { SymbolType symbolType = GetSymbolType(i); SymbolName symName(name->GetBuffer(), name->GetLength()); Symbol *sym = Anew(alloc, Symbol, symName, nullptr, symbolType); sym->SetScopeSlot(static_cast<PropertyId>(i)); sym->SetIsBlockVar(GetIsBlockVariable(i)); if (GetHasFuncAssignment(i)) { sym->RestoreHasFuncAssignment(); } scope->AddNewSymbol(sym); if (parser) { parser->RestorePidRefForSym(sym); } TRACE_BYTECODE(_u("%12s %d\n"), sym->GetName().GetBuffer(), sym->GetScopeSlot()); } } this->scope = scope; DebugOnly(scope->isRestored = true); }
ArenaLiteralString* ArenaLiteralString::New(StaticType* type, const char16* content, charcount_t charLength, ArenaAllocator* arena) { return Anew(arena, ArenaLiteralString, type, content, charLength); }
void* AsmJsEncoder::Encode( FunctionBody* functionBody ) { Assert( functionBody ); mFunctionBody = functionBody; #if DBG_DUMP AsmJsJitTemplate::Globals::CurrentEncodingFunction = mFunctionBody; #endif AsmJsFunctionInfo* asmInfo = functionBody->GetAsmJsFunctionInfo(); FunctionEntryPointInfo* entryPointInfo = ((FunctionEntryPointInfo*)(functionBody->GetDefaultEntryPointInfo())); // number of var on the stack + ebp + eip mIntOffset = asmInfo->GetIntByteOffset() + GetOffset<Var>(); mDoubleOffset = asmInfo->GetDoubleByteOffset() + GetOffset<Var>(); mFloatOffset = asmInfo->GetFloatByteOffset() + GetOffset<Var>(); mSimdOffset = asmInfo->GetSimdByteOffset() + GetOffset<Var>(); NoRecoverMemoryArenaAllocator localAlloc(_u("BE-AsmJsEncoder"), GetPageAllocator(), Js::Throw::OutOfMemory); mLocalAlloc = &localAlloc; mRelocLabelMap = Anew( mLocalAlloc, RelocLabelMap, mLocalAlloc ); mTemplateData = AsmJsJitTemplate::InitTemplateData(); mEncodeBufferSize = GetEncodeBufferSize(functionBody); mEncodeBuffer = AnewArray((&localAlloc), BYTE, mEncodeBufferSize); mPc = mEncodeBuffer; mReader.Create( functionBody ); ip = mReader.GetIP(); #ifdef ENABLE_DEBUG_CONFIG_OPTIONS if( PHASE_TRACE( Js::AsmjsEncoderPhase, mFunctionBody ) ) { Output::Print( _u("\n\n") ); functionBody->DumpFullFunctionName(); Output::Print( _u("\n StackSize = %d , Offsets: Var = %d, Int = %d, Double = %d\n"), mFunctionBody->GetAsmJsFunctionInfo()->GetTotalSizeinBytes(), GetOffset<Var>(), GetOffset<int>(), GetOffset<double>() ); } #endif AsmJsJitTemplate::FunctionEntry::ApplyTemplate( this, mPc ); while( ReadOp() ){} AsmJsJitTemplate::FunctionExit::ApplyTemplate( this, mPc ); AsmJsJitTemplate::FreeTemplateData( mTemplateData ); #if DBG_DUMP AsmJsJitTemplate::Globals::CurrentEncodingFunction = nullptr; #endif ApplyRelocs(); ptrdiff_t codeSize = mPc - mEncodeBuffer; if( codeSize > 0 ) { Assert( ::Math::FitsInDWord( codeSize ) ); BYTE *buffer; EmitBufferAllocation *allocation = GetCodeGenAllocator()->emitBufferManager.AllocateBuffer( codeSize, &buffer, 0, 0 ); functionBody->GetAsmJsFunctionInfo()->mTJBeginAddress = buffer; if (buffer == nullptr) { Js::Throw::OutOfMemory(); } if (!GetCodeGenAllocator()->emitBufferManager.CommitBuffer(allocation, buffer, codeSize, mEncodeBuffer)) { Js::Throw::OutOfMemory(); } functionBody->GetScriptContext()->GetThreadContext()->SetValidCallTargetForCFG(buffer); // TODO: improve this once EntryPoint cleanup work is complete! #if 0 const char16 *const functionName = functionBody->GetDisplayName(); const char16 *const suffix = _u("TJ"); char16 functionNameArray[256]; const size_t functionNameCharLength = functionBody->GetDisplayNameLength(); wcscpy_s(functionNameArray, 256, functionName); wcscpy_s(&functionNameArray[functionNameCharLength], 256 - functionNameCharLength, suffix); #endif JS_ETW(EventWriteMethodLoad(functionBody->GetScriptContext(), (void *)buffer, codeSize, EtwTrace::GetFunctionId(functionBody), 0 /* methodFlags - for future use*/, MethodType_Jit, EtwTrace::GetSourceId(functionBody), functionBody->GetLineNumber(), functionBody->GetColumnNumber(), functionBody->GetDisplayName())); entryPointInfo->SetTJCodeGenDone(); // set the codegen to done state for TJ entryPointInfo->SetCodeSize(codeSize); return buffer; } return nullptr; }
// This will only store the pointer and length, not making a copy of the buffer InternalString *InternalString::NewNoCopy(ArenaAllocator* alloc, const char16* content, charcount_t length) { InternalString* newInstance = Anew(alloc, InternalString, const_cast<char16*> (content), length); return newInstance; }
///---------------------------------------------------------------------------- /// /// Encoder::Encode /// /// Main entrypoint of encoder. Encode each IR instruction into the /// appropriate machine encoding. /// ///---------------------------------------------------------------------------- void Encoder::Encode() { NoRecoverMemoryArenaAllocator localAlloc(_u("BE-Encoder"), m_func->m_alloc->GetPageAllocator(), Js::Throw::OutOfMemory); m_tempAlloc = &localAlloc; uint32 instrCount = m_func->GetInstrCount(); size_t totalJmpTableSizeInBytes = 0; JmpTableList * jumpTableListForSwitchStatement = nullptr; m_encoderMD.Init(this); m_encodeBufferSize = UInt32Math::Mul(instrCount, MachMaxInstrSize); m_encodeBufferSize += m_func->m_totalJumpTableSizeInBytesForSwitchStatements; m_encodeBuffer = AnewArray(m_tempAlloc, BYTE, m_encodeBufferSize); #if DBG_DUMP m_instrNumber = 0; m_offsetBuffer = AnewArray(m_tempAlloc, uint, instrCount); #endif m_pragmaInstrToRecordMap = Anew(m_tempAlloc, PragmaInstrList, m_tempAlloc); if (DoTrackAllStatementBoundary()) { // Create a new list, if we are tracking all statement boundaries. m_pragmaInstrToRecordOffset = Anew(m_tempAlloc, PragmaInstrList, m_tempAlloc); } else { // Set the list to the same as the throw map list, so that processing of the list // of pragma are done on those only. m_pragmaInstrToRecordOffset = m_pragmaInstrToRecordMap; } #if defined(_M_IX86) || defined(_M_X64) // for BR shortening m_inlineeFrameRecords = Anew(m_tempAlloc, InlineeFrameRecords, m_tempAlloc); #endif m_pc = m_encodeBuffer; m_inlineeFrameMap = Anew(m_tempAlloc, InlineeFrameMap, m_tempAlloc); m_bailoutRecordMap = Anew(m_tempAlloc, BailoutRecordMap, m_tempAlloc); IR::PragmaInstr* pragmaInstr = nullptr; uint32 pragmaOffsetInBuffer = 0; #ifdef _M_X64 bool inProlog = false; #endif bool isCallInstr = false; FOREACH_INSTR_IN_FUNC(instr, m_func) { Assert(Lowerer::ValidOpcodeAfterLower(instr, m_func)); if (GetCurrentOffset() + MachMaxInstrSize < m_encodeBufferSize) { ptrdiff_t count; #if DBG_DUMP AssertMsg(m_instrNumber < instrCount, "Bad instr count?"); __analysis_assume(m_instrNumber < instrCount); m_offsetBuffer[m_instrNumber++] = GetCurrentOffset(); #endif if (instr->IsPragmaInstr()) { switch(instr->m_opcode) { #ifdef _M_X64 case Js::OpCode::PrologStart: m_func->m_prologEncoder.Begin(m_pc - m_encodeBuffer); inProlog = true; continue; case Js::OpCode::PrologEnd: m_func->m_prologEncoder.End(); inProlog = false; continue; #endif case Js::OpCode::StatementBoundary: pragmaOffsetInBuffer = GetCurrentOffset(); pragmaInstr = instr->AsPragmaInstr(); pragmaInstr->m_offsetInBuffer = pragmaOffsetInBuffer; // will record after BR shortening with adjusted offsets if (DoTrackAllStatementBoundary()) { m_pragmaInstrToRecordOffset->Add(pragmaInstr); } break; default: continue; } } else if (instr->IsBranchInstr() && instr->AsBranchInstr()->IsMultiBranch()) { Assert(instr->GetSrc1() && instr->GetSrc1()->IsRegOpnd()); IR::MultiBranchInstr * multiBranchInstr = instr->AsBranchInstr()->AsMultiBrInstr(); if (multiBranchInstr->m_isSwitchBr && (multiBranchInstr->m_kind == IR::MultiBranchInstr::IntJumpTable || multiBranchInstr->m_kind == IR::MultiBranchInstr::SingleCharStrJumpTable)) { BranchJumpTableWrapper * branchJumpTableWrapper = multiBranchInstr->GetBranchJumpTable(); if (jumpTableListForSwitchStatement == nullptr) { jumpTableListForSwitchStatement = Anew(m_tempAlloc, JmpTableList, m_tempAlloc); } jumpTableListForSwitchStatement->Add(branchJumpTableWrapper); totalJmpTableSizeInBytes += (branchJumpTableWrapper->tableSize * sizeof(void*)); } else { //Reloc Records EncoderMD * encoderMD = &(this->m_encoderMD); multiBranchInstr->MapMultiBrTargetByAddress([=](void ** offset) -> void { #if defined(_M_ARM32_OR_ARM64) encoderMD->AddLabelReloc((byte*) offset); #else encoderMD->AppendRelocEntry(RelocTypeLabelUse, (void*) (offset)); #endif }); } } else { isCallInstr = LowererMD::IsCall(instr); if (pragmaInstr && (instr->isInlineeEntryInstr || isCallInstr)) { // will record throw map after BR shortening with adjusted offsets m_pragmaInstrToRecordMap->Add(pragmaInstr); pragmaInstr = nullptr; // Only once per pragma instr -- do we need to make this record? } if (instr->HasBailOutInfo()) { Assert(this->m_func->hasBailout); Assert(LowererMD::IsCall(instr)); instr->GetBailOutInfo()->FinalizeBailOutRecord(this->m_func); } if (instr->isInlineeEntryInstr) { m_encoderMD.EncodeInlineeCallInfo(instr, GetCurrentOffset()); } if (instr->m_opcode == Js::OpCode::InlineeStart) { Assert(!instr->isInlineeEntryInstr); if (pragmaInstr) { m_pragmaInstrToRecordMap->Add(pragmaInstr); pragmaInstr = nullptr; } Func* inlinee = instr->m_func; if (inlinee->frameInfo && inlinee->frameInfo->record) { inlinee->frameInfo->record->Finalize(inlinee, GetCurrentOffset()); #if defined(_M_IX86) || defined(_M_X64) // Store all records to be adjusted for BR shortening m_inlineeFrameRecords->Add(inlinee->frameInfo->record); #endif } continue; } } count = m_encoderMD.Encode(instr, m_pc, m_encodeBuffer); #if DBG_DUMP if (PHASE_TRACE(Js::EncoderPhase, this->m_func)) { instr->Dump((IRDumpFlags)(IRDumpFlags_SimpleForm | IRDumpFlags_SkipEndLine | IRDumpFlags_SkipByteCodeOffset)); Output::SkipToColumn(80); for (BYTE * current = m_pc; current < m_pc + count; current++) { Output::Print(_u("%02X "), *current); } Output::Print(_u("\n")); Output::Flush(); } #endif #ifdef _M_X64 if (inProlog) m_func->m_prologEncoder.EncodeInstr(instr, count & 0xFF); #endif m_pc += count; #if defined(_M_IX86) || defined(_M_X64) // for BR shortening. if (instr->isInlineeEntryInstr) m_encoderMD.AppendRelocEntry(RelocType::RelocTypeInlineeEntryOffset, (void*) (m_pc - MachPtr)); #endif if (isCallInstr) { isCallInstr = false; this->RecordInlineeFrame(instr->m_func, GetCurrentOffset()); } if (instr->HasBailOutInfo() && Lowerer::DoLazyBailout(this->m_func)) { this->RecordBailout(instr, (uint32)(m_pc - m_encodeBuffer)); } } else { Fatal(); } }
void ProbeContainer::UpdateFramePointers(bool fMatchWithCurrentScriptContext) { ArenaAllocator* pDiagArena = debugManager->GetDiagnosticArena()->Arena(); framePointers = Anew(pDiagArena, DiagStack, pDiagArena); JavascriptStackWalker walker(pScriptContext, !fMatchWithCurrentScriptContext, nullptr/*returnAddress*/, true/*forceFullWalk*/); DiagStack* tempFramePointers = Anew(pDiagArena, DiagStack, pDiagArena); const bool isLibraryFrameEnabledDebugger = IsLibraryStackFrameSupportEnabled(); walker.WalkUntil([&](JavascriptFunction* func, ushort frameIndex) -> bool { if (isLibraryFrameEnabledDebugger || !func->IsLibraryCode()) { DiagStackFrame* frm = nullptr; InterpreterStackFrame *interpreterFrame = walker.GetCurrentInterpreterFrame(); ScriptContext* frameScriptContext = walker.GetCurrentScriptContext(); Assert(frameScriptContext); if (!fMatchWithCurrentScriptContext && !frameScriptContext->IsScriptContextInDebugMode() && tempFramePointers->Count() == 0) { // this means the top frame is not in the debug mode. We shouldn't be stopping for this break. // This could happen if the exception happens on the diagnosticsScriptEngine. return true; } // Ignore frames which are not in debug mode, which can happen when diag engine calls into user engine under debugger // -- topmost frame is under debugger but some frames could be in non-debug mode as they are from diag engine. if (frameScriptContext->IsScriptContextInDebugMode() && (!fMatchWithCurrentScriptContext || frameScriptContext == pScriptContext)) { if (interpreterFrame) { frm = Anew(pDiagArena, DiagInterpreterStackFrame, interpreterFrame, frameIndex); } else { #if ENABLE_NATIVE_CODEGEN if (func->IsScriptFunction()) { frm = Anew(pDiagArena, DiagNativeStackFrame, ScriptFunction::FromVar(walker.GetCurrentFunction()), walker.GetByteCodeOffset(), walker.GetCurrentArgv(), walker.GetCurrentCodeAddr(), frameIndex); } else #else Assert(!func->IsScriptFunction()); #endif { frm = Anew(pDiagArena, DiagRuntimeStackFrame, func, walker.GetCurrentNativeLibraryEntryName(), walker.GetCurrentArgv(), frameIndex); } } } if (frm) { tempFramePointers->Push(frm); } } return false; }); OUTPUT_TRACE(Js::DebuggerPhase, _u("ProbeContainer::UpdateFramePointers: detected %d frames (this=%p, fMatchWithCurrentScriptContext=%d)\n"), tempFramePointers->Count(), this, fMatchWithCurrentScriptContext); while (tempFramePointers->Count()) { framePointers->Push(tempFramePointers->Pop()); } }