Skip to content

Commit 5d51cf6

Browse files
committed
Added test trace and phase
1 parent 8aa44c3 commit 5d51cf6

File tree

9 files changed

+77
-32
lines changed

9 files changed

+77
-32
lines changed

lib/Backend/Func.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
6666
m_hasCalls(false),
6767
m_hasInlineArgsOpt(false),
6868
m_canDoInlineArgsOpt(true),
69-
unoptableInlineArgCount(0),
69+
unoptimizableArgumentsObjReference(0),
7070
m_doFastPaths(false),
7171
hasBailout(false),
7272
firstIRTemp(0),

lib/Backend/Func.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
725725
StackSym * tempSymDouble;
726726
StackSym * tempSymBool;
727727
uint32 loopCount;
728-
uint32 unoptableInlineArgCount;
728+
uint32 unoptimizableArgumentsObjReference;
729729
Js::ProfileId callSiteIdInParentFunc;
730730
InlineeFrameInfo* cachedInlineeFrameInfo;
731731
bool m_hasCalls: 1; // This is more accurate compared to m_isLeaf

lib/Backend/GlobOpt.cpp

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ GlobOpt::OptArguments(IR::Instr *instr)
15881588
if (CurrentBlockData()->IsArgumentsOpnd(src1))
15891589
{
15901590
instr->usesStackArgumentsObject = true;
1591-
instr->m_func->unoptableInlineArgCount++;
1591+
instr->m_func->unoptimizableArgumentsObjReference++;
15921592
}
15931593

15941594
if (CurrentBlockData()->IsArgumentsOpnd(src1) &&
@@ -1608,15 +1608,15 @@ GlobOpt::OptArguments(IR::Instr *instr)
16081608
if (builtinFunction == Js::BuiltinFunction::JavascriptFunction_Apply)
16091609
{
16101610
CurrentBlockData()->ClearArgumentsSym(src1->AsRegOpnd());
1611-
instr->m_func->unoptableInlineArgCount--;
1611+
instr->m_func->unoptimizableArgumentsObjReference--;
16121612
}
16131613
}
16141614
else if (builtinOpnd->IsRegOpnd())
16151615
{
16161616
if (builtinOpnd->AsRegOpnd()->m_sym->m_builtInIndex == Js::BuiltinFunction::JavascriptFunction_Apply)
16171617
{
16181618
CurrentBlockData()->ClearArgumentsSym(src1->AsRegOpnd());
1619-
instr->m_func->unoptableInlineArgCount--;
1619+
instr->m_func->unoptimizableArgumentsObjReference--;
16201620
}
16211621
}
16221622
}
@@ -2449,7 +2449,7 @@ GlobOpt::OptInstr(IR::Instr *&instr, bool* isInstrRemoved)
24492449
OptimizeChecks(instr);
24502450
OptArraySrc(&instr, &src1Val, &src2Val);
24512451
OptNewScObject(&instr, src1Val);
2452-
OptArgLenAndConst(instr, &src1Val);
2452+
OptStackArgLenAndConst(instr, &src1Val);
24532453

24542454
instr = this->OptPeep(instr, src1Val, src2Val);
24552455

@@ -13206,15 +13206,21 @@ GlobOpt::OptArraySrc(IR::Instr ** const instrRef, Value ** src1Val, Value ** src
1320613206
}
1320713207

1320813208
void
13209-
GlobOpt::OptArgLenAndConst(IR::Instr* instr, Value** src1Val)
13209+
GlobOpt::OptStackArgLenAndConst(IR::Instr* instr, Value** src1Val)
1321013210
{
13211-
if (instr->usesStackArgumentsObject && instr->IsInlined())
13211+
if (!PHASE_OFF(Js::StackArgLenConstOptPhase, instr->m_func) && instr->m_func->IsStackArgsEnabled() && instr->usesStackArgumentsObject && instr->IsInlined())
1321213212
{
1321313213
IR::Opnd* src1 = instr->GetSrc1();
13214-
auto replaceInstr = [&](IR::Opnd* newopnd, Js::OpCode opCode = Js::OpCode::Ld_A)
13214+
auto replaceInstr = [&](IR::Opnd* newopnd, Js::OpCode opcode)
1321513215
{
13216+
if (PHASE_TESTTRACE(Js::StackArgLenConstOptPhase, instr->m_func))
13217+
{
13218+
Output::Print(_u("Inlined function %s have replaced opcode %s with opcode %s for stack arg optimization. \n"), instr->m_func->GetJITFunctionBody()->GetDisplayName(),
13219+
Js::OpCodeUtil::GetOpCodeName(instr->m_opcode), Js::OpCodeUtil::GetOpCodeName(opcode));
13220+
Output::Flush();
13221+
}
1321613222
this->CaptureByteCodeSymUses(instr);
13217-
instr->m_opcode = opCode;
13223+
instr->m_opcode = opcode;
1321813224
instr->ReplaceSrc1(newopnd);
1321913225
if (instr->HasBailOutInfo())
1322013226
{
@@ -13229,10 +13235,9 @@ GlobOpt::OptArgLenAndConst(IR::Instr* instr, Value** src1Val)
1322913235
case Js::OpCode::LdLen_A:
1323013236
{
1323113237
IR::AddrOpnd* newopnd = IR::AddrOpnd::New(Js::TaggedInt::ToVarUnchecked(instr->m_func->actualCount - 1), IR::AddrOpndKindConstantVar, instr->m_func);
13232-
replaceInstr(newopnd);
13238+
replaceInstr(newopnd, Js::OpCode::Ld_A);
1323313239
break;
1323413240
}
13235-
1323613241
case Js::OpCode::LdElemI_A:
1323713242
case Js::OpCode::TypeofElem:
1323813243
{
@@ -13251,26 +13256,32 @@ GlobOpt::OptArgLenAndConst(IR::Instr* instr, Value** src1Val)
1325113256
}
1325213257
return false;
1325313258
});
13259+
13260+
Js::OpCode replacementOpcode;
13261+
if (instr->m_opcode == Js::OpCode::TypeofElem)
13262+
{
13263+
replacementOpcode = Js::OpCode::Typeof;
13264+
}
13265+
else
13266+
{
13267+
replacementOpcode = Js::OpCode::Ld_A;
13268+
}
13269+
1325413270
// If we cannot find the right instruction. I.E. When calling arguments[2] and no arguments were passed to the func
1325513271
if (defInstr == nullptr)
1325613272
{
1325713273
IR::Opnd * undefined = IR::AddrOpnd::New(instr->m_func->GetScriptContextInfo()->GetUndefinedAddr(), IR::AddrOpndKindDynamicVar, instr->m_func, true);
1325813274
undefined->SetValueType(ValueType::Undefined);
13259-
replaceInstr(undefined);
13275+
replaceInstr(undefined, replacementOpcode);
1326013276
}
1326113277
else
1326213278
{
13263-
if (instr->m_opcode == Js::OpCode::TypeofElem) {
13264-
replaceInstr(defInstr->GetSrc1(), Js::OpCode::Typeof);
13265-
}
13266-
else {
13267-
replaceInstr(defInstr->GetSrc1());
13268-
}
13279+
replaceInstr(defInstr->GetSrc1(), replacementOpcode);
1326913280
}
1327013281
}
1327113282
else
1327213283
{
13273-
instr->m_func->unoptableInlineArgCount++;
13284+
instr->m_func->unoptimizableArgumentsObjReference++;
1327413285
}
1327513286
break;
1327613287
}

lib/Backend/GlobOpt.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ class GlobOpt
690690
IR::Instr* CreateBoundsCheckInstr(IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset, IR::BailOutKind bailoutkind, BailOutInfo* bailoutInfo, Func* func);
691691
IR::Instr* AttachBoundsCheckData(IR::Instr* instr, IR::Opnd* lowerBound, IR::Opnd* upperBound, int offset);
692692
void OptArraySrc(IR::Instr **const instrRef, Value ** src1Val, Value ** src2Val);
693-
void OptArgLenAndConst(IR::Instr* instr, Value** src1Val);
693+
void OptStackArgLenAndConst(IR::Instr* instr, Value** src1Val);
694694

695695
private:
696696
void TrackIntSpecializedAddSubConstant(IR::Instr *const instr, const AddSubConstantInfo *const addSubConstantInfo, Value *const dstValue, const bool updateSourceBounds);

lib/Backend/GlobOptBailOut.cpp

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -482,12 +482,14 @@ GlobOpt::CaptureByteCodeSymUses(IR::Instr * instr)
482482
void
483483
GlobOpt::ProcessInlineeEnd(IR::Instr* instr)
484484
{
485-
if (instr->m_func->hasArgLenAndConstOpt && instr->m_func->unoptableInlineArgCount == 0)
485+
if (!PHASE_OFF(Js::StackArgLenConstOptPhase, instr->m_func) && instr->m_func->IsStackArgsEnabled()
486+
&& instr->m_func->hasArgLenAndConstOpt && instr->m_func->unoptimizableArgumentsObjReference == 0)
486487
{
487488
instr->m_func->hasUnoptimizedArgumentsAccess = false;
488489
if (DoInlineArgsOpt(instr->m_func))
489490
{
490491
instr->m_func->m_hasInlineArgsOpt = true;
492+
Assert(instr->m_func->cachedInlineeFrameInfo);
491493
instr->m_func->frameInfo = instr->m_func->cachedInlineeFrameInfo;
492494
}
493495
}
@@ -588,23 +590,19 @@ GlobOpt::TrackCalls(IR::Instr * instr)
588590
this->func->UpdateMaxInlineeArgOutSize(this->currentBlock->globOptData.inlinedArgOutSize);
589591
this->EndTrackCall(instr);
590592

591-
auto createFrameInfo = [&](Func* inlineeFunc)
592-
{
593-
InlineeFrameInfo* frameInfo = InlineeFrameInfo::New(inlineeFunc->m_alloc);
594-
frameInfo->floatSyms = CurrentBlockData()->liveFloat64Syms->CopyNew(this->alloc);
595-
frameInfo->intSyms = CurrentBlockData()->liveInt32Syms->MinusNew(CurrentBlockData()->liveLossyInt32Syms, this->alloc);
596-
frameInfo->varSyms = CurrentBlockData()->liveVarSyms->CopyNew(this->alloc);
597-
return frameInfo;
598-
};
593+
InlineeFrameInfo* inlineeFrameInfo = InlineeFrameInfo::New(instr->m_func->m_alloc);
594+
inlineeFrameInfo->floatSyms = CurrentBlockData()->liveFloat64Syms->CopyNew(this->alloc);
595+
inlineeFrameInfo->intSyms = CurrentBlockData()->liveInt32Syms->MinusNew(CurrentBlockData()->liveLossyInt32Syms, this->alloc);
596+
inlineeFrameInfo->varSyms = CurrentBlockData()->liveVarSyms->CopyNew(this->alloc);
599597

600598
if (DoInlineArgsOpt(instr->m_func))
601599
{
602600
instr->m_func->m_hasInlineArgsOpt = true;
603-
instr->m_func->frameInfo = createFrameInfo(func);
601+
instr->m_func->frameInfo = inlineeFrameInfo;
604602
}
605603
else
606604
{
607-
instr->m_func->cachedInlineeFrameInfo = createFrameInfo(instr->m_func);
605+
instr->m_func->cachedInlineeFrameInfo = inlineeFrameInfo;
608606
}
609607
break;
610608
}

lib/Common/ConfigFlagsList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ PHASE(All)
165165
PHASE(CheckThis)
166166
PHASE(StackArgOpt)
167167
PHASE(StackArgFormalsOpt)
168+
PHASE(StackArgLenConstOpt)
168169
PHASE(IndirCopyProp)
169170
PHASE(ArrayCheckHoist)
170171
PHASE(ArrayMissingValueCheckHoist)

test/Function/rlexe.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,14 @@
434434
<tags>exclude_dynapogo</tags>
435435
</default>
436436
</test>
437+
<test>
438+
<default>
439+
<files>stackArgsLenConstOpt.js</files>
440+
<compile-flags>-mic:1 -off:simpleJit -testtrace:StackArgLenConstOpt</compile-flags>
441+
<tags>exclude_dynapogo,exclude_nonative,require_backend,exclude_forceserialized,exclude_arm64</tags>
442+
<baseline>stackArgsLenConstOpt.baseline</baseline>
443+
</default>
444+
</test>
437445
<test>
438446
<default>
439447
<files>childCallsEvalJitLoopBody.js</files>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Inlined function x_min have replaced opcode LdLen_A with opcode Ld_A for stack arg optimization.
2+
Inlined function x_min have replaced opcode LdElemI_A with opcode Ld_A for stack arg optimization.
3+
Inlined function x_min have replaced opcode LdElemI_A with opcode Ld_A for stack arg optimization.
4+
Inlined function x_min have replaced opcode LdElemI_A with opcode Ld_A for stack arg optimization.
5+
pass

test/Function/stackArgsLenConstOpt.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
//-------------------------------------------------------------------------------------------------------
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
4+
//-------------------------------------------------------------------------------------------------------
5+
6+
function x_min() {
7+
if (arguments.length < 3) {
8+
if (arguments[0] < arguments[1]) return arguments[0];
9+
else return arguments[1];
10+
}
11+
return 1;
12+
}
13+
14+
function test0() {
15+
x_min(15,2);
16+
}
17+
18+
for (var i = 0; i < 100; i++) {
19+
test0();
20+
}
21+
22+
WScript.Echo("pass");

0 commit comments

Comments
 (0)