-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
NewScObj refactor #6180
base: master
Are you sure you want to change the base?
NewScObj refactor #6180
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1779,6 +1779,7 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re | |
case Js::OpCode::SpreadObjectLiteral: | ||
// fall through | ||
case Js::OpCode::SetComputedNameVar: | ||
case Js::OpCode::UpNewScObjCache: | ||
{ | ||
IR::Instr *instr = IR::Instr::New(newOpcode, m_func); | ||
instr->SetSrc1(this->BuildSrcOpnd(R0)); | ||
|
@@ -1805,6 +1806,17 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re | |
this->AddInstr(instr, offset); | ||
return; | ||
} | ||
|
||
// A dest symbol that has a def but no use can be emitted. The symbol can then be reused | ||
// as a dest of another instr. When this occurs the symbol cannot refer to either of the | ||
// two def instrs as its instrDef. In order to ensure that a GenCtorObj instr can be | ||
// referred to using its dest symbol, we force the dest symbol to be a single def. We | ||
// want this property for GenCtorObj because NewScObj* instrs will need to refer to their | ||
// related GenCtorObj instr, this is done through walking up the ArgOut chain and checking | ||
// the ArgOuts' values' instrDefs for the GenCtorObj opcode. | ||
case Js::OpCode::GenCtorObj: | ||
SetTempUsed(R0, TRUE); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any reason why this isn't the same as case for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is SetTempUsed accomplishing here? R0 is not a temp and shouldn't be renumbered regardless. (Edit: I see, the passed-in "R0", not the byte code reg "R0". There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's odd that we should have to do this. What does the byte code sequence look like? Where is the reg defined? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do you have any input on this question? Thanks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This hack is necessary for the following scenario:
We need instrDef in order to find the GenCtorObj instr during the ArgOut chain traversal. so to solve this issue we make sure that the symbol of a GenCtorObj instr is unique. This is unnecessary for UpNewScObjCache because UpNewScObjCache is not involved in any ArgOut chain traversal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you give me a script that exhibits the behavior you're talking about? If an unused dst is not consumed at the def point, we'll have more problems than just the one you're describing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pleath Looks like we ran into this issue for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Arf. Do you have a little script that behaves this way? We need an automated way of detecting these. Maybe a debug flag that indicates a parse node is participating in a question expression. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now that I think of it, a hint from the parser to identify intermediate results of ?: ops might allow us to simplify all these things and eliminate Unused altogether. That's probably the way to go, not least because there's nothing that requires Unused for correctness, so we'll keep getting these unrenamed lifetimes. I'll look into that. |
||
break; | ||
} | ||
|
||
IR::RegOpnd * dstOpnd = this->BuildDstOpnd(R0); | ||
|
@@ -1820,7 +1832,6 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re | |
dstSym->m_builtInIndex = symSrc1->m_builtInIndex; | ||
} | ||
break; | ||
|
||
case Js::OpCode::ProfiledStrictLdThis: | ||
newOpcode = Js::OpCode::StrictLdThis; | ||
if (m_func->HasProfileInfo()) | ||
|
@@ -6536,7 +6547,6 @@ IRBuilder::BuildCallI_Helper(Js::OpCode newOpcode, uint32 offset, Js::RegSlot ds | |
case Js::OpCode::NewScObjArray: | ||
case Js::OpCode::NewScObjArraySpread: | ||
symDst->m_isSafeThis = true; | ||
symDst->m_isNotNumber = true; | ||
break; | ||
} | ||
} | ||
|
@@ -6551,7 +6561,6 @@ IRBuilder::BuildCallI_Helper(Js::OpCode newOpcode, uint32 offset, Js::RegSlot ds | |
void | ||
IRBuilder::BuildCallCommon(IR::Instr * instr, StackSym * symDst, Js::ArgSlot argCount, Js::CallFlags flags) | ||
{ | ||
Js::OpCode newOpcode = instr->m_opcode; | ||
|
||
IR::Instr * argInstr = nullptr; | ||
IR::Instr * prevInstr = instr; | ||
|
@@ -6578,15 +6587,6 @@ IRBuilder::BuildCallCommon(IR::Instr * instr, StackSym * symDst, Js::ArgSlot arg | |
this->callTreeHasSomeProfileInfo = false; | ||
} | ||
|
||
if (newOpcode == Js::OpCode::NewScObject || newOpcode == Js::OpCode::NewScObjArray | ||
|| newOpcode == Js::OpCode::NewScObjectSpread || newOpcode == Js::OpCode::NewScObjArraySpread) | ||
{ | ||
#if DBG | ||
count++; | ||
#endif | ||
m_argsOnStack++; | ||
} | ||
|
||
argCount = Js::CallInfo::GetArgCountWithExtraArgs(flags, argCount); | ||
|
||
if (argInstr) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like this is going to produce a guard check where we don't really need one. Is that true?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GenCtorObj is performing similar functionality to NewScObjectNoCtor; this change was made because the only instr that can reach this point is GenCtorObj thus
isCtorInlined || ctorCache->IsTypeFinal()
would always return true.The way to determine if this bailout is necessary is to see why NewScObjectNoCtor instrs were originally emitted and if the emitted GenCtorObj instr has those same properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The key difference is that GenCtorObj is emitted whether the ctor is inlined or not. That isn't true of NewScObjectNoCtor, which is only emitted as the result of inlining (I think). If there isn't an optimization requiring a guard check (usually inlining, but also, apparently, final type opt on the type assigned to the new object), we shouldn't need a guard check. The final type opt seems to belong to GenCtorObj now, since it's creating the object according to the hints in the ctorCache.