From e170da8841a77f8329891495781667310d0d07ff Mon Sep 17 00:00:00 2001 From: Kunal Pathak Date: Thu, 23 Mar 2017 09:22:43 -0700 Subject: [PATCH] chakracore: Update chakracore release/2.0 Sync to https://github.com/Microsoft/ChakraCore/commit/c970d0fc72dc9cd9cf9536f65d8a24396bcef518 PR-URL: nodejs/node-chakracore#197 Reviewed-By: Hitesh Kanwathirtha --- deps/chakrashim/core/Build/compile_clang.sh | 3 + .../core/Build/scripts/post_build.ps1 | 10 +- .../core/lib/Backend/BackendApi.cpp | 5 +- .../core/lib/Backend/BackwardPass.cpp | 2 + .../core/lib/Backend/GlobOptFields.cpp | 2 - deps/chakrashim/core/lib/Backend/IR.h | 1 + .../chakrashim/core/lib/Backend/IRBuilder.cpp | 24 +- .../core/lib/Backend/IRBuilderAsmJs.cpp | 2 +- deps/chakrashim/core/lib/Backend/JITType.h | 2 +- deps/chakrashim/core/lib/Backend/Lower.cpp | 9 +- .../core/lib/Backend/LowerMDShared.cpp | 4 +- .../core/lib/Backend/LowerMDShared.h | 2 +- .../core/lib/Backend/NativeCodeData.cpp | 22 +- .../core/lib/Backend/NativeCodeGenerator.cpp | 14 +- .../core/lib/Backend/amd64/LowererMDArch.cpp | 41 +- .../core/lib/Backend/amd64/LowererMDArch.h | 2 +- .../core/lib/Backend/arm/LowerMD.cpp | 33 +- .../chakrashim/core/lib/Backend/arm/LowerMD.h | 2 +- .../core/lib/Backend/arm64/LowerMD.h | 2 +- .../core/lib/Backend/i386/LowererMDArch.cpp | 42 +- .../core/lib/Backend/i386/LowererMDArch.h | 2 +- .../core/lib/Common/Core/StackBackTrace.h | 4 +- .../Common/DataStructures/DictionaryStats.cpp | 6 +- .../Common/DataStructures/ImmutableList.cpp | 6 +- .../lib/Common/DataStructures/ImmutableList.h | 17 +- .../core/lib/Common/Memory/Allocator.h | 135 ++-- .../core/lib/Common/Memory/ArenaAllocator.h | 14 +- .../core/lib/Common/Memory/HeapAllocator.h | 18 +- .../Common/Memory/HeapAllocatorOperators.cpp | 11 + deps/chakrashim/core/lib/Jsrt/JsrtHelper.cpp | 7 +- deps/chakrashim/core/lib/Jsrt/JsrtRuntime.cpp | 10 +- deps/chakrashim/core/lib/Parser/Hash.cpp | 2 +- deps/chakrashim/core/lib/Parser/Hash.h | 9 +- deps/chakrashim/core/lib/Parser/Parse.cpp | 33 + deps/chakrashim/core/lib/Parser/Scan.cpp | 4 +- deps/chakrashim/core/lib/Parser/Scan.h | 7 +- .../core/lib/Runtime/Base/Debug.cpp | 6 +- .../core/lib/Runtime/Base/EtwTrace.h | 15 +- .../core/lib/Runtime/Base/FunctionBody.cpp | 349 ++++++----- .../core/lib/Runtime/Base/ScriptContext.cpp | 31 +- .../Base/ThreadBoundThreadContextManager.cpp | 18 +- .../Base/ThreadBoundThreadContextManager.h | 3 +- .../core/lib/Runtime/Base/Utf8SourceInfo.cpp | 4 +- .../core/lib/Runtime/Base/Utf8SourceInfo.h | 2 +- .../Base/WindowsGlobalizationAdapter.cpp | 6 +- .../lib/Runtime/ByteCode/ByteCodeEmitter.cpp | 9 +- .../core/lib/Runtime/ByteCode/FuncInfo.cpp | 2 +- .../core/lib/Runtime/ByteCode/FuncInfo.h | 3 +- .../core/lib/Runtime/Language/AsmJs.cpp | 10 +- .../Language/AsmJsByteCodeGenerator.cpp | 2 + .../core/lib/Runtime/Language/AsmJsModule.cpp | 11 +- .../Language/InterpreterStackFrame.cpp | 11 +- .../Runtime/Language/JavascriptConversion.cpp | 3 +- .../Language/JavascriptStackWalker.cpp | 43 +- .../Runtime/Language/JavascriptStackWalker.h | 4 +- .../lib/Runtime/Language/ProfilingHelpers.cpp | 1 + .../Runtime/Language/StackTraceArguments.cpp | 5 +- .../lib/Runtime/Library/ArgumentsObject.cpp | 6 +- .../core/lib/Runtime/Library/ArrayBuffer.cpp | 6 + .../Runtime/Library/DateImplementation.cpp | 57 +- .../lib/Runtime/Library/DateImplementation.h | 77 +-- .../core/lib/Runtime/Library/GlobalObject.cpp | 13 +- .../lib/Runtime/Library/JavascriptArray.cpp | 39 +- .../lib/Runtime/Library/JavascriptDate.cpp | 55 +- .../core/lib/Runtime/Library/JavascriptDate.h | 4 +- .../Runtime/Library/JavascriptFunction.cpp | 5 +- .../lib/Runtime/Library/JavascriptLibrary.cpp | 1 - .../lib/Runtime/Library/JavascriptProxy.cpp | 9 +- .../core/pal/src/thread/pal_thread.cpp | 40 +- .../test/Array/Array_TypeConfusion_bugs.js | 27 + .../core/test/Array/array_conv_src.js | 36 ++ deps/chakrashim/core/test/Array/rlexe.xml | 5 + .../core/test/AsmJs/nested.baseline | 2 + deps/chakrashim/core/test/AsmJs/nested.js | 12 + .../core/test/AsmJs/qmarkbug.baseline | 4 +- deps/chakrashim/core/test/AsmJs/qmarkbug.js | 62 +- deps/chakrashim/core/test/AsmJs/rlexe.xml | 7 + .../core/test/AsmJs/shadowingBug.baseline | 8 +- .../core/test/AsmJs/shadowingBug.js | 6 +- deps/chakrashim/core/test/Date/marshalbug.js | 19 + deps/chakrashim/core/test/Date/rlexe.xml | 9 + .../core/test/es6/default-splitscope.js | 17 + .../core/test/es6/lambda-params-shadow.js | 9 +- deps/chakrashim/core/test/es6/proxybugs.js | 592 +++++++++--------- deps/chakrashim/core/test/runcitests.cmd | 12 +- .../RecyclerChecker/FunctionBody.analyze.txt | 460 -------------- .../RecyclerChecker/FunctionBody.check.txt | 583 ----------------- .../tools/RecyclerChecker/RecyclerChecker.cpp | 30 +- .../core/tools/RecyclerChecker/blah.txt | 25 - 89 files changed, 1356 insertions(+), 1928 deletions(-) create mode 100644 deps/chakrashim/core/test/Array/array_conv_src.js create mode 100644 deps/chakrashim/core/test/AsmJs/nested.baseline create mode 100644 deps/chakrashim/core/test/AsmJs/nested.js create mode 100644 deps/chakrashim/core/test/Date/marshalbug.js delete mode 100644 deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.analyze.txt delete mode 100644 deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.check.txt delete mode 100644 deps/chakrashim/core/tools/RecyclerChecker/blah.txt diff --git a/deps/chakrashim/core/Build/compile_clang.sh b/deps/chakrashim/core/Build/compile_clang.sh index 0fc3ab5ece4..c10f2cd159a 100644 --- a/deps/chakrashim/core/Build/compile_clang.sh +++ b/deps/chakrashim/core/Build/compile_clang.sh @@ -118,5 +118,8 @@ make -j4 install if [ $? == 0 ]; then echo -e "Done!\n./build.sh args are given below;\n\n" + # Create a local bfd-plugins and copy LLVMgold.so into there. + mkdir -p "${ROOT}/build/lib/bfd-plugins/" + cp "${ROOT}/build/lib/LLVMgold.so" "${ROOT}/build/lib/bfd-plugins/" echo "--cxx=${ROOT}/build/bin/clang++ --cc=${ROOT}/build/bin/clang" fi diff --git a/deps/chakrashim/core/Build/scripts/post_build.ps1 b/deps/chakrashim/core/Build/scripts/post_build.ps1 index 8aee200a5c1..e99d95bb690 100644 --- a/deps/chakrashim/core/Build/scripts/post_build.ps1 +++ b/deps/chakrashim/core/Build/scripts/post_build.ps1 @@ -30,6 +30,8 @@ param ( [string]$srcsrvcmdpath, [string]$bvtcmdpath = "", + [string]$testparams = "", + [string]$repo = "core", [string]$logFile = "", @@ -71,8 +73,8 @@ if ($arch -eq "*") { $buildName = ConstructBuildName -arch $arch -flavor $flavor -subtype $subtype - if (($logFile -eq "") -and (Test-Path Env:\TF_BUILD_BINARIESDIRECTORY)) { - $logFile = "${Env:TF_BUILD_BINARIESDIRECTORY}\logs\post_build.${buildName}.log" + if (($logFile -eq "") -and (Test-Path $buildRoot)) { + $logFile = "${buildRoot}\logs\post_build.${buildName}.log" if (Test-Path -Path $logFile) { Remove-Item $logFile -Force } @@ -114,7 +116,9 @@ if ($arch -eq "*") { # run tests if (-not $skipTests) { - ExecuteCommand("$bvtcmdpath -$arch$flavor") + # marshall environment var for cmd script + $Env:TF_BUILD_BINARIESDIRECTORY = $buildRoot + ExecuteCommand("$bvtcmdpath -$arch$flavor $testparams") } } diff --git a/deps/chakrashim/core/lib/Backend/BackendApi.cpp b/deps/chakrashim/core/lib/Backend/BackendApi.cpp index 9a53fd957f2..5d13266c145 100644 --- a/deps/chakrashim/core/lib/Backend/BackendApi.cpp +++ b/deps/chakrashim/core/lib/Backend/BackendApi.cpp @@ -197,5 +197,8 @@ SetProfilerFromNativeCodeGen(NativeCodeGenerator * toNativeCodeGen, NativeCodeGe void DeleteNativeCodeData(NativeCodeData * data) { - delete data; + if (data) + { + HeapDelete(data); + } } diff --git a/deps/chakrashim/core/lib/Backend/BackwardPass.cpp b/deps/chakrashim/core/lib/Backend/BackwardPass.cpp index aaa53d5e29e..72124351a71 100644 --- a/deps/chakrashim/core/lib/Backend/BackwardPass.cpp +++ b/deps/chakrashim/core/lib/Backend/BackwardPass.cpp @@ -2535,6 +2535,8 @@ BackwardPass::ProcessBlock(BasicBlock * block) } #endif + AssertOrFailFastMsg(!instr->IsLowered(), "Lowered instruction detected in pre-lower context!"); + this->currentInstr = instr; this->currentRegion = this->currentBlock->GetFirstInstr()->AsLabelInstr()->GetRegion(); diff --git a/deps/chakrashim/core/lib/Backend/GlobOptFields.cpp b/deps/chakrashim/core/lib/Backend/GlobOptFields.cpp index d57f26408ad..8b34a299256 100644 --- a/deps/chakrashim/core/lib/Backend/GlobOptFields.cpp +++ b/deps/chakrashim/core/lib/Backend/GlobOptFields.cpp @@ -3194,8 +3194,6 @@ GlobOpt::UpdateObjPtrValueType(IR::Opnd * opnd, IR::Instr * instr) } break; case Js::TypeIds_Array: - case Js::TypeIds_NativeFloatArray: - case Js::TypeIds_NativeIntArray: // Because array can change type id, we can only make it definite if we are doing array check hoist // so that implicit call will be installed between the array checks. if (!DoArrayCheckHoist() || diff --git a/deps/chakrashim/core/lib/Backend/IR.h b/deps/chakrashim/core/lib/Backend/IR.h index 31afb8894f8..aa135d8fad7 100644 --- a/deps/chakrashim/core/lib/Backend/IR.h +++ b/deps/chakrashim/core/lib/Backend/IR.h @@ -486,6 +486,7 @@ class Instr bool dstIsAlwaysConvertedToNumber : 1; bool isCallInstrProtectedByNoProfileBailout : 1; bool hasSideEffects : 1; // The instruction cannot be dead stored + bool isNonFastPathFrameDisplay : 1; protected: bool isCloned:1; bool hasBailOutInfo:1; diff --git a/deps/chakrashim/core/lib/Backend/IRBuilder.cpp b/deps/chakrashim/core/lib/Backend/IRBuilder.cpp index 817965c6033..2e898452346 100644 --- a/deps/chakrashim/core/lib/Backend/IRBuilder.cpp +++ b/deps/chakrashim/core/lib/Backend/IRBuilder.cpp @@ -704,7 +704,7 @@ IRBuilder::Build() } } #endif - AssertMsg(Js::OpCodeUtil::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()"); + AssertOrFailFastMsg(Js::OpCodeUtil::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()"); uint layoutAndSize = layoutSize * Js::OpLayoutType::Count + Js::OpCodeUtil::GetOpCodeLayout(newOpcode); switch(layoutAndSize) @@ -6824,22 +6824,16 @@ IRBuilder::BuildEmpty(Js::OpCode newOpcode, uint32 offset) Js::Constants::NoByteCodeOffset); } - IR::RegOpnd* tempRegOpnd = IR::RegOpnd::New(StackSym::New(this->m_func), TyVar, this->m_func); + IR::Instr* lfd = IR::Instr::New( + Js::OpCode::LdFrameDisplay, + this->BuildDstOpnd(this->m_func->GetJITFunctionBody()->GetLocalFrameDisplayReg()), + this->BuildDstOpnd(this->m_func->GetJITFunctionBody()->GetLocalClosureReg()), + this->BuildDstOpnd(this->m_func->GetJITFunctionBody()->GetLocalFrameDisplayReg()), + this->m_func); this->AddInstr( - IR::Instr::New( - Js::OpCode::LdFrameDisplay, - tempRegOpnd, - this->BuildSrcOpnd(this->m_func->GetJITFunctionBody()->GetLocalClosureReg()), - this->BuildSrcOpnd(this->m_func->GetJITFunctionBody()->GetLocalFrameDisplayReg()), - this->m_func), - Js::Constants::NoByteCodeOffset); - this->AddInstr( - IR::Instr::New( - Js::OpCode::MOV, - this->BuildDstOpnd(this->m_func->GetJITFunctionBody()->GetLocalFrameDisplayReg()), - tempRegOpnd, - this->m_func), + lfd, Js::Constants::NoByteCodeOffset); + lfd->isNonFastPathFrameDisplay = true; } break; diff --git a/deps/chakrashim/core/lib/Backend/IRBuilderAsmJs.cpp b/deps/chakrashim/core/lib/Backend/IRBuilderAsmJs.cpp index 01bf932658e..487655e278b 100644 --- a/deps/chakrashim/core/lib/Backend/IRBuilderAsmJs.cpp +++ b/deps/chakrashim/core/lib/Backend/IRBuilderAsmJs.cpp @@ -144,7 +144,7 @@ IRBuilderAsmJs::Build() { Assert(newOpcode != Js::OpCodeAsmJs::EndOfBlock); - AssertMsg(Js::OpCodeUtilAsmJs::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()"); + AssertOrFailFastMsg(Js::OpCodeUtilAsmJs::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()"); uint layoutAndSize = layoutSize * Js::OpLayoutTypeAsmJs::Count + Js::OpCodeUtilAsmJs::GetOpCodeLayout(newOpcode); switch (layoutAndSize) diff --git a/deps/chakrashim/core/lib/Backend/JITType.h b/deps/chakrashim/core/lib/Backend/JITType.h index 332c8220d98..bca3844b2a0 100644 --- a/deps/chakrashim/core/lib/Backend/JITType.h +++ b/deps/chakrashim/core/lib/Backend/JITType.h @@ -39,7 +39,7 @@ class JITTypeHolderBase JITTypeHolderBase(JITType * t); template - JITTypeHolderBase(JITTypeHolderBase other) : t(PointerValue(other.t)) {} + JITTypeHolderBase(const JITTypeHolderBase& other) : t(PointerValue(other.t)) {} template void operator =(const JITTypeHolderBase &other) { t = other.t; } diff --git a/deps/chakrashim/core/lib/Backend/Lower.cpp b/deps/chakrashim/core/lib/Backend/Lower.cpp index fc1497d237e..ce056004e98 100644 --- a/deps/chakrashim/core/lib/Backend/Lower.cpp +++ b/deps/chakrashim/core/lib/Backend/Lower.cpp @@ -12884,13 +12884,13 @@ void Lowerer::LowerBoundCheck(IR::Instr *const instr) // jo $bailOut // $bailOut: (insertBeforeInstr) Assert(!offsetOpnd || offsetOpnd->GetValue() == offset); - IR::RegOpnd *const addResultOpnd = IR::RegOpnd::New(TyMachReg, func); + IR::RegOpnd *const addResultOpnd = IR::RegOpnd::New(TyInt32, func); autoReuseAddResultOpnd.Initialize(addResultOpnd, func); InsertAdd( true, addResultOpnd, rightOpnd, - offsetOpnd ? offsetOpnd->UseWithNewType(TyMachReg, func) : IR::IntConstOpnd::New(offset, TyMachReg, func, true), + offsetOpnd ? offsetOpnd->UseWithNewType(TyInt32, func) : IR::IntConstOpnd::New(offset, TyInt32, func, true), insertBeforeInstr); InsertBranch(LowererMD::MDOverflowBranchOpcode, bailOutLabel, insertBeforeInstr); @@ -17114,7 +17114,8 @@ Lowerer::GenerateFastStElemI(IR::Instr *& stElem, bool *instrIsInHelperBlockRef) // Convert reg to int32 // Note: ToUint32 is implemented as (uint32)ToInt32() - m_lowererMD.EmitLoadInt32(instr, true /*conversionFromObjectAllowed*/); + bool bailOutOnHelperCall = (stElem->HasBailOutInfo() && (stElem->GetBailOutKind() & IR::BailOutOnArrayAccessHelperCall)); + m_lowererMD.EmitLoadInt32(instr, true /*conversionFromObjectAllowed*/, bailOutOnHelperCall, labelHelper); // MOV indirOpnd, reg InsertMove(indirOpnd, reg, stElem); @@ -23522,7 +23523,7 @@ void Lowerer::LowerLdFrameDisplay(IR::Instr *instr, bool doStackFrameDisplay) // If the dst opnd is a byte code temp, that indicates we're prepending a block scope or some such and // shouldn't attempt to do this. if (envDepth == (uint16)-1 || - (!doStackFrameDisplay && instr->GetDst()->AsRegOpnd()->m_sym->IsTempReg(instr->m_func)) || + (!doStackFrameDisplay && (instr->isNonFastPathFrameDisplay || instr->GetDst()->AsRegOpnd()->m_sym->IsTempReg(instr->m_func))) || PHASE_OFF(Js::FrameDisplayFastPathPhase, func)) { if (isStrict) diff --git a/deps/chakrashim/core/lib/Backend/LowerMDShared.cpp b/deps/chakrashim/core/lib/Backend/LowerMDShared.cpp index 1e43a2914db..1f8d2a1868e 100644 --- a/deps/chakrashim/core/lib/Backend/LowerMDShared.cpp +++ b/deps/chakrashim/core/lib/Backend/LowerMDShared.cpp @@ -7999,9 +7999,9 @@ LowererMD::EmitLoadVar(IR::Instr *instrLoad, bool isFromUint32, bool isHelper) } bool -LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed) +LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut) { - return lowererMDArch.EmitLoadInt32(instrLoad, conversionFromObjectAllowed); + return lowererMDArch.EmitLoadInt32(instrLoad, conversionFromObjectAllowed, bailOutOnHelper, labelBailOut); } void diff --git a/deps/chakrashim/core/lib/Backend/LowerMDShared.h b/deps/chakrashim/core/lib/Backend/LowerMDShared.h index 0d7704f2cfb..5079e3ce3ce 100644 --- a/deps/chakrashim/core/lib/Backend/LowerMDShared.h +++ b/deps/chakrashim/core/lib/Backend/LowerMDShared.h @@ -211,7 +211,7 @@ class LowererMD static void EmitPtrInstr(IR::Instr *instr); void EmitLoadVar(IR::Instr *instr, bool isFromUint32 = false, bool isHelper = false); void EmitLoadVarNoCheck(IR::RegOpnd * dst, IR::RegOpnd * src, IR::Instr *instrLoad, bool isFromUint32, bool isHelper); - bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed); + bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr); void EmitIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); void EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); diff --git a/deps/chakrashim/core/lib/Backend/NativeCodeData.cpp b/deps/chakrashim/core/lib/Backend/NativeCodeData.cpp index 79f8bc19276..dff10a2a0e5 100644 --- a/deps/chakrashim/core/lib/Backend/NativeCodeData.cpp +++ b/deps/chakrashim/core/lib/Backend/NativeCodeData.cpp @@ -4,7 +4,7 @@ //------------------------------------------------------------------------------------------------------- #include "Backend.h" -NativeCodeData::NativeCodeData(DataChunk * chunkList) +NativeCodeData::NativeCodeData(DataChunk * chunkList) : chunkList(chunkList) { #ifdef PERF_COUNTERS @@ -169,7 +169,7 @@ NativeCodeData::VerifyExistFixupEntry(void* targetAddr, void* addrToFixup, void* { if (entry->addrOffset == offset) { - // The following assertions can be false positive in case a data field happen to + // The following assertions can be false positive in case a data field happen to // have value fall into NativeCodeData memory range AssertMsg(entry->targetTotalOffset == targetChunk->offset, "Missing fixup"); return; @@ -188,12 +188,14 @@ NativeCodeData::DeleteChunkList(DataChunkT * chunkList) { DataChunkT * current = next; next = next->next; - delete current; + + // TODO: Should be HeapDeletePlus, but we don't know plusSize + HeapDelete(current, AllocatorDeleteFlags::UnknownSize); } } -NativeCodeData::Allocator::Allocator() - : chunkList(nullptr), +NativeCodeData::Allocator::Allocator() + : chunkList(nullptr), lastChunkList(nullptr), isOOPJIT(JITManager::GetJITManager()->IsJITServer()) { @@ -226,7 +228,7 @@ char * NativeCodeData::Allocator::Alloc(DECLSPEC_GUARD_OVERFLOW size_t requestSize) { Assert(!finalized); - char * data = nullptr; + char * data = nullptr; requestSize = Math::Align(requestSize, sizeof(void*)); if (isOOPJIT) @@ -237,9 +239,9 @@ NativeCodeData::Allocator::Alloc(DECLSPEC_GUARD_OVERFLOW size_t requestSize) // positive while verifying missing fixup entries // Allocation without zeroing out, and with bool field in the structure // will increase the chance of false positive because of reusing memory - // without zeroing, and the bool field is set to false, makes the garbage - // memory not changed, and the garbage memory might be just pointing to the - // same range of NativeCodeData memory, the checking tool will report false + // without zeroing, and the bool field is set to false, makes the garbage + // memory not changed, and the garbage memory might be just pointing to the + // same range of NativeCodeData memory, the checking tool will report false // poisitive, see NativeCodeData::VerifyExistFixupEntry for more DataChunk * newChunk = HeapNewStructPlusZ(requestSize, DataChunk); #else @@ -301,7 +303,7 @@ NativeCodeData::Allocator::AllocZero(DECLSPEC_GUARD_OVERFLOW size_t requestSize) // Allocated with HeapNewStructPlusZ for chk build memset(data, 0, requestSize); #else - if (!isOOPJIT) + if (!isOOPJIT) { memset(data, 0, requestSize); } diff --git a/deps/chakrashim/core/lib/Backend/NativeCodeGenerator.cpp b/deps/chakrashim/core/lib/Backend/NativeCodeGenerator.cpp index 4fc7570b21e..d92dffa0ef5 100644 --- a/deps/chakrashim/core/lib/Backend/NativeCodeGenerator.cpp +++ b/deps/chakrashim/core/lib/Backend/NativeCodeGenerator.cpp @@ -953,13 +953,13 @@ NativeCodeGenerator::CodeGen(PageAllocator * pageAllocator, CodeGenWorkItem* wor pNumberAllocator, #endif codeGenProfiler, !foreground); - + if (!this->scriptContext->GetThreadContext()->GetPreReservedVirtualAllocator()->IsInRange((void*)jitWriteData.codeAddress)) { this->scriptContext->GetJitFuncRangeCache()->AddFuncRange((void*)jitWriteData.codeAddress, jitWriteData.codeSize); } } - + if (JITManager::GetJITManager()->IsOOPJITEnabled() && PHASE_VERBOSE_TRACE(Js::BackEndPhase, workItem->GetFunctionBody())) { LARGE_INTEGER freq; @@ -1198,7 +1198,7 @@ void NativeCodeGenerator::LogCodeGenStart(CodeGenWorkItem * workItem, LARGE_INTE size_t sizeInChars = workItem->GetDisplayName(displayName, 256); if (sizeInChars > 256) { - displayName = new WCHAR[sizeInChars]; + displayName = HeapNewArray(WCHAR, sizeInChars); workItem->GetDisplayName(displayName, 256); } JS_ETW(EventWriteJSCRIPT_FUNCTION_JIT_START( @@ -1213,7 +1213,7 @@ void NativeCodeGenerator::LogCodeGenStart(CodeGenWorkItem * workItem, LARGE_INTE if (displayName != displayNameBuffer) { - delete[] displayName; + HeapDeleteArray(sizeInChars, displayName); } } } @@ -1315,7 +1315,7 @@ void NativeCodeGenerator::LogCodeGenDone(CodeGenWorkItem * workItem, LARGE_INTEG size_t sizeInChars = workItem->GetDisplayName(displayName, 256); if (sizeInChars > 256) { - displayName = new WCHAR[sizeInChars]; + displayName = HeapNewArray(WCHAR, sizeInChars); workItem->GetDisplayName(displayName, 256); } void* entryPoint; @@ -1331,7 +1331,7 @@ void NativeCodeGenerator::LogCodeGenDone(CodeGenWorkItem * workItem, LARGE_INTEG if (displayName != displayNameBuffer) { - delete[] displayName; + HeapDeleteArray(sizeInChars, displayName); } } } @@ -3194,7 +3194,7 @@ NativeCodeGenerator::QueueFreeNativeCodeGenAllocation(void* address) //DeRegister Entry Point for CFG ThreadContext::GetContextForCurrentThread()->SetValidCallTargetForCFG(address, false); } - + if ((!JITManager::GetJITManager()->IsOOPJITEnabled() && !this->scriptContext->GetThreadContext()->GetPreReservedVirtualAllocator()->IsInRange((void*)address)) || (JITManager::GetJITManager()->IsOOPJITEnabled() && !PreReservedVirtualAllocWrapper::IsInRange((void*)this->scriptContext->GetThreadContext()->GetPreReservedRegionAddr(), (void*)address))) { diff --git a/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.cpp b/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.cpp index 7a8df7cc6c6..5945cf394d8 100644 --- a/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.cpp +++ b/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.cpp @@ -1183,7 +1183,9 @@ LowererMDArch::LowerAsmJsLdElemHelper(IR::Instr * instr, bool isSimdLoad /*= fal // MOV tmp, cmpOnd Lowerer::InsertMove(tmp, cmpOpnd, helperLabel); // ADD tmp, dataWidth - Lowerer::InsertAdd(false, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + Lowerer::InsertAdd(true, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + // JB helper + Lowerer::InsertBranch(Js::OpCode::JB, helperLabel, helperLabel); // CMP tmp, size // JG $helper lowererMD->m_lowerer->InsertCompareBranch(tmp, instr->UnlinkSrc2(), Js::OpCode::BrGt_A, true, helperLabel, helperLabel); @@ -1259,7 +1261,9 @@ LowererMDArch::LowerAsmJsStElemHelper(IR::Instr * instr, bool isSimdStore /*= fa // MOV tmp, cmpOnd Lowerer::InsertMove(tmp, cmpOpnd, helperLabel); // ADD tmp, dataWidth - Lowerer::InsertAdd(false, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + Lowerer::InsertAdd(true, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + // JB helper + Lowerer::InsertBranch(Js::OpCode::JB, helperLabel, helperLabel); // CMP tmp, size // JG $helper lowererMD->m_lowerer->InsertCompareBranch(tmp, instr->UnlinkSrc2(), Js::OpCode::BrGt_A, true, helperLabel, helperLabel); @@ -2611,7 +2615,7 @@ LowererMDArch::EmitUIntToFloat(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrIns } bool -LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed) +LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut) { // // r1 = MOV src1 @@ -2664,8 +2668,29 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo (src1ValueType.IsLikelyFloat() || src1ValueType.IsLikelyUntaggedInt()) && !(instrLoad->HasBailOutInfo() && (instrLoad->GetBailOutKind() == IR::BailOutIntOnly || instrLoad->GetBailOutKind() == IR::BailOutExpectingInteger)); - if (!isNotInt) + if (isNotInt) { + // Known to be non-integer. If we are required to bail out on helper call, just re-jit. + if (!doFloatToIntFastPath && bailOutOnHelper) + { + if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func)) + { + // Aggressive int type specialization is already off for some reason. Prevent trying to rejit again + // because it won't help and the same thing will happen again. Just abort jitting this function. + if(PHASE_TRACE(Js::BailOutPhase, this->m_func)) + { + Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n")); + Output::Flush(); + } + throw Js::OperationAbortedException(); + } + + throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled); + } + } + else + { + // It could be an integer in this case. if (!isInt) { if(doFloatToIntFastPath) @@ -2753,7 +2778,13 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo return true; } - if (conversionFromObjectAllowed) + if (bailOutOnHelper) + { + Assert(labelBailOut); + lowererMD->m_lowerer->InsertBranch(Js::OpCode::Br, labelBailOut, instrLoad); + instrLoad->Remove(); + } + else if (conversionFromObjectAllowed) { lowererMD->m_lowerer->LowerUnaryHelperMem(instrLoad, IR::HelperConv_ToInt32); } diff --git a/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.h b/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.h index 734c54979e1..e7db75a69e4 100644 --- a/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.h +++ b/deps/chakrashim/core/lib/Backend/amd64/LowererMDArch.h @@ -97,7 +97,7 @@ class LowererMDArch void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); void EmitLongToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); - bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed); + bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOnHelperCall, IR::LabelInstr * labelBailOut); IR::Instr * LoadCheckedFloat(IR::RegOpnd *opndOrig, IR::RegOpnd *opndFloat, IR::LabelInstr *labelInline, IR::LabelInstr *labelHelper, IR::Instr *instrInsert, const bool checkForNullInLoopBody = false); diff --git a/deps/chakrashim/core/lib/Backend/arm/LowerMD.cpp b/deps/chakrashim/core/lib/Backend/arm/LowerMD.cpp index cf2e1738884..13c36057098 100644 --- a/deps/chakrashim/core/lib/Backend/arm/LowerMD.cpp +++ b/deps/chakrashim/core/lib/Backend/arm/LowerMD.cpp @@ -7342,7 +7342,7 @@ LowererMD::EmitLoadVarNoCheck(IR::RegOpnd * dst, IR::RegOpnd * src, IR::Instr *i } bool -LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed) +LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut) { // isInt: // dst = ASR r1, AtomTag @@ -7386,8 +7386,29 @@ LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed) (src1ValueType.IsLikelyFloat() || src1ValueType.IsLikelyUntaggedInt()) && !(instrLoad->HasBailOutInfo() && (instrLoad->GetBailOutKind() == IR::BailOutIntOnly || instrLoad->GetBailOutKind() == IR::BailOutExpectingInteger)); - if (!isNotInt) + if (isNotInt) { + // Known to be non-integer. If we are required to bail out on helper call, just re-jit. + if (!doFloatToIntFastPath && bailOutOnHelper) + { + if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func)) + { + // Aggressive int type specialization is already off for some reason. Prevent trying to rejit again + // because it won't help and the same thing will happen again. Just abort jitting this function. + if(PHASE_TRACE(Js::BailOutPhase, this->m_func)) + { + Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n")); + Output::Flush(); + } + throw Js::OperationAbortedException(); + } + + throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled); + } + } + else + { + // Could be an integer in this case. if (!isInt) { if(doFloatToIntFastPath) @@ -7444,7 +7465,13 @@ LowererMD::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed) return true; } - if (conversionFromObjectAllowed) + if (bailOutOnHelper) + { + Assert(labelBailOut); + this->m_lowerer->InsertBranch(Js::OpCode::Br, labelBailOut, instrLoad); + instrLoad->Remove(); + } + else if (conversionFromObjectAllowed) { this->m_lowerer->LowerUnaryHelperMem(instrLoad, IR::HelperConv_ToInt32); } diff --git a/deps/chakrashim/core/lib/Backend/arm/LowerMD.h b/deps/chakrashim/core/lib/Backend/arm/LowerMD.h index 215bc0eff65..e31facabcbe 100644 --- a/deps/chakrashim/core/lib/Backend/arm/LowerMD.h +++ b/deps/chakrashim/core/lib/Backend/arm/LowerMD.h @@ -144,7 +144,7 @@ class LowererMD static void EmitInt4Instr(IR::Instr *instr); static void EmitPtrInstr(IR::Instr *instr); void EmitLoadVar(IR::Instr *instr, bool isFromUint32 = false, bool isHelper = false); - bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed); + bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr); IR::Instr * LowerInt64Assign(IR::Instr * instr) { Assert(UNREACHED); return nullptr; } static void LowerInt4NegWithBailOut(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel); diff --git a/deps/chakrashim/core/lib/Backend/arm64/LowerMD.h b/deps/chakrashim/core/lib/Backend/arm64/LowerMD.h index 45eb2813f25..59b4f120836 100644 --- a/deps/chakrashim/core/lib/Backend/arm64/LowerMD.h +++ b/deps/chakrashim/core/lib/Backend/arm64/LowerMD.h @@ -140,7 +140,7 @@ class LowererMD static void EmitInt4Instr(IR::Instr *instr) { __debugbreak(); } static void EmitPtrInstr(IR::Instr *instr) { __debugbreak(); } void EmitLoadVar(IR::Instr *instr, bool isFromUint32 = false, bool isHelper = false) { __debugbreak(); } - bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed) { __debugbreak(); return 0; } + bool EmitLoadInt32(IR::Instr *instr, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr) { __debugbreak(); return 0; } IR::Instr * LowerInt64Assign(IR::Instr * instr) { __debugbreak(); return nullptr; } static void LowerInt4NegWithBailOut(IR::Instr *const instr, const IR::BailOutKind bailOutKind, IR::LabelInstr *const bailOutLabel, IR::LabelInstr *const skipBailOutLabel) { __debugbreak(); } diff --git a/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.cpp b/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.cpp index fd39426b95b..b2a12c3bd67 100644 --- a/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.cpp +++ b/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.cpp @@ -1027,7 +1027,9 @@ LowererMDArch::LowerAsmJsLdElemHelper(IR::Instr * instr, bool isSimdLoad /*= fal // MOV tmp, cmpOnd Lowerer::InsertMove(tmp, cmpOpnd, helperLabel); // ADD tmp, dataWidth - Lowerer::InsertAdd(false, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + Lowerer::InsertAdd(true, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + // JB helper + Lowerer::InsertBranch(Js::OpCode::JB, helperLabel, helperLabel); // CMP tmp, size // JG $helper lowererMD->m_lowerer->InsertCompareBranch(tmp, instr->UnlinkSrc2(), Js::OpCode::BrGt_A, true, helperLabel, helperLabel); @@ -1087,7 +1089,9 @@ LowererMDArch::LowerAsmJsStElemHelper(IR::Instr * instr, bool isSimdStore /*= fa // MOV tmp, cmpOnd Lowerer::InsertMove(tmp, cmpOpnd, helperLabel); // ADD tmp, dataWidth - Lowerer::InsertAdd(false, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + Lowerer::InsertAdd(true, tmp, tmp, IR::IntConstOpnd::New((uint32)dataWidth, tmp->GetType(), m_func, true), helperLabel); + // JB helper + Lowerer::InsertBranch(Js::OpCode::JB, helperLabel, helperLabel); // CMP tmp, size // JG $helper lowererMD->m_lowerer->InsertCompareBranch(tmp, instr->UnlinkSrc2(), Js::OpCode::BrGt_A, true, helperLabel, helperLabel); @@ -2605,7 +2609,7 @@ LowererMDArch::EmitLongToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInser } bool -LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed) +LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper, IR::LabelInstr * labelBailOut) { // if(doShiftFirst) // { @@ -2663,9 +2667,29 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo instrLoad->InsertBefore(instr); } - // It could be an integer in this case - if (!isNotInt) + if (isNotInt) { + // Known to be non-integer. If we are required to bail out on helper call, just re-jit. + if (!doFloatToIntFastPath && bailOutOnHelper) + { + if(!GlobOpt::DoAggressiveIntTypeSpec(this->m_func)) + { + // Aggressive int type specialization is already off for some reason. Prevent trying to rejit again + // because it won't help and the same thing will happen again. Just abort jitting this function. + if(PHASE_TRACE(Js::BailOutPhase, this->m_func)) + { + Output::Print(_u(" Aborting JIT because AggressiveIntTypeSpec is already off\n")); + Output::Flush(); + } + throw Js::OperationAbortedException(); + } + + throw Js::RejitException(RejitReason::AggressiveIntTypeSpecDisabled); + } + } + else + { + // It could be an integer in this case if(doShiftFirst) { // r1 = SAR r1, VarTag_Shift (move last-shifted bit into CF) @@ -2781,7 +2805,13 @@ LowererMDArch::EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllo return true; } - if (conversionFromObjectAllowed) + if (bailOutOnHelper) + { + Assert(labelBailOut); + lowererMD->m_lowerer->InsertBranch(Js::OpCode::Br, labelBailOut, instrLoad); + instrLoad->Remove(); + } + else if (conversionFromObjectAllowed) { lowererMD->m_lowerer->LowerUnaryHelperMem(instrLoad, IR::HelperConv_ToInt32); } diff --git a/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.h b/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.h index 88b2754d638..aab6612a260 100644 --- a/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.h +++ b/deps/chakrashim/core/lib/Backend/i386/LowererMDArch.h @@ -85,7 +85,7 @@ class LowererMDArch void EmitIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); void EmitUIntToLong(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); void EmitLongToInt(IR::Opnd *dst, IR::Opnd *src, IR::Instr *instrInsert); - bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed); + bool EmitLoadInt32(IR::Instr *instrLoad, bool conversionFromObjectAllowed, bool bailOutOnHelper = false, IR::LabelInstr * labelBailOut = nullptr); IR::Instr * LoadCheckedFloat(IR::RegOpnd *opndOrig, IR::RegOpnd *opndFloat, IR::LabelInstr *labelInline, IR::LabelInstr *labelHelper, IR::Instr *instrInsert, const bool checkForNullInLoopBody = false); diff --git a/deps/chakrashim/core/lib/Common/Core/StackBackTrace.h b/deps/chakrashim/core/lib/Common/Core/StackBackTrace.h index 04e0f99c908..57f761d8a48 100644 --- a/deps/chakrashim/core/lib/Common/Core/StackBackTrace.h +++ b/deps/chakrashim/core/lib/Common/Core/StackBackTrace.h @@ -141,8 +141,8 @@ template struct _TraceRingBuffer { T* buf; - _TraceRingBuffer() { buf = new T[count]; } - ~_TraceRingBuffer() { delete[] buf; } + _TraceRingBuffer() { buf = HeapNewArray(T, count); } + ~_TraceRingBuffer() { HeapDeleteArray(count, buf); } }; template struct _TraceRingBuffer diff --git a/deps/chakrashim/core/lib/Common/DataStructures/DictionaryStats.cpp b/deps/chakrashim/core/lib/Common/DataStructures/DictionaryStats.cpp index 0326e52c2fe..d3aac0afa49 100644 --- a/deps/chakrashim/core/lib/Common/DataStructures/DictionaryStats.cpp +++ b/deps/chakrashim/core/lib/Common/DataStructures/DictionaryStats.cpp @@ -15,7 +15,7 @@ DictionaryStats* DictionaryStats::Create(const char* name, uint bucketCount) Js::Configuration::Global.flags.ProfileDictionary < 0) return NULL; - return ::new DictionaryStats(name, bucketCount); + return NoCheckHeapNew(DictionaryStats, name, bucketCount); } DictionaryStats* DictionaryStats::Clone() @@ -238,10 +238,10 @@ void DictionaryStats::ClearStats() { DictionaryStats *pCurrent = pNext; pNext = pNext->pNext; - delete pCurrent; + NoCheckHeapDelete(pCurrent); } current = current->pNext; - delete type; + NoCheckHeapDelete(type); } dictionaryTypes = NULL; } diff --git a/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.cpp b/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.cpp index 98f844e474b..d21eaa0ef43 100644 --- a/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.cpp +++ b/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.cpp @@ -50,16 +50,16 @@ void regex::ImmutableStringBuilder::AppendWithCopy(_In_z_ LPCWSTR str AssertMsg(str != nullptr, "str != nullptr"); size_t strLength = wcslen(str) + 1; // include null-terminated - WCHAR* buffer = new WCHAR[strLength]; + WCHAR* buffer = HeapNewNoThrowArray(WCHAR, strLength); IfNullThrowOutOfMemory(buffer); wcsncpy_s(buffer, strLength, str, strLength); // append in front of the tracked allocated strings - AllocatedStringChunk* newAllocatedString = new AllocatedStringChunk(); + AllocatedStringChunk* newAllocatedString = HeapNewNoThrow(AllocatedStringChunk); if (newAllocatedString == nullptr) { // cleanup - delete[] buffer; + HeapDeleteArray(strLength, buffer); Js::Throw::OutOfMemory(); } diff --git a/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.h b/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.h index a1f13569b84..6b53d5e8da3 100644 --- a/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.h +++ b/deps/chakrashim/core/lib/Common/DataStructures/ImmutableList.h @@ -678,7 +678,7 @@ namespace regex T ** ToReferenceArrayInHeap(size_t size) { Assert(size == Count()); - auto result = new T *[size]; + auto result = HeapNewNoThrowArray(T*, size); IfNullThrowOutOfMemory(result); auto current = this; @@ -717,7 +717,7 @@ namespace regex current = current->next; } current->next = nullptr; - delete []arr; + HeapDeleteArray(size, arr); return result; } @@ -744,7 +744,7 @@ namespace regex current->next = result; result = current; } - delete []arr; + HeapDeleteArray(size, arr); return result; } @@ -946,8 +946,11 @@ namespace regex { nextAllocatedStringChunk = allocatedStringChunk->next; - delete[] allocatedStringChunk->dataPtr; - delete allocatedStringChunk; + // TODO: Should be HeapDeleteArray, but don't know size + HeapDelete(allocatedStringChunk->dataPtr, + AllocatorDeleteFlags::UnknownSize); + + HeapDelete(allocatedStringChunk); allocatedStringChunk = nextAllocatedStringChunk; } @@ -956,7 +959,7 @@ namespace regex { auto current = head; head = head->next; - delete current; + HeapDelete(current); } } @@ -987,7 +990,7 @@ namespace regex // Generate new chunk if (currentIndex == chunkSize) { - StringChunk *newChunk = new StringChunk(); + StringChunk *newChunk = HeapNewNoThrow(StringChunk); IfNullThrowOutOfMemory(newChunk); if (tail == nullptr) diff --git a/deps/chakrashim/core/lib/Common/Memory/Allocator.h b/deps/chakrashim/core/lib/Common/Memory/Allocator.h index edd7db996c4..93701abdcd2 100644 --- a/deps/chakrashim/core/lib/Common/Memory/Allocator.h +++ b/deps/chakrashim/core/lib/Common/Memory/Allocator.h @@ -146,18 +146,29 @@ inline T* PostAllocationCallback(const type_info& objType, T *obj) #define AllocatorNewNoThrowNoRecoveryArrayZ(AllocatorType, alloc, T, count) AllocatorNewNoThrowNoRecoveryArrayBase(AllocatorType, alloc, AllocZero, T, count) -#define AllocatorDelete(AllocatorType, alloc, obj) DeleteObject(alloc, obj) -#define AllocatorDeleteInline(AllocatorType, alloc, obj) DeleteObjectInline(alloc, obj) -#define AllocatorDeleteLeaf(TAllocator, alloc, obj) DeleteObject::AllocatorType>(alloc, obj) -#define AllocatorDeletePlus(AllocatorType, alloc, size, obj) DeleteObject(alloc, obj, size); -#define AllocatorDeletePlusLeaf(TAllocator, alloc, size, obj) DeleteObject::AllocatorType>(alloc, obj, size); -#define AllocatorDeletePlusPrefix(AllocatorType, alloc, size, obj) DeleteObject(alloc, obj, size, true); -#define AllocatorDeletePlusPrefixLeaf(TAllocator, alloc, size, obj) DeleteObject::AllocatorType>(alloc, obj, size, true); -#define AllocatorDeleteArray(AllocatorType, alloc, count, obj) DeleteArray(alloc, count, obj) -#define AllocatorDeleteArrayLeaf(TAllocator, alloc, count, obj) DeleteArray::AllocatorType>(alloc, count, obj) +// A few versions below supplies optional flags through ..., used by HeapDelete. +#define AllocatorDelete(AllocatorType, alloc, obj, ...) \ + DeleteObject(alloc, obj) +#define AllocatorDeleteInline(AllocatorType, alloc, obj) \ + DeleteObjectInline(alloc, obj) +#define AllocatorDeleteLeaf(TAllocator, alloc, obj) \ + DeleteObject::AllocatorType>(alloc, obj) +#define AllocatorDeletePlus(AllocatorType, alloc, size, obj, ...) \ + DeleteObject(alloc, obj, size); +#define AllocatorDeletePlusLeaf(TAllocator, alloc, size, obj) \ + DeleteObject::AllocatorType>(alloc, obj, size); +#define AllocatorDeletePlusPrefix(AllocatorType, alloc, size, obj, ...) \ + DeleteObject(alloc, obj, size, true); +#define AllocatorDeletePlusPrefixLeaf(TAllocator, alloc, size, obj) \ + DeleteObject::AllocatorType>(alloc, obj, size, true); +#define AllocatorDeleteArray(AllocatorType, alloc, count, obj) \ + DeleteArray(alloc, count, obj) +#define AllocatorDeleteArrayLeaf(TAllocator, alloc, count, obj) \ + DeleteArray::AllocatorType>(alloc, count, obj) // Free routine where we don't care about following C++ semantics (e.g. calling the destructor) -#define AllocatorFree(alloc, freeFunc, obj, size) (alloc->*freeFunc)(obj, size) +#define AllocatorFree(alloc, freeFunc, obj, size) \ + (alloc->*freeFunc)((void*)obj, size) // default type allocator implementation template @@ -226,31 +237,43 @@ struct ForceLeafAllocator typedef TAllocator AllocatorType; }; -template +// Optional AllocatorDelete flags +enum class AllocatorDeleteFlags +{ + None, + UnknownSize, // used to bypass size check +}; +template +struct _AllocatorDelete +{ + static size_t Size() { return sizeof(T); } + static size_t Size(size_t plusSize) { return sizeof(T) + plusSize; } +}; +template +struct _AllocatorDelete +{ + static size_t Size() { return (size_t)-1; } + static size_t Size(size_t plusSize) { return (size_t)-1; } +}; + +template void DeleteObject(typename AllocatorInfo::AllocatorType * allocator, T * obj) { obj->~T(); auto freeFunc = AllocatorInfo::InstAllocatorFunc::GetFreeFunc(); // Use InstAllocatorFunc - (allocator->*freeFunc)(obj, sizeof(T)); + (allocator->*freeFunc)( + (void*)obj, _AllocatorDelete::Size()); } -template +template void DeleteObject(typename AllocatorInfo::AllocatorType * allocator, WriteBarrierPtr obj) { - obj->~T(); - - auto freeFunc = AllocatorInfo::InstAllocatorFunc::GetFreeFunc(); // Use InstAllocatorFunc - (allocator->*freeFunc)(obj, sizeof(T)); -} - -template -void DeleteObject(typename AllocatorInfo::AllocatorType * allocator, NoWriteBarrierPtr obj) -{ - obj->~T(); - - auto freeFunc = AllocatorInfo::InstAllocatorFunc::GetFreeFunc(); // Use InstAllocatorFunc - (allocator->*freeFunc)(obj, sizeof(T)); + DeleteObject(allocator, PointerValue(obj)); } template @@ -260,7 +283,9 @@ void DeleteObjectInline(TAllocator * allocator, T * obj) allocator->FreeInline(obj, sizeof(T)); } -template +template void DeleteObject(typename AllocatorInfo::AllocatorType * allocator, T * obj, size_t plusSize) { obj->~T(); @@ -270,10 +295,13 @@ void DeleteObject(typename AllocatorInfo::AllocatorType * allocat Assert(sizeof(T) + plusSize >= sizeof(T)); auto freeFunc = AllocatorInfo::InstAllocatorFunc::GetFreeFunc(); // Use InstAllocatorFunc - (allocator->*freeFunc)(obj, sizeof(T) + plusSize); + (allocator->*freeFunc)( + (void*)obj, _AllocatorDelete::Size(plusSize)); } -template +template void DeleteObject(typename AllocatorInfo::AllocatorType * allocator, T * obj, size_t plusSize, bool prefix) { Assert(prefix); @@ -287,7 +315,8 @@ void DeleteObject(typename AllocatorInfo::AllocatorType * allocat Assert(plusSize == Math::Align(plusSize, sizeof(size_t))); auto freeFunc = AllocatorInfo::InstAllocatorFunc::GetFreeFunc(); // Use InstAllocatorFunc - (allocator->*freeFunc)(((char *)obj) - plusSize, sizeof(T) + plusSize); + (allocator->*freeFunc)(((char *)obj) - plusSize, + _AllocatorDelete::Size(plusSize)); } #define ZERO_LENGTH_ARRAY (void *)sizeof(void *) @@ -311,18 +340,54 @@ inline T * AllocateArray(TAllocator * allocator, char * (TAllocator::*AllocFunc) return new (allocator, AllocFunc) T[count]; } +// Skip item destructor loop on some trivial types. The loop is likely to be +// optimized away in release build. Skipping it improves debug build. +// +struct _true_value { static const bool value = true; }; +struct _false_value { static const bool value = false; }; +template struct _has_trivial_destructor : _false_value {}; +template struct _has_trivial_destructor : _true_value {}; +template <> struct _has_trivial_destructor : _true_value {}; +template <> struct _has_trivial_destructor : _true_value {}; +template <> struct _has_trivial_destructor : _true_value {}; +template <> struct _has_trivial_destructor : _true_value {}; +template <> struct _has_trivial_destructor : _true_value {}; +template <> struct _has_trivial_destructor : _true_value {}; + +template +struct _DestructArray +{ + template + static void Destruct(size_t count, T* obj) + { + for (size_t i = 0; i < count; i++) + { + obj[i].~T(); + } + } +}; +template <> +struct _DestructArray +{ + template + static void Destruct(size_t count, T* obj) {} +}; + +template +void DestructArray(size_t count, T* obj) +{ + _DestructArray<_has_trivial_destructor::value>::Destruct(count, obj); +} + template void DeleteArray(typename AllocatorInfo::AllocatorType * allocator, size_t count, T * obj) { - if(count == 0) + if (count == 0) { return; } - for (size_t i = 0; i < count; i++) - { - obj[i].~T(); - } + DestructArray(count, obj); // DeleteArray can only be called when an array is allocated successfully. // So the add should never overflow diff --git a/deps/chakrashim/core/lib/Common/Memory/ArenaAllocator.h b/deps/chakrashim/core/lib/Common/Memory/ArenaAllocator.h index 71b8b03636d..3b737cb8ea6 100644 --- a/deps/chakrashim/core/lib/Common/Memory/ArenaAllocator.h +++ b/deps/chakrashim/core/lib/Common/Memory/ArenaAllocator.h @@ -802,16 +802,21 @@ class RefCounted volatile LONG refCount; protected: + RefCounted() + : refCount(1) + { + } + virtual ~RefCounted() { } -public: - RefCounted() - : refCount(1) + void operator delete(void* p, size_t size) { + HeapFree(p, size); } +public: uint32 AddRef(void) { return (uint32)InterlockedIncrement(&refCount); @@ -823,7 +828,7 @@ class RefCounted if (0 == refs) { - delete this; + delete this; // invokes overrided operator delete } return refs; @@ -882,7 +887,6 @@ class ReferencedArenaAdapter : public RefCounted bool deleteFlag; public: - ~ReferencedArenaAdapter() { if (this->arena) diff --git a/deps/chakrashim/core/lib/Common/Memory/HeapAllocator.h b/deps/chakrashim/core/lib/Common/Memory/HeapAllocator.h index 74673e2cd3e..d9b5d689b27 100644 --- a/deps/chakrashim/core/lib/Common/Memory/HeapAllocator.h +++ b/deps/chakrashim/core/lib/Common/Memory/HeapAllocator.h @@ -12,12 +12,14 @@ #define HeapNewStructPlusZ(size, T, ...) AllocatorNewStructPlusZ(HeapAllocator, &HeapAllocator::Instance, size, T) #define HeapNewArray(T, count, ...) AllocatorNewArray(HeapAllocator, &HeapAllocator::Instance, T, count) #define HeapNewArrayZ(T, count, ...) AllocatorNewArrayZ(HeapAllocator, &HeapAllocator::Instance, T, count) -#define HeapDelete(obj) AllocatorDelete(HeapAllocator, &HeapAllocator::Instance, obj) -#define HeapDeletePlus(size, obj) AllocatorDeletePlus(HeapAllocator, &HeapAllocator::Instance, size, obj) -#define HeapDeletePlusPrefix(size, obj) AllocatorDeletePlusPrefix(HeapAllocator, &HeapAllocator::Instance, size, obj) +#define HeapDelete(obj, ...) \ + AllocatorDelete(HeapAllocator, &HeapAllocator::Instance, obj, ##__VA_ARGS__) +#define HeapDeletePlus(size, obj, ...) \ + AllocatorDeletePlus(HeapAllocator, &HeapAllocator::Instance, size, obj, ##__VA_ARGS__) +#define HeapDeletePlusPrefix(size, obj, ...) \ + AllocatorDeletePlusPrefix(HeapAllocator, &HeapAllocator::Instance, size, obj, ##__VA_ARGS__) #define HeapDeleteArray(count, obj) AllocatorDeleteArray(HeapAllocator, &HeapAllocator::Instance, count, obj) - #define HeapNewNoThrow(T, ...) AllocatorNewNoThrow(HeapAllocator, &HeapAllocator::Instance, T, __VA_ARGS__) #define HeapNewNoThrowZ(T, ...) AllocatorNewNoThrowZ(HeapAllocator, &HeapAllocator::Instance, T, __VA_ARGS__) #define HeapNewNoThrowPlus(size, T, ...) AllocatorNewNoThrowPlus(HeapAllocator, &HeapAllocator::Instance, size, T, __VA_ARGS__) @@ -349,7 +351,7 @@ typedef NoThrowHeapAllocator NoThrowNoMemProtectHeapAllocator; //---------------------------------------- // Default operator new/delete overrides //---------------------------------------- -#if !defined(USED_IN_STATIC_LIB) +#if defined(NTBUILD) && !defined(USED_IN_STATIC_LIB) _Ret_maybenull_ void * __cdecl operator new(DECLSPEC_GUARD_OVERFLOW size_t byteSize); _Ret_maybenull_ void * __cdecl operator new[](DECLSPEC_GUARD_OVERFLOW size_t byteSize); #endif @@ -445,3 +447,9 @@ operator delete(void * obj, NoCheckHeapAllocator * alloc, char * (NoCheckHeapAll { alloc->Free(obj, (size_t)-1); } + +// Free routine where we don't care about following C++ semantics (e.g. calling the destructor) +inline void HeapFree(void* obj, size_t size) +{ + AllocatorFree(&HeapAllocator::Instance, &HeapAllocator::Free, obj, size); +} diff --git a/deps/chakrashim/core/lib/Common/Memory/HeapAllocatorOperators.cpp b/deps/chakrashim/core/lib/Common/Memory/HeapAllocatorOperators.cpp index 66a165c1833..cdb9d6807de 100644 --- a/deps/chakrashim/core/lib/Common/Memory/HeapAllocatorOperators.cpp +++ b/deps/chakrashim/core/lib/Common/Memory/HeapAllocatorOperators.cpp @@ -8,6 +8,16 @@ // Default operator new/delete overrides //---------------------------------------- +// Update: +// +// Overriding global operator new/delete causes problems in host. +// Do not use global operator new/delete. +// +// To support memory tracking, use explicit HeapNew/HeapDelete. +// + +// Only keep following for Chakra Full +#ifdef NTBUILD _Ret_maybenull_ void * __cdecl operator new(DECLSPEC_GUARD_OVERFLOW size_t byteSize) { @@ -31,3 +41,4 @@ operator delete[](void * obj) _NOEXCEPT_ { HeapAllocator::Instance.Free(obj, (size_t)-1); } +#endif diff --git a/deps/chakrashim/core/lib/Jsrt/JsrtHelper.cpp b/deps/chakrashim/core/lib/Jsrt/JsrtHelper.cpp index 503297e594a..2995bff7199 100644 --- a/deps/chakrashim/core/lib/Jsrt/JsrtHelper.cpp +++ b/deps/chakrashim/core/lib/Jsrt/JsrtHelper.cpp @@ -109,12 +109,7 @@ void JsrtCallbackState::ObjectBeforeCallectCallbackWrapper(JsObjectBeforeCollect // we do not track the main thread. When it exits do the cleanup below #ifdef CHAKRA_STATIC_LIBRARY atexit([]() { - ThreadContext *threadContext = ThreadContext::GetContextForCurrentThread(); - if (threadContext) - { - if (threadContext->IsInScript()) return; - ThreadBoundThreadContextManager::DestroyContextAndEntryForCurrentThread(); - } + ThreadBoundThreadContextManager::DestroyContextAndEntryForCurrentThread(); JsrtRuntime::Uninitialize(); diff --git a/deps/chakrashim/core/lib/Jsrt/JsrtRuntime.cpp b/deps/chakrashim/core/lib/Jsrt/JsrtRuntime.cpp index 2298346ec85..85f87326a71 100644 --- a/deps/chakrashim/core/lib/Jsrt/JsrtRuntime.cpp +++ b/deps/chakrashim/core/lib/Jsrt/JsrtRuntime.cpp @@ -53,16 +53,20 @@ void JsrtRuntime::Uninitialize() while (currentThreadContext) { Assert(!currentThreadContext->IsScriptActive()); -#ifdef CHAKRA_STATIC_LIBRARY - if (currentThreadContext->IsInScript()) break; -#endif JsrtRuntime* currentRuntime = static_cast(currentThreadContext->GetJSRTRuntime()); tmpThreadContext = currentThreadContext; currentThreadContext = currentThreadContext->Next(); +#ifdef CHAKRA_STATIC_LIBRARY + // xplat-todo: Cleanup staticlib shutdown. This only shuts down threads. + // Other closing contexts / finalizers having trouble with current + // runtime/context. + RentalThreadContextManager::DestroyThreadContext(tmpThreadContext); +#else currentRuntime->CloseContexts(); RentalThreadContextManager::DestroyThreadContext(tmpThreadContext); HeapDelete(currentRuntime); +#endif } } diff --git a/deps/chakrashim/core/lib/Parser/Hash.cpp b/deps/chakrashim/core/lib/Parser/Hash.cpp index 917f2da506e..56d8e75bd3d 100644 --- a/deps/chakrashim/core/lib/Parser/Hash.cpp +++ b/deps/chakrashim/core/lib/Parser/Hash.cpp @@ -34,7 +34,7 @@ HashTbl * HashTbl::Create(uint cidHash, ErrHandler * perr) return nullptr; if (!phtbl->Init(cidHash)) { - delete phtbl; + delete phtbl; // invokes overrided operator delete return nullptr; } diff --git a/deps/chakrashim/core/lib/Parser/Hash.h b/deps/chakrashim/core/lib/Parser/Hash.h index a1f2487a0b1..20a0832aed2 100644 --- a/deps/chakrashim/core/lib/Parser/Hash.h +++ b/deps/chakrashim/core/lib/Parser/Hash.h @@ -318,7 +318,7 @@ class HashTbl void Release(void) { - delete this; + delete this; // invokes overrided operator delete } @@ -378,8 +378,8 @@ class HashTbl NoReleaseAllocator* GetAllocator() {return &m_noReleaseAllocator;} bool Contains(_In_reads_(cch) LPCOLESTR prgch, int32 cch); -private: +private: NoReleaseAllocator m_noReleaseAllocator; // to allocate identifiers Ident ** m_prgpidName; // hash table for names @@ -396,6 +396,11 @@ class HashTbl } ~HashTbl(void) {} + void operator delete(void* p, size_t size) + { + HeapFree(p, size); + } + // Called to grow the number of buckets in the table to reduce the table density. void Grow(); diff --git a/deps/chakrashim/core/lib/Parser/Parse.cpp b/deps/chakrashim/core/lib/Parser/Parse.cpp index 2480e551996..1bf82d66e98 100644 --- a/deps/chakrashim/core/lib/Parser/Parse.cpp +++ b/deps/chakrashim/core/lib/Parser/Parse.cpp @@ -2863,6 +2863,7 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall, _Inout_opt_ charcount_t *plastRParen /*= nullptr*/) { ParseNodePtr pnode = nullptr; + PidRefStack *savedTopAsyncRef = nullptr; charcount_t ichMin = 0; size_t iecpMin = 0; size_t iuMin; @@ -2915,6 +2916,13 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall, isLambdaExpr = true; goto LFunction; } + else if (m_token.tk == tkLParen) + { + // This is potentially an async arrow function. Save the state of the async references + // in case it needs to be restored. (Note that the case of a single parameter with no ()'s + // is detected upstream and need not be handled here.) + savedTopAsyncRef = pid->GetTopRef(); + } } // Don't push a reference if this is a single lambda parameter, because we'll reparse with @@ -3269,6 +3277,18 @@ LFunction : pnode = ParsePostfixOperators(pnode, fAllowCall, fInNew, isAsyncExpr, &fCanAssign, &term, pfIsDotOrIndex); + if (savedTopAsyncRef != nullptr && + this->m_token.tk == tkDArrow) + { + // This is an async arrow function; we're going to back up and reparse it. + // Make sure we don't leave behind a bogus reference to the 'async' identifier. + for (IdentPtr pid = wellKnownPropertyPids.async; pid->GetTopRef() != savedTopAsyncRef;) + { + Assert(pid->GetTopRef() != nullptr); + pid->RemovePrevPidRef(nullptr); + } + } + // Pass back identifier if requested if (pToken && term.tk == tkID) { @@ -5178,6 +5198,19 @@ bool Parser::ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, usho paramScope->SetCannotMergeWithBodyScope(); } } + if (paramScope->GetCanMergeWithBodyScope() && !fDeclaration && pnodeFnc->sxFnc.pnodeName != nullptr) + { + Symbol* funcSym = pnodeFnc->sxFnc.pnodeName->sxVar.sym; + if (funcSym->GetPid()->GetTopRef()->GetFuncScopeId() > pnodeFnc->sxFnc.functionId) + { + // This is a function expression with name captured in the param scope. In non-eval, non-split cases the function + // name symbol is added to the body scope to make it accessible in the body. But if there is a function or var + // declaration with the same name in the body then adding to the body will fail. So in this case we have to add + // the name symbol to the param scope by splitting it. + paramScope->SetCannotMergeWithBodyScope(); + } + } + } } diff --git a/deps/chakrashim/core/lib/Parser/Scan.cpp b/deps/chakrashim/core/lib/Parser/Scan.cpp index e0827d76f39..d76080e8f52 100644 --- a/deps/chakrashim/core/lib/Parser/Scan.cpp +++ b/deps/chakrashim/core/lib/Parser/Scan.cpp @@ -1713,7 +1713,7 @@ tokens Scanner::ScanForcingPid() { this->m_DeferredParseFlags = deferredParseFlagsSave; }); - + return result; } return Scan(); @@ -1748,7 +1748,7 @@ tokens Scanner::ScanCore(bool identifyKwds) EncodedCharPtr p = m_currentCharacter; EncodedCharPtr last = m_pchLast; bool seenDelimitedCommentEnd = false; - + // store the last token m_tkPrevious = m_ptoken->tk; m_iecpLimTokPrevious = IecpLimTok(); // Introduced for use by lambda parsing to find correct span of expression lambdas diff --git a/deps/chakrashim/core/lib/Parser/Scan.h b/deps/chakrashim/core/lib/Parser/Scan.h index b7da8ca0cf4..b3c67b5fcc9 100644 --- a/deps/chakrashim/core/lib/Parser/Scan.h +++ b/deps/chakrashim/core/lib/Parser/Scan.h @@ -370,7 +370,7 @@ class Scanner : public IScanner, public EncodingPolicy } void Release(void) { - delete this; + delete this; // invokes overrided operator delete } tokens Scan(); @@ -714,6 +714,11 @@ class Scanner : public IScanner, public EncodingPolicy Scanner(Parser* parser, HashTbl *phtbl, Token *ptoken, ErrHandler *perr, Js::ScriptContext *scriptContext); ~Scanner(void); + void operator delete(void* p, size_t size) + { + HeapFree(p, size); + } + template void SeekAndScan(const RestorePoint& restorePoint); diff --git a/deps/chakrashim/core/lib/Runtime/Base/Debug.cpp b/deps/chakrashim/core/lib/Runtime/Base/Debug.cpp index c31ff747def..4acd2761a92 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/Debug.cpp +++ b/deps/chakrashim/core/lib/Runtime/Base/Debug.cpp @@ -32,16 +32,16 @@ WCHAR* DumpCallStackFull(uint frameCount, bool print) Js::JavascriptFunction *jsFunc = walker.GetCurrentFunction(); Js::FunctionBody * jsBody = jsFunc->GetFunctionBody(); - Js::CallInfo const * callInfo = walker.GetCallInfo(); + const Js::CallInfo callInfo = walker.GetCallInfo(); const WCHAR* sourceFileName = _u("NULL"); ULONG line = 0; LONG column = 0; walker.GetSourcePosition(&sourceFileName, &line, &column); StringCchPrintf(buffer, _countof(buffer), _u("%s [%s] (0x%p, Args=%u"), jsBody->GetDisplayName(), jsBody->GetDebugNumberSet(debugStringBuffer), jsFunc, - callInfo->Count); + callInfo.Count); sb.AppendSz(buffer); - for (uint i = 0; i < callInfo->Count; i++) + for (uint i = 0; i < callInfo.Count; i++) { StringCchPrintf(buffer, _countof(buffer), _u(", 0x%p"), walker.GetJavascriptArgs()[i]); sb.AppendSz(buffer); diff --git a/deps/chakrashim/core/lib/Runtime/Base/EtwTrace.h b/deps/chakrashim/core/lib/Runtime/Base/EtwTrace.h index bf4e516a956..b3a41cf3309 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/EtwTrace.h +++ b/deps/chakrashim/core/lib/Runtime/Base/EtwTrace.h @@ -79,11 +79,12 @@ enum MethodType : uint16 Assert(entryPoint->IsNativeCode()); \ char16 functionNameArray[NameBufferLength]; \ const char16 *functionName; \ + size_t requiredCharCapacity = 0; \ bool deleteFunctionName = false; \ const ExecutionMode jitMode = entryPoint->GetJitMode(); \ if(jitMode == ExecutionMode::SimpleJit) \ { \ - const size_t requiredCharCapacity = \ + requiredCharCapacity = \ GetSimpleJitFunctionName(Body, functionNameArray, _countof(functionNameArray)); \ if(requiredCharCapacity == 0) \ { \ @@ -92,7 +93,7 @@ enum MethodType : uint16 else \ { \ Assert(requiredCharCapacity > NameBufferLength); \ - char16 *const allocatedFunctionName = new char16[requiredCharCapacity]; \ + char16 *const allocatedFunctionName = HeapNewNoThrowArray(char16, requiredCharCapacity);\ if(allocatedFunctionName) \ { \ const size_t newRequiredCharCapacity = \ @@ -136,7 +137,7 @@ enum MethodType : uint16 functionName); \ if(deleteFunctionName) \ { \ - delete[] functionName; \ + HeapDeleteArray(requiredCharCapacity, functionName); \ } #define LogMethodInterpretedThunkEvent(Function, Body) \ @@ -172,7 +173,7 @@ enum MethodType : uint16 size_t bufferSize = GetLoopBodyName(Body, loopHeader, loopBodyName, NameBufferLength); \ if(bufferSize > NameBufferLength) /* insufficient buffer space*/ \ { \ - loopBodyName = new WCHAR[bufferSize]; \ + loopBodyName = HeapNewNoThrowArray(WCHAR, bufferSize); \ if(loopBodyName) \ { \ GetLoopBodyName(Body, loopHeader, loopBodyName, bufferSize); \ @@ -206,7 +207,7 @@ enum MethodType : uint16 loopBodyName); \ if(loopBodyNameArray != loopBodyName) \ { \ - delete[] loopBodyName; \ + HeapDeleteArray(bufferSize, loopBodyName); \ } @@ -218,7 +219,7 @@ enum MethodType : uint16 size_t bufferSize = Body->GetLoopBodyName(loopNumber, loopBodyName, NameBufferLength); \ if(bufferSize > NameBufferLength) /* insufficient buffer space*/ \ { \ - loopBodyName = new WCHAR[bufferSize]; \ + loopBodyName = HeapNewNoThrowArray(WCHAR, bufferSize); \ if(loopBodyName) \ { \ GetLoopBodyName(Body, loopHeader, loopBodyName, bufferSize); \ @@ -252,7 +253,7 @@ enum MethodType : uint16 loopBodyName); \ if(loopBodyNameArray != loopBodyName) \ { \ - delete[] loopBodyName; \ + HeapDeleteArray(bufferSize, loopBodyName); \ } // diff --git a/deps/chakrashim/core/lib/Runtime/Base/FunctionBody.cpp b/deps/chakrashim/core/lib/Runtime/Base/FunctionBody.cpp index bf47551c0ec..032af8f10c7 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/FunctionBody.cpp +++ b/deps/chakrashim/core/lib/Runtime/Base/FunctionBody.cpp @@ -2146,6 +2146,7 @@ namespace Js return GetFunctionBody(); } + bool asmjsParseFailed = false; BOOL fParsed = FALSE; FunctionBody* returnFunctionBody = nullptr; ENTER_PINNED_SCOPE(Js::PropertyRecordList, propertyRecordList); @@ -2155,227 +2156,232 @@ namespace Js bool isDebugOrAsmJsReparse = false; FunctionBody* funcBody = nullptr; - AutoRestoreFunctionInfo autoRestoreFunctionInfo(this, DefaultEntryThunk); - - // If m_hasBeenParsed = true, one of the following things happened: - // - We had multiple function objects which were all defer-parsed, but with the same function body and one of them - // got the body to be parsed before another was called - // - We are in debug mode and had our thunks switched to DeferParseThunk - // - This is an already parsed asm.js module, which has been invalidated at link time and must be reparsed as a non-asm.js function - if (!this->m_hasBeenParsed) { + AutoRestoreFunctionInfo autoRestoreFunctionInfo(this, DefaultEntryThunk); + + + // If m_hasBeenParsed = true, one of the following things happened things happened: + // - We had multiple function objects which were all defer-parsed, but with the same function body and one of them + // got the body to be parsed before another was called + // - We are in debug mode and had our thunks switched to DeferParseThunk + // - This is an already parsed asm.js module, which has been invalidated at link time and must be reparsed as a non-asm.js function + if (!this->m_hasBeenParsed) + { this->GetUtf8SourceInfo()->StopTrackingDeferredFunction(this->GetLocalFunctionId()); funcBody = FunctionBody::NewFromParseableFunctionInfo(this, propertyRecordList); - autoRestoreFunctionInfo.funcBody = funcBody; + autoRestoreFunctionInfo.funcBody = funcBody; - PERF_COUNTER_DEC(Code, DeferredFunction); - - if (!this->GetSourceContextInfo()->IsDynamic()) - { - PHASE_PRINT_TESTTRACE1(Js::DeferParsePhase, _u("TestTrace: Deferred function parsed - ID: %d; Display Name: %s; Length: %d; Nested Function Count: %d; Utf8SourceInfo: %d; Source Length: %d; Is Top Level: %s; Source Url: %s\n"), m_functionNumber, this->GetDisplayName(), this->m_cchLength, this->GetNestedCount(), this->m_utf8SourceInfo->GetSourceInfoId(), this->m_utf8SourceInfo->GetCchLength(), this->GetIsTopLevel() ? _u("True") : _u("False"), this->GetSourceContextInfo()->url); - } - else - { - PHASE_PRINT_TESTTRACE1(Js::DeferParsePhase, _u("TestTrace: Deferred function parsed - ID: %d; Display Name: %s; Length: %d; Nested Function Count: %d; Utf8SourceInfo: %d; Source Length: %d\n; Is Top Level: %s;"), m_functionNumber, this->GetDisplayName(), this->m_cchLength, this->GetNestedCount(), this->m_utf8SourceInfo->GetSourceInfoId(), this->m_utf8SourceInfo->GetCchLength(), this->GetIsTopLevel() ? _u("True") : _u("False")); - } + PERF_COUNTER_DEC(Code, DeferredFunction); - if (!this->GetIsTopLevel() && - !this->GetSourceContextInfo()->IsDynamic() && - this->m_scriptContext->DoUndeferGlobalFunctions()) - { - this->GetUtf8SourceInfo()->UndeferGlobalFunctions([this](const Utf8SourceInfo::DeferredFunctionsDictionary::EntryType& func) + if (!this->GetSourceContextInfo()->IsDynamic()) + { + PHASE_PRINT_TESTTRACE1(Js::DeferParsePhase, _u("TestTrace: Deferred function parsed - ID: %d; Display Name: %s; Length: %d; Nested Function Count: %d; Utf8SourceInfo: %d; Source Length: %d; Is Top Level: %s; Source Url: %s\n"), m_functionNumber, this->GetDisplayName(), this->m_cchLength, this->GetNestedCount(), this->m_utf8SourceInfo->GetSourceInfoId(), this->m_utf8SourceInfo->GetCchLength(), this->GetIsTopLevel() ? _u("True") : _u("False"), this->GetSourceContextInfo()->url); + } + else { - Js::ParseableFunctionInfo *nextFunc = func.Value(); - JavascriptExceptionObject* pExceptionObject = nullptr; + PHASE_PRINT_TESTTRACE1(Js::DeferParsePhase, _u("TestTrace: Deferred function parsed - ID: %d; Display Name: %s; Length: %d; Nested Function Count: %d; Utf8SourceInfo: %d; Source Length: %d\n; Is Top Level: %s;"), m_functionNumber, this->GetDisplayName(), this->m_cchLength, this->GetNestedCount(), this->m_utf8SourceInfo->GetSourceInfoId(), this->m_utf8SourceInfo->GetCchLength(), this->GetIsTopLevel() ? _u("True") : _u("False")); + } - if (nextFunc != nullptr && this != nextFunc) + if (!this->GetIsTopLevel() && + !this->GetSourceContextInfo()->IsDynamic() && + this->m_scriptContext->DoUndeferGlobalFunctions()) + { + this->GetUtf8SourceInfo()->UndeferGlobalFunctions([this](const Utf8SourceInfo::DeferredFunctionsDictionary::EntryType& func) { - try - { - nextFunc->Parse(); - } - catch (OutOfMemoryException) {} - catch (StackOverflowException) {} - catch (const Js::JavascriptException& err) - { - pExceptionObject = err.GetAndClear(); - } + Js::ParseableFunctionInfo *nextFunc = func.Value(); + JavascriptExceptionObject* pExceptionObject = nullptr; - // Do not do anything with an OOM or SOE, returning true is fine, it will then be undeferred (or attempted to again when called) - if(pExceptionObject) + if (nextFunc != nullptr && this != nextFunc) { - if(pExceptionObject != ThreadContext::GetContextForCurrentThread()->GetPendingOOMErrorObject() && - pExceptionObject != ThreadContext::GetContextForCurrentThread()->GetPendingSOErrorObject()) + try { - JavascriptExceptionOperators::DoThrow(pExceptionObject, /*scriptContext*/nullptr); + nextFunc->Parse(); + } + catch (OutOfMemoryException) {} + catch (StackOverflowException) {} + catch (const Js::JavascriptException& err) + { + pExceptionObject = err.GetAndClear(); + } + + // Do not do anything with an OOM or SOE, returning true is fine, it will then be undeferred (or attempted to again when called) + if (pExceptionObject) + { + if (pExceptionObject != ThreadContext::GetContextForCurrentThread()->GetPendingOOMErrorObject() && + pExceptionObject != ThreadContext::GetContextForCurrentThread()->GetPendingSOErrorObject()) + { + JavascriptExceptionOperators::DoThrow(pExceptionObject, /*scriptContext*/nullptr); + } } } - } - return true; - }); + return true; + }); + } } - } - else - { - bool isDebugReparse = m_scriptContext->IsScriptContextInSourceRundownOrDebugMode() && !this->GetUtf8SourceInfo()->GetIsLibraryCode(); - bool isAsmJsReparse = m_isAsmjsMode && !isDebugReparse; - - isDebugOrAsmJsReparse = isAsmJsReparse || isDebugReparse; + else + { + bool isDebugReparse = m_scriptContext->IsScriptContextInSourceRundownOrDebugMode() && !this->GetUtf8SourceInfo()->GetIsLibraryCode(); + bool isAsmJsReparse = m_isAsmjsMode && !isDebugReparse; - funcBody = this->GetFunctionBody(); + isDebugOrAsmJsReparse = isAsmJsReparse || isDebugReparse; - if (isDebugOrAsmJsReparse) - { - #if ENABLE_DEBUG_CONFIG_OPTIONS - char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]; - #endif - #if DBG - Assert( - funcBody->IsReparsed() - || m_scriptContext->IsScriptContextInSourceRundownOrDebugMode() - || m_isAsmjsMode); - #endif - OUTPUT_TRACE(Js::DebuggerPhase, _u("Full nested reparse of function: %s (%s)\n"), funcBody->GetDisplayName(), funcBody->GetDebugNumberSet(debugStringBuffer)); + funcBody = this->GetFunctionBody(); - if (funcBody->GetByteCode()) + if (isDebugOrAsmJsReparse) { - // The current function needs to be cleaned up before getting generated in the debug mode. - funcBody->CleanupToReparse(); - } +#if ENABLE_DEBUG_CONFIG_OPTIONS + char16 debugStringBuffer[MAX_FUNCTION_BODY_DEBUG_STRING_SIZE]; +#endif +#if DBG + Assert( + funcBody->IsReparsed() + || m_scriptContext->IsScriptContextInSourceRundownOrDebugMode() + || m_isAsmjsMode); +#endif + OUTPUT_TRACE(Js::DebuggerPhase, _u("Full nested reparse of function: %s (%s)\n"), funcBody->GetDisplayName(), funcBody->GetDebugNumberSet(debugStringBuffer)); + if (funcBody->GetByteCode()) + { + // The current function needs to be cleaned up before getting generated in the debug mode. + funcBody->CleanupToReparse(); + } + + } } - } - // Note that we may be trying to re-gen an already-completed function. (This can happen, for instance, - // in the case of named function expressions inside "with" statements in compat mode.) - // In such a case, there's no work to do. - if (funcBody->GetByteCode() == nullptr) - { + // Note that we may be trying to re-gen an already-completed function. (This can happen, for instance, + // in the case of named function expressions inside "with" statements in compat mode.) + // In such a case, there's no work to do. + if (funcBody->GetByteCode() == nullptr) + { #if ENABLE_PROFILE_INFO - Assert(!funcBody->HasExecutionDynamicProfileInfo()); + Assert(!funcBody->HasExecutionDynamicProfileInfo()); #endif - // In debug or asm.js mode, the scriptlet will be asked to recompile again. - AssertMsg(isDebugOrAsmJsReparse || funcBody->GetGrfscr() & fscrGlobalCode || CONFIG_FLAG(DeferNested), "Deferred parsing of non-global procedure?"); - - HRESULT hr = NO_ERROR; - HRESULT hrParser = NO_ERROR; - HRESULT hrParseCodeGen = NO_ERROR; + // In debug or asm.js mode, the scriptlet will be asked to recompile again. + AssertMsg(isDebugOrAsmJsReparse || funcBody->GetGrfscr() & fscrGlobalCode || CONFIG_FLAG(DeferNested), "Deferred parsing of non-global procedure?"); - BEGIN_LEAVE_SCRIPT_INTERNAL(m_scriptContext) - { - bool isCesu8 = m_scriptContext->GetSource(funcBody->GetSourceIndex())->IsCesu8(); - - size_t offset = this->StartOffset(); - charcount_t charOffset = this->StartInDocument(); - size_t length = this->LengthInBytes(); - - LPCUTF8 pszStart = this->GetStartOfDocument(); - - uint32 grfscr = funcBody->GetGrfscr() | fscrDeferredFnc; + HRESULT hr = NO_ERROR; + HRESULT hrParser = NO_ERROR; + HRESULT hrParseCodeGen = NO_ERROR; - // For the global function we want to re-use the glo functionbody which is already created in the non-debug mode - if (!funcBody->GetIsGlobalFunc()) + BEGIN_LEAVE_SCRIPT_INTERNAL(m_scriptContext) { - grfscr &= ~fscrGlobalCode; - } + bool isCesu8 = m_scriptContext->GetSource(funcBody->GetSourceIndex())->IsCesu8(); - if (!funcBody->GetIsDeclaration() && !funcBody->GetIsGlobalFunc()) // No refresh may reparse global function (e.g. eval code) - { - // Notify the parser that the top-level function was defined in an expression, - // (not a function declaration statement). - grfscr |= fscrDeferredFncExpression; - } - if (!CONFIG_FLAG(DeferNested) || isDebugOrAsmJsReparse) - { - grfscr &= ~fscrDeferFncParse; // Disable deferred parsing if not DeferNested, or doing a debug/asm.js re-parse - } + size_t offset = this->StartOffset(); + charcount_t charOffset = this->StartInDocument(); + size_t length = this->LengthInBytes(); - if (isDebugOrAsmJsReparse) - { - grfscr |= fscrNoAsmJs; // Disable asm.js when debugging or if linking failed - } + LPCUTF8 pszStart = this->GetStartOfDocument(); - BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT - { - CompileScriptException se; - Parser ps(m_scriptContext, funcBody->GetIsStrictMode() ? TRUE : FALSE); - ParseNodePtr parseTree; + uint32 grfscr = funcBody->GetGrfscr() | fscrDeferredFnc; - uint nextFunctionId = funcBody->GetLocalFunctionId(); - hrParser = ps.ParseSourceWithOffset(&parseTree, pszStart, offset, length, charOffset, isCesu8, grfscr, &se, - &nextFunctionId, funcBody->GetRelativeLineNumber(), funcBody->GetSourceContextInfo(), - funcBody); -// Assert(FAILED(hrParser) || nextFunctionId == funcBody->deferredParseNextFunctionId || isDebugOrAsmJsReparse || isByteCodeDeserialization); + // For the global function we want to re-use the glo functionbody which is already created in the non-debug mode + if (!funcBody->GetIsGlobalFunc()) + { + grfscr &= ~fscrGlobalCode; + } - if (FAILED(hrParser)) + if (!funcBody->GetIsDeclaration() && !funcBody->GetIsGlobalFunc()) // No refresh may reparse global function (e.g. eval code) { - hrParseCodeGen = MapDeferredReparseError(hrParser, se); // Map certain errors like OOM/SOE - AssertMsg(FAILED(hrParseCodeGen) && SUCCEEDED(hrParser), "Syntax errors should never be detected on deferred re-parse"); + // Notify the parser that the top-level function was defined in an expression, + // (not a function declaration statement). + grfscr |= fscrDeferredFncExpression; } - else + if (!CONFIG_FLAG(DeferNested) || isDebugOrAsmJsReparse) { - TRACE_BYTECODE(_u("\nDeferred parse %s\n"), funcBody->GetDisplayName()); - Js::AutoDynamicCodeReference dynamicFunctionReference(m_scriptContext); + grfscr &= ~fscrDeferFncParse; // Disable deferred parsing if not DeferNested, or doing a debug/asm.js re-parse + } - bool forceNoNative = isDebugOrAsmJsReparse ? this->GetScriptContext()->IsInterpreted() : false; + if (isDebugOrAsmJsReparse) + { + grfscr |= fscrNoAsmJs; // Disable asm.js when debugging or if linking failed + } - ParseableFunctionInfo* rootFunc = funcBody->GetParseableFunctionInfo(); - hrParseCodeGen = GenerateByteCode(parseTree, grfscr, m_scriptContext, - &rootFunc, funcBody->GetSourceIndex(), - forceNoNative, &ps, &se, funcBody->GetScopeInfo(), functionRef); - funcBody->SetParseableFunctionInfo(rootFunc); + BEGIN_TRANSLATE_EXCEPTION_TO_HRESULT + { + CompileScriptException se; + Parser ps(m_scriptContext, funcBody->GetIsStrictMode() ? TRUE : FALSE); + ParseNodePtr parseTree; - if (se.ei.scode == JSERR_AsmJsCompileError) - { - // if asm.js compilation failed, reparse without asm.js - m_grfscr |= fscrNoAsmJs; - se.Clear(); - return Parse(functionRef, isByteCodeDeserialization); - } + uint nextFunctionId = funcBody->GetLocalFunctionId(); + hrParser = ps.ParseSourceWithOffset(&parseTree, pszStart, offset, length, charOffset, isCesu8, grfscr, &se, + &nextFunctionId, funcBody->GetRelativeLineNumber(), funcBody->GetSourceContextInfo(), + funcBody); + // Assert(FAILED(hrParser) || nextFunctionId == funcBody->deferredParseNextFunctionId || isDebugOrAsmJsReparse || isByteCodeDeserialization); - if (SUCCEEDED(hrParseCodeGen)) + if (FAILED(hrParser)) { - fParsed = TRUE; + hrParseCodeGen = MapDeferredReparseError(hrParser, se); // Map certain errors like OOM/SOE + AssertMsg(FAILED(hrParseCodeGen) && SUCCEEDED(hrParser), "Syntax errors should never be detected on deferred re-parse"); } else { - Assert(hrParseCodeGen == SCRIPT_E_RECORDED); - hrParseCodeGen = se.ei.scode; + TRACE_BYTECODE(_u("\nDeferred parse %s\n"), funcBody->GetDisplayName()); + Js::AutoDynamicCodeReference dynamicFunctionReference(m_scriptContext); + + bool forceNoNative = isDebugOrAsmJsReparse ? this->GetScriptContext()->IsInterpreted() : false; + + ParseableFunctionInfo* rootFunc = funcBody->GetParseableFunctionInfo(); + hrParseCodeGen = GenerateByteCode(parseTree, grfscr, m_scriptContext, + &rootFunc, funcBody->GetSourceIndex(), + forceNoNative, &ps, &se, funcBody->GetScopeInfo(), functionRef); + funcBody->SetParseableFunctionInfo(rootFunc); + + if (SUCCEEDED(hrParseCodeGen)) + { + fParsed = TRUE; + } + else + { + Assert(hrParseCodeGen == SCRIPT_E_RECORDED); + hrParseCodeGen = se.ei.scode; + } } } + END_TRANSLATE_EXCEPTION_TO_HRESULT(hr); } - END_TRANSLATE_EXCEPTION_TO_HRESULT(hr); - } - END_LEAVE_SCRIPT_INTERNAL(m_scriptContext); + END_LEAVE_SCRIPT_INTERNAL(m_scriptContext); - THROW_KNOWN_HRESULT_EXCEPTIONS(hr, m_scriptContext); + THROW_KNOWN_HRESULT_EXCEPTIONS(hr, m_scriptContext); - Assert(hr == NO_ERROR); + Assert(hr == NO_ERROR); - if (!SUCCEEDED(hrParser)) + if (!SUCCEEDED(hrParser)) + { + JavascriptError::ThrowError(m_scriptContext, VBSERR_InternalError); + } + else if (!SUCCEEDED(hrParseCodeGen)) + { + /* + * VBSERR_OutOfStack is of type kjstError but we throw a (more specific) StackOverflowError when a hard stack + * overflow occurs. To keep the behavior consistent I'm special casing it here. + */ + if (hrParseCodeGen == VBSERR_OutOfStack) + { + JavascriptError::ThrowStackOverflowError(m_scriptContext); + } + else if (hrParseCodeGen == JSERR_AsmJsCompileError) + { + asmjsParseFailed = true; + } + else + { + JavascriptError::MapAndThrowError(m_scriptContext, hrParseCodeGen); + } + } + } + else { - JavascriptError::ThrowError(m_scriptContext, VBSERR_InternalError); + fParsed = FALSE; } - else if (!SUCCEEDED(hrParseCodeGen)) + + if (!asmjsParseFailed) { - /* - * VBSERR_OutOfStack is of type kjstError but we throw a (more specific) StackOverflowError when a hard stack - * overflow occurs. To keep the behavior consistent I'm special casing it here. - */ - if (hrParseCodeGen == VBSERR_OutOfStack) - { - JavascriptError::ThrowStackOverflowError(m_scriptContext); - } - JavascriptError::MapAndThrowError(m_scriptContext, hrParseCodeGen); + autoRestoreFunctionInfo.Clear(); } } - else - { - fParsed = FALSE; - } - - autoRestoreFunctionInfo.Clear(); if (fParsed == TRUE) { @@ -2385,13 +2391,20 @@ namespace Js this->m_hasBeenParsed = true; returnFunctionBody = funcBody; } - else + else if(!asmjsParseFailed) { returnFunctionBody = this->GetFunctionBody(); } LEAVE_PINNED_SCOPE(); + if (asmjsParseFailed) + { + // disable asm.js and reparse on failure + m_grfscr |= fscrNoAsmJs; + return Parse(functionRef, isByteCodeDeserialization); + } + return returnFunctionBody; } diff --git a/deps/chakrashim/core/lib/Runtime/Base/ScriptContext.cpp b/deps/chakrashim/core/lib/Runtime/Base/ScriptContext.cpp index 27e01051a76..bd2649345e0 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/ScriptContext.cpp +++ b/deps/chakrashim/core/lib/Runtime/Base/ScriptContext.cpp @@ -293,7 +293,7 @@ namespace Js CleanupDocumentContext = nullptr; #endif - // Do this after all operations that may cause potential exceptions + // Do this after all operations that may cause potential exceptions. Note: InitialAllocations may still throw! threadContext->RegisterScriptContext(this); numberAllocator.Initialize(this->GetRecycler()); @@ -468,6 +468,10 @@ namespace Js } } + // Normally the JavascriptLibraryBase will unregister the scriptContext from the threadContext. + // In cases where we don't finish initialization e.g. OOM, manually unregister the scriptContext. + threadContext->UnregisterScriptContext(this); + #if ENABLE_BACKGROUND_PARSING if (this->backgroundParser != nullptr) { @@ -1810,7 +1814,7 @@ namespace Js // Free unused bytes Assert(cbNeeded + 1 <= cbUtf8Buffer); *ppSourceInfo = Utf8SourceInfo::New(this, utf8Script, (int)length, - cbNeeded, pSrcInfo, isLibraryCode, scriptSource); + cbNeeded, pSrcInfo, isLibraryCode); } else { @@ -1830,7 +1834,7 @@ namespace Js // the 'length' here is not correct - we will get the length from the parser - however parser hasn't done yet. // Once the parser is done we will update the utf8sourceinfo's lenght correctly with parser's *ppSourceInfo = Utf8SourceInfo::New(this, script, - (int)length, cb, pSrcInfo, isLibraryCode, scriptSource); + (int)length, cb, pSrcInfo, isLibraryCode); } } } @@ -3813,6 +3817,7 @@ namespace Js ScriptContext* scriptContext = function->GetScriptContext(); bool functionEnterEventSent = false; char16 *pwszExtractedFunctionName = NULL; + size_t functionNameLen = 0; const char16 *pwszFunctionName = NULL; HRESULT hrOfEnterEvent = S_OK; @@ -3872,16 +3877,16 @@ namespace Js const char16 *pwszNameEnd = wcsstr(pwszToString, _u("(")); if (pwszNameStart == nullptr || pwszNameEnd == nullptr || ((int)(pwszNameEnd - pwszNameStart) <= 0)) { - int len = ((JavascriptString *)sourceString)->GetLength() + 1; - pwszExtractedFunctionName = new char16[len]; - wcsncpy_s(pwszExtractedFunctionName, len, pwszToString, _TRUNCATE); + functionNameLen = ((JavascriptString *)sourceString)->GetLength() + 1; + pwszExtractedFunctionName = HeapNewArray(char16, functionNameLen); + wcsncpy_s(pwszExtractedFunctionName, functionNameLen, pwszToString, _TRUNCATE); } else { - int len = (int)(pwszNameEnd - pwszNameStart); - AssertMsg(len > 0, "Allocating array with zero or negative length?"); - pwszExtractedFunctionName = new char16[len]; - wcsncpy_s(pwszExtractedFunctionName, len, pwszNameStart + 1, _TRUNCATE); + functionNameLen = pwszNameEnd - pwszNameStart; + AssertMsg(functionNameLen < INT_MAX, "Allocating array with zero or negative length?"); + pwszExtractedFunctionName = HeapNewArray(char16, functionNameLen); + wcsncpy_s(pwszExtractedFunctionName, functionNameLen, pwszNameStart + 1, _TRUNCATE); } pwszFunctionName = pwszExtractedFunctionName; } @@ -3998,7 +4003,7 @@ namespace Js scriptContext->OnDispatchFunctionExit(pwszFunctionName); if (pwszExtractedFunctionName != NULL) { - delete[]pwszExtractedFunctionName; + HeapDeleteArray(functionNameLen, pwszExtractedFunctionName); } } } @@ -4468,7 +4473,7 @@ void ScriptContext::RegisterConstructorCache(Js::PropertyId propertyId, Js::Cons } #endif -JITPageAddrToFuncRangeCache * +JITPageAddrToFuncRangeCache * ScriptContext::GetJitFuncRangeCache() { return jitFuncRangeCache; @@ -6149,7 +6154,7 @@ void ScriptContext::RegisterPrototypeChainEnsuredToHaveOnlyWritableDataPropertie { return jitPageAddrToFuncRangeMap; } - + JITPageAddrToFuncRangeCache::LargeJITFuncAddrToSizeMap * JITPageAddrToFuncRangeCache::GetLargeJITFuncAddrToSizeMap() { return largeJitFuncToSizeMap; diff --git a/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.cpp b/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.cpp index dbf3b1da43f..1038f5f175f 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.cpp +++ b/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.cpp @@ -223,10 +223,19 @@ JsUtil::JobProcessor * ThreadBoundThreadContextManager::GetSharedJobProcessor() void RentalThreadContextManager::DestroyThreadContext(ThreadContext* threadContext) { - ShutdownThreadContext(threadContext); + bool deleteThreadContext = true; + +#ifdef CHAKRA_STATIC_LIBRARY + // xplat-todo: Cleanup staticlib shutdown. Deleting contexts / finalizers having + // trouble with current runtime/context. + deleteThreadContext = false; +#endif + + ShutdownThreadContext(threadContext, deleteThreadContext); } -void ThreadContextManagerBase::ShutdownThreadContext(ThreadContext* threadContext) +void ThreadContextManagerBase::ShutdownThreadContext( + ThreadContext* threadContext, bool deleteThreadContext /*= true*/) { #if DBG @@ -238,5 +247,8 @@ void ThreadContextManagerBase::ShutdownThreadContext(ThreadContext* threadContex #endif threadContext->ShutdownThreads(); - HeapDelete(threadContext); + if (deleteThreadContext) + { + HeapDelete(threadContext); + } } diff --git a/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.h b/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.h index 011d08b839f..e16724ebc25 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.h +++ b/deps/chakrashim/core/lib/Runtime/Base/ThreadBoundThreadContextManager.h @@ -7,7 +7,8 @@ class ThreadContextManagerBase { protected: - static void ShutdownThreadContext(ThreadContext* threadContext); + static void ShutdownThreadContext( + ThreadContext* threadContext, bool deleteThreadContext = true); }; class ThreadBoundThreadContextManager : public ThreadContextManagerBase diff --git a/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.cpp b/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.cpp index 8e73c404b33..82fd82d5de8 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.cpp +++ b/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.cpp @@ -218,12 +218,12 @@ namespace Js Utf8SourceInfo* Utf8SourceInfo::New(ScriptContext* scriptContext, LPCUTF8 utf8String, int32 length, - size_t numBytes, SRCINFO const* srcInfo, bool isLibraryCode, Js::Var scriptSource) + size_t numBytes, SRCINFO const* srcInfo, bool isLibraryCode) { utf8char_t * newUtf8String = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), utf8char_t, numBytes + 1); js_memcpy_s(newUtf8String, numBytes + 1, utf8String, numBytes + 1); return NewWithNoCopy(scriptContext, newUtf8String, length, numBytes, - srcInfo, isLibraryCode, scriptSource); + srcInfo, isLibraryCode); } Utf8SourceInfo* diff --git a/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.h b/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.h index 6b92b12c401..39fb6d099a5 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.h +++ b/deps/chakrashim/core/lib/Runtime/Base/Utf8SourceInfo.h @@ -299,7 +299,7 @@ namespace Js bool isLibraryCode, Js::Var scriptSource = nullptr); static Utf8SourceInfo* New(ScriptContext* scriptContext, LPCUTF8 utf8String, int32 length, size_t numBytes, SRCINFO const* srcInfo, - bool isLibraryCode, Js::Var scriptSource = nullptr); + bool isLibraryCode); static Utf8SourceInfo* NewWithNoCopy(ScriptContext* scriptContext, LPCUTF8 utf8String, int32 length, size_t numBytes, SRCINFO const* srcInfo, bool isLibraryCode, Js::Var scriptSource = nullptr); diff --git a/deps/chakrashim/core/lib/Runtime/Base/WindowsGlobalizationAdapter.cpp b/deps/chakrashim/core/lib/Runtime/Base/WindowsGlobalizationAdapter.cpp index 4ff80e20f88..11145742a6b 100644 --- a/deps/chakrashim/core/lib/Runtime/Base/WindowsGlobalizationAdapter.cpp +++ b/deps/chakrashim/core/lib/Runtime/Base/WindowsGlobalizationAdapter.cpp @@ -151,7 +151,7 @@ namespace Js public: HRESULT RuntimeClassInitialize(HSTRING *string, uint32 length) { - this->items = new HSTRING[length]; + this->items = HeapNewNoThrowArray(HSTRING, length); if (this->items == nullptr) { @@ -171,7 +171,7 @@ namespace Js { if(this->items != nullptr) { - delete [] items; + HeapDeleteArray(this->length, items); } } @@ -666,7 +666,7 @@ if (this->object) \ HRESULT hr = formatter->get_NumeralSystem(hNumeralSystem); return VerifyResult(hNumeralSystem, hr); } - + HRESULT WindowsGlobalizationAdapter::GetCalendar(_In_ DateTimeFormatting::IDateTimeFormatter* formatter, HSTRING * hCalendar) { HRESULT hr = formatter->get_Calendar(hCalendar); diff --git a/deps/chakrashim/core/lib/Runtime/ByteCode/ByteCodeEmitter.cpp b/deps/chakrashim/core/lib/Runtime/ByteCode/ByteCodeEmitter.cpp index a1d46680add..f53ac3c080f 100644 --- a/deps/chakrashim/core/lib/Runtime/ByteCode/ByteCodeEmitter.cpp +++ b/deps/chakrashim/core/lib/Runtime/ByteCode/ByteCodeEmitter.cpp @@ -3320,6 +3320,7 @@ void ByteCodeGenerator::EmitOneFunction(ParseNode *pnode) { // Emit bytecode to copy the initial values from param names to their corresponding body bindings. // We have to do this after the rest param is marked as false for need declaration. + Symbol* funcSym = funcInfo->root->sxFnc.GetFuncSymbol(); paramScope->ForEachSymbol([&](Symbol* param) { Symbol* varSym = funcInfo->GetBodyScope()->FindLocalSymbol(param->GetName()); Assert(varSym || pnode->sxFnc.pnodeName->sxVar.sym == param); @@ -3328,7 +3329,9 @@ void ByteCodeGenerator::EmitOneFunction(ParseNode *pnode) { // Do not copy the arguments to the body if it is not used } - else if (varSym && varSym->GetSymbolType() == STVariable && (varSym->IsInSlot(funcInfo) || varSym->GetLocation() != Js::Constants::NoRegister)) + else if ((funcSym == nullptr || funcSym != param) // Do not copy the symbol over to body as the function expression symbol + // is expected to stay inside the function expression scope + && (varSym && varSym->GetSymbolType() == STVariable && (varSym->IsInSlot(funcInfo) || varSym->GetLocation() != Js::Constants::NoRegister))) { // Simulating EmitPropLoad here. We can't directly call the method as we have to use the param scope specifically. // Walking the scope chain is not possible at this time. @@ -3634,9 +3637,9 @@ void ByteCodeGenerator::EmitScopeList(ParseNode *pnode, ParseNode *breakOnBodySc { exit(JSERR_AsmJsCompileError); } - else if (!(flags & fscrDeferFncParse)) + else { - // If deferral is not allowed, throw and reparse everything with asm.js disabled. + // if asm.js parse error happened, reparse with asm.js disabled. throw Js::AsmJsParseException(); } } diff --git a/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.cpp b/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.cpp index 2bd8a38e33a..4991588d932 100644 --- a/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.cpp +++ b/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.cpp @@ -13,7 +13,7 @@ FuncInfo::FuncInfo( Js::ParseableFunctionInfo* byteCodeFunction) : alloc(alloc), varRegsCount(0), - constRegsCount(2), + constRegsCount(InitialConstRegsCount), inArgsCount(0), innerScopeCount(0), currentInnerScopeIndex((uint)-1), diff --git a/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.h b/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.h index c9725acda85..ed6dad03b70 100644 --- a/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.h +++ b/deps/chakrashim/core/lib/Runtime/ByteCode/FuncInfo.h @@ -83,6 +83,8 @@ class FuncInfo uint nextForInLoopLevel; uint maxForInLoopLevel; public: + static const Js::RegSlot InitialConstRegsCount = 2; // constRegsCount is set to 2 because R0 is the return register, and R1 is the root object + ArenaAllocator *alloc; // set in Bind/Assign pass Js::RegSlot varRegsCount; // number of registers used for non-constants @@ -192,7 +194,6 @@ class FuncInfo Symbol *innerArgumentsSymbol; JsUtil::List nonUserNonTempRegistersToInitialize; - // constRegsCount is set to 2 because R0 is the return register, and R1 is the root object. FuncInfo( const char16 *name, ArenaAllocator *alloc, diff --git a/deps/chakrashim/core/lib/Runtime/Language/AsmJs.cpp b/deps/chakrashim/core/lib/Runtime/Language/AsmJs.cpp index 9e87e8c9ddf..5516a491009 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/AsmJs.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/AsmJs.cpp @@ -919,7 +919,11 @@ namespace Js { ParseNode* endStmt = m.GetCurrentParserNode(); - Assert( endStmt->nop == knopList ); + if (endStmt->nop != knopList) + { + return m.Fail(endStmt, _u("Module must have a return")); + } + ParseNode* node = ParserWrapper::GetBinaryLeft( endStmt ); ParseNode* endNode = ParserWrapper::GetBinaryRight( endStmt ); @@ -961,6 +965,10 @@ namespace Js } ParseNode* objectElement = ParserWrapper::GetUnaryNode(objNode); + if (!objectElement) + { + return m.Fail(node, _u("Return object must not be empty")); + } while( objectElement ) { ParseNode* member = nullptr; diff --git a/deps/chakrashim/core/lib/Runtime/Language/AsmJsByteCodeGenerator.cpp b/deps/chakrashim/core/lib/Runtime/Language/AsmJsByteCodeGenerator.cpp index ef62ed78d7a..0646117ea4e 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/AsmJsByteCodeGenerator.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/AsmJsByteCodeGenerator.cpp @@ -3324,6 +3324,8 @@ namespace Js byteCodeGen->Writer()->EndStatement(functionNode); byteCodeGen->Writer()->End(); + functionBody->CheckAndSetConstantCount(FuncInfo::InitialConstRegsCount); + autoCleanup.Done(); } diff --git a/deps/chakrashim/core/lib/Runtime/Language/AsmJsModule.cpp b/deps/chakrashim/core/lib/Runtime/Language/AsmJsModule.cpp index 7de3ee92528..eca10fb536e 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/AsmJsModule.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/AsmJsModule.cpp @@ -1091,9 +1091,14 @@ namespace Js { if( DefineIdentifier( name, func ) ) { - func->SetFunctionIndex( pnodeFnc->sxFnc.nestedIndex ); - // Add extra check to make sure all the slots between 0 - Count are filled with func; - mFunctionArray.SetItem( func->GetFunctionIndex(), func ); + uint index = (uint)mFunctionArray.Count(); + if (pnodeFnc->sxFnc.nestedIndex != index) + { + return nullptr; + } + func->SetFunctionIndex( (RegSlot)index ); + mFunctionArray.Add( func ); + Assert(index + 1 == (uint)mFunctionArray.Count()); return func; } // Error adding function diff --git a/deps/chakrashim/core/lib/Runtime/Language/InterpreterStackFrame.cpp b/deps/chakrashim/core/lib/Runtime/Language/InterpreterStackFrame.cpp index 9b20e1d67a8..ac12ebbd77b 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/InterpreterStackFrame.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/InterpreterStackFrame.cpp @@ -2768,16 +2768,18 @@ namespace Js AsmJsScriptFunction* scriptFuncObj = (AsmJsScriptFunction*)ScriptFunction::OP_NewScFunc(pDisplay, functionInfo); localModuleFunctions[modFunc.location] = scriptFuncObj; + + if (scriptFuncObj->GetDynamicType()->GetEntryPoint() == DefaultDeferredDeserializeThunk) + { + JavascriptFunction::DeferredDeserialize(scriptFuncObj); + } + if (i == 0 && info->GetUsesChangeHeap()) { scriptFuncObj->GetDynamicType()->SetEntryPoint(AsmJsChangeHeapBuffer); } else { - if (scriptFuncObj->GetDynamicType()->GetEntryPoint() == DefaultDeferredDeserializeThunk) - { - JavascriptFunction::DeferredDeserialize(scriptFuncObj); - } scriptFuncObj->GetDynamicType()->SetEntryPoint(AsmJsExternalEntryPoint); scriptFuncObj->GetFunctionBody()->GetAsmJsFunctionInfo()->SetModuleFunctionBody(asmJsModuleFunctionBody); } @@ -6342,6 +6344,7 @@ const byte * InterpreterStackFrame::OP_ProfiledLoopBodyStart(const byte * ip) PROBE_STACK(scriptContext, outArgs.Info.Count * sizeof(Var) + Js::Constants::MinStackDefault); // args + function call outArgsSize = outArgs.Info.Count * sizeof(Var); outArgs.Values = (Var*)_alloca(outArgsSize); + ZeroMemory(outArgs.Values, outArgsSize); } else { diff --git a/deps/chakrashim/core/lib/Runtime/Language/JavascriptConversion.cpp b/deps/chakrashim/core/lib/Runtime/Language/JavascriptConversion.cpp index 96f77ede828..56fb8ab2639 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/JavascriptConversion.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/JavascriptConversion.cpp @@ -415,8 +415,7 @@ namespace Js // if IsES6ToPrimitiveEnabled flag is off we also fall back to OrdinaryToPrimitive return MethodCallToPrimitive(aValue, hint, requestContext); } - //NOTE: Consider passing requestContext to JavascriptDate::ToString - return CrossSite::MarshalVar(requestContext, JavascriptDate::ToString(dateObject)); + return JavascriptDate::ToString(dateObject, requestContext); } } diff --git a/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.cpp b/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.cpp index a75d9b28c6b..1bcfe7f7808 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.cpp @@ -154,7 +154,7 @@ namespace Js Assert(IsJavascriptFrame()); AssertMsg(this->GetCurrentFunction()->IsScriptFunction(), "GetPermanentArguments should not be called for non-script function as there is no slot allocated for it."); - const uint32 paramCount = GetCallInfo()->Count; + const uint32 paramCount = GetCallInfo().Count; if (paramCount == 0) { // glob function doesn't allocate ArgumentsObject slot on stack @@ -206,8 +206,8 @@ namespace Js else #endif { - CallInfo const *callInfo = this->GetCallInfo(); - if (callInfo->Count == 0) + const CallInfo callInfo = this->GetCallInfo(); + if (callInfo.Count == 0) { *pVarThis = JavascriptOperators::OP_GetThis(scriptContext->GetLibrary()->GetUndefined(), moduleId, scriptContext); return false; @@ -218,14 +218,14 @@ namespace Js } } - BOOL IsEval(const CallInfo* callInfo) + BOOL IsEval(CallInfo callInfo) { - return (callInfo->Flags & CallFlags_Eval) != 0; + return (callInfo.Flags & CallFlags_Eval) != 0; } BOOL JavascriptStackWalker::IsCallerGlobalFunction() const { - CallInfo const* callInfo = this->GetCallInfo(); + const CallInfo callInfo = this->GetCallInfo(); JavascriptFunction* function = this->GetCurrentFunction(); if (IsLibraryStackFrameEnabled(this->scriptContext) && !function->IsScriptFunction()) @@ -241,14 +241,14 @@ namespace Js else { AssertMsg(FALSE, "Here we should only have script functions which were already parsed/deserialized."); - return callInfo->Count == 0 || IsEval(callInfo); + return callInfo.Count == 0 || IsEval(callInfo); } } BOOL JavascriptStackWalker::IsEvalCaller() const { - CallInfo const* callInfo = this->GetCallInfo(); - return (callInfo->Flags & CallFlags_Eval) != 0; + const CallInfo callInfo = this->GetCallInfo(); + return (callInfo.Flags & CallFlags_Eval) != 0; } Var JavascriptStackWalker::GetCurrentNativeArgumentsObject() const @@ -831,7 +831,7 @@ namespace Js if (this->IsJavascriptFrame() && this->GetCurrentFunction() == funcTarget) { // Skip internal names - Assert( !(this->GetCallInfo()->Flags & CallFlags_InternalFrame) ); + Assert( !(this->GetCallInfo().Flags & CallFlags_InternalFrame) ); return true; } } @@ -1008,32 +1008,41 @@ namespace Js return GetCurrentFunction(false); } - CallInfo const * JavascriptStackWalker::GetCallInfo(bool includeInlinedFrames /* = true */) const + CallInfo JavascriptStackWalker::GetCallInfo(bool includeInlinedFrames /* = true */) const { Assert(this->IsJavascriptFrame()); + CallInfo callInfo; if (includeInlinedFrames && inlinedFramesBeingWalked) { // Since we don't support inlining constructors yet, its questionable if we should handle the // hidden frame display here? - return (CallInfo const *)&inlinedFrameCallInfo; + callInfo = inlinedFrameCallInfo; } else if (this->GetCurrentFunction()->GetFunctionInfo()->IsCoroutine()) { JavascriptGenerator* gen = JavascriptGenerator::FromVar(this->GetCurrentArgv()[JavascriptFunctionArgIndex_This]); - return &gen->GetArguments().Info; + callInfo = gen->GetArguments().Info; } else if (this->isNativeLibraryFrame) { // Return saved callInfo. Do not read from stack as compiler may stackpack/optimize args. - return &this->prevNativeLibraryEntry->callInfo; + callInfo = this->prevNativeLibraryEntry->callInfo; } else { - return (CallInfo const *)&this->GetCurrentArgv()[JavascriptFunctionArgIndex_CallInfo]; + callInfo = *(CallInfo const *)&this->GetCurrentArgv()[JavascriptFunctionArgIndex_CallInfo]; } + + if (callInfo.Flags & Js::CallFlags_ExtraArg) + { + callInfo.Flags = (CallFlags)(callInfo.Flags & ~Js::CallFlags_ExtraArg); + callInfo.Count--; + } + + return callInfo; } - CallInfo const *JavascriptStackWalker::GetCallInfoFromPhysicalFrame() const + CallInfo JavascriptStackWalker::GetCallInfoFromPhysicalFrame() const { return GetCallInfo(false); } @@ -1076,7 +1085,7 @@ namespace Js bool JavascriptStackWalker::IsCurrentPhysicalFrameForLoopBody() const { - return !!(this->GetCallInfoFromPhysicalFrame()->Flags & CallFlags_InternalFrame); + return !!(this->GetCallInfoFromPhysicalFrame().Flags & CallFlags_InternalFrame); } bool JavascriptStackWalker::IsWalkable(ScriptContext *scriptContext) diff --git a/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.h b/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.h index 9b6ca8e9522..ea7b1867e7f 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.h +++ b/deps/chakrashim/core/lib/Runtime/Language/JavascriptStackWalker.h @@ -212,8 +212,8 @@ namespace Js JavascriptFunction *GetCurrentFunction(bool includeInlinedFrames = true) const; void SetCurrentFunction(JavascriptFunction * function); - CallInfo const *GetCallInfo(bool includeInlinedFrames = true) const; - CallInfo const *GetCallInfoFromPhysicalFrame() const; + CallInfo GetCallInfo(bool includeInlinedFrames = true) const; + CallInfo GetCallInfoFromPhysicalFrame() const; bool GetThis(Var *pThis, int moduleId) const; Js::Var * GetJavascriptArgs() const; void **GetCurrentArgv() const; diff --git a/deps/chakrashim/core/lib/Runtime/Language/ProfilingHelpers.cpp b/deps/chakrashim/core/lib/Runtime/Language/ProfilingHelpers.cpp index 023f7a2792d..9b4c607c221 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/ProfilingHelpers.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/ProfilingHelpers.cpp @@ -487,6 +487,7 @@ namespace Js PROBE_STACK(scriptContext, outArgs.Info.Count * sizeof(Var) + Js::Constants::MinStackDefault); // args + function call outArgsSize = outArgs.Info.Count * sizeof(Var); outArgs.Values = (Var*)_alloca(outArgsSize); + ZeroMemory(outArgs.Values, outArgsSize); } else { diff --git a/deps/chakrashim/core/lib/Runtime/Language/StackTraceArguments.cpp b/deps/chakrashim/core/lib/Runtime/Language/StackTraceArguments.cpp index 4cc379e4b93..a3b06192dbd 100644 --- a/deps/chakrashim/core/lib/Runtime/Language/StackTraceArguments.cpp +++ b/deps/chakrashim/core/lib/Runtime/Language/StackTraceArguments.cpp @@ -68,9 +68,10 @@ namespace Js { types = 0; if (!walker.IsCallerGlobalFunction()) { - int64 numberOfArguments = walker.GetCallInfo()->Count; + const CallInfo callInfo = walker.GetCallInfo(); + int64 numberOfArguments = callInfo.Count; if (numberOfArguments > 0) numberOfArguments --; // Don't consider 'this' - if (walker.GetCallInfo()->Flags & Js::CallFlags_ExtraArg) + if (callInfo.Flags & Js::CallFlags_ExtraArg) { Assert(numberOfArguments > 0 ); // skip the last FrameDisplay argument. diff --git a/deps/chakrashim/core/lib/Runtime/Library/ArgumentsObject.cpp b/deps/chakrashim/core/lib/Runtime/Library/ArgumentsObject.cpp index 1c958fdef3a..de25ebeb01d 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/ArgumentsObject.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/ArgumentsObject.cpp @@ -67,9 +67,9 @@ namespace Js AssertMsg(JavascriptOperators::GetTypeId(funcCaller) == TypeIds_Function, "non function caller"); - CallInfo const *callInfo = walker->GetCallInfo(); - uint32 paramCount = callInfo->Count; - CallFlags flags = callInfo->Flags; + const CallInfo callInfo = walker->GetCallInfo(); + uint32 paramCount = callInfo.Count; + CallFlags flags = callInfo.Flags; if (paramCount == 0 || (flags & CallFlags_Eval)) { diff --git a/deps/chakrashim/core/lib/Runtime/Library/ArrayBuffer.cpp b/deps/chakrashim/core/lib/Runtime/Library/ArrayBuffer.cpp index e4072ca38a0..cfddedf8fdc 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/ArrayBuffer.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/ArrayBuffer.cpp @@ -297,6 +297,12 @@ namespace Js if (args.Info.Count >= 3) { newBufferLength = ToIndex(args[2], JSERR_ArrayLengthConstructIncorrect, scriptContext, MaxArrayBufferLength); + + // ToIndex above can call user script (valueOf) which can detach the buffer + if (arrayBuffer->IsDetached()) + { + JavascriptError::ThrowTypeError(scriptContext, JSERR_DetachedTypedArray, _u("ArrayBuffer.transfer")); + } } return arrayBuffer->TransferInternal(newBufferLength); diff --git a/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.cpp b/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.cpp index 9ff744462ef..ad335264f36 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.cpp @@ -119,7 +119,7 @@ namespace Js { ///---------------------------------------------------------------------------- ///---------------------------------------------------------------------------- - DateImplementation::DateImplementation(double value, ScriptContext* scriptContext) + DateImplementation::DateImplementation(double value) { // Assume DateImplementation is allocated in the recycler and is zero initialized // Do not stack allocate of this struct, as it doesn't initialize all fields. @@ -129,7 +129,6 @@ namespace Js { Assert(!ThreadContext::IsOnStack(this)); AssertValue(this, 0, sizeof(DateImplementation)); - m_scriptContext = scriptContext; m_modified = false; SetTvUtc(value); @@ -155,82 +154,83 @@ namespace Js { } JavascriptString* - DateImplementation::GetString(DateStringFormat dsf, DateTimeFlag noDateTime) + DateImplementation::GetString(DateStringFormat dsf, + ScriptContext* requestContext, DateTimeFlag noDateTime) { if (JavascriptNumber::IsNan(m_tvUtc)) { - return m_scriptContext->GetLibrary()->GetInvalidDateString(); + return requestContext->GetLibrary()->GetInvalidDateString(); } switch (dsf) { default: - EnsureYmdLcl(); - return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext); + EnsureYmdLcl(requestContext); + return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext); #ifdef ENABLE_GLOBALIZATION case DateStringFormat::Locale: - EnsureYmdLcl(); + EnsureYmdLcl(requestContext); if( m_ymdLcl.year > 1600 && m_ymdLcl.year < 10000 ) { // The year falls in the range which can be handled by both the Win32 // function GetDateFormat and the COM+ date type // - the latter is for forward compatibility with JS 7. - JavascriptString *bs = GetDateLocaleString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext); + JavascriptString *bs = GetDateLocaleString(&m_ymdLcl, &m_tzd, noDateTime, requestContext); if (bs != nullptr) { return bs; } else { - return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext); + return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext); } } else { - return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, m_scriptContext); + return GetDateDefaultString(&m_ymdLcl, &m_tzd, noDateTime, requestContext); } #endif case DateStringFormat::GMT: EnsureYmdUtc(); - return GetDateGmtString(&m_ymdUtc, m_scriptContext); + return GetDateGmtString(&m_ymdUtc, requestContext); } } JavascriptString* - DateImplementation::GetISOString() + DateImplementation::GetISOString(ScriptContext* requestContext) { // ES5 15.9.5.43: throw RangeError if time value is not a finite number if (!Js::NumberUtilities::IsFinite(m_tvUtc)) { - JavascriptError::ThrowRangeError(m_scriptContext, JSERR_NeedNumber); + JavascriptError::ThrowRangeError(requestContext, JSERR_NeedNumber); } - CompoundString *const bs = CompoundString::NewWithCharCapacity(30, m_scriptContext->GetLibrary()); + CompoundString *const bs = CompoundString::NewWithCharCapacity(30, requestContext->GetLibrary()); - GetDateComponent(bs, DateData::FullYear, 0); + GetDateComponent(bs, DateData::FullYear, 0, requestContext); bs->AppendChars(_u('-')); // month - GetDateComponent(bs, DateData::Month, 1/*adjustment*/); + GetDateComponent(bs, DateData::Month, 1/*adjustment*/, requestContext); bs->AppendChars(_u('-')); // date - GetDateComponent(bs, DateData::Date, 0); + GetDateComponent(bs, DateData::Date, 0, requestContext); bs->AppendChars(_u('T')); // hours - GetDateComponent(bs, DateData::Hours, 0); + GetDateComponent(bs, DateData::Hours, 0, requestContext); bs->AppendChars(_u(':')); // minutes - GetDateComponent(bs, DateData::Minutes, 0); + GetDateComponent(bs, DateData::Minutes, 0, requestContext); bs->AppendChars(_u(':')); // seconds - GetDateComponent(bs, DateData::Seconds, 0); + GetDateComponent(bs, DateData::Seconds, 0, requestContext); // ES5 fill in milliseconds but v5.8 does not bs->AppendChars(_u('.')); // milliseconds - GetDateComponent(bs, DateData::Milliseconds, 0); + GetDateComponent(bs, DateData::Milliseconds, 0, requestContext); bs->AppendChars(_u('Z')); @@ -238,9 +238,10 @@ namespace Js { } void - DateImplementation::GetDateComponent(CompoundString *bs, DateData componentType, int adjust) + DateImplementation::GetDateComponent(CompoundString *bs, DateData componentType, int adjust, + ScriptContext* requestContext) { - double value = this->GetDateData(componentType, true /* fUTC */, m_scriptContext); + double value = this->GetDateData(componentType, true /* fUTC */, requestContext); if(Js::NumberUtilities::IsFinite(value)) { const int ival = (int)value + adjust; @@ -339,10 +340,10 @@ namespace Js { ///---------------------------------------------------------------------------- void - DateImplementation::SetTvLcl(double tv) + DateImplementation::SetTvLcl(double tv, ScriptContext* requestContext) { m_grfval = 0; - m_tvUtc = GetTvUtc(tv, m_scriptContext); + m_tvUtc = GetTvUtc(tv, requestContext); } JavascriptString* @@ -580,7 +581,7 @@ namespace Js { } else { - EnsureYmdLcl(); + EnsureYmdLcl(scriptContext); pymd = &m_ymdLcl; } @@ -1709,7 +1710,7 @@ namespace Js { } else { - EnsureYmdLcl(); + EnsureYmdLcl(scriptContext); pymd = &m_ymdLcl; tv = m_tvLcl; } @@ -1782,7 +1783,7 @@ namespace Js { } else { - SetTvLcl(tv); + SetTvLcl(tv, scriptContext); } m_modified = true; diff --git a/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.h b/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.h index 152e8a97598..ef46cb6d085 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.h +++ b/deps/chakrashim/core/lib/Runtime/Library/DateImplementation.h @@ -30,7 +30,7 @@ namespace Js { static double DoubleToTvUtc(double tv); private: DateImplementation(VirtualTableInfoCtorEnum) { m_modified = false; } - DateImplementation(double value, ScriptContext* scriptContext); + DateImplementation(double value); BEGIN_ENUM_BYTE(DateStringFormat) Default, @@ -103,12 +103,14 @@ namespace Js { void ClearModified() { m_modified = false; } private: - JavascriptString* GetString(DateStringFormat dsf, DateTimeFlag noDateTime = DateTimeFlag::None); + JavascriptString* GetString(DateStringFormat dsf, ScriptContext* requestContext, + DateTimeFlag noDateTime = DateTimeFlag::None); - JavascriptString* GetISOString(); - void GetDateComponent(CompoundString *bs, DateData componentType, int adjust); + JavascriptString* GetISOString(ScriptContext* requestContext); + void GetDateComponent(CompoundString *bs, DateData componentType, int adjust, + ScriptContext* requestContext); - void SetTvLcl(double tv); + void SetTvLcl(double tv, ScriptContext* requestContext); double GetDateData(DateData dd, bool fUtc, ScriptContext* scriptContext); double SetDateData(Arguments args, DateData dd, bool fUtc, ScriptContext* scriptContext); @@ -175,11 +177,6 @@ namespace Js { } } - inline void EnsureTvLcl(void) - { - EnsureTvLcl(m_scriptContext); - } - ///------------------------------------------------------------------------------ /// Make sure m_ymdLcl is valid. (Shared with hybrid debugging, which may use a fake scriptContext.) ///------------------------------------------------------------------------------ @@ -195,11 +192,6 @@ namespace Js { m_grfval |= DateValueType::YearMonthDayLocal; } - inline void EnsureYmdLcl(void) - { - EnsureYmdLcl(m_scriptContext); - } - ///------------------------------------------------------------------------------ /// Make sure m_ymdUtc is valid. ///------------------------------------------------------------------------------ @@ -214,61 +206,61 @@ namespace Js { } - inline Var GetFullYear() + inline Var GetFullYear(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar(m_ymdLcl.year, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar(m_ymdLcl.year, requestContext); } - inline Var GetYear() + inline Var GetYear(ScriptContext* requestContext) { - EnsureYmdLcl(); + EnsureYmdLcl(requestContext); // WOOB bug 1099381: ES5 spec B.2.4: getYear() must return YearFromTime() - 1900. // Note that negative value is OK for the spec. int value = m_ymdLcl.year - 1900; - return JavascriptNumber::ToVar(value, m_scriptContext); + return JavascriptNumber::ToVar(value, requestContext); } - inline Var GetMonth() + inline Var GetMonth(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar(m_ymdLcl.mon, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar(m_ymdLcl.mon, requestContext); } - inline Var GetDate() + inline Var GetDate(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar(m_ymdLcl.mday + 1, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar(m_ymdLcl.mday + 1, requestContext); } - inline Var GetDay() + inline Var GetDay(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar(m_ymdLcl.wday, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar(m_ymdLcl.wday, requestContext); } - inline Var GetHours() + inline Var GetHours(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar((m_ymdLcl.time / 3600000)%24, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar((m_ymdLcl.time / 3600000)%24, requestContext); } - inline Var GetMinutes() + inline Var GetMinutes(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar((m_ymdLcl.time / 60000) % 60, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar((m_ymdLcl.time / 60000) % 60, requestContext); } - inline Var GetSeconds() + inline Var GetSeconds(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar((m_ymdLcl.time / 1000) % 60, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar((m_ymdLcl.time / 1000) % 60, requestContext); } - inline Var GetDateMilliSeconds() + inline Var GetDateMilliSeconds(ScriptContext* requestContext) { - EnsureYmdLcl(); - return JavascriptNumber::ToVar(m_ymdLcl.time % 1000, m_scriptContext); + EnsureYmdLcl(requestContext); + return JavascriptNumber::ToVar(m_ymdLcl.time % 1000, requestContext); } template @@ -287,7 +279,6 @@ namespace Js { FieldNoBarrier(DateTime::YMD) m_ymdLcl; Field(TZD) m_tzd; Field(uint32) m_grfval; // Which fields are valid. m_tvUtc is always valid. - FieldNoBarrier(ScriptContext *) m_scriptContext; Field(bool) m_modified : 1; // Whether SetDateData was called on this class friend JavascriptDate; diff --git a/deps/chakrashim/core/lib/Runtime/Library/GlobalObject.cpp b/deps/chakrashim/core/lib/Runtime/Library/GlobalObject.cpp index 0aae614ab08..3229a05bf31 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/GlobalObject.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/GlobalObject.cpp @@ -882,7 +882,7 @@ namespace Js // So we need to pin it here (TODO: Change GenerateByteCode to take in the sourceInfo itself) ENTER_PINNED_SCOPE(Utf8SourceInfo, sourceInfo); sourceInfo = Utf8SourceInfo::New(scriptContext, utf8Source, cchSource, - cbSource, pSrcInfo, ((grfscr & fscrIsLibraryCode) != 0), nullptr); + cbSource, pSrcInfo, ((grfscr & fscrIsLibraryCode) != 0)); Parser parser(scriptContext, strictMode); bool forceNoNative = false; @@ -952,17 +952,16 @@ namespace Js { JavascriptError::ThrowStackOverflowError(scriptContext); } - JavascriptError::MapAndThrowError(scriptContext, hrCodeGen); - } - else - { - if (se.ei.scode == JSERR_AsmJsCompileError) + else if (hrCodeGen == JSERR_AsmJsCompileError) { // if asm.js compilation succeeded, retry with asm.js disabled grfscr |= fscrNoAsmJs; - se.Clear(); return DefaultEvalHelper(scriptContext, source, sourceLength, moduleID, grfscr, pszTitle, registerDocument, isIndirect, strictMode); } + JavascriptError::MapAndThrowError(scriptContext, hrCodeGen); + } + else + { Assert(funcBody != nullptr); funcBody->SetDisplayName(pszTitle); diff --git a/deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.cpp b/deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.cpp index 40f4256371d..4e12ac6f3d2 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/JavascriptArray.cpp @@ -477,6 +477,11 @@ namespace Js bool JavascriptArray::IsMissingItem(uint32 index) { + if (this->length <= index) + { + return false; + } + bool isIntArray = false, isFloatArray = false; this->GetArrayTypeAndConvert(&isIntArray, &isFloatArray); @@ -3163,11 +3168,14 @@ namespace Js if (scriptContext->GetConfig()->IsES6IsConcatSpreadableEnabled()) { - if (JavascriptOperators::IsConcatSpreadable(aItem)) + spreadableCheckedAndTrue = JavascriptOperators::IsConcatSpreadable(aItem) != FALSE; + if (!JavascriptNativeIntArray::Is(pDestArray)) { - spreadableCheckedAndTrue = true; + ConcatArgs(pDestArray, remoteTypeIds, args, scriptContext, idxArg, idxDest, spreadableCheckedAndTrue); + return pDestArray; } - else + + if(!spreadableCheckedAndTrue) { pDestArray->SetItem(idxDest, aItem, PropertyOperation_ThrowIfNotExtensible); idxDest = idxDest + 1; @@ -3236,11 +3244,14 @@ namespace Js if (scriptContext->GetConfig()->IsES6IsConcatSpreadableEnabled()) { - if (JavascriptOperators::IsConcatSpreadable(aItem)) + spreadableCheckedAndTrue = JavascriptOperators::IsConcatSpreadable(aItem) != FALSE; + if (!JavascriptNativeFloatArray::Is(pDestArray)) { - spreadableCheckedAndTrue = true; + ConcatArgs(pDestArray, remoteTypeIds, args, scriptContext, idxArg, idxDest, spreadableCheckedAndTrue); + return pDestArray; } - else + + if(!spreadableCheckedAndTrue) { pDestArray->SetItem(idxDest, aItem, PropertyOperation_ThrowIfNotExtensible); @@ -5320,6 +5331,11 @@ namespace Js pArr->SetHasNoMissingValues(false); } + // Above FillFromPrototypes call can change the length of the array. Our segment calculation below will + // not work with the stale length. Update the length. + // Note : since we are reversing the whole segment below - the functionality is not spec compliant already. + length = pArr->length; + SparseArraySegmentBase* seg = pArr->head; SparseArraySegmentBase *prevSeg = nullptr; SparseArraySegmentBase *nextSeg = nullptr; @@ -5801,7 +5817,7 @@ namespace Js // Prototype lookup for missing elements if (!pArr->HasNoMissingValues()) { - for (uint32 i = 0; i < newLen; i++) + for (uint32 i = 0; i < newLen && (i + start) < pArr->length; i++) { // array type might be changed in the below call to DirectGetItemAtFull // need recheck array type before checking array item [i + start] @@ -10150,6 +10166,9 @@ namespace Js if (JavascriptArray::Is(newObj)) { +#if ENABLE_COPYONACCESS_ARRAY + JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray(newObj); +#endif newArr = JavascriptArray::FromVar(newObj); } } @@ -10200,6 +10219,9 @@ namespace Js if (JavascriptArray::Is(newObj)) { +#if ENABLE_COPYONACCESS_ARRAY + JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray(newObj); +#endif newArr = JavascriptArray::FromVar(newObj); } } @@ -10310,6 +10332,9 @@ namespace Js // If the new object we created is an array, remember that as it will save us time setting properties in the object below if (JavascriptArray::Is(newObj)) { +#if ENABLE_COPYONACCESS_ARRAY + JavascriptLibrary::CheckAndConvertCopyOnAccessNativeIntArray(newObj); +#endif newArr = JavascriptArray::FromVar(newObj); } else if (TypedArrayBase::Is(newObj)) diff --git a/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.cpp b/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.cpp index f6debeb0824..c8893253e64 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.cpp @@ -12,13 +12,13 @@ namespace Js { JavascriptDate::JavascriptDate(double value, DynamicType * type) - : DynamicObject(type), m_date(value, type->GetScriptContext()) + : DynamicObject(type), m_date(value) { Assert(IsDateTypeId(type->GetTypeId())); } JavascriptDate::JavascriptDate(DynamicType * type) - : DynamicObject(type), m_date(0, type->GetScriptContext()) + : DynamicObject(type), m_date(0) { Assert(type->GetTypeId() == TypeIds_Date); } @@ -88,7 +88,7 @@ namespace Js // ES5 15.9.2.1: Date() should returns a string exactly the same as (new Date().toString()). JavascriptDate* pDate = NewInstanceAsConstructor(args, scriptContext, /* forceCurrentDate */ true); - JavascriptString* res = JavascriptDate::ToString(pDate); + JavascriptString* res = JavascriptDate::ToString(pDate, scriptContext); #if ENABLE_TTD if(scriptContext->ShouldPerformReplayAction()) @@ -228,7 +228,7 @@ namespace Js values[3] * 3600000 + values[4] * 60000 + values[5] * 1000 + values[6]); // Set the time. - pDate->m_date.SetTvLcl(timeValue); + pDate->m_date.SetTvLcl(timeValue, scriptContext); return pDate; } @@ -298,7 +298,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetDate(); + return date->m_date.GetDate(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -325,7 +325,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetDay(); + return date->m_date.GetDay(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -352,7 +352,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetFullYear(); + return date->m_date.GetFullYear(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -379,7 +379,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetYear(); + return date->m_date.GetYear(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -406,7 +406,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetHours(); + return date->m_date.GetHours(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -433,7 +433,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetDateMilliSeconds(); + return date->m_date.GetDateMilliSeconds(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -460,7 +460,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetMinutes(); + return date->m_date.GetMinutes(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -487,7 +487,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetMonth(); + return date->m_date.GetMonth(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -514,7 +514,7 @@ namespace Js if (!date->m_date.IsNaN()) { - return date->m_date.GetSeconds(); + return date->m_date.GetSeconds(scriptContext); } return scriptContext->GetLibrary()->GetNaN(); } @@ -1247,7 +1247,7 @@ namespace Js AssertMsg(args.Info.Count > 0, "Negative argument count"); return date->m_date.GetString( - DateImplementation::DateStringFormat::Default, + DateImplementation::DateStringFormat::Default, scriptContext, DateImplementation::DateTimeFlag::NoTime); } @@ -1273,7 +1273,7 @@ namespace Js JavascriptDate* date = JavascriptDate::FromVar(args[0]); AssertMsg(args.Info.Count > 0, "Negative argument count"); - return date->m_date.GetISOString(); + return date->m_date.GetISOString(scriptContext); } Var JavascriptDate::EntryToJSON(RecyclableObject* function, CallInfo callInfo, ...) @@ -1363,7 +1363,7 @@ namespace Js AssertMsg(args.Info.Count > 0, "Negative argument count"); return date->m_date.GetString( - DateImplementation::DateStringFormat::Locale, + DateImplementation::DateStringFormat::Locale, scriptContext, DateImplementation::DateTimeFlag::NoTime); } @@ -1411,18 +1411,20 @@ namespace Js #endif AssertMsg(args.Info.Count > 0, "Negative argument count"); - return JavascriptDate::ToLocaleString(date); + return JavascriptDate::ToLocaleString(date, scriptContext); } - JavascriptString* JavascriptDate::ToLocaleString(JavascriptDate* date) + JavascriptString* JavascriptDate::ToLocaleString(JavascriptDate* date, + ScriptContext* requestContext) { - return date->m_date.GetString(DateImplementation::DateStringFormat::Locale); + return date->m_date.GetString(DateImplementation::DateStringFormat::Locale, requestContext); } - JavascriptString* JavascriptDate::ToString(JavascriptDate* date) + JavascriptString* JavascriptDate::ToString(JavascriptDate* date, + ScriptContext* requestContext) { Assert(date); - return date->m_date.GetString(DateImplementation::DateStringFormat::Default); + return date->m_date.GetString(DateImplementation::DateStringFormat::Default, requestContext); } Var JavascriptDate::EntryToLocaleTimeString(RecyclableObject* function, CallInfo callInfo, ...) @@ -1470,7 +1472,7 @@ namespace Js AssertMsg(args.Info.Count > 0, "Negative argument count"); return date->m_date.GetString( - DateImplementation::DateStringFormat::Locale, + DateImplementation::DateStringFormat::Locale, scriptContext, DateImplementation::DateTimeFlag::NoDate); } @@ -1497,7 +1499,7 @@ namespace Js AssertMsg(args.Info.Count > 0, "Negative argument count"); return date->m_date.GetString( - DateImplementation::DateStringFormat::Default, + DateImplementation::DateStringFormat::Default, scriptContext, DateImplementation::DateTimeFlag::NoDate); } @@ -1533,7 +1535,7 @@ namespace Js AssertMsg(args.Info.Count > 0, "Negative argument count"); return date->m_date.GetString( - DateImplementation::DateStringFormat::GMT, + DateImplementation::DateStringFormat::GMT, scriptContext, DateImplementation::DateTimeFlag::None); } @@ -1583,7 +1585,7 @@ namespace Js JavascriptDate* date = JavascriptDate::FromVar(args[0]); AssertMsg(args.Info.Count > 0, "Negative argument count"); - return JavascriptDate::ToString(date); + return JavascriptDate::ToString(date, scriptContext); } BOOL JavascriptDate::TryInvokeRemotely(JavascriptMethod entryPoint, ScriptContext * scriptContext, Arguments & args, Var * result) @@ -1628,7 +1630,8 @@ namespace Js BOOL JavascriptDate::GetDiagValueString(StringBuilder* stringBuilder, ScriptContext* requestContext) { ENTER_PINNED_SCOPE(JavascriptString, valueStr); - valueStr = this->m_date.GetString(DateImplementation::DateStringFormat::Default); + valueStr = this->m_date.GetString( + DateImplementation::DateStringFormat::Default, requestContext); stringBuilder->Append(valueStr->GetString(), valueStr->GetLength()); LEAVE_PINNED_SCOPE(); return TRUE; diff --git a/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.h b/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.h index c086db4dd76..58fe70be2c8 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.h +++ b/deps/chakrashim/core/lib/Runtime/Library/JavascriptDate.h @@ -132,8 +132,8 @@ namespace Js static Var EntryValueOf(RecyclableObject* function, CallInfo callInfo, ...); static Var EntrySymbolToPrimitive(RecyclableObject* function, CallInfo callInfo, ...); - static JavascriptString* ToLocaleString(JavascriptDate* date); - static JavascriptString* ToString(JavascriptDate* date); + static JavascriptString* ToLocaleString(JavascriptDate* date, ScriptContext* requestContext); + static JavascriptString* ToString(JavascriptDate* date, ScriptContext* requestContext); virtual BOOL ToPrimitive(JavascriptHint hint, Var* result, ScriptContext * requestContext) override; virtual BOOL GetDiagValueString(StringBuilder* stringBuilder, ScriptContext* requestContext) override; diff --git a/deps/chakrashim/core/lib/Runtime/Library/JavascriptFunction.cpp b/deps/chakrashim/core/lib/Runtime/Library/JavascriptFunction.cpp index 94215318990..f260a077f00 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/JavascriptFunction.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/JavascriptFunction.cpp @@ -1111,6 +1111,7 @@ namespace Js PROBE_STACK(scriptContext, outArgs.Info.Count * sizeof(Var) + Js::Constants::MinStackDefault); // args + function call outArgsSize = outArgs.Info.Count * sizeof(Var); outArgs.Values = (Var*)_alloca(outArgsSize); + ZeroMemory(outArgs.Values, outArgsSize); } else { @@ -2787,9 +2788,9 @@ void __cdecl _alloca_probe_16() Var args = nullptr; //Create a copy of the arguments and return it. - CallInfo const *callInfo = walker.GetCallInfo(); + const CallInfo callInfo = walker.GetCallInfo(); args = JavascriptOperators::LoadHeapArguments( - this, callInfo->Count - 1, + this, callInfo.Count - 1, walker.GetJavascriptArgs(), scriptContext->GetLibrary()->GetNull(), scriptContext->GetLibrary()->GetNull(), diff --git a/deps/chakrashim/core/lib/Runtime/Library/JavascriptLibrary.cpp b/deps/chakrashim/core/lib/Runtime/Library/JavascriptLibrary.cpp index 0281c3e9551..4fe94f21e09 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/JavascriptLibrary.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/JavascriptLibrary.cpp @@ -1053,7 +1053,6 @@ namespace Js // during PostCollectCallBack before Dispose deleting the script context. scriptContext->ResetWeakReferenceDictionaryList(); scriptContext->SetIsFinalized(); - scriptContext->GetThreadContext()->UnregisterScriptContext(scriptContext); scriptContext->MarkForClose(); } } diff --git a/deps/chakrashim/core/lib/Runtime/Library/JavascriptProxy.cpp b/deps/chakrashim/core/lib/Runtime/Library/JavascriptProxy.cpp index dddde80d479..9186aaffea6 100644 --- a/deps/chakrashim/core/lib/Runtime/Library/JavascriptProxy.cpp +++ b/deps/chakrashim/core/lib/Runtime/Library/JavascriptProxy.cpp @@ -1821,8 +1821,15 @@ namespace Js return JavascriptOperators::SetItem(receiver, targetObj, indexVal, newValue, scriptContext, PropertyOperationFlags::PropertyOperation_None, skipPrototypeCheck); } case SetPropertyTrapKind::SetPropertyWPCacheKind: + { + Var name = GetName(requestContext, propertyId); + if (!JavascriptString::Is(name) || !VirtualTableInfo::HasVirtualTable(JavascriptString::FromVar(name))) + { + name = nullptr; + } return JavascriptOperators::SetPropertyWPCache(receiver, targetObj, propertyId, newValue, requestContext, - static_cast(GetName(requestContext, propertyId)), PropertyOperationFlags::PropertyOperation_None); + static_cast(name), PropertyOperationFlags::PropertyOperation_None); + } default: Assert(FALSE); } diff --git a/deps/chakrashim/core/pal/src/thread/pal_thread.cpp b/deps/chakrashim/core/pal/src/thread/pal_thread.cpp index 21337b2b176..c578ab5dec5 100644 --- a/deps/chakrashim/core/pal/src/thread/pal_thread.cpp +++ b/deps/chakrashim/core/pal/src/thread/pal_thread.cpp @@ -2834,8 +2834,27 @@ int CorUnix::CThreadMachExceptionHandlers::GetIndexOfHandler(exception_mask_t bm #endif // HAVE_MACH_EXCEPTIONS +#ifndef __APPLE__ +#define THREAD_LOCAL thread_local +#else +#define THREAD_LOCAL _Thread_local +#endif + +#ifndef __IOS__ +static THREAD_LOCAL ULONG_PTR s_cachedHighLimit = 0; +static THREAD_LOCAL ULONG_PTR s_cachedLowLimit = 0; +#endif + void GetCurrentThreadStackLimits(ULONG_PTR* lowLimit, ULONG_PTR* highLimit) { +#ifndef __IOS__ + if (s_cachedLowLimit) + { + *lowLimit = s_cachedLowLimit; + *highLimit = s_cachedHighLimit; + return; + } +#endif pthread_t currentThreadHandle = pthread_self(); #ifdef __APPLE__ @@ -2866,14 +2885,12 @@ void GetCurrentThreadStackLimits(ULONG_PTR* lowLimit, ULONG_PTR* highLimit) *lowLimit = (ULONG_PTR) stackend; *highLimit = (ULONG_PTR) stackbase; #endif -} -#ifndef __APPLE__ -#define THREAD_LOCAL thread_local -#else -#define THREAD_LOCAL _Thread_local +#ifndef __IOS__ + s_cachedLowLimit = *lowLimit; + s_cachedHighLimit = *highLimit; #endif -static THREAD_LOCAL ULONG_PTR s_cachedThreadStackHighLimit = 0; +} bool IsAddressOnStack(ULONG_PTR address) { @@ -2882,17 +2899,12 @@ bool IsAddressOnStack(ULONG_PTR address) // bounds to speed up checking if a given address is on the stack // The semantics of IsAddressOnStack is that we care if a given address is // in the range of the current stack pointer - if (s_cachedThreadStackHighLimit == 0) - { - ULONG_PTR lowLimit, highLimit; - GetCurrentThreadStackLimits(&lowLimit, &highLimit); - - s_cachedThreadStackHighLimit = highLimit; - } + ULONG_PTR lowLimit, highLimit; + GetCurrentThreadStackLimits(&lowLimit, &highLimit); ULONG_PTR currentStackPtr = GetCurrentSP(); - if (currentStackPtr <= address && address < s_cachedThreadStackHighLimit) + if (currentStackPtr <= address && address < highLimit) { return true; } diff --git a/deps/chakrashim/core/test/Array/Array_TypeConfusion_bugs.js b/deps/chakrashim/core/test/Array/Array_TypeConfusion_bugs.js index e1867424929..43430fbc33a 100644 --- a/deps/chakrashim/core/test/Array/Array_TypeConfusion_bugs.js +++ b/deps/chakrashim/core/test/Array/Array_TypeConfusion_bugs.js @@ -593,5 +593,32 @@ var tests = [ assert.areEqual(101, arr.length); } }, + { + name: "Heap overread when splice mutates the array when executing slice", + body: function () + { + var getterCalled = false; + var a = [1, 2]; + for (var i = 0; i < 100 * 1024; i++) { + a.push(i); + } + delete a[0]; // Make a missing item + var protoObj = [11]; + Object.defineProperty(protoObj, '0', { + get : function () { + getterCalled = true; + Object.setPrototypeOf(a, Array.prototype); + a.splice(0); // head seg is now length=0 + return 42; + }, + configurable : true + }); + Object.setPrototypeOf(a, protoObj); + var b = a.slice(); + assert.isTrue(getterCalled); + assert.areEqual(0, a.length, "Getter will splice the array to zero length"); + assert.areEqual(100 * 1024 + 2, b.length, "Validating that slice will return the full array even though splice is deleting the whole array"); + } + }, ]; testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); diff --git a/deps/chakrashim/core/test/Array/array_conv_src.js b/deps/chakrashim/core/test/Array/array_conv_src.js new file mode 100644 index 00000000000..4b9610902b5 --- /dev/null +++ b/deps/chakrashim/core/test/Array/array_conv_src.js @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +"use strict"; + +function func(a, b, c) { + a[0] = 1.2; + b[0] = c; + a[1] = 2.2; + a[0] = 2.3023e-320; +} + +function main() { + var a = [1.1, 2.2]; + var b = new Uint32Array(100); + + // force to optimize + for (var i = 0; i < 0x10000; i++) + func(a, b, i); + + func(a, b, { + valueOf: function () { + a[0] = {}; + + return 0; + } + }); + + a[0].toString(); +} + +main(); + +WScript.Echo('pass'); \ No newline at end of file diff --git a/deps/chakrashim/core/test/Array/rlexe.xml b/deps/chakrashim/core/test/Array/rlexe.xml index 113ba7db645..3e990826167 100644 --- a/deps/chakrashim/core/test/Array/rlexe.xml +++ b/deps/chakrashim/core/test/Array/rlexe.xml @@ -733,4 +733,9 @@ bug_9575461.js + + + array_conv_src.js + + diff --git a/deps/chakrashim/core/test/AsmJs/nested.baseline b/deps/chakrashim/core/test/AsmJs/nested.baseline new file mode 100644 index 00000000000..898172b0cbf --- /dev/null +++ b/deps/chakrashim/core/test/AsmJs/nested.baseline @@ -0,0 +1,2 @@ +closure functions are not allowed +Asm.js compilation failed. diff --git a/deps/chakrashim/core/test/AsmJs/nested.js b/deps/chakrashim/core/test/AsmJs/nested.js new file mode 100644 index 00000000000..33c1f5378fe --- /dev/null +++ b/deps/chakrashim/core/test/AsmJs/nested.js @@ -0,0 +1,12 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +function AsmModule() { + "use asm"; + function f() { + function g() { } + } +} +AsmModule(); diff --git a/deps/chakrashim/core/test/AsmJs/qmarkbug.baseline b/deps/chakrashim/core/test/AsmJs/qmarkbug.baseline index 7bb6ab56132..3fb209591f2 100644 --- a/deps/chakrashim/core/test/AsmJs/qmarkbug.baseline +++ b/deps/chakrashim/core/test/AsmJs/qmarkbug.baseline @@ -1,11 +1,11 @@ -qmarkbug.js(9, 3) +qmarkbug.js(6, 5) Asm.js Compilation Error function : None::f Conditional expressions must be of type int, double, or float Asm.js compilation failed. -qmarkbug.js(25, 3) +qmarkbug.js(6, 5) Asm.js Compilation Error function : None::f Conditional expressions must be of type int, double, or float diff --git a/deps/chakrashim/core/test/AsmJs/qmarkbug.js b/deps/chakrashim/core/test/AsmJs/qmarkbug.js index 6a35e3e1f87..58a646c2aeb 100644 --- a/deps/chakrashim/core/test/AsmJs/qmarkbug.js +++ b/deps/chakrashim/core/test/AsmJs/qmarkbug.js @@ -3,34 +3,36 @@ // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- -var asmModule = -(function(stdlib, foreign, heap) { 'use asm'; var Uint8ArrayView = new stdlib.Uint8Array(heap); - var Int16ArrayView = new stdlib.Int16Array(heap); - function f(d0, i1) - { - d0 = +d0; - i1 = i1|0; - var i4 = 0; - i4 = ((0) ? 0 : ((Uint8ArrayView[0]))); - return +((-7.555786372591432e+22)); - } - return f; }) +eval(` +(function(stdlib, foreign, heap) { + 'use asm'; + var Uint8ArrayView = new stdlib.Uint8Array(heap); + var Int16ArrayView = new stdlib.Int16Array(heap); + function f(d0, i1) + { + d0 = +d0; + i1 = i1|0; + var i4 = 0; + i4 = ((0) ? 0 : ((Uint8ArrayView[0]))); + return +((-7.555786372591432e+22)); + } + return f; +})(this, {}, new ArrayBuffer(1<<24)); +`); - var asmHeap = new ArrayBuffer(1<<24); - var asmFun = asmModule(this, {}, asmHeap); - asmFun(); - var asmModule = -(function(stdlib, foreign, heap) { 'use asm'; var Uint8ArrayView = new stdlib.Uint8Array(heap); - var Int16ArrayView = new stdlib.Int16Array(heap); - function f(d0, i1) - { - d0 = +d0; - i1 = i1|0; - var i4 = 0; - i4 = ((0) ? ((Uint8ArrayView[0])): 0 ); - return +((-7.555786372591432e+22)); - } - return f; }) - - var asmFun = asmModule(this, {}, asmHeap); - asmFun(); +eval(` +(function(stdlib, foreign, heap) { + 'use asm'; + var Uint8ArrayView = new stdlib.Uint8Array(heap); + var Int16ArrayView = new stdlib.Int16Array(heap); + function f(d0, i1) + { + d0 = +d0; + i1 = i1|0; + var i4 = 0; + i4 = ((0) ? ((Uint8ArrayView[0])): 0 ); + return +((-7.555786372591432e+22)); + } + return f; +})(this, {}, new ArrayBuffer(1<<24)); +`); diff --git a/deps/chakrashim/core/test/AsmJs/rlexe.xml b/deps/chakrashim/core/test/AsmJs/rlexe.xml index bde05377672..1518bbdd524 100644 --- a/deps/chakrashim/core/test/AsmJs/rlexe.xml +++ b/deps/chakrashim/core/test/AsmJs/rlexe.xml @@ -819,4 +819,11 @@ bugGH2270.js + + + nested.js + nested.baseline + -forcedeferparse -testtrace:asmjs -simdjs + + diff --git a/deps/chakrashim/core/test/AsmJs/shadowingBug.baseline b/deps/chakrashim/core/test/AsmJs/shadowingBug.baseline index 5d7b043a3af..53dca1b58f2 100644 --- a/deps/chakrashim/core/test/AsmJs/shadowingBug.baseline +++ b/deps/chakrashim/core/test/AsmJs/shadowingBug.baseline @@ -1,18 +1,18 @@ -shadowingBug.js(7, 97) +shadowingBug.js(1, 97) Asm.js Compilation Error function : None::f1 Invalid identifier f64 Asm.js compilation failed. +0 -shadowingBug.js(8, 97) +shadowingBug.js(1, 97) Asm.js Compilation Error function : None::f1 Invalid identifier f64 Asm.js compilation failed. +NaN Var declaration with non-constant Asm.js compilation failed. 0 -NaN -0 0 diff --git a/deps/chakrashim/core/test/AsmJs/shadowingBug.js b/deps/chakrashim/core/test/AsmJs/shadowingBug.js index 8302c010a85..aa995384ede 100644 --- a/deps/chakrashim/core/test/AsmJs/shadowingBug.js +++ b/deps/chakrashim/core/test/AsmJs/shadowingBug.js @@ -4,9 +4,9 @@ //------------------------------------------------------------------------------------------------------- var buffer = new ArrayBuffer(1<<20); -print((function (stdlib,foreign,buffer) { "use asm"; var f64 = new stdlib.Float64Array(buffer); function f1(){ var f64 = 1.; f64[0] = 0.0;return +0.0;} return f1;})(this,{},buffer)()); -print((function (stdlib,foreign,buffer) { "use asm"; var f64 = new stdlib.Float64Array(buffer); function f1(){ var f64 = 1.; return +f64[0];} return f1;})(this,{},buffer)()); -print((function (stdlib,foreign,buffer) { "use asm"; const a = 10; function f1(){ var a =0; var b = a; return b|0;} return f1;})(this,{},buffer)()); +eval('print((function (stdlib,foreign,buffer) { "use asm"; var f64 = new stdlib.Float64Array(buffer); function f1(){ var f64 = 1.; f64[0] = 0.0;return +0.0;} return f1;})(this,{},buffer)())'); +eval('print((function (stdlib,foreign,buffer) { "use asm"; var f64 = new stdlib.Float64Array(buffer); function f1(){ var f64 = 1.; return +f64[0];} return f1;})(this,{},buffer)())'); +eval('print((function (stdlib,foreign,buffer) { "use asm"; const a = 10; function f1(){ var a =0; var b = a; return b|0;} return f1;})(this,{},buffer)())'); var f64Arr = new Float64Array(buffer); print(f64Arr[0]); \ No newline at end of file diff --git a/deps/chakrashim/core/test/Date/marshalbug.js b/deps/chakrashim/core/test/Date/marshalbug.js new file mode 100644 index 00000000000..1e9d7c58289 --- /dev/null +++ b/deps/chakrashim/core/test/Date/marshalbug.js @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +const crossSiteDate = + WScript.LoadScript("var x = new Date()", "samethread").x; + +// Run every Date method on the cross-site instance +Object.getOwnPropertyNames(Date.prototype) + .filter(name => !name.match(/^set/)) + .forEach(name => { + print(name); + try { + print(Date.prototype[name].call(crossSiteDate)); + } catch(e) { + // Ignore. Just to catch assertions on debug build. + } + }); diff --git a/deps/chakrashim/core/test/Date/rlexe.xml b/deps/chakrashim/core/test/Date/rlexe.xml index 0adbf948480..f2d1856d2d2 100644 --- a/deps/chakrashim/core/test/Date/rlexe.xml +++ b/deps/chakrashim/core/test/Date/rlexe.xml @@ -108,4 +108,13 @@ + + + marshalbug.js + + -nonative -intl- + + exclude_fre,exclude_dynapogo + + diff --git a/deps/chakrashim/core/test/es6/default-splitscope.js b/deps/chakrashim/core/test/es6/default-splitscope.js index 0a5da26a816..ebd632f758b 100644 --- a/deps/chakrashim/core/test/es6/default-splitscope.js +++ b/deps/chakrashim/core/test/es6/default-splitscope.js @@ -159,6 +159,23 @@ var tests = [ return a; } assert.areEqual(10, f11()(), "Recursive call to the function from the body scope returns the right value when eval is there in the body"); + + // [aneeshd] Commenting the test case to unblock the build + // function f13() { + // var a = function jnvgfg(sfgnmj = function ccunlk() { jnvgfg(undefined, 1); }, b) { + // if (b) { + // assert.areEqual(undefined, jnvgfg, "This refers to the instance in the body and the value of the function expression is not copied over"); + // } + // var jnvgfg = 10; + // if (!b) { + // sfgnmj(); + // return 100; + // } + // }; + // assert.areEqual(100, a(), "After the recursion the right value is returned by the split scoped function"); + // }; + // f13(); + } }, { diff --git a/deps/chakrashim/core/test/es6/lambda-params-shadow.js b/deps/chakrashim/core/test/es6/lambda-params-shadow.js index 1e45ab40bf3..69c07a584e5 100644 --- a/deps/chakrashim/core/test/es6/lambda-params-shadow.js +++ b/deps/chakrashim/core/test/es6/lambda-params-shadow.js @@ -18,7 +18,14 @@ class B extends A { } } let b = new B(); -if (count !== 3) { +class async extends A { + constructor() { + super(); + let Q = async A => { A }; + } +} +let a = new async(); +if (count !== 4) { WScript.Echo('fail'); } diff --git a/deps/chakrashim/core/test/es6/proxybugs.js b/deps/chakrashim/core/test/es6/proxybugs.js index b7db667450b..11419409484 100644 --- a/deps/chakrashim/core/test/es6/proxybugs.js +++ b/deps/chakrashim/core/test/es6/proxybugs.js @@ -1,107 +1,117 @@ -//------------------------------------------------------------------------------------------------------- -// Copyright (C) Microsoft. All rights reserved. -// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. -//------------------------------------------------------------------------------------------------------- - -WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js"); - -var tests = [ - { - name: "Setting proxy object on Map and WeakMap", - body() { - [WeakMap, Map].forEach(function(ctor) { - var target = {}; - let p = new Proxy(target, {}); - let map = new ctor(); - map.set(p, 101); - assert.areEqual(map.get(p), 101, ctor.name + " map should be able to set and get the proxy object"); - p.x = 20; - assert.areEqual(target.x, 20, "target object should work as expected even after proxy object is added to map"); - }); - } - }, - { - name: "Setting proxy object on Map and WeakMap - multiple sets and delete", - body() { - [WeakMap, Map].forEach(function(ctor) { - var target = {}; - let p = new Proxy(target, {}); - let map = new ctor(); - map.set(p, 101); - assert.areEqual(map.get(p), 101); - map.delete(p); - assert.areEqual(map.get(p), undefined, ctor.name + " map can remove the proxy object properly"); - map.set(p, 102); - assert.areEqual(map.get(p), 102, ctor.name + " proxy object can be set again and it returns 102"); - p.x = 20; - assert.areEqual(target.x, 20, "target object should work as expected even after proxy object is added to map"); - }); - } - }, - { - name: "Assertion validation : returning descriptor during getOwnPropertyDescriptor should not pollute the descriptor", - body() { - var target = {}; - var handler = {}; - var getOwnPropertyDescriptorCalled = false; - handler['defineProperty'] = function () { - assert.fail("This function will not be called as 'getOwnPropertyDescriptor' will add accessor"); - }; - - handler['getOwnPropertyDescriptor'] = function (t, property) { - getOwnPropertyDescriptorCalled = true; - Object.defineProperty(t, 'abc', { set: function () { } }); - return Reflect.getOwnPropertyDescriptor(t, property); - }; - - var proxy = new Proxy(target, handler); - proxy.abc = undefined; - assert.isTrue(getOwnPropertyDescriptorCalled); - } - }, - { - name: "Assertion validation : returning descriptor with writable false should not defineProperty again.", - body() { - var target = {}; - var handler = {}; - var getOwnPropertyDescriptorCalled = false; - handler['defineProperty'] = function () { - assert.fail("This function will not be called as 'getOwnPropertyDescriptor' will add property with writable false"); - }; - - handler['getOwnPropertyDescriptor'] = function (t, property) { - getOwnPropertyDescriptorCalled = true; - Object.defineProperty(t, 'abc', { value : 1, writable : false }); - return Reflect.getOwnPropertyDescriptor(t, property); - }; - - var proxy = new Proxy(target, handler); - proxy.abc = undefined; - assert.isTrue(getOwnPropertyDescriptorCalled); - } - }, - { - name: "No property found at getOwnPropertyDescriptor will call defineProperty", - body() { - var target = {}; - var handler = {}; - var definePropertyCalled = false; - var getOwnPropertyDescriptorCalled = false; - handler['defineProperty'] = function () { - definePropertyCalled = true; - }; - - handler['getOwnPropertyDescriptor'] = function (t, property) { - getOwnPropertyDescriptorCalled = true; - return Reflect.getOwnPropertyDescriptor(t, property); - }; - - var proxy = new Proxy(target, handler); - proxy.abc = undefined; - assert.isTrue(definePropertyCalled); - assert.isTrue(getOwnPropertyDescriptorCalled); - } - }, +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js"); + +var tests = [ + { + name: "Setting proxy object on Map and WeakMap", + body() { + [WeakMap, Map].forEach(function(ctor) { + var target = {}; + let p = new Proxy(target, {}); + let map = new ctor(); + map.set(p, 101); + assert.areEqual(map.get(p), 101, ctor.name + " map should be able to set and get the proxy object"); + p.x = 20; + assert.areEqual(target.x, 20, "target object should work as expected even after proxy object is added to map"); + }); + } + }, + { + name: "Setting proxy object on Map and WeakMap - multiple sets and delete", + body() { + [WeakMap, Map].forEach(function(ctor) { + var target = {}; + let p = new Proxy(target, {}); + let map = new ctor(); + map.set(p, 101); + assert.areEqual(map.get(p), 101); + map.delete(p); + assert.areEqual(map.get(p), undefined, ctor.name + " map can remove the proxy object properly"); + map.set(p, 102); + assert.areEqual(map.get(p), 102, ctor.name + " proxy object can be set again and it returns 102"); + p.x = 20; + assert.areEqual(target.x, 20, "target object should work as expected even after proxy object is added to map"); + }); + } + }, + { + name: "Assertion validation : returning descriptor during getOwnPropertyDescriptor should not pollute the descriptor", + body() { + var target = {}; + var handler = {}; + var getOwnPropertyDescriptorCalled = false; + handler['defineProperty'] = function () { + assert.fail("This function will not be called as 'getOwnPropertyDescriptor' will add accessor"); + }; + + handler['getOwnPropertyDescriptor'] = function (t, property) { + getOwnPropertyDescriptorCalled = true; + Object.defineProperty(t, 'abc', { set: function () { } }); + return Reflect.getOwnPropertyDescriptor(t, property); + }; + + var proxy = new Proxy(target, handler); + proxy.abc = undefined; + assert.isTrue(getOwnPropertyDescriptorCalled); + } + }, + { + name: "Assertion validation : returning descriptor with writable false should not defineProperty again.", + body() { + var target = {}; + var handler = {}; + var getOwnPropertyDescriptorCalled = false; + handler['defineProperty'] = function () { + assert.fail("This function will not be called as 'getOwnPropertyDescriptor' will add property with writable false"); + }; + + handler['getOwnPropertyDescriptor'] = function (t, property) { + getOwnPropertyDescriptorCalled = true; + Object.defineProperty(t, 'abc', { value : 1, writable : false }); + return Reflect.getOwnPropertyDescriptor(t, property); + }; + + var proxy = new Proxy(target, handler); + proxy.abc = undefined; + assert.isTrue(getOwnPropertyDescriptorCalled); + } + }, + { + name: "No property found at getOwnPropertyDescriptor will call defineProperty", + body() { + var target = {}; + var handler = {}; + var definePropertyCalled = false; + var getOwnPropertyDescriptorCalled = false; + handler['defineProperty'] = function () { + definePropertyCalled = true; + }; + + handler['getOwnPropertyDescriptor'] = function (t, property) { + getOwnPropertyDescriptorCalled = true; + return Reflect.getOwnPropertyDescriptor(t, property); + }; + + var proxy = new Proxy(target, handler); + proxy.abc = undefined; + assert.isTrue(definePropertyCalled); + assert.isTrue(getOwnPropertyDescriptorCalled); + } + }, + { + name: "Type confusion in JavascriptProxy::SetPropertyTrap when using a Symbol", + body: function () { + try{ Reflect.set((new Proxy({}, {has: function(){ return true; }})), 'abc', 0x44444444, new Uint32Array); } catch(e){} + try{ Reflect.set((new Proxy({}, {has: function(){ return true; }})), 'abc', 0x44444444, new Uint32Array); } catch(e){} + + var obj1 = Object.create(new Proxy({}, {})); + obj1[Symbol.species] = 0; + } + }, { name: "Assertion validation : revoking the proxy in getPrototypeOf trap", body() { @@ -119,190 +129,190 @@ var tests = [ assert.isTrue(trapCalled); } }, - { - name: "Assertion validation : revoking the proxy in setPrototypeOf trap", - body() { - var trapCalled = false; - var handler = { - setPrototypeOf : function(a, b) { - trapCalled = true; - obj.revoke(); - return true; - } - }; - - var obj = Proxy.revocable({}, handler); - var ret = Object.setPrototypeOf(obj.proxy, {}); - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in isExtensible trap", - body() { - var trapCalled = false; - var handler = { - isExtensible : function(a, b) { - trapCalled = true; - obj.revoke(); - return true; - } - }; - - var obj = Proxy.revocable({}, handler); - var ret = Object.isExtensible(obj.proxy); - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in preventExtensions trap", - body() { - var trapCalled = false; - var handler = { - preventExtensions : function(a, b) { - trapCalled = true; - obj.revoke(); - } - }; - - var obj = Proxy.revocable({}, handler); - Object.preventExtensions(obj.proxy); - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in getOwnPropertyDescriptor trap", - body() { - var trapCalled = false; - var handler = { - getOwnPropertyDescriptor : function(a, b, c) { - trapCalled = true; - obj.revoke(); - } - }; - - var obj = Proxy.revocable({}, handler); - assert.throws( () => { Object.getOwnPropertyDescriptor(obj.proxy, 'a'); }, TypeError); - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in has trap", - body() { - var trapCalled = false; - var handler = { - has : function(a, b, c) { - trapCalled = true; - obj.revoke(); - return false; - } - }; - - var obj = Proxy.revocable({}, handler); - 'a' in obj.proxy; - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in get trap", - body() { - var trapCalled = false; - var handler = { - get : function (a, b, c) { - trapCalled = true; - obj.revoke(); - return {}; - } - }; - - var obj = Proxy.revocable({}, handler); - var ret = obj.proxy.a; - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in set trap", - body() { - var trapCalled = false; - var handler = { - set : function (a, b, c) { - trapCalled = true; - obj.revoke(); - return {}; - } - }; - - var obj = Proxy.revocable({}, handler); - obj.proxy.a = 10; - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in deleteProperty trap", - body() { - var trapCalled = false; - var handler = { - deleteProperty : function (a, b, c) { - trapCalled = true; - obj.revoke(); - return {}; - } - }; - - var obj = Proxy.revocable({}, handler); - delete obj.proxy.a; - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in ownKeys trap", - body() { - var trapCalled = false; - var handler = { - ownKeys : function (a, b, c) { - trapCalled = true; - obj.revoke(); - return {}; - } - }; - - var obj = Proxy.revocable({}, handler); - Object.keys(obj.proxy); - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in apply trap", - body() { - var trapCalled = false; - var handler = { - get apply () { - trapCalled = true; - obj.revoke(); - } - }; - - var obj = Proxy.revocable(() => {}, handler); - obj.proxy(); - assert.isTrue(trapCalled); - } - }, - { - name: "Assertion validation : revoking the proxy in construct trap", - body() { - var trapCalled = false; - var handler = { - get construct () { - trapCalled = true; - obj.revoke(); - return () => { return {}; }; - } - }; - - var obj = Proxy.revocable(() => {}, handler); - new obj.proxy(); - assert.isTrue(trapCalled); - } - }, -]; - -testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); + { + name: "Assertion validation : revoking the proxy in setPrototypeOf trap", + body() { + var trapCalled = false; + var handler = { + setPrototypeOf : function(a, b) { + trapCalled = true; + obj.revoke(); + return true; + } + }; + + var obj = Proxy.revocable({}, handler); + var ret = Object.setPrototypeOf(obj.proxy, {}); + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in isExtensible trap", + body() { + var trapCalled = false; + var handler = { + isExtensible : function(a, b) { + trapCalled = true; + obj.revoke(); + return true; + } + }; + + var obj = Proxy.revocable({}, handler); + var ret = Object.isExtensible(obj.proxy); + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in preventExtensions trap", + body() { + var trapCalled = false; + var handler = { + preventExtensions : function(a, b) { + trapCalled = true; + obj.revoke(); + } + }; + + var obj = Proxy.revocable({}, handler); + Object.preventExtensions(obj.proxy); + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in getOwnPropertyDescriptor trap", + body() { + var trapCalled = false; + var handler = { + getOwnPropertyDescriptor : function(a, b, c) { + trapCalled = true; + obj.revoke(); + } + }; + + var obj = Proxy.revocable({}, handler); + assert.throws( () => { Object.getOwnPropertyDescriptor(obj.proxy, 'a'); }, TypeError); + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in has trap", + body() { + var trapCalled = false; + var handler = { + has : function(a, b, c) { + trapCalled = true; + obj.revoke(); + return false; + } + }; + + var obj = Proxy.revocable({}, handler); + 'a' in obj.proxy; + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in get trap", + body() { + var trapCalled = false; + var handler = { + get : function (a, b, c) { + trapCalled = true; + obj.revoke(); + return {}; + } + }; + + var obj = Proxy.revocable({}, handler); + var ret = obj.proxy.a; + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in set trap", + body() { + var trapCalled = false; + var handler = { + set : function (a, b, c) { + trapCalled = true; + obj.revoke(); + return {}; + } + }; + + var obj = Proxy.revocable({}, handler); + obj.proxy.a = 10; + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in deleteProperty trap", + body() { + var trapCalled = false; + var handler = { + deleteProperty : function (a, b, c) { + trapCalled = true; + obj.revoke(); + return {}; + } + }; + + var obj = Proxy.revocable({}, handler); + delete obj.proxy.a; + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in ownKeys trap", + body() { + var trapCalled = false; + var handler = { + ownKeys : function (a, b, c) { + trapCalled = true; + obj.revoke(); + return {}; + } + }; + + var obj = Proxy.revocable({}, handler); + Object.keys(obj.proxy); + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in apply trap", + body() { + var trapCalled = false; + var handler = { + get apply () { + trapCalled = true; + obj.revoke(); + } + }; + + var obj = Proxy.revocable(() => {}, handler); + obj.proxy(); + assert.isTrue(trapCalled); + } + }, + { + name: "Assertion validation : revoking the proxy in construct trap", + body() { + var trapCalled = false; + var handler = { + get construct () { + trapCalled = true; + obj.revoke(); + return () => { return {}; }; + } + }; + + var obj = Proxy.revocable(() => {}, handler); + new obj.proxy(); + assert.isTrue(trapCalled); + } + }, +]; + +testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" }); diff --git a/deps/chakrashim/core/test/runcitests.cmd b/deps/chakrashim/core/test/runcitests.cmd index 4be71dcdbd7..c9180b06505 100644 --- a/deps/chakrashim/core/test/runcitests.cmd +++ b/deps/chakrashim/core/test/runcitests.cmd @@ -28,8 +28,14 @@ @echo off setlocal +if "%TF_BUILD_BINARIESDIRECTORY%" == "" ( + echo TF_BUILD_BINARIESDIRECTORY is required for this script to work correctly. + exit /b 1 +) + set _RootDir=%~dp0.. set _StagingDir=%TF_BUILD_BINARIESDIRECTORY% +REM %TF_BUILD_DROPLOCATION% is not required -- used only for an informational message set _DropRootDir=%TF_BUILD_DROPLOCATION% set _HadFailures=0 @@ -82,7 +88,7 @@ set _HadFailures=0 call :summarizeLogs summary.log ) else ( - call :runTests %_BuildArch% %_BuildType% + call :runTests %_BuildArch% %_BuildType% %_ExtraArgs% call :runNativeTests %_BuildArch% %_BuildType% call :summarizeLogs summary.%_BuildArch%%_BuildType%.log ) @@ -114,7 +120,7 @@ set _HadFailures=0 :: ============================================================================ :runTests - call :do %_TestDir%\runtests.cmd -%1%2 -quiet -cleanupall -binDir %_StagingDir%\bin + call :do %_TestDir%\runtests.cmd -%1%2 %3 -quiet -cleanupall -binDir %_StagingDir%\bin if ERRORLEVEL 1 set _HadFailures=1 @@ -229,7 +235,7 @@ set _HadFailures=0 if /i "%1" == "-all" set _RunAll=1& goto :ArgOk - if not "%1" == "" echo Unknown argument: %1 & set fShowGetHelp=1 + if not "%1" == "" set _ExtraArgs=%_ExtraArgs% %1& goto :ArgOk goto :eof diff --git a/deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.analyze.txt b/deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.analyze.txt deleted file mode 100644 index 1e80875560d..00000000000 --- a/deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.analyze.txt +++ /dev/null @@ -1,460 +0,0 @@ -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: ScopeObjectChain -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: ScopeObjectChain -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: ScopeObjectChain -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: ScopeObjectChain -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: ScopeObjectChain -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: DebuggerScope -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocFinalizedWithBarrierInlined -Type: FunctionEntryPointInfo -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocWithBarrier -Type: PropertyIdArray -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrs -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocZeroWithBarrier -Type: AuxPtrsFix -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWithBarrier -Type: PropertyIdOnRegSlotsContainer -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: AuxStatementData -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: AuxStatementData -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocWithBarrier -Type: List -AllocFunc: AllocFinalizedWithBarrierInlined -Type: FunctionBody -AllocFunc: AllocWithBarrier -Type: ProxyEntryPointInfo -AllocFunc: AllocWithBarrier -Type: SynchronizableList -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWithBarrier -Type: BaseDictionary -AllocFunc: AllocFinalizedWithBarrierInlined -Type: FunctionEntryPointInfo -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocFinalizedWithBarrierInlined -Type: FunctionEntryPointInfo -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocFinalizedWithBarrierInlined -Type: ParseableFunctionInfo -AllocFunc: AllocFinalizedWithBarrierInlined -Type: DeferDeserializeFunctionInfo -AllocFunc: AllocWithBarrier -Type: ProxyEntryPointInfo -AllocFunc: AllocWeakReferenceEntry -Type: RecyclerWeakReferenceBase -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: Alloc -Type: SListNode -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: Alloc -Type: SListNode -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo -AllocFunc: AllocWithBarrier -Type: PolymorphicInlineCacheInfo diff --git a/deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.check.txt b/deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.check.txt deleted file mode 100644 index 5eb692af252..00000000000 --- a/deps/chakrashim/core/tools/RecyclerChecker/FunctionBody.check.txt +++ /dev/null @@ -1,583 +0,0 @@ -Type with barrier found: "Js::InlineCachePointerArray" -Type with barrier found: "Js::AuxPtrsFix" -Type with barrier found: "Js::AuxPtrs" -In "Js::AuxPtrs::AllocAuxPtrFix" - Allocating "AuxPtrs16" in write barriered memory -In "Js::AuxPtrs::AllocAuxPtrFix" - Allocating "AuxPtrs32" in write barriered memory -In "Js::AuxPtrs::AllocAuxPtr" - Allocating "AuxPtrsT" in write barriered memory -In "Js::AuxPtrs::AllocAuxPtr" - Allocating "AuxPtrsT" in write barriered memory -Type with barrier found: "Js::CompactCounters" -Type with barrier found: "Js::FunctionProxy" -Type with barrier found: "Js::ParseableFunctionInfo" -Type with barrier found: "Js::FunctionBody" -In "Js::FunctionBody::StatementMap::New" - Allocating "struct Js::FunctionBody::StatementMap" in write barriered memory -Type with barrier found: "Js::FunctionBody::SourceInfo" -In "Js::ScopeObjectChain::ScopeObjectChain" - Allocating "ScopeObjectChainList" in write barriered memory -In "Js::JavascriptLibrary::EnsureReferencedPropertyRecordList" - Allocating "ReferencedPropertyRecordHashSet" in write barriered memory -In "SRCINFO::Copy" - Allocating "class SRCINFO" in write barriered memory -In "Js::SparseArraySegment::Allocate" - Allocating "SparseArraySegment" in write barriered memory -In "Js::FunctionBody::RecordStatementMap" - Allocating "StatementMapList" in write barriered memory -In "Js::FunctionBody::RecordStatementAdjustment" - Allocating "StatementAdjustmentRecordList" in write barriered memory -In "Js::FunctionBody::NewFromRecycler" - Allocating "class Js::FunctionBody" in write barriered memory -In "Js::FunctionBody::FunctionBody" - Allocating "FunctionEntryPointList" in write barriered memory -In "Js::DeferDeserializeFunctionInfo::DeferDeserializeFunctionInfo" - Allocating "class Js::ProxyEntryPointInfo" in write barriered memory -In "Js::DeferDeserializeFunctionInfo::New" - Allocating "class Js::DeferDeserializeFunctionInfo" in write barriered memory -In "Js::ParseableFunctionInfo::ParseableFunctionInfo" - Allocating "struct Js::ParseableFunctionInfo::NestedArray" in write barriered memory -In "Js::ParseableFunctionInfo::ParseableFunctionInfo" - Allocating "class Js::FunctionEntryPointInfo" in write barriered memory -In "Js::ParseableFunctionInfo::ParseableFunctionInfo" - Allocating "class Js::ProxyEntryPointInfo" in write barriered memory -In "Js::ParseableFunctionInfo::New" - Allocating "class Js::ParseableFunctionInfo" in write barriered memory -In "Js::FunctionProxy::EnsureFunctionObjectTypeList" - Allocating "FunctionTypeWeakRefList" in write barriered memory -In "Js::ParseableFunctionInfo::Parse" - Allocating "Js::PropertyRecordList" in write barriered memory -In "Js::PropertyIdOnRegSlotsContainer::New" - Allocating "struct Js::PropertyIdOnRegSlotsContainer" in write barriered memory -In "Js::DebuggerScope::EnsurePropertyListIsAllocated" - Allocating "DebuggerScopePropertyList" in write barriered memory -In "Js::FunctionBody::AllocatePropertyIdArrayForFormals" - Allocating "Js::PropertyIdArray" in write barriered memory -In "Js::FunctionBody::CreateNewDefaultEntryPoint" - Allocating "class Js::FunctionEntryPointInfo" in write barriered memory -In "Js::FunctionBody::RecordStartScopeObject" - Allocating "class Js::ScopeObjectChain" in write barriered memory -In "Js::FunctionBody::AddScopeObject" - Allocating "class Js::DebuggerScope" in write barriered memory -In "Js::FunctionBody::EnsureAuxStatementData" - Allocating "struct Js::FunctionBody::AuxStatementData" in write barriered memory -In "Js::FunctionBody::RecordCrossFrameEntryExitRecord" - Allocating "CrossFrameEntryExitRecordList" in write barriered memory -In "Js::EntryPointPolymorphicInlineCacheInfo::EnsureInlineeInfo" - Allocating "class Js::PolymorphicInlineCacheInfo" in write barriered memory -------------------------- - -pointerClasses -------------------------- - - (anonymous struct)::(anonymous union)::(anonymous) - (anonymous) - ArenaMemoryData - ArenaMemoryDataSummary - AsmJsDataIDL - AutoDisableInterrupt - AutoProfilingUserCode - AutoSetDispatchHaltFlag - BlockIdsStack - CmdLineArgsParser - CmdLineArgsParser::Exception - CodeGenWorkItemIDL - CompileScriptException - ConstTableContentIDL - EquivalentTypeSetIDL - ErrHandler - ExpirableObject - FixedFieldIDL - FunctionBodyDataIDL - FunctionJITRuntimeIDL - FunctionJITTimeDataIDL - HashTbl - HashTbl::ReservedWordInfo - HostDebugContext - HostScriptContext - HostScriptContextCallbackFunctor - Ident - InlinedFrameLayout - InterruptPoller - JITOutputIDL - JavascriptStringIDL - Js::ActivationObjectEx - Js::AgentOfBuffer - Js::Amd64StackFrame - Js::Arguments - Js::ArrayBuffer - Js::ArrayBuffer::ArrayBufferDetachedState - Js::ArrayBufferDetachedStateBase - Js::ArrayBufferParent - Js::AsmJsScriptFunction - Js::AsyncBreakController - Js::AutoDynamicCodeReference - Js::ByteBlock - Js::ByteCodeCache - Js::ByteCodeReader - Js::Cache - Js::CharClassifier - Js::CharStringCache - Js::CompoundString - Js::CompoundString::Block - Js::CompoundString::BlockInfo - Js::CompoundString::Builder - Js::ConcatStringBuilder - Js::ConcatStringWrapping - Js::ConstructorCache::ContentStruct - Js::CtorCacheTransferData - Js::DebugContext - Js::DebugManager - Js::DebuggerScope - Js::DeferDeserializeFunctionInfo - Js::DynamicObject - Js::DynamicObject::(anonymous) - Js::DynamicObjectPropertyEnumerator - Js::DynamicObjectPropertyEnumerator::CachedData - Js::DynamicType - Js::EnterScriptObject - Js::EntryPointInfo - Js::EnumeratedObjectCache - Js::EquivalentTypeCache - Js::ExternalLibraryBase - Js::FuncCacheEntry - Js::FunctionBody::AuxStatementData - Js::FunctionCodeGenRuntimeData - Js::FunctionEntryPointInfo - Js::FunctionInfo - Js::GlobalObject - Js::InlineCache - Js::InlineCache::(anonymous union)::s_accessor - Js::InlineCache::(anonymous union)::s_local - Js::InlineCache::(anonymous union)::s_proto - Js::InternalString - Js::InterpreterHaltState - Js::InterpreterStackFrame - Js::InterpreterStackFrame::PushPopFrameHelper - Js::InterpreterStackFrame::Setup - Js::IsConcatSpreadableCache - Js::IsInstInlineCache - Js::JavascriptArray - Js::JavascriptArray::(anonymous) - Js::JavascriptArray::ArrayElementEnumerator - Js::JavascriptArray::Element - Js::JavascriptError - Js::JavascriptExceptionContext - Js::JavascriptExceptionContext::StackFrame - Js::JavascriptExceptionContext::StackFrame::(anonymous) - Js::JavascriptExceptionObject - Js::JavascriptExceptionOperators::AutoCatchHandlerExists - Js::JavascriptExternalFunction - Js::JavascriptExternalFunction::(anonymous) - Js::JavascriptFunction - Js::JavascriptLibrary - Js::JavascriptLibraryBase - Js::JavascriptNativeArray - Js::JavascriptProxy - Js::JavascriptStaticEnumerator - Js::JavascriptString - Js::JitEquivalentTypeGuard - Js::LeaveScriptObject - Js::LoopEntryPointInfo - Js::LoopHeader - Js::ModuleNameRecord - Js::ModuleRecordBase - Js::PathTypeHandler - Js::PathTypeHandlerBase - Js::PolymorphicCacheUtilizationArray - Js::PolymorphicInlineCache - Js::PolymorphicInlineCacheInfo - Js::ProbeContainer - Js::PropertyCache - Js::PropertyDescriptor - Js::PropertyIdOnRegSlotsContainer - Js::PropertyString - Js::PropertyValueInfo - Js::ProxyEntryPointInfo - Js::RecyclableObject - Js::RestrictedErrorStrings - Js::ReturnedValue - Js::RootObjectBase - Js::RootObjectInlineCache - Js::RuntimeFunction - Js::ScopeInfo - Js::ScopeInfo::AutoCapturesAllScope - Js::ScopeInfo::MapSymbolData - Js::ScopeInfo::SymbolInfo::(anonymous) - Js::ScopeObjectChain - Js::ScopeSlots - Js::ScriptConfiguration - Js::ScriptContext - Js::ScriptContext::AutoEnumeratingRecyclerObjects - Js::ScriptContext::FieldAccessStatsEntry - Js::ScriptContext::RejitStats - Js::ScriptContextBase - Js::ScriptContextOptimizationOverrideInfo - Js::ScriptEntryExitRecord - Js::ScriptFunction - Js::ScriptFunctionType - Js::ScriptFunctionWithInlineCache - Js::SegmentBTree - Js::SegmentBTreeRoot - Js::ServerSourceTextModuleRecord - Js::SharableState - Js::SharedArrayBuffer - Js::SharedContents - Js::SimplePathTypeHandler - Js::SimplePropertyDescriptor - Js::SimplePropertyDescriptor::(anonymous) - Js::SimpleSourceHolder - Js::SmallSpanSequence - Js::SourceTextModuleRecord - Js::SparseArraySegmentBase - Js::StatementLocation - Js::StepController - Js::StringBuilder - Js::StringBuilder::Data::(anonymous union)::st_Chained - Js::StringCopyInfo - Js::StringCopyInfoStack - Js::SynchronizableList - Js::TempArenaAllocatorWrapper - Js::ThrowTypeErrorOnFailureHelper - Js::TwoLevelHashDictionary - Js::TwoLevelHashDictionary::AutoRestoreSetInAdd - Js::TwoLevelHashRecord::(anonymous) - Js::Type - Js::TypeEquivalenceRecord - Js::TypeGuardTransferData - Js::TypePath - Js::TypedArrayBase - Js::Utf8SourceInfo - Js::Utf8SourceInfo::(anonymous) - Js::VarArrayVarCount - Js::WaiterList - Js::_iJIT_Method_Inline_Load - Js::_iJIT_Method_Load - Js::_iJIT_Method_Load_V2 - Js::_iJIT_Method_Load_V3 - Js::_iJIT_Method_Update - JsUtil::Cache - JsUtil::CharacterBuffer - JsUtil::GrowingArray - JsUtil::Job - JsUtil::JobManager - JsUtil::LineOffsetCache - JsUtil::MRURetentionPolicy - JsUtil::MruDictionary::MruDictionaryData - JsUtil::ReadOnlyList - JsUtil::SingleJobManager - JsUtil::WaitableJobManager - JsUtil::WaitableSingleJobManager - JsUtil::WeakRefDictionaryEntry - JsUtil::WeaklyReferencedKeyDictionary - JsUtil::WeaklyReferencedKeyDictionary::EntryRemovalCallback - LabelId - LazyBailOutRecord - Memory::NoWriteBarrierPtr - Memory::WriteBarrierObjectConstructorTrigger - Memory::WriteBarrierPtr - MemoryProfiler - ModuleImportOrExportEntry - NativeDataFixupEntry - NativeDataFixupRecord - NativeLibraryEntryRecord - NativeLibraryEntryRecord::Entry - NoReleaseAllocator - NoReleaseAllocator::NraBlock - ObjTypeSpecFldIDL - ParseContext - Parser - Parser::AutoTempForcePid - Parser::IdentToken - Parser::ParserState - Parser::WellKnownPropertyPids - PerfHintItem - PidRefStack - PnBin - PnBlock - PnCall - PnCase - PnCatch - PnClass - PnExportDefault - PnFinally - PnFnc - PnFor - PnForInOrForOf - PnHelperCall2 - PnIf - PnJump - PnLabel - PnModule - PnParamPattern - PnPid - PnProg - PnReturn - PnStmt - PnStrTemplate - PnSwitch - PnTri - PnTry - PnTryCatch - PnTryFinally - PnUni - PnVar - PnWhile - PnWith - PolymorphicInlineCacheInfoIDL - ProfileDataIDL - RecyclableObjectContent - RecyclableObjectIDL - SAChunk - SRCINFO - Scanner - Scanner::TemporaryBuffer - SmallSpanSequenceIDL - SourceContextInfo::(anonymous union)::(anonymous) - SparseArray - TTD::EventLog - TTD::FileReader - TTD::FileWriter - TTD::IOStreamFunctions - TTD::InflateMap - TTD::MarkTable - TTD::NSLogEvents::EventLogEntryVTableEntry - TTD::NSLogEvents::ExternalCallEventLogEntry - TTD::NSLogEvents::ExternalCbRegisterCallEventLogEntry - TTD::NSLogEvents::JsRTByteBufferAction - TTD::NSLogEvents::JsRTCallFunctionAction - TTD::NSLogEvents::JsRTCallFunctionAction_AdditionalInfo - TTD::NSLogEvents::JsRTCallbackAction - TTD::NSLogEvents::JsRTCodeParseAction - TTD::NSLogEvents::JsRTCodeParseAction_AdditionalInfo - TTD::NSLogEvents::JsRTConstructCallAction - TTD::NSLogEvents::JsRTDoubleArgumentAction - TTD::NSLogEvents::JsRTRawBufferCopyAction - TTD::NSLogEvents::JsRTRawBufferModifyAction - TTD::NSLogEvents::JsRTStringArgumentAction - TTD::NSLogEvents::JsRTVarsArgumentAction - TTD::NSLogEvents::JsRTVarsWithBoolAndPIDArgumentAction - TTD::NSLogEvents::JsRTVarsWithIntegralUnionArgumentAction - TTD::NSLogEvents::SnapshotEventLogEntry - TTD::NSSnapObjects::DependsOnInfo - TTD::NSSnapObjects::SnapArrayBufferInfo - TTD::NSSnapObjects::SnapArrayInfo - TTD::NSSnapObjects::SnapArrayInfoBlock - TTD::NSSnapObjects::SnapBoundFunctionInfo - TTD::NSSnapObjects::SnapES5ArrayGetterSetterEntry - TTD::NSSnapObjects::SnapES5ArrayInfo - TTD::NSSnapObjects::SnapHeapArgumentsInfo - TTD::NSSnapObjects::SnapMapInfo - TTD::NSSnapObjects::SnapObject - TTD::NSSnapObjects::SnapObjectVTable - TTD::NSSnapObjects::SnapPromiseInfo - TTD::NSSnapObjects::SnapPromiseReactionTaskFunctionInfo - TTD::NSSnapObjects::SnapRegexInfo - TTD::NSSnapObjects::SnapScriptFunctionInfo - TTD::NSSnapObjects::SnapSetInfo - TTD::NSSnapType::SnapHandler - TTD::NSSnapType::SnapType - TTD::NSSnapValues::FunctionBodyResolveInfo - TTD::NSSnapValues::ScriptFunctionScopeInfo - TTD::NSSnapValues::SlotArrayInfo - TTD::NSSnapValues::SnapContext - TTD::NSSnapValues::SnapFunctionBodyScopeChain - TTD::NSSnapValues::SnapPrimitiveValue - TTD::NSSnapValues::SnapPrimitiveValue::(anonymous) - TTD::NSSnapValues::SnapPromiseCapabilityInfo - TTD::NSSnapValues::TopLevelCommonBodyResolveInfo - TTD::ScriptContextTTD - TTD::SingleCallCounter - TTD::SlabAllocatorBase - TTD::SlabAllocatorBase::LargeSlabBlock - TTD::SlabAllocatorBase::SlabBlock - TTD::SnapShot - TTD::SnapshotExtractor - TTD::TTDExceptionFramePopper - TTD::TTDIdentifierDictionary - TTD::TTDJsRTActionResultAutoRecorder - TTD::TTDJsRTFunctionCallActionPopperRecorder - TTD::TTDNestingDepthAutoAdjuster - TTD::TTDPendingAsyncBufferModification - TTD::TTDebuggerAbortException - TTD::TTDebuggerSourceLocation - TTD::TTEventList - TTD::TTEventList::Iterator - TTD::TTEventList::TTEventListLink - TTD::TTModeStack - TTD::TTString - TTD::TTUriString - TTD::TextFormatReader - TTD::TextFormatWriter - TTD::UnorderedArrayList - TTD::UnorderedArrayList::Iterator - TTD::UnorderedArrayList::UnorderedArrayListLink - TTD::UtilSupport::TTAutoString - ThreadContext - ThreadContext::AutoDisableExpiration - ThreadContext::CollectCallBack - ThreadContext::PropertyGuardEntry - ThreadContext::RecyclableData - ThreadContext::SourceDynamicProfileManagerCache - ThreadContext::WorkerThread - Token::(anonymous union)::(anonymous) - Token::(anonymous) - TypeGuardTransferEntryIDL - UCrtC99MathApis - UnifiedRegex::CharMap - UnifiedRegex::CharSet::FullRep - UnifiedRegex::CharTrie - UnifiedRegex::LoopInfo - UnifiedRegex::Matcher - UnifiedRegex::Program - UnifiedRegex::Program::Instructions - UnifiedRegex::Program::Octoquad - UnifiedRegex::RegexKey - UnifiedRegex::RegexPattern - UnifiedRegex::RegexPattern::UnifiedRep - UnifiedRegex::RuntimeCharSet - UnifiedRegex::RuntimeCharTrie - UnifiedRegex::ScannersMixin - UnifiedRegex::TextbookBoyerMoore - UnifiedRegex::TextbookBoyerMooreSetup - UnifiedRegex::TextbookBoyerMooreWithLinearMap - UpdatedPropertysIDL - VirtualTableRegistry::TableEntry - XProcNumberPageSegment - sigaction - sigaction::(anonymous) - sigaltstack - sigcontext::(anonymous) - sigevent::(anonymous union)::(anonymous) - sigstack - sigval - sigvec - std::__exception_ptr::exception_ptr - std::type_info - ucontext -------------------------- - -------------------------- - -barrieredClasses -------------------------- - - Js::AuxPtrs - Js::AuxPtrsFix - Js::CompactCounters - Js::FunctionBody - Js::FunctionBody::SourceInfo - Js::FunctionProxy - Js::InlineCachePointerArray - Js::ParseableFunctionInfo -------------------------- - -Recycler allocations -------------------------- - -AllocFinalizedWithBarrierInlined -------------------------- - - class Js::DeferDeserializeFunctionInfo - class Js::FunctionBody - class Js::FunctionEntryPointInfo - class Js::ParseableFunctionInfo -------------------------- - -------------------------- - -AllocLeafInlined -------------------------- - - Js::FakePropertyGuardWeakReference - Js::PropertyGuard -------------------------- - -------------------------- - -AllocLeafZero -------------------------- - - SparseArraySegment -------------------------- - -------------------------- - -AllocWeakReferenceEntry -------------------------- - - class Memory::RecyclerWeakReferenceBase -------------------------- - -------------------------- - -AllocWithBarrier -------------------------- - - CrossFrameEntryExitRecordList - DebuggerScopePropertyList - FunctionEntryPointList - FunctionTypeWeakRefList - Js::PropertyIdArray - Js::PropertyRecordList - ReferencedPropertyRecordHashSet - ScopeObjectChainList - StatementAdjustmentRecordList - StatementMapList - class Js::DebuggerScope - class Js::PolymorphicInlineCacheInfo - class Js::ProxyEntryPointInfo - class Js::ScopeObjectChain - class SRCINFO - struct Js::FunctionBody::AuxStatementData - struct Js::FunctionBody::StatementMap - struct Js::PropertyIdOnRegSlotsContainer -------------------------- - -------------------------- - -AllocZeroWithBarrier -------------------------- - - AuxPtrs16 - AuxPtrs32 - AuxPtrsT - SparseArraySegment - struct Js::ParseableFunctionInfo::NestedArray -------------------------- - -------------------------- - -barrierAllocations -------------------------- - - AuxPtrs16 - AuxPtrs32 - AuxPtrsT - CrossFrameEntryExitRecordList - DebuggerScopePropertyList - FunctionEntryPointList - FunctionTypeWeakRefList - Js::PropertyIdArray - Js::PropertyRecordList - ReferencedPropertyRecordHashSet - ScopeObjectChainList - SparseArraySegment - StatementAdjustmentRecordList - StatementMapList - class Js::DebuggerScope - class Js::DeferDeserializeFunctionInfo - class Js::FunctionBody - class Js::FunctionEntryPointInfo - class Js::ParseableFunctionInfo - class Js::PolymorphicInlineCacheInfo - class Js::ProxyEntryPointInfo - class Js::ScopeObjectChain - class SRCINFO - struct Js::FunctionBody::AuxStatementData - struct Js::FunctionBody::StatementMap - struct Js::ParseableFunctionInfo::NestedArray - struct Js::PropertyIdOnRegSlotsContainer -------------------------- - diff --git a/deps/chakrashim/core/tools/RecyclerChecker/RecyclerChecker.cpp b/deps/chakrashim/core/tools/RecyclerChecker/RecyclerChecker.cpp index a980c9d2fa4..8f4d0aa0527 100644 --- a/deps/chakrashim/core/tools/RecyclerChecker/RecyclerChecker.cpp +++ b/deps/chakrashim/core/tools/RecyclerChecker/RecyclerChecker.cpp @@ -111,20 +111,24 @@ void MainVisitor::ProcessUnbarrieredFields( string fieldTypeName = qualType.getAsString(); string fieldName = field->getNameAsString(); + if (StartsWith(fieldTypeName, "WriteBarrierPtr<") || // WriteBarrierPtr fields + Contains(fieldTypeName, "_no_write_barrier_policy, ")) // FieldNoBarrier + { + continue; // skip + } + // If an annotated field type is struct/class/union (RecordType), the // field type in turn should likely be annoatated. - if (StartsWith(fieldTypeName, "typename WriteBarrierFieldTypeTraits") || - StartsWith(fieldTypeName, "WriteBarrierFieldTypeTraits") || - StartsWith(fieldTypeName, "const typename WriteBarrierFieldTypeTraits") || - StartsWith(fieldTypeName, "const WriteBarrierFieldTypeTraits") || - fieldName.length() == 0) // anonymous union/struct + if (fieldTypeName.back() != '*' // not "... *" + && + ( + StartsWith(fieldTypeName, "typename WriteBarrierFieldTypeTraits") || + StartsWith(fieldTypeName, "WriteBarrierFieldTypeTraits") || + StartsWith(fieldTypeName, "const typename WriteBarrierFieldTypeTraits") || + StartsWith(fieldTypeName, "const WriteBarrierFieldTypeTraits") || + fieldName.length() == 0 // anonymous union/struct + )) { - // Do not track down FieldNoBarrier types - if (Contains(fieldTypeName, "_no_write_barrier_policy, ")) - { - continue; - } - auto originalType = qualType->getUnqualifiedDesugaredType(); if (auto arrayType = dyn_cast(originalType)) { @@ -142,10 +146,6 @@ void MainVisitor::ProcessUnbarrieredFields( } } } - else if (StartsWith(fieldTypeName, "WriteBarrierPtr<")) - { - // do nothing, explicit WriteBarrierPtr use - } else { SourceLocation location = field->getLocStart(); diff --git a/deps/chakrashim/core/tools/RecyclerChecker/blah.txt b/deps/chakrashim/core/tools/RecyclerChecker/blah.txt deleted file mode 100644 index f3ffc2c4b0c..00000000000 --- a/deps/chakrashim/core/tools/RecyclerChecker/blah.txt +++ /dev/null @@ -1,25 +0,0 @@ -CXXRecordDecl represents a class/struct declaration - -Use the fields property to iterate over all the fields of the class: -for (const auto& field : cl->fields) { - const auto& name = field->getName(); - const auto field_cl = field->getType()->getAsCXXRecordDecl(); - } - -Running clang analyzer: - clang -Xclang -fno-color-diagnostics -Xclang -analyze -Xclang -analyzer-checker=chakra.RecyclerChecker -Xclang -load -Xclang /home/hiteshk/code/clang-php-checker/Build/libclangRecyclerChecker.so -DBIT64=1 -DDBG=1 -DDBG_DUMP=1 -DDEBUG=1 -DDISABLE_JIT=1 -DFEATURE_PAL -DLINUX64 -DNO_PAL_MINMAX -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX=1 -DSTACK_ALIGN=16 -DUNICODE -D_AMD64_ -D_DEBUG=1 -D_M_AMD64 -D_M_X64 -D_M_X64_OR_ARM64 -D_SAFECRT_USE_CPP_OVERLOADS=1 -D__LINUX__=1 -D__STDC_WANT_LIB_EXT1__=1 -I../../. -I../../lib/Common -I../../lib/Common/PlaceHolder -I../../pal -I../../pal/inc -I../../pal/inc/rt -I../../lib/Runtime/. -I../../lib/Runtime/../Common -I../../lib/Runtime/../Backend -I../../lib/Runtime/../Parser -I../../lib/Runtime/ByteCode -I../../lib/Runtime/PlatformAgnostic -I../../lib/Runtime/Math -I../../lib/Runtime/Base -Werror -Wno-missing-braces -Wno-reorder -Wno-microsoft -Wno-unused-value -Wno-int-to-void-pointer-cast -Wno-invalid-offsetof -Wno-undefined-inline -Wno-inconsistent-missing-override -Wno-c++14-extensions -Wno-macro-redefined -Wno-pragmas -Wno-invalid-token-paste -Wno-format -Wno-invalid-noreturn -Wno-null-arithmetic -Wno-tautological-constant-out-of-range-compare -Wno-tautological-undefined-compare -Wno-address-of-temporary -Wno-null-conversion -Wno-return-type -Wno-switch -Wno-int-to-pointer-cast -fdelayed-template-parsing -fno-omit-frame-pointer -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer -g -fms-extensions -msse4.1 -fPIC -std=gnu++11 /home/hiteshk/code/core/lib/Runtime/Base/FunctionBody.cpp - - -Running a clang plugin: - clang -Xclang -fno-color-diagnostics -DBIT64=1 -DDBG=1 -DDBG_DUMP=1 -DDEBUG=1 -DDISABLE_JIT=1 -DFEATURE_PAL -DLINUX64 -DNO_PAL_MINMAX -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX=1 -DSTACK_ALIGN=16 -DUNICODE -D_AMD64_ -D_DEBUG=1 -D_M_AMD64 -D_M_X64 -D_M_X64_OR_ARM64 -D_SAFECRT_USE_CPP_OVERLOADS=1 -D__LINUX__=1 -D__STDC_WANT_LIB_EXT1__=1 -I../../. -I../../lib/Common -I../../lib/Common/PlaceHolder -I../../pal -I../../pal/inc -I../../pal/inc/rt -I../../lib/Runtime/. -I../../lib/Runtime/../Common -I../../lib/Runtime/../Backend -I../../lib/Runtime/../Parser -I../../lib/Runtime/ByteCode -I../../lib/Runtime/PlatformAgnostic -I../../lib/Runtime/Math -I../../lib/Runtime/Base -Werror -Wno-missing-braces -Wno-reorder -Wno-microsoft -Wno-unused-value -Wno-int-to-void-pointer-cast -Wno-invalid-offsetof -Wno-undefined-inline -Wno-inconsistent-missing-override -Wno-c++14-extensions -Wno-macro-redefined -Wno-pragmas -Wno-invalid-token-paste -Wno-format -Wno-invalid-noreturn -Wno-null-arithmetic -Wno-tautological-constant-out-of-range-compare -Wno-tautological-undefined-compare -Wno-address-of-temporary -Wno-null-conversion -Wno-return-type -Wno-switch -Wno-int-to-pointer-cast -fdelayed-template-parsing -fno-omit-frame-pointer -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer -g -fms-extensions -msse4.1 -fPIC -std=gnu++11 -fsyntax-only -Xclang -load -Xclang /home/hiteshk/code/clang-php-checker/Build/libclangRecyclerChecker.so -Xclang -plugin -Xclang check-recycler /home/hiteshk/code/core/lib/Runtime/Base/FunctionBody.cpp - - - _ZNK5clang15DeclarationName11getAsStringEv - - - - - leish@LEISH1:/mnt/c/chakra/core/lib/Runtime$ clang -Xclang -fno-color-diagnostics -DBIT64=1 -DDBG=1 -DDBG_DUMP=1 -DDEBUG=1 -DDISABLE_JIT=1 -DFEATURE_PAL -DLINUX64 -DNO_PAL_MINMAX -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX=1 -DSTACK_ALIGN=16 -DUNICODE -D_AMD64_ -D_DEBUG=1 -D_M_AMD64 -D_M_X64 -D_M_X64_OR_ARM64 -D_SAFECRT_USE_CPP_OVERLOADS=1 -D__LINUX__=1 -D__STDC_WANT_LIB_EXT1__=1 -I../../. -I../../lib/Common -I../../lib/Common/PlaceHolder -I../../pal -I../../pal/inc -I../../pal/inc/rt -I../../lib/Runtime/. -I../../lib/Runtime/../Common -I../../lib/Runtime/../Backend -I../../lib/Runtime/../Parser -I../../lib/Runtime/ByteCode -I../../lib/Runtime/PlatformAgnostic -I../../lib/Runtime/Math -I../../lib/Runtime/Base -I../../lib/JITIDL/ -Werror -Wno-missing-braces -Wno-reorder -Wno-microsoft -Wno-unused-value -Wno-int-to-void-pointer-cast -Wno-invalid-offsetof -Wno-undefined-inline -Wno-inconsistent-missing-override -Wno-c++14-extensions -Wno-macro-redefined -Wno-pragmas -Wno-invalid-token-paste -Wno-format -Wno-invalid-noreturn -Wno-null-arithmetic -Wno-tautological-constant-out-of-range-compare -Wno-tautological-undefined-compare -Wno-address-of-temporary -Wno-null-conversion -Wno-return-type -Wno-switch -Wno-int-to-pointer-cast -fdelayed-template-parsing -fno-omit-frame-pointer -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer -g -fms-extensions -msse4.1 -fPIC -std=gnu++11 -fsyntax-only -Xclang -load -Xclang ../../tools/RecyclerChecker/Build/libclangRecyclerChecker.so -Xclang -plugin -Xclang check-recycler -v Base/FunctionBody.cpp - - -clang -Xclang -fno-color-diagnostics -Xclang -analyze -Xclang -analyzer-checker=chakra.RecyclerChecker -Xclang -load -Xclang ../../tools/RecyclerChecker/Build/libclangRecyclerChecker.so -DBIT64=1 -DDBG=1 -DDBG_DUMP=1 -DDEBUG=1 -DDISABLE_JIT=1 -DFEATURE_PAL -DLINUX64 -DNO_PAL_MINMAX -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX=1 -DSTACK_ALIGN=16 -DUNICODE -D_AMD64_ -D_DEBUG=1 -D_M_AMD64 -D_M_X64 -D_M_X64_OR_ARM64 -D_SAFECRT_USE_CPP_OVERLOADS=1 -D__LINUX__=1 -D__STDC_WANT_LIB_EXT1__=1 -I../../. -I../../lib/Common -I../../lib/Common/PlaceHolder -I../../pal -I../../pal/inc -I../../pal/inc/rt -I../../lib/Runtime/. -I../../lib/Runtime/../Common -I../../lib/Runtime/../Backend -I../../lib/Runtime/../Parser -I../../lib/Runtime/ByteCode -I../../lib/Runtime/PlatformAgnostic -I../../lib/Runtime/Math -I../../lib/Runtime/Base -I../../lib/JITIDL/ -Werror -Wno-missing-braces -Wno-reorder -Wno-microsoft -Wno-unused-value -Wno-int-to-void-pointer-cast -Wno-invalid-offsetof -Wno-undefined-inline -Wno-inconsistent-missing-override -Wno-c++14-extensions -Wno-macro-redefined -Wno-pragmas -Wno-invalid-token-paste -Wno-format -Wno-invalid-noreturn -Wno-null-arithmetic -Wno-tautological-constant-out-of-range-compare -Wno-tautological-undefined-compare -Wno-address-of-temporary -Wno-null-conversion -Wno-return-type -Wno-switch -Wno-int-to-pointer-cast -fdelayed-template-parsing -fno-omit-frame-pointer -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer -g -fms-extensions -msse4.1 -fPIC -std=gnu++11 -v Base/FunctionBody.cpp \ No newline at end of file