Skip to content

Commit

Permalink
[MERGE #5120 @aneeshdk] Moving HomeObj field out of ScriptFunction
Browse files Browse the repository at this point in the history
Merge pull request #5120 from aneeshdk:MoveHomeObjOutOfScriptFunc

Only class member functions and object literal methods have home object set. So moving this field out of ScriptFunction should help us reduce the size of normal ScriptFunctions.

As part of this the SetHomeObj opcode is also removed. Instead we set the home object along with the creation of the function.
  • Loading branch information
aneeshdk committed May 12, 2018
2 parents 5625917 + 9c8394f commit c246386
Show file tree
Hide file tree
Showing 42 changed files with 21,490 additions and 21,092 deletions.
2 changes: 2 additions & 0 deletions lib/Backend/GlobOpt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13922,6 +13922,8 @@ GlobOpt::PreLowerCanonicalize(IR::Instr *instr, Value **pSrc1Val, Value **pSrc2V
case Js::OpCode::Not_I4:
case Js::OpCode::NewScFunc:
case Js::OpCode::NewScGenFunc:
case Js::OpCode::NewScFuncHomeObj:
case Js::OpCode::NewScGenFuncHomeObj:
case Js::OpCode::NewScArray:
case Js::OpCode::NewScIntArray:
case Js::OpCode::NewScFltArray:
Expand Down
181 changes: 149 additions & 32 deletions lib/Backend/IRBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1877,14 +1877,6 @@ IRBuilder::BuildReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::Re

switch (newOpcode)
{
case Js::OpCode::SetHomeObj:
{
IR::Instr *instr = IR::Instr::New(Js::OpCode::SetHomeObj, m_func);
instr->SetSrc1(this->BuildSrcOpnd(R0));
instr->SetSrc2(src1Opnd);
this->AddInstr(instr, offset);
return;
}
case Js::OpCode::SetComputedNameVar:
{
IR::Instr *instr = IR::Instr::New(Js::OpCode::SetComputedNameVar, m_func);
Expand Down Expand Up @@ -3339,6 +3331,35 @@ IRBuilder::BuildElementSlot(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fie
return;
}

case Js::OpCode::NewScFuncHomeObj:
case Js::OpCode::NewScGenFuncHomeObj:
{
Js::FunctionInfoPtrPtr infoRef = m_func->GetJITFunctionBody()->GetNestedFuncRef(slotId);
IR::AddrOpnd * functionBodySlotOpnd = IR::AddrOpnd::New((Js::Var)infoRef, IR::AddrOpndKindDynamicMisc, m_func);
IR::Opnd * environmentOpnd = GetEnvironmentOperand(offset);
IR::Opnd * homeObjOpnd = this->BuildSrcOpnd(fieldRegSlot);
regOpnd = this->BuildDstOpnd(regSlot);

instr = IR::Instr::New(Js::OpCode::ExtendArg_A, IR::RegOpnd::New(TyVar, m_func), homeObjOpnd, m_func);
this->AddInstr(instr, offset);

instr = IR::Instr::New(Js::OpCode::ExtendArg_A, IR::RegOpnd::New(TyVar, m_func), functionBodySlotOpnd, instr->GetDst(), m_func);
this->AddInstr(instr, offset);

instr = IR::Instr::New(Js::OpCode::ExtendArg_A, IR::RegOpnd::New(TyVar, m_func), environmentOpnd, instr->GetDst(), m_func);
this->AddInstr(instr, offset);

instr = IR::Instr::New(newOpcode, regOpnd, instr->GetDst(), m_func);

if (regOpnd->m_sym->m_isSingleDef)
{
regOpnd->m_sym->m_isSafeThis = true;
regOpnd->m_sym->m_isNotNumber = true;
}
this->AddInstr(instr, offset);
return;
}

case Js::OpCode::LdObjSlot:
newOpcode = Js::OpCode::LdSlot;
goto ObjSlotCommon;
Expand Down Expand Up @@ -3692,30 +3713,7 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
{
IR::Opnd * functionBodySlotOpnd = IR::IntConstOpnd::New(slotId, TyInt32, m_func, true);

// The byte code doesn't refer directly to a closure environment. Get the implicit one
// that's pointed to by the function body.
if (m_func->DoStackFrameDisplay() && m_func->GetLocalFrameDisplaySym())
{
// Read the scope slot pointer back using the stack closure sym.
fieldOpnd = this->BuildFieldOpnd(Js::OpCode::LdSlotArr, m_func->GetLocalFrameDisplaySym()->m_id, 0, (Js::PropertyIdIndexType)-1, PropertyKindSlotArray);

regOpnd = IR::RegOpnd::New(TyVar, m_func);
instr = IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func);
this->AddInstr(instr, offset);
symID = regOpnd->m_sym->m_id;
}
else
{
symID = this->GetEnvRegForInnerFrameDisplay();
Assert(symID != Js::Constants::NoRegister);
if (IsLoopBody() && !RegIsConstant(symID))
{
this->EnsureLoopBodyLoadSlot(symID);
}
}

StackSym *stackSym = StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func);
IR::Opnd * environmentOpnd = IR::RegOpnd::New(stackSym, TyVar, m_func);
IR::Opnd *environmentOpnd = GetEnvironmentOperand(offset);
regOpnd = this->BuildDstOpnd(regSlot);
if (stackFuncPtrSym)
{
Expand Down Expand Up @@ -3749,6 +3747,35 @@ IRBuilder::BuildElementSlotI1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
}
}

IR::Opnd*
IRBuilder::GetEnvironmentOperand(uint32 offset)
{
SymID symID;
// The byte code doesn't refer directly to a closure environment. Get the implicit one
// that's pointed to by the function body.
if (m_func->DoStackFrameDisplay() && m_func->GetLocalFrameDisplaySym())
{
// Read the scope slot pointer back using the stack closure sym.
IR::Opnd *fieldOpnd = this->BuildFieldOpnd(Js::OpCode::LdSlotArr, m_func->GetLocalFrameDisplaySym()->m_id, 0, (Js::PropertyIdIndexType) - 1, PropertyKindSlotArray);
IR::RegOpnd *regOpnd = IR::RegOpnd::New(TyVar, m_func);
this->AddInstr(
IR::Instr::New(Js::OpCode::LdSlotArr, regOpnd, fieldOpnd, m_func),
offset);
symID = regOpnd->m_sym->m_id;
}
else
{
symID = this->GetEnvRegForInnerFrameDisplay();
Assert(symID != Js::Constants::NoRegister);
if (IsLoopBody() && !RegIsConstant(symID))
{
this->EnsureLoopBodyLoadSlot(symID);
}
}

return IR::RegOpnd::New(StackSym::FindOrCreate(symID, (Js::RegSlot)symID, m_func), TyVar, m_func);
}

template <typename SizePolicy>
void
IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset)
Expand Down Expand Up @@ -3982,6 +4009,96 @@ IRBuilder::BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot r
break;
}
}

template <typename SizePolicy>
void
IRBuilder::BuildElementSlotI3(Js::OpCode newOpcode, uint32 offset)
{
Assert(!OpCodeAttr::IsProfiledOp(newOpcode));
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));
auto layout = m_jnReader.GetLayout<Js::OpLayoutT_ElementSlotI3<SizePolicy>>();

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->Value);
this->DoClosureRegCheck(layout->Instance);
this->DoClosureRegCheck(layout->HomeObj);
}

BuildElementSlotI3(newOpcode, offset, layout->Instance, layout->Value, layout->SlotIndex, layout->HomeObj, Js::Constants::NoProfileId);
}

template <typename SizePolicy>
void
IRBuilder::BuildProfiledElementSlotI3(Js::OpCode newOpcode, uint32 offset)
{
Assert(OpCodeAttr::IsProfiledOp(newOpcode));
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));
auto layout = m_jnReader.GetLayout<Js::OpLayoutDynamicProfile<Js::OpLayoutT_ElementSlotI3<SizePolicy>>>();

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->Value);
this->DoClosureRegCheck(layout->Instance);
this->DoClosureRegCheck(layout->HomeObj);
}

Js::OpCodeUtil::ConvertNonCallOpToNonProfiled(newOpcode);
BuildElementSlotI3(newOpcode, offset, layout->Instance, layout->Value, layout->SlotIndex, layout->HomeObj, layout->profileId);
}

void
IRBuilder::BuildElementSlotI3(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fieldRegSlot, Js::RegSlot regSlot,
int32 slotId, Js::RegSlot homeObj, Js::ProfileId profileId)
{
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));

IR::Instr * instr;
IR::RegOpnd * regOpnd;

switch (newOpcode)
{
case Js::OpCode::NewInnerScFuncHomeObj:
newOpcode = Js::OpCode::NewScFuncHomeObj;
goto NewScFuncCommon;

case Js::OpCode::NewInnerScGenFuncHomeObj:
newOpcode = Js::OpCode::NewScGenFuncHomeObj;

NewScFuncCommon:
{
Js::FunctionInfoPtrPtr infoRef = m_func->GetJITFunctionBody()->GetNestedFuncRef(slotId);
IR::AddrOpnd * functionBodySlotOpnd = IR::AddrOpnd::New((Js::Var)infoRef, IR::AddrOpndKindDynamicMisc, m_func);
IR::Opnd * environmentOpnd = this->BuildSrcOpnd(fieldRegSlot);
IR::Opnd * homeObjOpnd = this->BuildSrcOpnd(homeObj);
regOpnd = this->BuildDstOpnd(regSlot);

instr = IR::Instr::New(Js::OpCode::ExtendArg_A, IR::RegOpnd::New(TyVar, m_func), homeObjOpnd, m_func);
this->AddInstr(instr, offset);

instr = IR::Instr::New(Js::OpCode::ExtendArg_A, IR::RegOpnd::New(TyVar, m_func), functionBodySlotOpnd, instr->GetDst(), m_func);
this->AddInstr(instr, offset);

instr = IR::Instr::New(Js::OpCode::ExtendArg_A, IR::RegOpnd::New(TyVar, m_func), environmentOpnd, instr->GetDst(), m_func);
this->AddInstr(instr, offset);

instr = IR::Instr::New(newOpcode, regOpnd, instr->GetDst(), m_func);

if (regOpnd->m_sym->m_isSingleDef)
{
regOpnd->m_sym->m_isSafeThis = true;
regOpnd->m_sym->m_isNotNumber = true;
}
this->AddInstr(instr, offset);
return;
}

default:
AssertMsg(UNREACHED, "Unknown ElementSlotI3 opcode");
Fatal();
}
}

IR::SymOpnd *
IRBuilder::BuildLoopBodySlotOpnd(SymID symId)
{
Expand Down
4 changes: 3 additions & 1 deletion lib/Backend/IRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ class IRBuilder
int32 slotId, Js::ProfileId profileId);
void BuildElementSlotI2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlot,
int32 slotId1, int32 slotId2, Js::ProfileId profileId);
void BuildElementSlotI3(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fieldRegSlot, Js::RegSlot regSlot,
int32 slotId, Js::RegSlot homeObjLocation, Js::ProfileId profileId);
void BuildArgIn0(uint32 offset, Js::RegSlot R0);
void BuildArg(Js::OpCode newOpcode, uint32 offset, Js::ArgSlot argument, Js::RegSlot srcRegSlot);
void BuildArgIn(uint32 offset, Js::RegSlot dstRegSlot, uint16 argument);
Expand Down Expand Up @@ -320,7 +322,7 @@ class IRBuilder
void InsertDoneLoopBodyLoopCounter(uint32 lastOffset);

IR::RegOpnd * InsertConvPrimStr(IR::RegOpnd * srcOpnd, uint offset, bool forcePreOpBailOutIfNeeded);

IR::Opnd * IRBuilder::GetEnvironmentOperand(uint32 offset);
bool DoLoadInstructionArrayProfileInfo();
bool AllowNativeArrayProfileInfo();

Expand Down
12 changes: 12 additions & 0 deletions lib/Backend/JITTimeFunctionBody.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,18 @@ JITTimeFunctionBody::IsLambda() const
return Js::FunctionInfo::IsLambda(GetAttributes());
}

bool
JITTimeFunctionBody::HasComputedName() const
{
return Js::FunctionInfo::HasComputedName(GetAttributes());
}

bool
JITTimeFunctionBody::HasHomeObj() const
{
return Js::FunctionInfo::HasHomeObj(GetAttributes());
}

bool
JITTimeFunctionBody::HasImplicitArgIns() const
{
Expand Down
2 changes: 2 additions & 0 deletions lib/Backend/JITTimeFunctionBody.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ class JITTimeFunctionBody
bool NeedScopeObjectForArguments(bool hasNonSimpleParams) const;
bool GetDoScopeObjectCreation() const;
void EnsureConsistentConstCount() const;
bool HasComputedName() const;
bool HasHomeObj() const;

const byte * GetByteCodeBuffer() const;
StatementMapIDL * GetFullStatementMap() const;
Expand Down
6 changes: 6 additions & 0 deletions lib/Backend/JnHelperMethod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,12 @@ const char16 *GetVtableName(VTableValue value)
case VtableStackScriptFunction:
return _u("vtable StackScriptFunction");
break;
case VtableScriptFunctionWithInlineCacheAndHomeObj:
return _u("vtable ScriptFunctionWithInlineCacheAndHomeObj");
break;
case VtableScriptFunctionWithInlineCacheHomeObjAndComputedName:
return _u("vtable ScriptFunctionWithInlineCacheHomeObjAndComputedName");
break;
case VtableConcatStringMulti:
return _u("vtable ConcatStringMulti");
break;
Expand Down
3 changes: 2 additions & 1 deletion lib/Backend/JnHelperMethodList.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
HELPERCALL(Invalid, nullptr, 0)

HELPERCALL(ScrFunc_OP_NewScFunc, Js::ScriptFunction::OP_NewScFunc, 0)
HELPERCALL(ScrFunc_OP_NewScFuncHomeObj, Js::ScriptFunction::OP_NewScFuncHomeObj, 0)
HELPERCALL(ScrFunc_OP_NewScGenFunc, Js::JavascriptGeneratorFunction::OP_NewScGenFunc, 0)
HELPERCALL(ScrFunc_OP_NewScGenFuncHomeObj, Js::JavascriptGeneratorFunction::OP_NewScGenFuncHomeObj, 0)
HELPERCALL(ScrFunc_CheckAlignment, Js::JavascriptFunction::CheckAlignment, 0)
HELPERCALL(ScrObj_LdHandlerScope, Js::JavascriptOperators::OP_LdHandlerScope, 0)
HELPERCALL(ScrObj_LdFrameDisplay, Js::JavascriptOperators::OP_LdFrameDisplay, 0)
Expand Down Expand Up @@ -506,7 +508,6 @@ HELPERCALL(SpreadCall, Js::JavascriptFunction::EntrySpreadCall, 0)

HELPERCALL(LdHomeObj, Js::JavascriptOperators::OP_LdHomeObj, 0)
HELPERCALL(LdFuncObj, Js::JavascriptOperators::OP_LdFuncObj, 0)
HELPERCALL(SetHomeObj, Js::JavascriptOperators::OP_SetHomeObj, 0)
HELPERCALL(LdHomeObjProto, Js::JavascriptOperators::OP_LdHomeObjProto, 0)
HELPERCALL(LdFuncObjProto, Js::JavascriptOperators::OP_LdFuncObjProto, 0)

Expand Down
Loading

0 comments on commit c246386

Please sign in to comment.