Skip to content

Commit bf4e24d

Browse files
authored
ArraySort cleanup (#6429)
1. No longer create a separate comparison array when using the defaultCompare on a non-string array, this copy is slow and could use a lot of memory. 2. Edit ByteCodeEmitter so that template literals don't emit unnecessary empty string concatenations. 3. Use a template literal for string coercion in the default sort compare - does toString() instead of the incorrect toString(toPrimitive()) that was done before AND due to the change in (2) above is significantly more efficient. 4. Some drive by cleanup.
1 parent e31b9f5 commit bf4e24d

14 files changed

+17047
-17872
lines changed

lib/Runtime/ByteCode/ByteCodeCacheReleaseFileVersion.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
44
//-------------------------------------------------------------------------------------------------------
55
// NOTE: If there is a merge conflict the correct fix is to make a new GUID.
6-
// This file was generated with tools\update_bytecode_version.ps1
6+
// This file was generated with tools/xplatRegenByteCode.py
77

8-
// {2C341884-72E5-4799-923C-DB8EDAFEEA89}
8+
// {51f0edaa-63a2-4d76-bcac-160b8dd6c2ad}
99
const GUID byteCodeCacheReleaseFileVersion =
10-
{ 0x2C341884, 0x72E5, 0x4799, { 0x92, 0x3C, 0xDB, 0x8E, 0xDA, 0xFE, 0xEA, 0x89 } };
10+
{ 0x51f0edaa, 0x63a2, 0x4d76, {0xbc, 0xac, 0x16, 0x0b, 0x8d, 0xd6, 0xc2, 0xad } };

lib/Runtime/ByteCode/ByteCodeEmitter.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8931,12 +8931,23 @@ void EmitStringTemplate(ParseNodeStrTemplate *pnodeStrTemplate, ByteCodeGenerato
89318931
ParseNode* stringNodeList = pnodeStrTemplate->pnodeStringLiterals;
89328932

89338933
// Emit the first string and load that into the pnode location.
8934-
Emit(stringNodeList->AsParseNodeBin()->pnode1, byteCodeGenerator, funcInfo, false);
8934+
// skip loading the string if it is empty
8935+
ParseNode* firstString = stringNodeList->AsParseNodeBin()->pnode1;
8936+
bool skippedFirst = false;
8937+
if (firstString->AsParseNodeStr()->pid->Cch() == 0)
8938+
{
8939+
skippedFirst = true;
8940+
}
8941+
else
8942+
{
8943+
Emit(stringNodeList->AsParseNodeBin()->pnode1, byteCodeGenerator, funcInfo, false);
89358944

8936-
Assert(pnodeStrTemplate->location != stringNodeList->AsParseNodeBin()->pnode1->location);
8945+
Assert(pnodeStrTemplate->location != stringNodeList->AsParseNodeBin()->pnode1->location);
8946+
8947+
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Ld_A, pnodeStrTemplate->location, stringNodeList->AsParseNodeBin()->pnode1->location);
8948+
funcInfo->ReleaseLoc(stringNodeList->AsParseNodeBin()->pnode1);
8949+
}
89378950

8938-
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Ld_A, pnodeStrTemplate->location, stringNodeList->AsParseNodeBin()->pnode1->location);
8939-
funcInfo->ReleaseLoc(stringNodeList->AsParseNodeBin()->pnode1);
89408951

89418952
ParseNode* expressionNodeList = pnodeStrTemplate->pnodeSubstitutionExpressions;
89428953
ParseNode* stringNode;
@@ -8968,10 +8979,20 @@ void EmitStringTemplate(ParseNodeStrTemplate *pnodeStrTemplate, ByteCodeGenerato
89688979
// Emit the expression and append it to the string we're building.
89698980
Emit(expressionNode, byteCodeGenerator, funcInfo, false);
89708981

8971-
Js::RegSlot toStringLocation = funcInfo->AcquireTmpRegister();
8972-
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Conv_Str, toStringLocation, expressionNode->location);
8973-
byteCodeGenerator->Writer()->Reg3(Js::OpCode::Add_A, pnodeStrTemplate->location, pnodeStrTemplate->location, toStringLocation);
8974-
funcInfo->ReleaseTmpRegister(toStringLocation);
8982+
// if this is the first expression AND the initial string was empty write directly to the pnodeStrTemplate location
8983+
if (skippedFirst == true)
8984+
{
8985+
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Conv_Str, pnodeStrTemplate->location, expressionNode->location);
8986+
skippedFirst = false;
8987+
}
8988+
else
8989+
{
8990+
Js::RegSlot toStringLocation = funcInfo->AcquireTmpRegister();
8991+
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Conv_Str, toStringLocation, expressionNode->location);
8992+
byteCodeGenerator->Writer()->Reg3(Js::OpCode::Add_A, pnodeStrTemplate->location, pnodeStrTemplate->location, toStringLocation);
8993+
funcInfo->ReleaseTmpRegister(toStringLocation);
8994+
}
8995+
89758996
funcInfo->ReleaseLoc(expressionNode);
89768997

89778998
// Move to the next string in the list - we already got ahead of the expressions in the first string literal above.
@@ -8990,9 +9011,12 @@ void EmitStringTemplate(ParseNodeStrTemplate *pnodeStrTemplate, ByteCodeGenerato
89909011

89919012
// Emit the string node following the previous expression and append it to the string.
89929013
// This is either just some string in the list or it is the last string.
8993-
Emit(stringNode, byteCodeGenerator, funcInfo, false);
8994-
byteCodeGenerator->Writer()->Reg3(Js::OpCode::Add_A, pnodeStrTemplate->location, pnodeStrTemplate->location, stringNode->location);
8995-
funcInfo->ReleaseLoc(stringNode);
9014+
if (stringNode->AsParseNodeStr()->pid->Cch() != 0)
9015+
{
9016+
Emit(stringNode, byteCodeGenerator, funcInfo, false);
9017+
byteCodeGenerator->Writer()->Reg3(Js::OpCode::Add_A, pnodeStrTemplate->location, pnodeStrTemplate->location, stringNode->location);
9018+
funcInfo->ReleaseLoc(stringNode);
9019+
}
89969020
}
89979021
}
89989022
}

0 commit comments

Comments
 (0)