Skip to content

Commit 23057cf

Browse files
committed
implement BigInt literal, BigInt constructor and comparison operator
add javascript bigint class and bigint object class (raw) add esbigint config flag add bigint init prototype, statictype, dynamictype to library change FScanNumber to recognize BigInt literal add bigint token, parsenode in parser add BigIntConstant to ByteCode and link it to JavascriptString for now add init bigint from a string, allocate bigint constants value comparison bigint literal add comparison operator support for BigInt object fix ch trace:parse, dump:bytecote fix FScanNumber set ESBigInt flag to false and fix scancore add test for bigint refactor code support signed bigint bytecode regen, address PR comments
1 parent 73a097d commit 23057cf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+11830
-574
lines changed

bin/NativeTests/BigUIntTest.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace Js
2626
}
2727

2828
template <typename EncodedChar>
29-
double Js::NumberUtilities::StrToDbl(const EncodedChar *, const EncodedChar **, bool& )
29+
double Js::NumberUtilities::StrToDbl(const EncodedChar *, const EncodedChar **, LikelyNumberType& , bool)
3030
{
3131
Assert(false);
3232
return 0.0;// don't care

lib/Common/Common/NumberUtilities.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,8 @@ using namespace Js;
684684
double NumberUtilities::StrToDbl(const EncodedChar * psz, const EncodedChar **ppchLim, Js::ScriptContext *const scriptContext)
685685
{
686686
Assert(scriptContext);
687-
bool likelyInt = true;
688-
return Js::NumberUtilities::StrToDbl<EncodedChar>(psz, ppchLim, likelyInt);
687+
LikelyNumberType likelyType = LikelyNumberType::Int;
688+
return Js::NumberUtilities::StrToDbl<EncodedChar>(psz, ppchLim, likelyType);
689689
}
690690

691691
template double NumberUtilities::StrToDbl<char16>(const char16 * psz, const char16 **ppchLim, Js::ScriptContext *const scriptContext);

lib/Common/Common/NumberUtilities.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@
44
//-------------------------------------------------------------------------------------------------------
55
#pragma once
66

7+
enum class LikelyNumberType
8+
{
9+
Double,
10+
Int,
11+
BigInt,
12+
};
13+
14+
715
namespace Js
816
{
917
class NumberConstants : public NumberConstantsBase
@@ -217,7 +225,7 @@ namespace Js
217225

218226
// Implemented in lib\parser\common. Should move to lib\common
219227
template<typename EncodedChar>
220-
static double StrToDbl(const EncodedChar *psz, const EncodedChar **ppchLim, bool& likelyInt);
228+
static double StrToDbl(const EncodedChar *psz, const EncodedChar **ppchLim, LikelyNumberType& likelyType, bool isESBigIntEnabled = false);
221229

222230
static BOOL FDblToStr(double dbl, __out_ecount(nDstBufSize) char16 *psz, int nDstBufSize);
223231
static int FDblToStr(double dbl, NumberUtilities::FormatType ft, int nDigits, __out_ecount(cchDst) char16 *pchDst, int cchDst);

lib/Common/Common/NumberUtilities_strtod.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -893,13 +893,13 @@ static double AdjustDbl(double dbl, const EncodedChar *prgch, int32 cch, int32 l
893893
String to Double.
894894
***************************************************************************/
895895
template <typename EncodedChar>
896-
double Js::NumberUtilities::StrToDbl( const EncodedChar *psz, const EncodedChar **ppchLim, bool& likelyInt )
896+
double Js::NumberUtilities::StrToDbl( const EncodedChar *psz, const EncodedChar **ppchLim, LikelyNumberType& likelyNumberType, bool isBigIntEnabled)
897897
{
898898
uint32 lu;
899899
BIGNUM num;
900900
BIGNUM numHi;
901901
BIGNUM numLo;
902-
double dbl;
902+
double dbl = 0;
903903
double dblLo;
904904
#if DBG
905905
bool canUseLowPrec = false;
@@ -990,12 +990,19 @@ double Js::NumberUtilities::StrToDbl( const EncodedChar *psz, const EncodedChar
990990
case 'E':
991991
case 'e':
992992
goto LGetExp;
993+
case 'n':
994+
if (isBigIntEnabled)
995+
{
996+
goto LBigInt;
997+
}
998+
default:
999+
likelyNumberType = LikelyNumberType::Int;
9931000
}
9941001
goto LEnd;
9951002

9961003
LGetRight:
9971004
Assert(*pch == '.');
998-
likelyInt = false;
1005+
likelyNumberType = LikelyNumberType::Double;
9991006
pch++;
10001007
if (NULL == pchMinDig)
10011008
{
@@ -1043,6 +1050,13 @@ double Js::NumberUtilities::StrToDbl( const EncodedChar *psz, const EncodedChar
10431050
if (lwExp > 100000000)
10441051
lwExp = 100000000;
10451052
}
1053+
goto LEnd;
1054+
1055+
LBigInt:
1056+
pch++;
1057+
likelyNumberType = LikelyNumberType::BigInt;
1058+
*ppchLim = pch;
1059+
goto LDone;
10461060

10471061
LEnd:
10481062
*ppchLim = pch;
@@ -1256,8 +1270,8 @@ double Js::NumberUtilities::StrToDbl( const EncodedChar *psz, const EncodedChar
12561270
return dbl;
12571271
}
12581272

1259-
template double Js::NumberUtilities::StrToDbl<char16>( const char16 * psz, const char16 **ppchLim, bool& likelyInt );
1260-
template double Js::NumberUtilities::StrToDbl<utf8char_t>(const utf8char_t * psz, const utf8char_t **ppchLim, bool& likelyInt);
1273+
template double Js::NumberUtilities::StrToDbl<char16>( const char16 * psz, const char16 **ppchLim, LikelyNumberType& likelyInt, bool isBigIntEnabled );
1274+
template double Js::NumberUtilities::StrToDbl<utf8char_t>(const utf8char_t * psz, const utf8char_t **ppchLim, LikelyNumberType& likelyInt, bool isBigIntEnabled );
12611275

12621276
/***************************************************************************
12631277
Uses big integer arithmetic to get the sequence of digits.
@@ -2439,8 +2453,8 @@ BOOL Js::NumberUtilities::FNonZeroFiniteDblToStr(double dbl, __out_ecount(cchDst
24392453
{
24402454
if (FormatDigits(rgb, pbLim, wExp10, pchDst, cchDst))
24412455
{
2442-
bool likelyInt = true;
2443-
dblT = StrToDbl<char16>(pchDst, &pch,likelyInt);
2456+
LikelyNumberType likelyInt = LikelyNumberType::Int;
2457+
dblT = StrToDbl<char16>(pchDst, &pch, likelyInt);
24442458
Assert(0 == *pch);
24452459
Assert(dblT == dbl);
24462460
}
@@ -2465,7 +2479,7 @@ BOOL Js::NumberUtilities::FNonZeroFiniteDblToStr(double dbl, __out_ecount(cchDst
24652479
}
24662480

24672481
#if DBG
2468-
bool likelyInt = true;
2482+
LikelyNumberType likelyInt = LikelyNumberType::Int;
24692483
dblT = StrToDbl<char16>(pchDst, &pch, likelyInt);
24702484
Assert(0 == *pch);
24712485
Assert(dblT == dbl);

lib/Common/ConfigFlagsList.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,7 @@ PHASE(All)
650650
#define DEFAULT_CONFIG_ES6Unscopables (true)
651651
#define DEFAULT_CONFIG_ES6RegExSticky (true)
652652
#define DEFAULT_CONFIG_ES2018RegExDotAll (true)
653+
#define DEFAULT_CONFIG_ESBigInt (false)
653654
#ifdef COMPILE_DISABLE_ES6RegExPrototypeProperties
654655
// If ES6RegExPrototypeProperties needs to be disabled by compile flag, DEFAULT_CONFIG_ES6RegExPrototypeProperties should be false
655656
#define DEFAULT_CONFIG_ES6RegExPrototypeProperties (false)
@@ -1083,6 +1084,7 @@ FLAGNR(Boolean, EntryPointInfoRpcData , "Keep encoded rpc buffer for jitted func
10831084

10841085
FLAGNR(Boolean, LdChakraLib , "Access to the Chakra internal library with the __chakraLibrary keyword", DEFAULT_CONFIG_LdChakraLib)
10851086
FLAGNR(Boolean, TestChakraLib , "Access to the Chakra internal library with the __chakraLibrary keyword without global access restriction", DEFAULT_CONFIG_TestChakraLib)
1087+
10861088
// ES6 (BLUE+1) features/flags
10871089

10881090
// Master ES6 flag to enable STABLE ES6 features/flags
@@ -1178,6 +1180,9 @@ FLAGNR(Boolean, WinRTDelegateInterfaces , "Treat WinRT Delegates as Interfaces w
11781180
FLAGR(Boolean, WinRTAdaptiveApps , "Enable the adaptive apps feature, allowing for variable projection." , DEFAULT_CONFIG_WinRTAdaptiveApps)
11791181
#endif
11801182

1183+
// ES BigInt flag
1184+
FLAGR(Boolean, ESBigInt, "Enable ESBigInt flag", DEFAULT_CONFIG_ESBigInt)
1185+
11811186
// This flag to be removed once JITing generator functions is stable
11821187
FLAGNR(Boolean, JitES6Generators , "Enable JITing of ES6 generators", false)
11831188

lib/Parser/Parse.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,15 @@ ParseNodeStr * Parser::CreateStrNode(IdentPtr pid)
10521052
return pnode;
10531053
}
10541054

1055+
ParseNodeBigInt * Parser::CreateBigIntNode(IdentPtr pid)
1056+
{
1057+
Assert(!this->m_deferringAST);
1058+
ParseNodeBigInt * pnode = Anew(&m_nodeAllocator, ParseNodeBigInt, this->GetScanner()->IchMinTok(), this->GetScanner()->IchLimTok(), pid);
1059+
pnode->isNegative = false;
1060+
AddAstSize(sizeof(ParseNodeBigInt));
1061+
return pnode;
1062+
}
1063+
10551064
ParseNodeName * Parser::CreateNameNode(IdentPtr pid)
10561065
{
10571066
ParseNodeName * pnode = Anew(&m_nodeAllocator, ParseNodeName, this->GetScanner()->IchMinTok(), this->GetScanner()->IchLimTok(), pid);
@@ -3344,6 +3353,20 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
33443353
this->GetScanner()->Scan();
33453354
break;
33463355

3356+
case tkBigIntCon:
3357+
if (IsStrictMode() && this->GetScanner()->IsOctOrLeadingZeroOnLastTKNumber())
3358+
{
3359+
Error(ERRES5NoOctal);
3360+
}
3361+
3362+
if (buildAST)
3363+
{
3364+
pnode = CreateBigIntNode(m_token.GetBigInt());
3365+
}
3366+
fCanAssign = FALSE;
3367+
this->GetScanner()->Scan();
3368+
break;
3369+
33473370
case tkFltCon:
33483371
if (IsStrictMode() && this->GetScanner()->IsOctOrLeadingZeroOnLastTKNumber())
33493372
{
@@ -8786,15 +8809,20 @@ ParseNodePtr Parser::ParseExpr(int oplMin,
87868809
}
87878810
else if (nop == knopNeg &&
87888811
((pnodeT->nop == knopInt && pnodeT->AsParseNodeInt()->lw != 0) ||
8789-
(pnodeT->nop == knopFlt && (pnodeT->AsParseNodeFloat()->dbl != 0 || this->m_InAsmMode))))
8812+
(pnodeT->nop == knopFlt && (pnodeT->AsParseNodeFloat()->dbl != 0 || this->m_InAsmMode)) ||
8813+
(pnodeT->nop == knopBigInt)))
87908814
{
87918815
// Fold a unary '-' on a number into the value of the number itself.
87928816
pnode = pnodeT;
87938817
if (pnode->nop == knopInt)
87948818
{
87958819
pnode->AsParseNodeInt()->lw = -pnode->AsParseNodeInt()->lw;
87968820
}
8797-
else
8821+
else if (pnode->nop == knopBigInt)
8822+
{
8823+
pnode->AsParseNodeBigInt()->isNegative = true;
8824+
}
8825+
else
87988826
{
87998827
pnode->AsParseNodeFloat()->dbl = -pnode->AsParseNodeFloat()->dbl;
88008828
}
@@ -9160,6 +9188,7 @@ ParseNodePtr Parser::ParseExpr(int oplMin,
91609188
{
91619189
case knopName:
91629190
case knopInt:
9191+
case knopBigInt:
91639192
case knopFlt:
91649193
case knopStr:
91659194
case knopRegExp:
@@ -12271,6 +12300,9 @@ ParseNode* Parser::CopyPnode(ParseNode *pnode) {
1227112300
}
1227212301
//PTNODE(knopInt , "int const" ,None ,Int ,fnopLeaf|fnopConst)
1227312302
case knopInt:
12303+
return pnode;
12304+
//PTNODE(knopBigInt , "bigint const" ,None ,BigInt ,fnopLeaf|fnopConst)
12305+
case knopBigInt:
1227412306
return pnode;
1227512307
//PTNODE(knopFlt , "flt const" ,None ,Flt ,fnopLeaf|fnopConst)
1227612308
case knopFlt:
@@ -13348,6 +13380,11 @@ void PrintPnodeWIndent(ParseNode *pnode, int indentAmt) {
1334813380
Indent(indentAmt);
1334913381
Output::Print(_u("%d\n"), pnode->AsParseNodeInt()->lw);
1335013382
break;
13383+
//PTNODE(knopInt , "int const" ,None ,Int ,fnopLeaf|fnopConst)
13384+
case knopBigInt:
13385+
Indent(indentAmt);
13386+
Output::Print(_u("%s%s\n"), pnode->AsParseNodeBigInt()->isNegative? "-" : "", pnode->AsParseNodeBigInt()->pid->Psz());
13387+
break;
1335113388
//PTNODE(knopFlt , "flt const" ,None ,Flt ,fnopLeaf|fnopConst)
1335213389
case knopFlt:
1335313390
Indent(indentAmt);

lib/Parser/Parse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ class Parser
378378

379379
ParseNodeInt * CreateIntNode(int32 lw);
380380
ParseNodeStr * CreateStrNode(IdentPtr pid);
381+
ParseNodeBigInt * CreateBigIntNode(IdentPtr pid);
381382
ParseNodeName * CreateNameNode(IdentPtr pid);
382383
ParseNodeName * CreateNameNode(IdentPtr pid, PidRefStack * ref, charcount_t ichMin, charcount_t ichLim);
383384
ParseNodeSpecialName * CreateSpecialNameNode(IdentPtr pid, PidRefStack * ref, charcount_t ichMin, charcount_t ichLim);

lib/Parser/Scan.cpp

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -587,12 +587,12 @@ IdentPtr Scanner<EncodingPolicy>::PidOfIdentiferAt(EncodedCharPtr p, EncodedChar
587587
}
588588

589589
template <typename EncodingPolicy>
590-
typename Scanner<EncodingPolicy>::EncodedCharPtr Scanner<EncodingPolicy>::FScanNumber(EncodedCharPtr p, double *pdbl, bool& likelyInt, size_t savedMultiUnits)
590+
typename Scanner<EncodingPolicy>::EncodedCharPtr Scanner<EncodingPolicy>::FScanNumber(EncodedCharPtr p, double *pdbl, LikelyNumberType& likelyType, size_t savedMultiUnits)
591591
{
592592
EncodedCharPtr last = m_pchLast;
593593
EncodedCharPtr pchT = nullptr;
594594
bool baseSpecified = false;
595-
likelyInt = true;
595+
likelyType = LikelyNumberType::Int;
596596
// Reset
597597
m_OctOrLeadingZeroOnLastTKNumber = false;
598598

@@ -617,7 +617,8 @@ typename Scanner<EncodingPolicy>::EncodedCharPtr Scanner<EncodingPolicy>::FScanN
617617
case '.':
618618
case 'e':
619619
case 'E':
620-
likelyInt = false;
620+
case 'n':
621+
likelyType = LikelyNumberType::Double;
621622
// Floating point
622623
goto LFloat;
623624

@@ -668,8 +669,12 @@ typename Scanner<EncodingPolicy>::EncodedCharPtr Scanner<EncodingPolicy>::FScanN
668669
else
669670
{
670671
LFloat:
671-
*pdbl = Js::NumberUtilities::StrToDbl(p, &pchT, likelyInt);
672+
*pdbl = Js::NumberUtilities::StrToDbl(p, &pchT, likelyType, m_scriptContext->GetConfig()->IsESBigIntEnabled());
672673
Assert(pchT == p || !Js::NumberUtilities::IsNan(*pdbl));
674+
if (likelyType == LikelyNumberType::BigInt)
675+
{
676+
Assert(*pdbl == 0);
677+
}
673678
// fall through to LIdCheck
674679
}
675680

@@ -1723,28 +1728,36 @@ tokens Scanner<EncodingPolicy>::ScanCore(bool identifyKwds)
17231728
Assert(chType == _C_DIG || chType == _C_DOT);
17241729
p = m_pchMinTok;
17251730
this->RestoreMultiUnits(m_cMinTokMultiUnits);
1726-
bool likelyInt = true;
1727-
pchT = FScanNumber(p, &dbl, likelyInt, savedMultiUnits);
1731+
LikelyNumberType likelyType = LikelyNumberType::Int;
1732+
pchT = FScanNumber(p, &dbl, likelyType, savedMultiUnits);
17281733
if (p == pchT)
17291734
{
17301735
this->RestoreMultiUnits(savedMultiUnits);
17311736
Assert(this->PeekFirst(p, last) != '.');
17321737
Error(ERRbadNumber);
17331738
}
17341739
Assert(!Js::NumberUtilities::IsNan(dbl));
1735-
1740+
if (likelyType == LikelyNumberType::BigInt)
1741+
{
1742+
Assert(m_scriptContext->GetConfig()->IsESBigIntEnabled());
1743+
AssertOrFailFast(pchT - p < UINT_MAX);
1744+
token = tkBigIntCon;
1745+
m_ptoken->SetBigInt(this->GetHashTbl()->PidHashNameLen(p, pchT, (uint32) (pchT - p)));
1746+
p = pchT;
1747+
break;
1748+
}
17361749
p = pchT;
17371750

17381751
int32 value;
1739-
if (likelyInt && Js::NumberUtilities::FDblIsInt32(dbl, &value))
1752+
if ((likelyType == LikelyNumberType::Int) && Js::NumberUtilities::FDblIsInt32(dbl, &value))
17401753
{
17411754
m_ptoken->SetLong(value);
17421755
token = tkIntCon;
17431756
}
17441757
else
17451758
{
17461759
token = tkFltCon;
1747-
m_ptoken->SetDouble(dbl, likelyInt);
1760+
m_ptoken->SetDouble(dbl, likelyType == LikelyNumberType::Int);
17481761
}
17491762

17501763
break;

lib/Parser/Scan.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct Token
5858
Assert(tk == tkStrCon || tk == tkStrTmplBasic || tk == tkStrTmplBegin || tk == tkStrTmplMid || tk == tkStrTmplEnd);
5959
return u.pid;
6060
}
61+
6162
IdentPtr GetIdentifier(HashTbl * hashTbl)
6263
{
6364
Assert(IsIdentifier() || IsReservedWord());
@@ -74,6 +75,12 @@ struct Token
7475
return u.lw;
7576
}
7677

78+
IdentPtr GetBigInt() const
79+
{
80+
Assert(tk == tkBigIntCon);
81+
return u.pid;
82+
}
83+
7784
double GetDouble() const
7885
{
7986
Assert(tk == tkFltCon);
@@ -138,6 +145,12 @@ struct Token
138145
this->u.maybeInt = maybeInt;
139146
}
140147

148+
void SetBigInt(IdentPtr pid)
149+
{
150+
this->u.pid = pid;
151+
this->u.pchMin = nullptr;
152+
}
153+
141154
tokens SetRegex(UnifiedRegex::RegexPattern *const pattern, Parser *const parser);
142155
};
143156

@@ -788,7 +801,7 @@ class Scanner : public IScanner, public EncodingPolicy
788801
tokens SkipComment(EncodedCharPtr *pp, /* out */ bool* containTypeDef);
789802
tokens ScanRegExpConstant(ArenaAllocator* alloc);
790803
tokens ScanRegExpConstantNoAST(ArenaAllocator* alloc);
791-
EncodedCharPtr FScanNumber(EncodedCharPtr p, double *pdbl, bool& likelyInt, size_t savedMultiUnits);
804+
EncodedCharPtr FScanNumber(EncodedCharPtr p, double *pdbl, LikelyNumberType& likelyInt, size_t savedMultiUnits);
792805
IdentPtr PidOfIdentiferAt(EncodedCharPtr p, EncodedCharPtr last, bool fHadEscape, bool fHasMultiChar);
793806
IdentPtr PidOfIdentiferAt(EncodedCharPtr p, EncodedCharPtr last);
794807
uint32 UnescapeToTempBuf(EncodedCharPtr p, EncodedCharPtr last);

lib/Parser/ptlist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ PTNODE(knopNone , "<none>" , Nop , None , fnopNone
2323
***************************************************************************/
2424
PTNODE(knopName , "name" , Nop , Name , fnopLeaf|fnopAllowDefer, "NameExpr" )
2525
PTNODE(knopInt , "int const" , Nop , Int , fnopLeaf|fnopConst , "NumberLit" )
26+
PTNODE(knopBigInt , "bigint const" , Nop , BigInt , fnopLeaf|fnopConst , "BigIntLit" )
2627
PTNODE(knopImport , "import" , Nop , None , fnopLeaf , "ImportExpr" )
2728
PTNODE(knopFlt , "flt const" , Nop , Float , fnopLeaf|fnopConst , "NumberLit" )
2829
PTNODE(knopStr , "str const" , Nop , Str , fnopLeaf|fnopConst , "StringLit" )

0 commit comments

Comments
 (0)