Skip to content

Commit

Permalink
Experimental Internal Commands
Browse files Browse the repository at this point in the history
  • Loading branch information
rhuanjl committed May 2, 2020
1 parent 8b38076 commit e58e250
Show file tree
Hide file tree
Showing 22 changed files with 1,752 additions and 1,576 deletions.
1 change: 1 addition & 0 deletions lib/Common/ConfigFlagsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,7 @@ FLAGR(Boolean, SkipSplitOnNoResult, "If the result of Regex split isn't used, sk
FLAGNR(String, TestEtwDll , "Path of the TestEtwEventSink DLL", nullptr)
#endif
#ifdef ENABLE_TEST_HOOKS
FLAGNR(Boolean, EnableInternalCommands, "Enable certain internal instructions within JS files - intended for library code only," , false)
FLAGNR(Boolean, Force32BitByteCode, "Force CC to generate 32bit bytecode intended only for regenerating bytecode headers.", false)
#endif

Expand Down
93 changes: 93 additions & 0 deletions lib/Parser/Parse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,13 @@ Parser::Parser(Js::ScriptContext* scriptContext, BOOL strictMode, PageAllocator

// init PID members
InitPids();

#ifdef ENABLE_TEST_HOOKS
if (scriptContext->GetConfig()->IsInternalCommandsEnabled())
{
InitInternalCommandPids();
}
#endif
}

Parser::~Parser(void)
Expand Down Expand Up @@ -2626,6 +2633,74 @@ void Parser::CheckForDuplicateExportEntry(ModuleImportOrExportEntryList* exportE
}
}

#ifdef ENABLE_TEST_HOOKS
template<bool buildAST>
ParseNodePtr Parser::ParseInternalCommand()
{
this->GetScanner()->Scan();
if (m_token.tk != tkID)
{
Error(ERRTokenAfter, GetTokenString(m_token.tk), _u("@@"));
}
charcount_t ichMin = this->GetScanner()->IchMinTok();

// find the command type
InternalCommandType type;
IdentPtr id = m_token.GetIdentifier(GetHashTbl());

if (id == internalCommandPids.Conv_Num)
{
type = InternalCommandType::Conv_Num;
}
else if (id == internalCommandPids.Conv_Obj)
{
type = InternalCommandType::Conv_Obj;
}
else
{
Error(ERRTokenAfter, m_token.GetIdentifier(GetHashTbl())->Psz(), _u("@@"));
}

// parse the parameters - currently only accept identifiers
this->GetScanner()->Scan();
ChkCurTok(tkLParen, ERRnoLparen);
ParseNodePtr params = nullptr;
ParseNodePtr * lastParam = nullptr;
ParseNodePtr currentParam = nullptr;

for (;;)
{
currentParam = ParseExpr<buildAST>(0);
if (buildAST)
{
AddToNodeListEscapedUse(&params, &lastParam, currentParam);
}

if (m_token.tk == tkComma)
{
this->GetScanner()->Scan();
}
else if (m_token.tk == tkRParen)
{
this->GetScanner()->Scan();
break;
}
else
{
Error(ERRTokenAfter, GetTokenString(m_token.tk), GetTokenString(this->GetScanner()->GetPrevious()));
}
}

ParseNodePtr command = nullptr;
if (buildAST)
{
command = Anew(&m_nodeAllocator, ParseNodeInternalCommand, ichMin, this->GetScanner()->IchLimTok(), type, params);
}

return command;
}
#endif

template<bool buildAST>
void Parser::ParseImportClause(ModuleImportOrExportEntryList* importEntryList, bool parsingAfterComma)
{
Expand Down Expand Up @@ -3744,6 +3819,16 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
}
break;

#ifdef ENABLE_TEST_HOOKS
case tkIntCommand:
if (!m_scriptContext->GetConfig()->IsInternalCommandsEnabled())
{
Error(ERRTokenAfter, _u("@@"), GetTokenString(GetScanner()->GetPrevious()));
}
pnode = ParseInternalCommand<buildAST>();
break;
#endif

#if ENABLE_BACKGROUND_PARSING
case tkCASE:
{
Expand Down Expand Up @@ -11775,6 +11860,14 @@ void Parser::InitPids()
wellKnownPropertyPids._importMeta = this->GetHashTbl()->PidHashNameLen(_u("*import.meta*"), sizeof("*import.meta*") - 1);
}

#ifdef ENABLE_TEST_HOOKS
void Parser::InitInternalCommandPids()
{
internalCommandPids.Conv_Num = this->GetHashTbl()->PidHashNameLen(_u("Conv_Num"), sizeof("Conv_Num") - 1);
internalCommandPids.Conv_Obj = this->GetHashTbl()->PidHashNameLen(_u("Conv_Obj"), sizeof("Conv_Obj") - 1);
}
#endif

void Parser::RestoreScopeInfo(Js::ScopeInfo * scopeInfo)
{
if (!scopeInfo)
Expand Down
17 changes: 17 additions & 0 deletions lib/Parser/Parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,10 @@ class Parser

void InitPids();

#ifdef ENABLE_TEST_HOOKS
void InitInternalCommandPids();
#endif

/***********************************************************************
Members needed just for parsing.
***********************************************************************/
Expand Down Expand Up @@ -504,6 +508,15 @@ class Parser

WellKnownPropertyPids wellKnownPropertyPids;

#ifdef ENABLE_TEST_HOOKS
struct InternalCommandPids
{
IdentPtr Conv_Num;
IdentPtr Conv_Obj;
};
InternalCommandPids internalCommandPids;
#endif

charcount_t m_sourceLim; // The actual number of characters parsed.

Js::ParseableFunctionInfo* m_functionBody; // For a deferred parsed function, the function body is non-null
Expand Down Expand Up @@ -975,6 +988,10 @@ class Parser
charcount_t ichMin,
_Out_opt_ BOOL* pfCanAssign = nullptr);

#ifdef ENABLE_TEST_HOOKS
template<bool buildAST> ParseNodePtr ParseInternalCommand();
#endif

void CheckIfImportOrExportStatementValidHere();
bool IsTopLevelModuleFunc();

Expand Down
10 changes: 10 additions & 0 deletions lib/Parser/Scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2195,6 +2195,16 @@ tokens Scanner<EncodingPolicy>::ScanCore(bool identifyKwds)
token = this->ScanStringConstant((OLECHAR)ch, &pchT);
p = pchT;
break;
#ifdef ENABLE_TEST_HOOKS
case '@':
if (this->PeekFirst(p,last) != '@')
{
goto LDefault;
}
p++;
token = tkIntCommand;
break;
#endif
}

break;
Expand Down
3 changes: 3 additions & 0 deletions lib/Parser/kwd-lsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@ TOK_DCL(tkEllipsis , No, knopNone ,Spr, knopEllipsis ) // ...
TOK_DCL(tkLParen , No, knopNone , No, knopNone ) // (
TOK_DCL(tkLBrack , No, knopNone , No, knopNone ) // [
TOK_DCL(tkDot , No, knopNone , No, knopNone ) // .
#ifdef ENABLE_TEST_HOOKS
TOK_DCL(tkIntCommand , No, knopNone , No, knopNone ) //@@
#endif

// String template tokens
TOK_DCL(tkStrTmplBasic , No, knopNone , No, knopNone ) // `...`
Expand Down
4 changes: 4 additions & 0 deletions lib/Parser/pnodewalk.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,10 @@ class ParseNodeWalker : public WalkerPolicy
case knopExportDefault:
return Walk(pnode->AsParseNodeExportDefault()->pnodeExpr, context);

#ifdef ENABLE_TEST_HOOKS
case knopIntCommand:
return Walk(pnode->AsParseNodeInternalCommand()->params, context);
#endif
default:
{
uint fnop = ParseNode::Grfnop(pnode->nop);
Expand Down
5 changes: 3 additions & 2 deletions lib/Parser/ptlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ PTNODE(knopObjectPatternMember, "{:} = " , Nop , Bin , fnopBin
PTNODE(knopArrayPattern, "[] = " , Nop , ArrLit , fnopUni , "ArrayAssignmentPattern" )
PTNODE(knopParamPattern, "({[]})" , Nop , ParamPattern, fnopUni , "DestructurePattern" )
PTNODE(knopExportDefault, "export default" , Nop , ExportDefault,fnopNone , "ExportDefault" )


#ifdef ENABLE_TEST_HOOKS
PTNODE(knopIntCommand, "intCommand" , Nop , None , fnopNone , "Internal Command" )
#endif
#undef PTNODE
#undef OP
8 changes: 8 additions & 0 deletions lib/Parser/ptree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,14 @@ ParseNodeModule * ParseNode::AsParseNodeModule()
return reinterpret_cast<ParseNodeModule*>(this);
}

#ifdef ENABLE_TEST_HOOKS
ParseNodeInternalCommand * ParseNode::AsParseNodeInternalCommand()
{
Assert(this->nop == knopIntCommand);
return reinterpret_cast<ParseNodeInternalCommand *>(this);
}
#endif

IdentPtr ParseNode::name()
{
if (this->nop == knopStr)
Expand Down
28 changes: 28 additions & 0 deletions lib/Parser/ptree.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ class ParseNodeForInOrForOf;
class ParseNodeFnc;
class ParseNodeProg;
class ParseNodeModule;
#ifdef ENABLE_TEST_HOOKS
class ParseNodeInternalCommand;
#endif


class ParseNode
{
Expand Down Expand Up @@ -163,6 +167,10 @@ class ParseNode
ParseNodeProg * AsParseNodeProg();
ParseNodeModule * AsParseNodeModule();

#ifdef ENABLE_TEST_HOOKS
ParseNodeInternalCommand * AsParseNodeInternalCommand();
#endif

static uint Grfnop(int nop)
{
Assert(nop < knopLim);
Expand Down Expand Up @@ -434,6 +442,26 @@ class ParseNodeObjLit : public ParseNodeUni
DISABLE_SELF_CAST(ParseNodeObjLit);
};

#ifdef ENABLE_TEST_HOOKS

typedef enum InternalCommandType
{
Conv_Num,
Conv_Obj
} InternalCommandType;

class ParseNodeInternalCommand : public ParseNode
{
public:
ParseNodeInternalCommand(charcount_t ichMin, charcount_t ichLim, InternalCommandType type, ParseNodePtr parameters) :
commandType(type), params(parameters), ParseNode(knopIntCommand, ichMin, ichLim) {}

InternalCommandType commandType;
ParseNodePtr params;
};
#endif


class FuncInfo;

enum PnodeBlockType : unsigned
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Base/ThreadConfigFlagsList.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ FLAG_RELEASE(IsESSymbolDescriptionEnabled, ESSymbolDescription)
FLAG_RELEASE(IsESGlobalThisEnabled, ESGlobalThis)
FLAG_RELEASE(IsES2018AsyncIterationEnabled, ES2018AsyncIteration)
#ifdef ENABLE_TEST_HOOKS
FLAG_RELEASE(IsInternalCommandsEnabled, EnableInternalCommands)
FLAG_RELEASE(Force32BitByteCode, Force32BitByteCode)
#endif
#ifdef ENABLE_PROJECTION
Expand Down
4 changes: 2 additions & 2 deletions lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
// NOTE: If there is a merge conflict the correct fix is to make a new GUID.
// This file was generated with tools/xplatRegenByteCode.py

// {51f0edaa-63a2-4d76-bcac-160b8dd6c2ad}
// {45bcaca5-bf94-42fc-aec0-6eab7fc28e68}
const GUID byteCodeCacheReleaseFileVersion =
{ 0x51f0edaa, 0x63a2, 0x4d76, {0xbc, 0xac, 0x16, 0x0b, 0x8d, 0xd6, 0xc2, 0xad } };
{ 0x45bcaca5, 0xbf94, 0x42fc, {0xae, 0xc0, 0x6e, 0xab, 0x7f, 0xc2, 0x8e, 0x68 } };
27 changes: 27 additions & 0 deletions lib/Runtime/ByteCode/ByteCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12295,6 +12295,33 @@ void Emit(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, FuncInfo* func
funcInfo->ReleaseLoc(pnode->AsParseNodeExportDefault()->pnodeExpr);
pnode = pnode->AsParseNodeExportDefault()->pnodeExpr;
break;
#ifdef ENABLE_TEST_HOOKS
case knopIntCommand:
{
byteCodeGenerator->StartStatement(pnode);
funcInfo->AcquireLoc(pnode);
ParseNodeInternalCommand* command = pnode->AsParseNodeInternalCommand();
ParseNode* params = command->params;
//ParseNode* param1 = params->AsParseNodeBin()->pnode1;
Emit(params, byteCodeGenerator, funcInfo, false);

switch (command->commandType)
{
case InternalCommandType::Conv_Num:
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Conv_Num, pnode->location, params->location);
break;
case InternalCommandType::Conv_Obj:
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Conv_Obj, pnode->location, params->location);
break;

default:
AssertOrFailFast(0);
}
funcInfo->ReleaseLoc(params);
byteCodeGenerator->EndStatement(pnode);
break;
}
#endif
default:
AssertMsg(0, "emit unhandled pnode op");
break;
Expand Down
7 changes: 7 additions & 0 deletions lib/Runtime/ByteCode/ByteCodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,13 @@ void Visit(ParseNode *pnode, ByteCodeGenerator* byteCodeGenerator, PrefixFn pref
Visit(pnode->AsParseNodeStrTemplate()->pnodeSubstitutionExpressions, byteCodeGenerator, prefix, postfix);
break;
}
#ifdef ENABLE_TEST_HOOKS
case knopIntCommand:
{
Visit(pnode->AsParseNodeInternalCommand()->params, byteCodeGenerator, prefix, postfix);
break;
}
#endif
case knopExportDefault:
Visit(pnode->AsParseNodeExportDefault()->pnodeExpr, byteCodeGenerator, prefix, postfix);
break;
Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Library/InJavascript/GenByteCode.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ call :Generate %1 %_BinLocation%\x64_debug %1%_suffix%.bc.64b.h
exit /B 0

:Generate
%2\%_binary% -GenerateLibraryByteCodeHeader:%3 -Intl %1
%2\%_binary% -GenerateLibraryByteCodeHeader:%3 -Intl -EnableInternalCommands%1
if "%errorlevel%" NEQ "0" (
echo %1: Error generating bytecode file. Ensure %3 writable.
set _HASERROR=1
Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Library/JsBuiltIn/GenByteCode.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ call :Generate %1 %_BinLocation%\x64_debug %1%_suffix%.bc.64b.h
exit /B 0

:Generate
%2\%_binary% -GenerateLibraryByteCodeHeader:%3 -JsBuiltIn -LdChakraLib %1
%2\%_binary% -GenerateLibraryByteCodeHeader:%3 -JsBuiltIn -LdChakraLib -EnableInternalCommands %1
if "%errorlevel%" NEQ "0" (
echo %1: Error generating bytecode file. Ensure %3 writable.
set _HASERROR=1
Expand Down
8 changes: 4 additions & 4 deletions lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,23 @@
if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined("Array.prototype.keys");
}
let o = __chakraLibrary.Object(this);
let o = @@Conv_Obj(this);
return __chakraLibrary.CreateArrayIterator(o, 0 /* ArrayIterationKind.Key*/);
});

platform.registerFunction(platform.FunctionKind.Array_values, function () {
if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined("Array.prototype.values");
}
let o = __chakraLibrary.Object(this);
let o = @@Conv_Obj(this);
return __chakraLibrary.CreateArrayIterator(o, 1 /* ArrayIterationKind.Value*/);
});

platform.registerFunction(platform.FunctionKind.Array_entries, function () {
if (this === null || this === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined("Array.prototype.entries");
}
let o = __chakraLibrary.Object(this);
let o = @@Conv_Obj(this);
return __chakraLibrary.CreateArrayIterator(o, 2 /* ArrayIterationKind.KeyAndValue*/);
});

Expand Down Expand Up @@ -170,7 +170,7 @@
if (obj === null || obj === undefined) {
__chakraLibrary.raiseThis_NullOrUndefined(builtInFunc);
}
return { o: __chakraLibrary.Object(obj), len: __chakraLibrary.toLength(obj["length"]) };
return { o: @@Conv_Obj(obj), len: __chakraLibrary.toLength(obj["length"]) };
}
});

Expand Down

0 comments on commit e58e250

Please sign in to comment.