From 615a61459739a095781a48230d91a918df58d567 Mon Sep 17 00:00:00 2001 From: Richard Date: Thu, 16 May 2024 21:27:23 +0100 Subject: [PATCH] JIT Generator (and Async func) loops (#6990) * Disable JitES6Generators * Jit Generator and async func LoopBodies * Update Tests cases for Generator Jit --- lib/Backend/IRBuilder.cpp | 10 +- lib/Backend/Lower.cpp | 5 +- lib/Backend/NativeCodeGenerator.cpp | 9 +- lib/Common/ConfigFlagsList.h | 6 +- lib/Runtime/Base/FunctionBody.h | 7 +- lib/Runtime/ByteCode/AsmJsByteCodeWriter.cpp | 3 +- lib/Runtime/ByteCode/ByteCodeEmitter.cpp | 5 +- lib/Runtime/ByteCode/ByteCodeWriter.cpp | 21 ++- lib/Runtime/ByteCode/ByteCodeWriter.h | 17 ++- lib/Runtime/ByteCode/WasmByteCodeWriter.cpp | 3 +- .../Language/InterpreterStackFrame.cpp | 6 +- test/es6/rlexe.xml | 43 ------ .../async-jit-bugs.js | 2 +- .../generator-jit-bugs.js | 2 +- .../jit-async-loop-body-2.baseline | 20 +++ .../jit-async-loop-body.baseline | 42 ++++++ test/es6GeneratorJit/jit-async-loop-body.js | 42 ++++++ .../jit-gen-loop-body-2.baseline | 13 ++ .../jit-gen-loop-body.baseline | 35 +++++ test/es6GeneratorJit/jit-gen-loop-body.js | 48 ++++++ .../jit-module-loop-body-2.baseline | 11 ++ .../jit-module-loop-body.baseline | 27 ++++ test/es6GeneratorJit/jit-module-loop-body.js | 41 +++++ test/es6GeneratorJit/newtest.js | 52 +++++++ test/es6GeneratorJit/rlexe.xml | 140 ++++++++++++++++++ test/rlexedirs.xml | 6 + 26 files changed, 548 insertions(+), 68 deletions(-) rename test/{es6 => es6GeneratorJit}/async-jit-bugs.js (94%) rename test/{es6 => es6GeneratorJit}/generator-jit-bugs.js (98%) create mode 100644 test/es6GeneratorJit/jit-async-loop-body-2.baseline create mode 100644 test/es6GeneratorJit/jit-async-loop-body.baseline create mode 100644 test/es6GeneratorJit/jit-async-loop-body.js create mode 100644 test/es6GeneratorJit/jit-gen-loop-body-2.baseline create mode 100644 test/es6GeneratorJit/jit-gen-loop-body.baseline create mode 100644 test/es6GeneratorJit/jit-gen-loop-body.js create mode 100644 test/es6GeneratorJit/jit-module-loop-body-2.baseline create mode 100644 test/es6GeneratorJit/jit-module-loop-body.baseline create mode 100644 test/es6GeneratorJit/jit-module-loop-body.js create mode 100644 test/es6GeneratorJit/newtest.js create mode 100644 test/es6GeneratorJit/rlexe.xml diff --git a/lib/Backend/IRBuilder.cpp b/lib/Backend/IRBuilder.cpp index 72ded2a0d5c..05c3ff31d33 100644 --- a/lib/Backend/IRBuilder.cpp +++ b/lib/Backend/IRBuilder.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "Backend.h" @@ -118,7 +118,7 @@ IRBuilder::DoBailOnNoProfile() return false; } - if (m_func->GetTopFunc()->GetJITFunctionBody()->IsCoroutine()) + if (m_func->GetTopFunc()->GetJITFunctionBody()->IsCoroutine() && !m_func->IsLoopBody()) { return false; } @@ -441,7 +441,7 @@ IRBuilder::Build() // Note that for generators, we insert the bailout after the jump table to allow // the generator's execution to proceed before bailing out. Otherwise, we would always // bail to the beginning of the function in the interpreter, creating an infinite loop. - if (m_func->IsJitInDebugMode() && !this->m_func->GetJITFunctionBody()->IsCoroutine()) + if (m_func->IsJitInDebugMode() && (!this->m_func->GetJITFunctionBody()->IsCoroutine() || this->IsLoopBody())) { this->InsertBailOutForDebugger(m_functionStartOffset, IR::BailOutForceByFlag | IR::BailOutBreakPointInFunction | IR::BailOutStep, nullptr); } @@ -1880,6 +1880,9 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re break; case Js::OpCode::Yield: + // Jitting Loop Bodies containing Yield is not possible, blocked at callsites of GenerateLoopBody + AssertMsg(!this->IsLoopBody(), "Attempting to JIT loop body containing Yield"); + instr = IR::Instr::New(newOpcode, dstOpnd, src1Opnd, m_func); this->AddInstr(instr, offset); IR::Instr* yieldInstr = instr->ConvertToBailOutInstr(instr, IR::BailOutForGeneratorYield); @@ -7849,6 +7852,7 @@ IRBuilder::GeneratorJumpTable::GeneratorJumpTable(Func* func, IRBuilder* irBuild IR::Instr* IRBuilder::GeneratorJumpTable::BuildJumpTable() { + AssertMsg(!this->m_func->IsLoopBody(), "Coroutine Loop Bodies can be jitted but should follow a different path"); if (!this->m_func->GetJITFunctionBody()->IsCoroutine()) { return this->m_irBuilder->m_lastInstr; diff --git a/lib/Backend/Lower.cpp b/lib/Backend/Lower.cpp index a4486bf8bef..dcda1eb9064 100644 --- a/lib/Backend/Lower.cpp +++ b/lib/Backend/Lower.cpp @@ -5467,7 +5467,7 @@ Lowerer::LowerPrologEpilog() instr = m_func->m_exitInstr; AssertMsg(instr->IsExitInstr(), "Last instr isn't an ExitInstr..."); - if (m_func->GetJITFunctionBody()->IsCoroutine()) + if (m_func->GetJITFunctionBody()->IsCoroutine() && !m_func->IsLoopBody()) { IR::LabelInstr* epilogueLabel = this->m_lowerGeneratorHelper.GetEpilogueForReturnStatements(); this->m_lowerGeneratorHelper.InsertNullOutGeneratorFrameInEpilogue(epilogueLabel); @@ -11527,6 +11527,7 @@ Lowerer::LowerArgIn(IR::Instr *instrArgIn) if (m_func->GetJITFunctionBody()->IsCoroutine()) { + AssertMsg(!m_func->IsLoopBody(), "LoopBody Jit should not involve Rest params"); generatorArgsPtrOpnd = LoadGeneratorArgsPtr(instrArgIn); } @@ -11544,7 +11545,7 @@ Lowerer::LowerArgIn(IR::Instr *instrArgIn) if (argIndex == 1) { // The "this" argument is not source-dependent and doesn't need to be checked. - if (m_func->GetJITFunctionBody()->IsCoroutine()) + if (m_func->GetJITFunctionBody()->IsCoroutine() && !m_func->IsLoopBody()) { generatorArgsPtrOpnd = LoadGeneratorArgsPtr(instrArgIn); ConvertArgOpndIfGeneratorFunction(instrArgIn, generatorArgsPtrOpnd); diff --git a/lib/Backend/NativeCodeGenerator.cpp b/lib/Backend/NativeCodeGenerator.cpp index a7d2585df16..2997e5dacae 100644 --- a/lib/Backend/NativeCodeGenerator.cpp +++ b/lib/Backend/NativeCodeGenerator.cpp @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "Backend.h" @@ -246,8 +247,11 @@ NativeCodeGenerator::GenerateAllFunctions(Js::FunctionBody * fn) for (uint i = 0; i < fn->GetLoopCount(); i++) { Js::LoopHeader * loopHeader = fn->GetLoopHeader(i); - Js::EntryPointInfo * entryPointInfo = loopHeader->GetCurrentEntryPointInfo(); - this->GenerateLoopBody(fn, loopHeader, entryPointInfo); + if (loopHeader->hasYield == false) + { + Js::EntryPointInfo * entryPointInfo = loopHeader->GetCurrentEntryPointInfo(); + this->GenerateLoopBody(fn, loopHeader, entryPointInfo); + } } } else @@ -631,6 +635,7 @@ void NativeCodeGenerator::GenerateLoopBody(Js::FunctionBody * fn, Js::LoopHeader ASSERT_THREAD(); Assert(fn->GetScriptContext()->GetNativeCodeGenerator() == this); Assert(entryPoint->jsMethod == nullptr); + Assert(!loopHeader->hasYield); #if DBG_DUMP if (PHASE_TRACE1(Js::JITLoopBodyPhase)) diff --git a/lib/Common/ConfigFlagsList.h b/lib/Common/ConfigFlagsList.h index 406b24eb1dc..45339a9da1c 100644 --- a/lib/Common/ConfigFlagsList.h +++ b/lib/Common/ConfigFlagsList.h @@ -675,12 +675,12 @@ PHASE(All) #define DEFAULT_CONFIG_ESNullishCoalescingOperator (true) #define DEFAULT_CONFIG_ESGlobalThis (true) -// Jitting generators has not been tested on ARM -// enabled only for x86 and x64 for now +// Jitting generator functions is not functional on ARM +// Also still contains significant bugs on x86/x64 hence disabled #ifdef _M_ARM32_OR_ARM64 #define DEFAULT_CONFIG_JitES6Generators (false) #else - #define DEFAULT_CONFIG_JitES6Generators (true) + #define DEFAULT_CONFIG_JitES6Generators (false) #endif #ifdef COMPILE_DISABLE_ES6RegExPrototypeProperties diff --git a/lib/Runtime/Base/FunctionBody.h b/lib/Runtime/Base/FunctionBody.h index 2a1cd86a807..470e8b21919 100644 --- a/lib/Runtime/Base/FunctionBody.h +++ b/lib/Runtime/Base/FunctionBody.h @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once @@ -725,6 +726,7 @@ namespace Js #if ENABLE_NATIVE_CODEGEN Field(uint) rejitCount; #endif + Field(bool) hasYield; Field(bool) isNested; Field(bool) isInTry; Field(bool) isInTryFinally; @@ -1153,8 +1155,9 @@ namespace Js bool IsJitLoopBodyPhaseEnabled() const { - // Consider: Allow JitLoopBody in generator functions for loops that do not yield. - return !PHASE_OFF(JITLoopBodyPhase, this) && !PHASE_OFF(FullJitPhase, this) && !this->IsCoroutine(); + return !PHASE_OFF(JITLoopBodyPhase, this) && !PHASE_OFF(FullJitPhase, this) && + (!this->IsCoroutine() || !CONFIG_FLAG(JitES6Generators) || this->IsModule()); + // Jitting loop bodies is currently disabled when testing the Jitting of whole generator functions } bool IsJitLoopBodyPhaseForced() const diff --git a/lib/Runtime/ByteCode/AsmJsByteCodeWriter.cpp b/lib/Runtime/ByteCode/AsmJsByteCodeWriter.cpp index e04455938b3..65ff5dce9a4 100644 --- a/lib/Runtime/ByteCode/AsmJsByteCodeWriter.cpp +++ b/lib/Runtime/ByteCode/AsmJsByteCodeWriter.cpp @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft Corporation and contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- @@ -632,7 +633,7 @@ namespace Js uint loopId = m_functionWrite->IncrLoopCount(); Assert((uint)m_loopHeaders->Count() == loopId); - m_loopHeaders->Add(LoopHeaderData(m_byteCodeData.GetCurrentOffset(), 0, m_loopNest > 0)); + m_loopHeaders->Add(LoopHeaderData(m_byteCodeData.GetCurrentOffset(), 0, m_loopNest > 0, false)); m_loopNest++; Js::OpCodeAsmJs loopBodyOpcode = Js::OpCodeAsmJs::AsmJsLoopBodyStart; this->MarkAsmJsLabel(loopEntrance); diff --git a/lib/Runtime/ByteCode/ByteCodeEmitter.cpp b/lib/Runtime/ByteCode/ByteCodeEmitter.cpp index 90745305b35..98533e8f0e6 100644 --- a/lib/Runtime/ByteCode/ByteCodeEmitter.cpp +++ b/lib/Runtime/ByteCode/ByteCodeEmitter.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "RuntimeByteCodePch.h" @@ -10477,6 +10477,9 @@ void EmitYieldAndResume( auto* writer = byteCodeGenerator->Writer(); + // If in a loop mark it as containing Yield and hence not eligible for Jit loop body + writer->SetCurrentLoopHasYield(); + if (inputReg != funcInfo->yieldRegister) writer->Reg2(Js::OpCode::Ld_A, funcInfo->yieldRegister, inputReg); diff --git a/lib/Runtime/ByteCode/ByteCodeWriter.cpp b/lib/Runtime/ByteCode/ByteCodeWriter.cpp index 01827f98f2a..955deccc8cf 100644 --- a/lib/Runtime/ByteCode/ByteCodeWriter.cpp +++ b/lib/Runtime/ByteCode/ByteCodeWriter.cpp @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "RuntimeByteCodePch.h" @@ -210,7 +210,7 @@ namespace Js } } - if (this->DoJitLoopBodies() && + if (this->DoJitLoopBodies() && this->HasLoopWithoutYield() && !(this->m_functionWrite->GetFunctionBody()->GetHasTry() && PHASE_OFF(Js::JITLoopBodyInTryCatchPhase, this->m_functionWrite)) && !(this->m_functionWrite->GetFunctionBody()->GetHasFinally() && PHASE_OFF(Js::JITLoopBodyInTryFinallyPhase, this->m_functionWrite))) { @@ -252,6 +252,7 @@ namespace Js loopHeader->startOffset = data.startOffset; loopHeader->endOffset = data.endOffset; loopHeader->isNested = data.isNested; + loopHeader->hasYield = data.hasYield; }); } @@ -3224,7 +3225,7 @@ namespace Js uint loopId = m_functionWrite->IncrLoopCount(); Assert((uint)m_loopHeaders->Count() == loopId); - m_loopHeaders->Add(LoopHeaderData(m_byteCodeData.GetCurrentOffset(), 0, m_loopNest > 0)); + m_loopHeaders->Add(LoopHeaderData(m_byteCodeData.GetCurrentOffset(), 0, m_loopNest > 0, false)); m_loopNest++; m_functionWrite->SetHasNestedLoop(m_loopNest > 1); @@ -3259,6 +3260,20 @@ namespace Js m_loopHeaders->Item(loopId).endOffset = m_byteCodeData.GetCurrentOffset(); } + void ByteCodeWriter::SetCurrentLoopHasYield() + { + if (m_loopNest > 0) + { + for (int i = 0; i < m_loopHeaders->Count(); ++i) + { + if (m_loopHeaders->Item(i).endOffset == 0) // check for loops we're currently inside + { + m_loopHeaders->Item(i).hasYield = true; + } + } + } + } + void ByteCodeWriter::IncreaseByteCodeCount() { m_byteCodeCount++; diff --git a/lib/Runtime/ByteCode/ByteCodeWriter.h b/lib/Runtime/ByteCode/ByteCodeWriter.h index 4c54d83fd23..2b596d6e877 100644 --- a/lib/Runtime/ByteCode/ByteCodeWriter.h +++ b/lib/Runtime/ByteCode/ByteCodeWriter.h @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once @@ -114,8 +114,9 @@ namespace Js uint startOffset; uint endOffset; bool isNested; + bool hasYield; LoopHeaderData() {} - LoopHeaderData(uint startOffset, uint endOffset, bool isNested) : startOffset(startOffset), endOffset(endOffset), isNested(isNested){} + LoopHeaderData(uint startOffset, uint endOffset, bool isNested, bool hasYield) : startOffset(startOffset), endOffset(endOffset), isNested(isNested), hasYield(hasYield){} }; JsUtil::List * m_labelOffsets; // Label offsets, once defined @@ -384,6 +385,18 @@ namespace Js uint EnterLoop(Js::ByteCodeLabel loopEntrance); void ExitLoop(uint loopId); + void SetCurrentLoopHasYield(); + bool HasLoopWithoutYield() + { + for (int i = 0; i < m_loopHeaders->Count(); ++i) + { + if(!m_loopHeaders->Item(i).hasYield) + { + return true; + } + } + return false; + } bool DoJitLoopBodies() const { return m_doJitLoopBodies; } bool DoInterruptProbes() const { return m_doInterruptProbe; } diff --git a/lib/Runtime/ByteCode/WasmByteCodeWriter.cpp b/lib/Runtime/ByteCode/WasmByteCodeWriter.cpp index 43134a20c12..09fbc963d9a 100644 --- a/lib/Runtime/ByteCode/WasmByteCodeWriter.cpp +++ b/lib/Runtime/ByteCode/WasmByteCodeWriter.cpp @@ -1,5 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft Corporation and contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #include "RuntimeByteCodePch.h" @@ -45,7 +46,7 @@ uint32 WasmByteCodeWriter::WasmLoopStart(ByteCodeLabel loopEntrance, __in_ecount uint loopId = m_functionWrite->IncrLoopCount(); Assert((uint)m_loopHeaders->Count() == loopId); - m_loopHeaders->Add(LoopHeaderData(m_byteCodeData.GetCurrentOffset(), 0, m_loopNest > 0)); + m_loopHeaders->Add(LoopHeaderData(m_byteCodeData.GetCurrentOffset(), 0, m_loopNest > 0, false)); m_loopNest++; this->MarkAsmJsLabel(loopEntrance); MULTISIZE_LAYOUT_WRITE(WasmLoopStart, Js::OpCodeAsmJs::WasmLoopBodyStart, loopId, curRegs); diff --git a/lib/Runtime/Language/InterpreterStackFrame.cpp b/lib/Runtime/Language/InterpreterStackFrame.cpp index 7b8535b5d1b..6a002ab3f01 100644 --- a/lib/Runtime/Language/InterpreterStackFrame.cpp +++ b/lib/Runtime/Language/InterpreterStackFrame.cpp @@ -1220,7 +1220,7 @@ namespace Js !(this->executeFunction->GetHasTry() && (PHASE_OFF((Js::JITLoopBodyInTryCatchPhase), this->executeFunction))) && !(this->executeFunction->GetHasFinally() && (PHASE_OFF((Js::JITLoopBodyInTryFinallyPhase), this->executeFunction))) && (this->executeFunction->ForceJITLoopBody() || this->executeFunction->IsJitLoopBodyPhaseEnabled()) && - !this->executeFunction->IsInDebugMode(); + !this->executeFunction->IsInDebugMode() && this->executeFunction->GetLoopHeaderArray() != nullptr; #endif // Pick a version of the LoopBodyStart OpCode handlers that is hardcoded to do loop body JIT and @@ -6057,7 +6057,7 @@ namespace Js Js::LoopEntryPointInfo * entryPointInfo = loopHeader->GetCurrentEntryPointInfo(); - if (fn->ForceJITLoopBody() && loopHeader->interpretCount == 0 && + if (fn->ForceJITLoopBody() && loopHeader->interpretCount == 0 && loopHeader->hasYield == false && (entryPointInfo != NULL && entryPointInfo->IsNotScheduled())) { #if ENABLE_PROFILE_INFO @@ -6250,7 +6250,7 @@ namespace Js return nullptr; } - if (!fn->DoJITLoopBody()) + if (!fn->DoJITLoopBody() || loopHeader->hasYield) { return nullptr; } diff --git a/test/es6/rlexe.xml b/test/es6/rlexe.xml index 1ff8919fd9a..a1c7fbab7ea 100644 --- a/test/es6/rlexe.xml +++ b/test/es6/rlexe.xml @@ -132,48 +132,6 @@ exclude_dynapogo - - - generator-jit-bugs.js - -JitES6Generators -args summary -endargs - exclude_nonative - - - - - generator-jit-bugs.js - -JitES6Generators -off:simplejit -args summary -endargs - exclude_nonative - - - - - generator-jit-bugs.js - -JitES6Generators -off:fulljit -args summary -endargs - exclude_nonative, exclude_dynapogo - - - - - async-jit-bugs.js - -JitES6Generators -args summary -endargs - exclude_nonative - - - - - async-jit-bugs.js - -JitES6Generators -off:simplejit -args summary -endargs - exclude_nonative - - - - - async-jit-bugs.js - -JitES6Generators -off:fulljit -args summary -endargs - exclude_nonative, exclude_dynapogo - - proto_basic.js @@ -913,7 +871,6 @@ generators-functionality.js - -ES6Generators -args summary -endargs exclude_arm diff --git a/test/es6/async-jit-bugs.js b/test/es6GeneratorJit/async-jit-bugs.js similarity index 94% rename from test/es6/async-jit-bugs.js rename to test/es6GeneratorJit/async-jit-bugs.js index 6dee055cc71..6b27e1817d8 100644 --- a/test/es6/async-jit-bugs.js +++ b/test/es6GeneratorJit/async-jit-bugs.js @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- diff --git a/test/es6/generator-jit-bugs.js b/test/es6GeneratorJit/generator-jit-bugs.js similarity index 98% rename from test/es6/generator-jit-bugs.js rename to test/es6GeneratorJit/generator-jit-bugs.js index 2594cc92d4f..96e0be58665 100644 --- a/test/es6/generator-jit-bugs.js +++ b/test/es6GeneratorJit/generator-jit-bugs.js @@ -1,6 +1,6 @@ //------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. -// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- diff --git a/test/es6GeneratorJit/jit-async-loop-body-2.baseline b/test/es6GeneratorJit/jit-async-loop-body-2.baseline new file mode 100644 index 00000000000..cebabd52a99 --- /dev/null +++ b/test/es6GeneratorJit/jit-async-loop-body-2.baseline @@ -0,0 +1,20 @@ +Beginning basicAsync +basicAsync Loop 0 a = 80 +basicAsync Loop 0 arguments[0] = 80 +basicAsync Loop 0 a = 160 +basicAsync Loop 0 arguments[0] = 160 +Loop 3 completed +Loop 4 k = 160 +Loop 4 k = 80 +Loop 4 k = 0 +Loop 4 completed +Beginning basicAsync +basicAsync Loop 0 a = 80 +basicAsync Loop 0 arguments[0] = 80 +basicAsync Loop 0 a = 160 +basicAsync Loop 0 arguments[0] = 160 +Loop 3 completed +Loop 4 k = 160 +Loop 4 k = 80 +Loop 4 k = 0 +Loop 4 completed diff --git a/test/es6GeneratorJit/jit-async-loop-body.baseline b/test/es6GeneratorJit/jit-async-loop-body.baseline new file mode 100644 index 00000000000..d9e00f69d6b --- /dev/null +++ b/test/es6GeneratorJit/jit-async-loop-body.baseline @@ -0,0 +1,42 @@ +Beginning basicAsync +---BeginBackEnd: function: printif--- +---EndBackEnd--- +---BeginBackEnd: function: printif--- +---EndBackEnd--- +---BeginBackEnd: function: basicAsync, loop:1--- +---EndBackEnd--- +basicAsync Loop 0 a = 80 +basicAsync Loop 0 arguments[0] = 80 +---BeginBackEnd: function: basicAsync, loop:0--- +---EndBackEnd--- +basicAsync Loop 0 a = 160 +basicAsync Loop 0 arguments[0] = 160 +Loop 3 completed +---BeginBackEnd: function: value--- +---EndBackEnd--- +---BeginBackEnd: function: value--- +---EndBackEnd--- +---BeginBackEnd: function: value--- +---EndBackEnd--- +Loop 4 k = 160 +---BeginBackEnd: function: basicAsync, loop:4--- +---EndBackEnd--- +Loop 4 k = 80 +Loop 4 k = 0 +Loop 4 completed +Beginning basicAsync +basicAsync Loop 0 a = 80 +basicAsync Loop 0 arguments[0] = 80 +basicAsync Loop 0 a = 160 +basicAsync Loop 0 arguments[0] = 160 +Loop 3 completed +---BeginBackEnd: function: Array.prototype.values--- +---EndBackEnd--- +---BeginBackEnd: function: Anonymous function--- +---EndBackEnd--- +---BeginBackEnd: function: Anonymous function--- +---EndBackEnd--- +Loop 4 k = 160 +Loop 4 k = 80 +Loop 4 k = 0 +Loop 4 completed diff --git a/test/es6GeneratorJit/jit-async-loop-body.js b/test/es6GeneratorJit/jit-async-loop-body.js new file mode 100644 index 00000000000..097174a1501 --- /dev/null +++ b/test/es6GeneratorJit/jit-async-loop-body.js @@ -0,0 +1,42 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +let bar = []; +let j = 0; + +function printif (text, x, mod) { + if (x % mod == 0) { + print (text + x); + } +} + +async function basicAsync(a, b) { + print("Beginning basicAsync") + await b; + var foo = [0.1, 0.2, 0.3, 0.4, 0]; + while (a < 200) { // Loop 0 - should be jitted + foo[a] = Math.random(); + printif(arguments.callee.name + " Loop 0 a = ", a, 80); + printif(arguments.callee.name + " Loop 0 arguments[0] = ", arguments[0], 80); + for (let k in foo) { bar[k] = a - k;} // Loop 1 - shuld be jitted + ++a; + } + while (true){ // Loop 2 - should not be jitted + for (j = 0; j < 100; ++j) { // Loop 3 - should not be jitted + await j; + foo[j] = j; + } + print("Loop 3 completed"); + for (let k of bar) { // Loop 4 - should be jitted + printif("Loop 4 k = ", k, 80); + foo[0] = foo[1] + 1; + } + print("Loop 4 completed"); + return j; + } +} + +basicAsync(4, 3).then(x => basicAsync(3, 2)); diff --git a/test/es6GeneratorJit/jit-gen-loop-body-2.baseline b/test/es6GeneratorJit/jit-gen-loop-body-2.baseline new file mode 100644 index 00000000000..69d659a198e --- /dev/null +++ b/test/es6GeneratorJit/jit-gen-loop-body-2.baseline @@ -0,0 +1,13 @@ +Beginning test of basicGenerator +basicGenerator Loop 0 a = 40 +basicGenerator Loop 0 arguments[0] = 40 +basicGenerator Loop 0 a = 80 +basicGenerator Loop 0 arguments[0] = 80 +Loop 3 completed +Loop 4 k = 80 +Loop 4 k = 40 +Loop 4 k = 0 +Loop 4 completed +yielded value = 80 +yielded value = 40 +yielded value = 0 diff --git a/test/es6GeneratorJit/jit-gen-loop-body.baseline b/test/es6GeneratorJit/jit-gen-loop-body.baseline new file mode 100644 index 00000000000..be92f4a3d28 --- /dev/null +++ b/test/es6GeneratorJit/jit-gen-loop-body.baseline @@ -0,0 +1,35 @@ +Beginning test of basicGenerator +---BeginBackEnd: function: printif--- +---EndBackEnd--- +---BeginBackEnd: function: printif--- +---EndBackEnd--- +---BeginBackEnd: function: basicGenerator, loop:1--- +---EndBackEnd--- +basicGenerator Loop 0 a = 40 +basicGenerator Loop 0 arguments[0] = 40 +---BeginBackEnd: function: basicGenerator, loop:0--- +---EndBackEnd--- +basicGenerator Loop 0 a = 80 +basicGenerator Loop 0 arguments[0] = 80 +Loop 3 completed +---BeginBackEnd: function: value--- +---EndBackEnd--- +---BeginBackEnd: function: value--- +---EndBackEnd--- +---BeginBackEnd: function: value--- +---EndBackEnd--- +Loop 4 k = 80 +---BeginBackEnd: function: basicGenerator, loop:4--- +---EndBackEnd--- +Loop 4 k = 40 +Loop 4 k = 0 +Loop 4 completed +---BeginBackEnd: function: Array.prototype.values--- +---EndBackEnd--- +---BeginBackEnd: function: Anonymous function--- +---EndBackEnd--- +---BeginBackEnd: function: Anonymous function--- +---EndBackEnd--- +yielded value = 80 +yielded value = 40 +yielded value = 0 diff --git a/test/es6GeneratorJit/jit-gen-loop-body.js b/test/es6GeneratorJit/jit-gen-loop-body.js new file mode 100644 index 00000000000..f72fcf8ddbf --- /dev/null +++ b/test/es6GeneratorJit/jit-gen-loop-body.js @@ -0,0 +1,48 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +let bar = []; +let j = 0; + +function printif (text, x, mod) { + if (x % mod == 0) { + print (text + x); + } +} + +function* basicGenerator(a, b) { + print("Beginning test of " + arguments.callee.name); + yield "yield 2nd param b =" + b; + var foo = [0.1, 0.2, 0.3, 0.4, 0]; + while (a < 100) { // Loop 0 - should be jitted + foo[a] = Math.random(); + printif(arguments.callee.name + " Loop 0 a = ", a, 40); + printif(arguments.callee.name + " Loop 0 arguments[0] = ", arguments[0], 40); + for (let k in foo) { bar[k] = a - k;} // Loop 1 - shuld be jitted + ++a; + } + while (true){ // Loop 2 - should not be jitted + for (j = 0; j < 100; ++j) { // Loop 3 - should not be jitted + if (j % 40 == 1) + yield j; + + foo[j] = j; + } + print("Loop 3 completed"); + for (let k of bar) { // Loop 4 - should be jitted + printif("Loop 4 k = ", k, 40); + foo[0] = foo[1] + 1; + } + print("Loop 4 completed"); + yield* bar; // Loop 5 - should not be jitted + return j; + } +} + +const gen = basicGenerator(5, 1); +for (let x = gen.next(); !x.done; x = gen.next() ) { + printif("yielded value = ", x.value, 40); +} diff --git a/test/es6GeneratorJit/jit-module-loop-body-2.baseline b/test/es6GeneratorJit/jit-module-loop-body-2.baseline new file mode 100644 index 00000000000..1d8802ac915 --- /dev/null +++ b/test/es6GeneratorJit/jit-module-loop-body-2.baseline @@ -0,0 +1,11 @@ +Loop 0 a = 40 +Loop 0 a = 80 +Loop 0 a = 120 +Loop 0 a = 160 +Loop 3 completed +Loop 4 k = 160 +Loop 4 k = 120 +Loop 4 k = 80 +Loop 4 k = 40 +Loop 4 k = 0 +Loop 4 completed diff --git a/test/es6GeneratorJit/jit-module-loop-body.baseline b/test/es6GeneratorJit/jit-module-loop-body.baseline new file mode 100644 index 00000000000..320dc2690cf --- /dev/null +++ b/test/es6GeneratorJit/jit-module-loop-body.baseline @@ -0,0 +1,27 @@ +---BeginBackEnd: function: printif--- +---EndBackEnd--- +---BeginBackEnd: function: printif--- +---EndBackEnd--- +---BeginBackEnd: function: Module code, loop:1--- +---EndBackEnd--- +Loop 0 a = 40 +Loop 0 a = 80 +Loop 0 a = 120 +---BeginBackEnd: function: Module code, loop:0--- +---EndBackEnd--- +Loop 0 a = 160 +Loop 3 completed +---BeginBackEnd: function: value--- +---EndBackEnd--- +---BeginBackEnd: function: value--- +---EndBackEnd--- +---BeginBackEnd: function: value--- +---EndBackEnd--- +Loop 4 k = 160 +---BeginBackEnd: function: Module code, loop:4--- +---EndBackEnd--- +Loop 4 k = 120 +Loop 4 k = 80 +Loop 4 k = 40 +Loop 4 k = 0 +Loop 4 completed diff --git a/test/es6GeneratorJit/jit-module-loop-body.js b/test/es6GeneratorJit/jit-module-loop-body.js new file mode 100644 index 00000000000..9ec92be8db3 --- /dev/null +++ b/test/es6GeneratorJit/jit-module-loop-body.js @@ -0,0 +1,41 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +let bar = []; +let j = 0, a = 3, b = 2; + +function printif (text, x, mod) { + if (x % mod == 0) { + print (text + x); + } +} + + +await b; +var foo = [0.1, 0.2, 0.3, 0.4, 0]; +while (a < 200) { // Loop 0 - should be jitted + foo[a] = Math.random(); + printif("Loop 0 a = ", a, 40); + for (let k in foo) { bar[k] = a - k;} // Loop 1 - shuld be jitted + ++a; +} +while (true){ // Loop 2 - should not be jitted + for (j = 0; j < 100; ++j) { // Loop 3 - should not be jitted + await j; + + foo[j] = j; + } + print("Loop 3 completed"); + for (let k of bar) { // Loop 4 - should be jitted + printif("Loop 4 k = ", k, 40); + foo[0] = foo[1] + 1; + } + print("Loop 4 completed"); + await j; + break; +} + + diff --git a/test/es6GeneratorJit/newtest.js b/test/es6GeneratorJit/newtest.js new file mode 100644 index 00000000000..797036cff90 --- /dev/null +++ b/test/es6GeneratorJit/newtest.js @@ -0,0 +1,52 @@ +//------------------------------------------------------------------------------------------------------- +// Copyright (C) Microsoft. All rights reserved. +// Copyright (c) ChakraCore Project Contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. +//------------------------------------------------------------------------------------------------------- + +// Simpler mini-test harness to avoid any complicating factors when testing these jit bugs +var results = 0; +var test = 0; +const verbose = WScript.Arguments[0] != "summary"; + +function check(actual, expected) { + if (actual != expected) + throw new Error("Generator produced " + actual + " instead of " + expected); + if (verbose) + print('Result ' + ++results + ' Generator correctly produced ' + actual); +} + +function title (name) { + if (verbose) { + print("Beginning Test " + ++test + ": " + name); + results = 0; + } +} + + +// Test 1 - Construction after self-reference in loop control +title("Construction after self-reference in loop control"); + +function testOne() +{ + function* foo(a1,a2) { + + for (let i = a1; i < foo; i = i + a2) + { + yield 0; + } + + function bar() {} + var b = new bar(); + } + + foo().next() + return true; +} + + +for (var i = 0; i < 30 ;++i){ + testOne(); +} + +print('pass') diff --git a/test/es6GeneratorJit/rlexe.xml b/test/es6GeneratorJit/rlexe.xml new file mode 100644 index 00000000000..b03e98961f7 --- /dev/null +++ b/test/es6GeneratorJit/rlexe.xml @@ -0,0 +1,140 @@ + + + + + generator-jit-bugs.js + -args summary -endargs + exclude_nonative + + + + + generator-jit-bugs.js + -JitES6Generators -args summary -endargs + exclude_nonative + + + + + generator-jit-bugs.js + -JitES6Generators -off:simplejit -args summary -endargs + exclude_nonative + + + + + generator-jit-bugs.js + -JitES6Generators -off:fulljit -args summary -endargs + exclude_nonative, exclude_dynapogo + + + + + async-jit-bugs.js + -args summary -endargs + exclude_nonative + + + + + async-jit-bugs.js + -JitES6Generators -args summary -endargs + exclude_nonative + + + + + async-jit-bugs.js + -JitES6Generators -off:simplejit -args summary -endargs + exclude_nonative + + + + + async-jit-bugs.js + -JitES6Generators -off:fulljit -args summary -endargs + exclude_nonative, exclude_dynapogo + + + + + async-jit-bugs.js + -off:fulljit -args summary -endargs + exclude_nonative, exclude_dynapogo + + + + + newTest.js + -args summary -endargs + exclude_nonative + + + + + newTest.js + -off:simplejit -args summary -endargs + exclude_nonative + + + + + newTest.js + -off:fulljit -args summary -endargs + exclude_nonative, exclude_dynapogo + + + + + newTest.js + -off:fulljit -args summary -endargs + exclude_nonative, exclude_dynapogo + + + + + jit-gen-loop-body.js + -testtrace:Backend + jit-gen-loop-body.baseline + exclude_test, exclude_nonative, exclude_dynapogo + + + + + jit-gen-loop-body.js + jit-gen-loop-body-2.baseline + exclude_nonative + + + + + jit-async-loop-body.js + -testtrace:Backend + jit-async-loop-body.baseline + exclude_test, exclude_nonative, exclude_dynapogo + + + + + jit-async-loop-body.js + jit-async-loop-body-2.baseline + exclude_nonative + + + + + jit-module-loop-body.js + -testtrace:Backend -module + jit-module-loop-body.baseline + exclude_test, exclude_nonative, exclude_dynapogo + + + + + jit-module-loop-body.js + -module + jit-module-loop-body-2.baseline + exclude_nonative + + + diff --git a/test/rlexedirs.xml b/test/rlexedirs.xml index 3c1782b1d19..5b61668f4c1 100644 --- a/test/rlexedirs.xml +++ b/test/rlexedirs.xml @@ -262,6 +262,12 @@ es6 + + + es6GeneratorJit + require_backend + + es6module