Skip to content

Commit

Permalink
Enable Jitting Generators and Async Functions
Browse files Browse the repository at this point in the history
- exclude ARM which has not been tested
- excludes code running with debugger attached (not tested)
- excludes functions containing try/catch (not tested)
- excludes Module globals (unlikely to benefit)
- add tests for bugs fixed above
  • Loading branch information
rhuanjl committed Mar 23, 2021
1 parent 72c05da commit ede39dd
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 14 deletions.
11 changes: 10 additions & 1 deletion lib/Common/ConfigFlagsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,15 @@ PHASE(All)
#define DEFAULT_CONFIG_ESArrayFindFromLast (false)
#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
#ifdef _M_ARM32_OR_ARM64
#define DEFAULT_CONFIG_JitES6Generators (false)
#else
#define DEFAULT_CONFIG_JitES6Generators (true)
#endif

#ifdef COMPILE_DISABLE_ES6RegExPrototypeProperties
// If ES6RegExPrototypeProperties needs to be disabled by compile flag, DEFAULT_CONFIG_ES6RegExPrototypeProperties should be false
#define DEFAULT_CONFIG_ES6RegExPrototypeProperties (false)
Expand Down Expand Up @@ -1206,7 +1215,7 @@ FLAGR(Boolean, ESImportMeta, "Enable import.meta keyword", DEFAULT_CONFIG_ESImpo
FLAGR(Boolean, ESGlobalThis, "Enable globalThis", DEFAULT_CONFIG_ESGlobalThis)

// This flag to be removed once JITing generator functions is stable
FLAGNR(Boolean, JitES6Generators , "Enable JITing of ES6 generators", false)
FLAGNR(Boolean, JitES6Generators , "Enable JITing of ES6 generators", DEFAULT_CONFIG_JitES6Generators)

FLAGNR(Boolean, FastLineColumnCalculation, "Enable fast calculation of line/column numbers from the source.", DEFAULT_CONFIG_FastLineColumnCalculation)
FLAGR (String, Filename , "Jscript source file", nullptr)
Expand Down
11 changes: 5 additions & 6 deletions lib/Runtime/Base/FunctionBody.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeBasePch.h"
Expand Down Expand Up @@ -341,13 +342,13 @@ namespace Js
bool
FunctionBody::SkipAutoProfileForCoroutine() const
{
return this->IsCoroutine() && CONFIG_ISENABLED(Js::JitES6GeneratorsFlag);
return this->IsCoroutine() && CONFIG_FLAG(JitES6Generators);
}

bool
FunctionBody::IsGeneratorAndJitIsDisabled() const
{
return this->IsCoroutine() && !(CONFIG_ISENABLED(Js::JitES6GeneratorsFlag) && !this->GetHasTry() && !this->IsInDebugMode() && !this->IsAsync());
return this->IsCoroutine() && !(CONFIG_FLAG(JitES6Generators) && !this->GetHasTry() && !this->IsInDebugMode() && !this->IsModule());
}

ScriptContext* EntryPointInfo::GetScriptContext()
Expand Down Expand Up @@ -7151,8 +7152,7 @@ namespace Js
!GetScriptContext()->IsScriptContextInDebugMode() &&
DoInterpreterProfile() &&
#pragma warning(suppress: 6235) // (<non-zero constant> || <expression>) is always a non-zero constant.
(!CONFIG_FLAG(NewSimpleJit) || DoInterpreterAutoProfile()) &&
!IsCoroutine(); // Generator JIT requires bailout which SimpleJit cannot do since it skips GlobOpt
(!CONFIG_FLAG(NewSimpleJit) || DoInterpreterAutoProfile());
}

bool FunctionBody::DoSimpleJitWithLock() const
Expand All @@ -7166,8 +7166,7 @@ namespace Js
!this->IsInDebugMode() &&
DoInterpreterProfileWithLock() &&
#pragma warning(suppress: 6235) // (<non-zero constant> || <expression>) is always a non-zero constant.
(!CONFIG_FLAG(NewSimpleJit) || DoInterpreterAutoProfile()) &&
!IsCoroutine(); // Generator JIT requires bailout which SimpleJit cannot do since it skips GlobOpt
(!CONFIG_FLAG(NewSimpleJit) || DoInterpreterAutoProfile());
}

bool FunctionBody::DoSimpleJitDynamicProfile() const
Expand Down
85 changes: 79 additions & 6 deletions test/es6/generator-jit-bugs.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,93 @@
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Copyright (c) 2021 ChakraCore Project Contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

let results = 0;
let 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 - const that is unused/replaced with undefined
function* foo() {
title("const that is unused/replaced with undefined");
function* gf1() {
const temp2 = null;
while (true) {
yield temp2;
}
}

const gen = foo();
const gen = gf1();

check(gen.next().value, null);
check(gen.next().value, null);
check(gen.next().value, null);

// Test 2 - load for-in enumerator in nested for-in loop
title("load for-in enumerator in nested for-in loop");
const arr = [0, 1, 2];
function* gf2() {
for (let a in arr) {
for (let b in arr) {
yield a + b;
}
}
}

const gen2 = gf2();

check(gen2.next().value, "00");
check(gen2.next().value, "01");
check(gen2.next().value, "02");
check(gen2.next().value, "10");
check(gen2.next().value, "11");
check(gen2.next().value, "12");
check(gen2.next().value, "20");
check(gen2.next().value, "21");
check(gen2.next().value, "22");
check(gen2.next().value, undefined);

// Test 3 - Bail on no profile losing loop control variable
title("Bail on no profile losing loop control variable");
function* gf3() {
for (let i = 0; i < 3; ++i) {
yield i;
}
}

const gen3 = gf3();

check(gen3.next().value, 0);
check(gen3.next().value, 1);
check(gen3.next().value, 2);

// Test 4 - yield* iterator fails to be restored after Bail on No Profile
title("Bail on no profile losing yield* iterator")
function* gf4() {
yield 0;
yield* [1,2,3];
}

const gen4 = gf4();

gen.next();
gen.next();
gen.next();
check(gen4.next().value, 0);
check(gen4.next().value, 1);
check(gen4.next().value, 2);
check(gen4.next().value, 3);

print("Pass");
print("pass");
16 changes: 15 additions & 1 deletion test/es6/rlexe.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,24 @@
<test>
<default>
<files>generator-jit-bugs.js</files>
<compile-flags>-JitES6Generators</compile-flags>
<compile-flags>-JitES6Generators -args summary -endargs</compile-flags>
<tags>exclude_nonative</tags>
</default>
</test>
<test>
<default>
<files>generator-jit-bugs.js</files>
<compile-flags>-JitES6Generators -off:simplejit -args summary -endargs</compile-flags>
<tags>exclude_nonative</tags>
</default>
</test>
<test>
<default>
<files>generator-jit-bugs.js</files>
<compile-flags>-JitES6Generators -off:fulljit -args summary -endargs</compile-flags>
<tags>exclude_nonative, exclude_dynapogo</tags>
</default>
</test>
<test>
<default>
<files>proto_basic.js</files>
Expand Down

0 comments on commit ede39dd

Please sign in to comment.