int32 * TextbookBoyerMooreSetup<C>::GetGoodSuffix(ArenaAllocator* allocator, const Char * pat, CharCount patLen, int skip) { // pat offset q |-> longest prefix of pat which is a proper suffix of pat[0..q] // (thanks to equivalence classes being in canonical order we only need to look at the first // character of each skip grouping in the pattern) int32* prefix = AnewArray(allocator, int32, patLen); prefix[0] = 0; int32 k = 0; for (CharCount q = 1; q < patLen; q++) { while (k > 0 && pat[k * skip] != pat[q * skip]) k = prefix[k - 1]; if (pat[k * skip] == pat[q * skip]) k++; prefix[q] = k; } // As above, but for rev(pat) int32* revPrefix = AnewArray(allocator, int32, patLen); revPrefix[0] = 0; k = 0; for (CharCount q = 1; q < patLen; q++) { while (k > 0 && pat[(patLen - k - 1) * skip] != pat[(patLen - q - 1) * skip]) k = revPrefix[k - 1]; if (pat[(patLen - k - 1) * skip] == pat[(patLen - q - 1) * skip]) k++; revPrefix[q] = k; } // pat prefix length l |-> least shift s.t. pat[0..l-1] is not mismatched int32 * goodSuffix = AnewArray(allocator, int32, patLen + 1); for (CharCount j = 0; j <= patLen; j++) goodSuffix[j] = patLen - prefix[patLen - 1]; for (CharCount l = 1; l <= patLen; l++) { CharCount j = patLen - revPrefix[l - 1]; int32 s = l - revPrefix[l - 1]; if (goodSuffix[j] > s) goodSuffix[j] = s; } // shift above one to the left for (CharCount j = 0; j < patLen; j++) goodSuffix[j] = goodSuffix[j + 1]; AdeleteArray(allocator, patLen, prefix); AdeleteArray(allocator, patLen, revPrefix); return goodSuffix; }
void WasmElementSegment::Init(const Js::WebAssemblyModule& module) { Assert(m_numElem > 0); m_elems = AnewArray(m_alloc, UINT32, m_numElem); memset(m_elems, Js::Constants::UninitializedValue, m_numElem * sizeof(UINT32)); }
const StElemInfo *ReadOnlyDynamicProfileInfo::GetStElemInfo(FunctionBody *functionBody, ProfileId stElemId) { Assert(functionBody); Assert(stElemId < functionBody->GetProfiledStElemCount()); // This data is accessed multiple times. Since the original profile data may be changing on the foreground thread, // the first time it's accessed it will be copied from the original profile data (if we're jitting in the // background). if(!stElemInfo) { if(backgroundAllocator) { // Jitting in the background StElemInfo *const info = AnewArray(backgroundAllocator, StElemInfo, functionBody->GetProfiledStElemCount()); js_memcpy_s( info, functionBody->GetProfiledStElemCount() * sizeof(info[0]), profileInfo->GetStElemInfo(), functionBody->GetProfiledStElemCount() * sizeof(info[0])); stElemInfo = info; } else { // Jitting in the foreground stElemInfo = profileInfo->GetStElemInfo(); } } return &stElemInfo[stElemId]; }
Var JavascriptSIMDObject::ToString(ScriptContext* scriptContext) const { Assert(scriptContext); Assert(typeDescriptor != TypeIds_SIMDObject); BEGIN_TEMP_ALLOCATOR(tempAllocator, scriptContext, _u("fromCodePoint")); char16* stringBuffer = AnewArray(tempAllocator, char16, SIMD_STRING_BUFFER_MAX); SIMDValue simdValue; switch (typeDescriptor) { case TypeIds_SIMDBool8x16: simdValue = JavascriptSIMDBool8x16::FromVar(value)->GetValue(); JavascriptSIMDBool8x16::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDInt8x16: simdValue = JavascriptSIMDInt8x16::FromVar(value)->GetValue(); JavascriptSIMDInt8x16::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDUint8x16: simdValue = JavascriptSIMDUint8x16::FromVar(value)->GetValue(); JavascriptSIMDUint8x16::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDBool16x8: simdValue = JavascriptSIMDBool16x8::FromVar(value)->GetValue(); JavascriptSIMDBool16x8::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDInt16x8: simdValue = JavascriptSIMDInt16x8::FromVar(value)->GetValue(); JavascriptSIMDInt16x8::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDUint16x8: simdValue = JavascriptSIMDUint16x8::FromVar(value)->GetValue(); JavascriptSIMDUint16x8::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDBool32x4: simdValue = JavascriptSIMDBool32x4::FromVar(value)->GetValue(); JavascriptSIMDBool32x4::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDInt32x4: simdValue = JavascriptSIMDInt32x4::FromVar(value)->GetValue(); JavascriptSIMDInt32x4::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDUint32x4: simdValue = JavascriptSIMDUint32x4::FromVar(value)->GetValue(); JavascriptSIMDUint32x4::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; case TypeIds_SIMDFloat32x4: simdValue = JavascriptSIMDFloat32x4::FromVar(value)->GetValue(); JavascriptSIMDFloat32x4::ToStringBuffer(simdValue, stringBuffer, SIMD_STRING_BUFFER_MAX, scriptContext); break; default: Assert(UNREACHED); } JavascriptString* string = JavascriptString::NewCopySzFromArena(stringBuffer, scriptContext, scriptContext->GeneralAllocator()); END_TEMP_ALLOCATOR(tempAllocator, scriptContext); return string; }
void JSONScanner::BuildUnescapedString(bool shouldSkipLastCharacter) { AssertMsg(this->allocator != nullptr, "We must have built the allocator"); AssertMsg(this->currentRangeCharacterPairList != nullptr, "We must have built the currentRangeCharacterPairList"); AssertMsg(this->currentRangeCharacterPairList->Count() > 0, "We need to build the current string only because we have escaped characters"); // Step 1: Ensure the buffer has sufficient space int requiredSize = this->GetCurrentStringLen(); if (requiredSize > this->stringBufferLength) { if (this->stringBuffer) { AdeleteArray(this->allocator, this->stringBufferLength, this->stringBuffer); this->stringBuffer = nullptr; } this->stringBuffer = AnewArray(this->allocator, char16, requiredSize); this->stringBufferLength = requiredSize; } // Step 2: Copy the data to the buffer int totalCopied = 0; char16* begin_copy = this->stringBuffer; int lastCharacterIndex = this->currentRangeCharacterPairList->Count() - 1; for (int i = 0; i <= lastCharacterIndex; i++) { RangeCharacterPair data = this->currentRangeCharacterPairList->Item(i); int charactersToCopy = data.m_rangeLength; js_wmemcpy_s(begin_copy, charactersToCopy, this->inputText + data.m_rangeStart, charactersToCopy); begin_copy += charactersToCopy; totalCopied += charactersToCopy; if (i == lastCharacterIndex && shouldSkipLastCharacter) { continue; } *begin_copy = data.m_char; begin_copy++; totalCopied++; } if (totalCopied != requiredSize) { OUTPUT_TRACE_DEBUGONLY(Js::JSONPhase, _u("BuildUnescapedString(): allocated size = %d != copying size %d\n"), requiredSize, totalCopied); AssertMsg(totalCopied == requiredSize, "BuildUnescapedString(): The allocated size and copying size should match."); } OUTPUT_TRACE_DEBUGONLY(Js::JSONPhase, _u("BuildUnescapedString(): unescaped string as '%.*s'\n"), GetCurrentStringLen(), this->stringBuffer); }
void RuntimeCharTrie::CloneFrom(ArenaAllocator* allocator, const CharTrie& other) { count = other.count; if (count > 0) { children = AnewArray(allocator, RuntimeCharTrieEntry, count); for (int i = 0; i < count; i++) { children[i].c = other.children[i].c; children[i].node.CloneFrom(allocator, other.children[i].node); } } else children = 0; }
char16* NarrowStringToWide(Context* ctx, const char* src, const size_t* srcSize = nullptr, charcount_t* dstSize = nullptr) { auto allocator = [&ctx](size_t size) {return (char16*)AnewArray(ctx->allocator, char16, size); }; char16* dst = nullptr; charcount_t size; HRESULT hr = utf8::NarrowStringToWide(allocator, src, srcSize ? *srcSize : strlen(src), &dst, &size); if (hr != S_OK) { JavascriptError::ThrowOutOfMemoryError(ctx->scriptContext); } if (dstSize) { *dstSize = size; } return dst; }
void MemoryLogger::Write(const char16* msg) { #ifdef EXCEPTION_CHECK // In most cases this will be called at runtime when we have exception check enabled. AutoNestedHandledExceptionType autoNestedHandledExceptionType(ExceptionType_DisableCheck); #endif AutoCriticalSection autocs(&m_criticalSection); // TODO: with circular buffer now we can use much granular lock. // Create a copy of the message. size_t len = wcslen(msg); char16* buf = AnewArray(m_alloc, char16, len + 1); js_wmemcpy_s(buf, len + 1, msg, len + 1); // Copy with the NULL-terminator. // m_current is the next position to write to. if (m_log[m_current]) { Adelete(m_alloc, m_log[m_current]); } m_log[m_current] = buf; m_current = (m_current + 1) % m_capacity; }
_u("Reset"), _u("Count")); Output::Print(_u("--------------------------------------------------------------------------------------------------------\n")); } int MemoryProfiler::CreateArenaUsageSummary(ArenaAllocator * alloc, bool liveOnly, _Outptr_result_buffer_(return) LPWSTR ** name_ptr, _Outptr_result_buffer_(return) ArenaMemoryDataSummary *** summaries_ptr) { Assert(alloc); LPWSTR *& name = *name_ptr; ArenaMemoryDataSummary **& summaries = *summaries_ptr; int count = arenaDataMap.Count(); name = AnewArray(alloc, LPWSTR, count); int i = 0; arenaDataMap.Map([&i, name](LPWSTR key, ArenaMemoryDataSummary*) { name[i++] = key; }); JsUtil::QuickSort<LPWSTR, DefaultComparer<LPWSTR>>::Sort(name, name + (count - 1)); summaries = AnewArray(alloc, ArenaMemoryDataSummary *, count); for (int i = 0; i < count; i++) { ArenaMemoryDataSummary * summary = arenaDataMap.Item(name[i]); ArenaMemoryData * data = summary->data; ArenaMemoryDataSummary * localSummary;
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; }
StringProfiler::HistogramIndex::HistogramIndex( ArenaAllocator* allocator, uint size ) { this->index = AnewArray(allocator, UintUintPair, size); this->count = 0; }
///---------------------------------------------------------------------------- /// /// 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(); } }
/* static */ void JITTimeProfileInfo::InitializeJITProfileData( __in ArenaAllocator * alloc, __in Js::DynamicProfileInfo * profileInfo, __in Js::FunctionBody *functionBody, __out ProfileDataIDL * data, bool isForegroundJIT) { if (profileInfo == nullptr) { return; } CompileAssert(sizeof(LdElemIDL) == sizeof(Js::LdElemInfo)); CompileAssert(sizeof(StElemIDL) == sizeof(Js::StElemInfo)); data->profiledLdElemCount = functionBody->GetProfiledLdElemCount(); data->profiledStElemCount = functionBody->GetProfiledStElemCount(); if (JITManager::GetJITManager()->IsOOPJITEnabled() || isForegroundJIT) { data->ldElemData = (LdElemIDL*)profileInfo->GetLdElemInfo(); data->stElemData = (StElemIDL*)profileInfo->GetStElemInfo(); } else { // for in-proc background JIT we need to explicitly copy LdElem and StElem info data->ldElemData = AnewArray(alloc, LdElemIDL, data->profiledLdElemCount); memcpy_s( data->ldElemData, data->profiledLdElemCount * sizeof(LdElemIDL), profileInfo->GetLdElemInfo(), functionBody->GetProfiledLdElemCount() * sizeof(Js::LdElemInfo) ); data->stElemData = AnewArray(alloc, StElemIDL, data->profiledStElemCount); memcpy_s( data->stElemData, data->profiledStElemCount * sizeof(StElemIDL), profileInfo->GetStElemInfo(), functionBody->GetProfiledStElemCount() * sizeof(Js::StElemInfo) ); } CompileAssert(sizeof(ArrayCallSiteIDL) == sizeof(Js::ArrayCallSiteInfo)); data->profiledArrayCallSiteCount = functionBody->GetProfiledArrayCallSiteCount(); data->arrayCallSiteData = (ArrayCallSiteIDL*)profileInfo->GetArrayCallSiteInfo(); data->arrayCallSiteDataAddr = (intptr_t)profileInfo->GetArrayCallSiteInfo(); CompileAssert(sizeof(FldIDL) == sizeof(Js::FldInfo)); data->inlineCacheCount = functionBody->GetProfiledFldCount(); data->fldData = (FldIDL*)profileInfo->GetFldInfo(); data->fldDataAddr = (intptr_t)profileInfo->GetFldInfo(); CompileAssert(sizeof(ThisIDL) == sizeof(Js::ThisInfo)); data->thisData = *reinterpret_cast<ThisIDL*>(&profileInfo->GetThisInfo()); CompileAssert(sizeof(CallSiteIDL) == sizeof(Js::CallSiteInfo)); data->profiledCallSiteCount = functionBody->GetProfiledCallSiteCount(); data->callSiteData = reinterpret_cast<CallSiteIDL*>(profileInfo->GetCallSiteInfo()); CompileAssert(sizeof(BVUnitIDL) == sizeof(BVUnit)); data->loopFlags = (BVFixedIDL*)profileInfo->GetLoopFlags(); CompileAssert(sizeof(ValueType) == sizeof(uint16)); data->profiledSlotCount = functionBody->GetProfiledSlotCount(); data->slotData = reinterpret_cast<uint16*>(profileInfo->GetSlotInfo()); data->profiledReturnTypeCount = functionBody->GetProfiledReturnTypeCount(); data->returnTypeData = reinterpret_cast<uint16*>(profileInfo->GetReturnTypeInfo()); data->profiledDivOrRemCount = functionBody->GetProfiledDivOrRemCount(); data->divideTypeInfo = reinterpret_cast<uint16*>(profileInfo->GetDivideTypeInfo()); data->profiledSwitchCount = functionBody->GetProfiledSwitchCount(); data->switchTypeInfo = reinterpret_cast<uint16*>(profileInfo->GetSwitchTypeInfo()); data->profiledInParamsCount = functionBody->GetProfiledInParamsCount(); data->parameterInfo = reinterpret_cast<uint16*>(profileInfo->GetParameterInfo()); data->loopCount = functionBody->GetLoopCount(); data->loopImplicitCallFlags = reinterpret_cast<byte*>(profileInfo->GetLoopImplicitCallFlags()); data->implicitCallFlags = static_cast<byte>(profileInfo->GetImplicitCallFlags()); data->flags = 0; data->flags |= profileInfo->IsAggressiveIntTypeSpecDisabled(false) ? Flags_disableAggressiveIntTypeSpec : 0; data->flags |= profileInfo->IsAggressiveIntTypeSpecDisabled(true) ? Flags_disableAggressiveIntTypeSpec_jitLoopBody : 0; data->flags |= profileInfo->IsAggressiveMulIntTypeSpecDisabled(false) ? Flags_disableAggressiveMulIntTypeSpec : 0; data->flags |= profileInfo->IsAggressiveMulIntTypeSpecDisabled(true) ? Flags_disableAggressiveMulIntTypeSpec_jitLoopBody : 0; data->flags |= profileInfo->IsDivIntTypeSpecDisabled(false) ? Flags_disableDivIntTypeSpec : 0; data->flags |= profileInfo->IsDivIntTypeSpecDisabled(true) ? Flags_disableDivIntTypeSpec_jitLoopBody : 0; data->flags |= profileInfo->IsLossyIntTypeSpecDisabled() ? Flags_disableLossyIntTypeSpec : 0; data->flags |= profileInfo->IsTrackCompoundedIntOverflowDisabled() ? Flags_disableTrackCompoundedIntOverflow : 0; data->flags |= profileInfo->IsFloatTypeSpecDisabled() ? Flags_disableFloatTypeSpec : 0; data->flags |= profileInfo->IsArrayCheckHoistDisabled(false) ? Flags_disableArrayCheckHoist : 0; data->flags |= profileInfo->IsArrayCheckHoistDisabled(true) ? Flags_disableArrayCheckHoist_jitLoopBody : 0; data->flags |= profileInfo->IsArrayMissingValueCheckHoistDisabled(false) ? Flags_disableArrayMissingValueCheckHoist : 0; data->flags |= profileInfo->IsArrayMissingValueCheckHoistDisabled(true) ? Flags_disableArrayMissingValueCheckHoist_jitLoopBody : 0; data->flags |= profileInfo->IsJsArraySegmentHoistDisabled(false) ? Flags_disableJsArraySegmentHoist : 0; data->flags |= profileInfo->IsJsArraySegmentHoistDisabled(true) ? Flags_disableJsArraySegmentHoist_jitLoopBody : 0; data->flags |= profileInfo->IsArrayLengthHoistDisabled(false) ? Flags_disableArrayLengthHoist : 0; data->flags |= profileInfo->IsArrayLengthHoistDisabled(true) ? Flags_disableArrayLengthHoist_jitLoopBody : 0; data->flags |= profileInfo->IsTypedArrayTypeSpecDisabled(false) ? Flags_disableTypedArrayTypeSpec : 0; data->flags |= profileInfo->IsTypedArrayTypeSpecDisabled(true) ? Flags_disableTypedArrayTypeSpec_jitLoopBody : 0; data->flags |= profileInfo->IsLdLenIntSpecDisabled() ? Flags_disableLdLenIntSpec : 0; data->flags |= profileInfo->IsBoundCheckHoistDisabled(false) ? Flags_disableBoundCheckHoist : 0; data->flags |= profileInfo->IsBoundCheckHoistDisabled(true) ? Flags_disableBoundCheckHoist_jitLoopBody : 0; data->flags |= profileInfo->IsLoopCountBasedBoundCheckHoistDisabled(false) ? Flags_disableLoopCountBasedBoundCheckHoist : 0; data->flags |= profileInfo->IsLoopCountBasedBoundCheckHoistDisabled(true) ? Flags_disableLoopCountBasedBoundCheckHoist_jitLoopBody : 0; data->flags |= profileInfo->IsFloorInliningDisabled() ? Flags_disableFloorInlining : 0; data->flags |= profileInfo->IsNoProfileBailoutsDisabled() ? Flags_disableNoProfileBailouts : 0; data->flags |= profileInfo->IsSwitchOptDisabled() ? Flags_disableSwitchOpt : 0; data->flags |= profileInfo->IsEquivalentObjTypeSpecDisabled() ? Flags_disableEquivalentObjTypeSpec : 0; data->flags |= profileInfo->IsObjTypeSpecDisabledInJitLoopBody() ? Flags_disableObjTypeSpec_jitLoopBody : 0; data->flags |= profileInfo->IsMemOpDisabled() ? Flags_disableMemOp : 0; data->flags |= profileInfo->IsCheckThisDisabled() ? Flags_disableCheckThis : 0; data->flags |= profileInfo->HasLdFldCallSiteInfo() ? Flags_hasLdFldCallSiteInfo : 0; data->flags |= profileInfo->IsStackArgOptDisabled() ? Flags_disableStackArgOpt : 0; data->flags |= profileInfo->IsLoopImplicitCallInfoDisabled() ? Flags_disableLoopImplicitCallInfo : 0; data->flags |= profileInfo->IsPowIntIntTypeSpecDisabled() ? Flags_disablePowIntIntTypeSpec : 0; }
Var JavascriptSIMDObject::ToLocaleString(const Var* args, uint numArgs, const char16 *typeString, const T (&laneValues)[N], CallInfo* callInfo, ScriptContext* scriptContext) const { Assert(args); Assert(N == 4 || N == 8 || N == 16); if (typeDescriptor == TypeIds_SIMDBool8x16 || typeDescriptor == TypeIds_SIMDBool16x8 || typeDescriptor == TypeIds_SIMDBool32x4) { return ToString(scriptContext); //Boolean types does not have toLocaleString. } // Creating a new arguments list for the JavascriptNumber generated from each lane.The optional SIMDToLocaleString Args are //added to this argument list. Var* newArgs = HeapNewArray(Var, numArgs); switch (numArgs) { case 1: break; case 2: newArgs[1] = args[1]; break; case 3: newArgs[1] = args[1]; newArgs[2] = args[2]; break; default: Assert(UNREACHED); } //Locale specifc seperator?? JavascriptString *seperator = JavascriptString::NewWithSz(_u(", "), scriptContext); uint idx = 0; Var laneVar = nullptr; BEGIN_TEMP_ALLOCATOR(tempAllocator, scriptContext, _u("fromCodePoint")); char16* stringBuffer = AnewArray(tempAllocator, char16, SIMD_STRING_BUFFER_MAX); JavascriptString *result = nullptr; swprintf_s(stringBuffer, 1024, typeString); result = JavascriptString::NewCopySzFromArena(stringBuffer, scriptContext, scriptContext->GeneralAllocator()); if (typeDescriptor == TypeIds_SIMDFloat32x4) { for (; idx < numLanes - 1; ++idx) { laneVar = JavascriptNumber::ToVarWithCheck(laneValues[idx], scriptContext); newArgs[0] = laneVar; JavascriptString *laneValue = JavascriptNumber::ToLocaleStringIntl(newArgs, *callInfo, scriptContext); result = JavascriptString::Concat(result, laneValue); result = JavascriptString::Concat(result, seperator); } laneVar = JavascriptNumber::ToVarWithCheck(laneValues[idx], scriptContext); newArgs[0] = laneVar; result = JavascriptString::Concat(result, JavascriptNumber::ToLocaleStringIntl(newArgs, *callInfo, scriptContext)); } else if (typeDescriptor == TypeIds_SIMDInt8x16 || typeDescriptor == TypeIds_SIMDInt16x8 || typeDescriptor == TypeIds_SIMDInt32x4) { for (; idx < numLanes - 1; ++idx) { laneVar = JavascriptNumber::ToVar(static_cast<int>(laneValues[idx]), scriptContext); newArgs[0] = laneVar; JavascriptString *laneValue = JavascriptNumber::ToLocaleStringIntl(newArgs, *callInfo, scriptContext); result = JavascriptString::Concat(result, laneValue); result = JavascriptString::Concat(result, seperator); } laneVar = JavascriptNumber::ToVar(static_cast<int>(laneValues[idx]), scriptContext); newArgs[0] = laneVar; result = JavascriptString::Concat(result, JavascriptNumber::ToLocaleStringIntl(newArgs, *callInfo, scriptContext)); } else { Assert((typeDescriptor == TypeIds_SIMDUint8x16 || typeDescriptor == TypeIds_SIMDUint16x8 || typeDescriptor == TypeIds_SIMDUint32x4)); for (; idx < numLanes - 1; ++idx) { laneVar = JavascriptNumber::ToVar(static_cast<uint>(laneValues[idx]), scriptContext); newArgs[0] = laneVar; JavascriptString *laneValue = JavascriptNumber::ToLocaleStringIntl(newArgs, *callInfo, scriptContext); result = JavascriptString::Concat(result, laneValue); result = JavascriptString::Concat(result, seperator); } laneVar = JavascriptNumber::ToVar(static_cast<uint>(laneValues[idx]), scriptContext); newArgs[0] = laneVar; result = JavascriptString::Concat(result, JavascriptNumber::ToLocaleStringIntl(newArgs, *callInfo, scriptContext)); } HeapDeleteArray(numArgs, newArgs); END_TEMP_ALLOCATOR(tempAllocator, scriptContext); return JavascriptString::Concat(result, JavascriptString::NewWithSz(_u(")"), scriptContext)); }
Js::Var WabtInterface::EntryConvertWast2Wasm(RecyclableObject* function, CallInfo callInfo, ...) { ScriptContext* scriptContext = function->GetScriptContext(); PROBE_STACK(function->GetScriptContext(), Constants::MinStackDefault); ARGUMENTS(args, callInfo); AssertMsg(args.Info.Count > 0, "Should always have implicit 'this'"); Assert(!(callInfo.Flags & CallFlags_New)); if (args.Info.Count < 2 || !JavascriptString::Is(args[1])) { JavascriptError::ThrowTypeError(scriptContext, WASMERR_NeedBufferSource); } bool isSpecText = false; if (args.Info.Count > 2) { // optional config object if (!JavascriptOperators::IsObject(args[2])) { JavascriptError::ThrowTypeError(scriptContext, JSERR_NeedObject, _u("config")); } DynamicObject * configObject = JavascriptObject::FromVar(args[2]); Js::Var isSpecVar = JavascriptOperators::OP_GetProperty(configObject, PropertyIds::spec, scriptContext); isSpecText = JavascriptConversion::ToBool(isSpecVar, scriptContext); } ArenaAllocator arena(_u("Wast2Wasm"), scriptContext->GetThreadContext()->GetPageAllocator(), Throw::OutOfMemory); Context context; size_t wastSize; char* wastBuffer = nullptr; ENTER_PINNED_SCOPE(JavascriptString, string); string = (JavascriptString*)args[1]; const char16* str = string->GetString(); context.allocator = &arena; context.scriptContext = scriptContext; size_t origSize = string->GetLength(); auto allocator = [&arena](size_t size) {return (utf8char_t*)AnewArray(&arena, byte, size);}; utf8::WideStringToNarrow(allocator, str, origSize, &wastBuffer, &wastSize); LEAVE_PINNED_SCOPE(); // string try { ChakraWabt::SpecContext spec; ChakraWabt::ChakraContext wabtCtx; wabtCtx.user_data = &context; wabtCtx.createBuffer = CreateBuffer; wabtCtx.features.sign_extends = CONFIG_FLAG(WasmSignExtends); if (isSpecText) { wabtCtx.spec = &spec; spec.setProperty = SetProperty; spec.int32ToVar = Int32ToVar; spec.int64ToVar = Int64ToVar; spec.stringToVar = StringToVar; spec.createObject = CreateObject; spec.createArray = CreateArray; spec.push = Push; } void* result = ChakraWabt::ConvertWast2Wasm(wabtCtx, wastBuffer, (uint)wastSize, isSpecText); if (result == nullptr) { return scriptContext->GetLibrary()->GetUndefined(); } return result; } catch (ChakraWabt::Error& e) { JavascriptError::ThrowTypeErrorVar(scriptContext, WABTERR_WabtError, NarrowStringToWide(&context, e.message)); } }