Skip to content
Permalink
Browse files

Reimplement class definitions to limit type creation

  • Loading branch information
pleath committed Sep 18, 2019
1 parent eaaf7ac commit 63a27a940603879495fb6bb69835791b4d868caa
Showing with 21,370 additions and 20,526 deletions.
  1. +3 −0 lib/Backend/FlowGraph.cpp
  2. +261 −42 lib/Backend/IRBuilder.cpp
  3. +10 −1 lib/Backend/IRBuilder.h
  4. +4 −1 lib/Backend/JnHelperMethodList.h
  5. +102 −31 lib/Backend/Lower.cpp
  6. +1 −1 lib/Backend/Lower.h
  7. +2 −0 lib/Backend/LowerMDShared.cpp
  8. +12 −0 lib/Backend/ServerScriptContext.cpp
  9. +2 −0 lib/Backend/ServerScriptContext.h
  10. +2 −0 lib/Backend/arm/LowerMD.cpp
  11. +2 −0 lib/Backend/arm64/LowerMD.cpp
  12. +2 −0 lib/JITIDL/JITTypes.h
  13. +13 −12 lib/Parser/Parse.cpp
  14. +0 −3 lib/Parser/pnodewalk.h
  15. +0 −1 lib/Parser/ptree.h
  16. +12 −0 lib/Runtime/Base/ScriptContext.cpp
  17. +2 −0 lib/Runtime/Base/ScriptContext.h
  18. +2 −0 lib/Runtime/Base/ScriptContextInfo.h
  19. +93 −11 lib/Runtime/ByteCode/ByteCodeDumper.cpp
  20. +129 −92 lib/Runtime/ByteCode/ByteCodeEmitter.cpp
  21. +0 −1 lib/Runtime/ByteCode/ByteCodeGenerator.cpp
  22. +4 −1 lib/Runtime/ByteCode/ByteCodeSerializer.cpp
  23. +118 −13 lib/Runtime/ByteCode/ByteCodeWriter.cpp
  24. +10 −2 lib/Runtime/ByteCode/ByteCodeWriter.h
  25. +5 −1 lib/Runtime/ByteCode/LayoutTypes.h
  26. +10 −1 lib/Runtime/ByteCode/OpCodes.h
  27. +47 −7 lib/Runtime/ByteCode/OpLayouts.h
  28. +6 −1 lib/Runtime/Language/InterpreterHandler.inl
  29. +106 −3 lib/Runtime/Language/InterpreterStackFrame.cpp
  30. +4 −1 lib/Runtime/Language/InterpreterStackFrame.h
  31. +8 −70 lib/Runtime/Language/JavascriptOperators.cpp
  32. +1 −1 lib/Runtime/Language/JavascriptOperators.h
  33. +5,274 −5,275 lib/Runtime/Library/InJavascript/Intl.js.bc.32b.h
  34. +5,273 −5,275 lib/Runtime/Library/InJavascript/Intl.js.bc.64b.h
  35. +4,618 −4,619 lib/Runtime/Library/InJavascript/Intl.js.nojit.bc.32b.h
  36. +4,617 −4,618 lib/Runtime/Library/InJavascript/Intl.js.nojit.bc.64b.h
  37. +55 −6 lib/Runtime/Library/JavascriptLibrary.cpp
  38. +10 −0 lib/Runtime/Library/JavascriptLibrary.h
  39. +104 −104 lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.bc.32b.h
  40. +104 −104 lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.bc.64b.h
  41. +104 −104 lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.nojit.bc.32b.h
  42. +104 −104 lib/Runtime/Library/JsBuiltIn/JsBuiltIn.js.nojit.bc.64b.h
  43. +98 −6 lib/Runtime/Library/ScriptFunction.cpp
  44. +2 −2 lib/Runtime/Library/ScriptFunction.h
  45. +15 −6 lib/Runtime/Types/ScriptFunctionType.cpp
  46. +1 −0 lib/Runtime/Types/ScriptFunctionType.h
  47. +11 −2 lib/Runtime/Types/SimpleDictionaryTypeHandler.cpp
  48. +5 −1 lib/Runtime/Types/SimpleDictionaryTypeHandler.h
  49. +2 −3 lib/Runtime/Types/SimpleTypeHandler.cpp
@@ -848,6 +848,9 @@ FlowGraph::RunPeeps()
case Js::OpCode::BrOnObject_A:
case Js::OpCode::BrOnClassConstructor:
case Js::OpCode::BrOnBaseConstructorKind:
case Js::OpCode::BrOnObjectOrNull_A:
case Js::OpCode::BrOnNotNullObj_A:
case Js::OpCode::BrOnConstructor_A:
if (tryUnsignedCmpPeep)
{
this->UnsignedCmpPeep(instr);
@@ -2242,6 +2242,191 @@ IRBuilder::BuildReg3C(Js::OpCode newOpCode, uint32 offset, Js::RegSlot dstRegSlo
this->AddInstr(instr, Js::Constants::NoByteCodeOffset);
}

void
IRBuilder::BuildReg2U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, uint index)
{
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));

switch (newOpcode)
{
case Js::OpCode::InitBaseClass:
{
IR::Opnd * opndProtoParent = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetObjectPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
IR::Opnd * opndCtorParent = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetFunctionPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
BuildInitClass(offset, R0, R1, opndProtoParent, opndCtorParent, GetEnvironmentOperand(offset), index);
break;
}

default:
AssertMsg(false, "Unknown Reg2U op");
break;
}
}

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

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->R0);
this->DoClosureRegCheck(layout->R1);
}

BuildReg2U(newOpcode, offset, layout->R0, layout->R1, layout->SlotIndex);
}

void
IRBuilder::BuildReg3U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2, uint index)
{
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));

switch (newOpcode)
{
case Js::OpCode::InitInnerBaseClass:
{
IR::Opnd * opndProtoParent = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetObjectPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
IR::Opnd * opndCtorParent = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetFunctionPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
BuildInitClass(offset, R0, R1, opndProtoParent, opndCtorParent, BuildSrcOpnd(R2), index);
break;
}

default:
AssertMsg(false, "Unknown Reg3U op");
break;
}
}

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

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->R0);
this->DoClosureRegCheck(layout->R1);
this->DoClosureRegCheck(layout->R2);
}

BuildReg3U(newOpcode, offset, layout->R0, layout->R1, layout->R2, layout->SlotIndex);
}

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

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->R0);
this->DoClosureRegCheck(layout->R1);
this->DoClosureRegCheck(layout->R2);
this->DoClosureRegCheck(layout->R3);
}

BuildReg4U(newOpcode, offset, layout->R0, layout->R1, layout->R2, layout->R3, layout->SlotIndex);
}

void
IRBuilder::BuildReg4U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2, Js::RegSlot R3, uint slotIndex)
{
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));

switch (newOpcode)
{
case Js::OpCode::InitClass:
{
BuildInitClass(offset, R0, R1, BuildSrcOpnd(R3), BuildSrcOpnd(R2), GetEnvironmentOperand(offset), slotIndex);
break;
}

default:
AssertMsg(false, "Unknown Reg4U opcode");
break;
}
}

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

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->R0);
this->DoClosureRegCheck(layout->R1);
this->DoClosureRegCheck(layout->R2);
this->DoClosureRegCheck(layout->R3);
this->DoClosureRegCheck(layout->R4);
}

BuildReg5U(newOpcode, offset, layout->R0, layout->R1, layout->R2, layout->R3, layout->R4, layout->SlotIndex);
}

void
IRBuilder::BuildReg5U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2, Js::RegSlot R3, Js::RegSlot R4, uint slotIndex)
{
Assert(OpCodeAttr::HasMultiSizeLayout(newOpcode));

switch (newOpcode)
{
case Js::OpCode::InitInnerClass:
{
BuildInitClass(offset, R0, R1, BuildSrcOpnd(R3), BuildSrcOpnd(R2), BuildSrcOpnd(R4), slotIndex);
break;
}

default:
AssertMsg(false, "Unknown Reg5U opcode");
break;
}
}

void
IRBuilder::BuildInitClass(uint32 offset, Js::RegSlot regConstructor, Js::RegSlot regProto, IR::Opnd * opndProtoParent, IR::Opnd * opndConstructorParent, IR::Opnd * opndEnvironment, uint index)
{
IR::RegOpnd * opndProto = BuildDstOpnd(regProto);
opndProto->SetValueType(ValueType::GetObject(ObjectType::Object));
IR::Instr * instr = IR::Instr::New(Js::OpCode::NewClassCtorProto, opndProto, opndProtoParent, m_func);
this->AddInstr(instr, offset);

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

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

Js::FunctionInfoPtrPtr infoRef = m_func->GetJITFunctionBody()->GetNestedFuncRef(index);
IR::AddrOpnd * functionBodySlotOpnd = IR::AddrOpnd::New((Js::Var)infoRef, IR::AddrOpndKindDynamicMisc, m_func);
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), opndEnvironment, instr->GetDst(), m_func);
this->AddInstr(instr, offset);

IR::RegOpnd * opndConstructor = BuildDstOpnd(regConstructor);
instr = IR::Instr::New(Js::OpCode::NewClassConstructor, opndConstructor, instr->GetDst(), m_func);
this->AddInstr(instr, offset);

Assert(opndConstructor->m_sym->m_isSingleDef);
opndConstructor->m_sym->m_isSafeThis = true;
opndConstructor->m_sym->m_isNotNumber = true;
}

///----------------------------------------------------------------------------
///
/// IRBuilder::BuildReg4
@@ -6684,48 +6869,6 @@ IRBuilder::BuildCallCommon(IR::Instr * instr, StackSym * symDst, Js::ArgSlot arg
}
}

///----------------------------------------------------------------------------
///
/// IRBuilder::BuildClass
///
/// Build IR instr for an InitClass instruction.
///
///----------------------------------------------------------------------------


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

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->Constructor);
this->DoClosureRegCheck(layout->Extends);
}

BuildClass(newOpcode, offset, layout->Constructor, layout->Extends);
}

void
IRBuilder::BuildClass(Js::OpCode newOpcode, uint32 offset, Js::RegSlot constructor, Js::RegSlot extends)
{
Assert(newOpcode == Js::OpCode::InitClass);

IR::Instr * insn = IR::Instr::New(newOpcode, m_func);
insn->SetSrc1(this->BuildSrcOpnd(constructor));

if (extends != Js::Constants::NoRegister)
{
insn->SetSrc2(this->BuildSrcOpnd(extends));
}

this->AddInstr(insn, offset);
}


///----------------------------------------------------------------------------
///
@@ -6797,6 +6940,24 @@ IRBuilder::BuildBrReg2(Js::OpCode newOpcode, uint32 offset)
BuildBrReg2(newOpcode, offset, m_jnReader.GetCurrentOffset() + layout->RelativeJumpOffset, layout->R1, layout->R2);
}

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

if (!PHASE_OFF(Js::ClosureRegCheckPhase, m_func))
{
this->DoClosureRegCheck(layout->R0);
this->DoClosureRegCheck(layout->R1);
this->DoClosureRegCheck(layout->R2);
}

BuildBrReg3(newOpcode, offset, m_jnReader.GetCurrentOffset() + layout->RelativeJumpOffset, layout->R0, layout->R1, layout->R2);
}

template <typename SizePolicy>
void
IRBuilder::BuildBrReg1Unsigned1(Js::OpCode newOpcode, uint32 offset)
@@ -6883,6 +7044,64 @@ IRBuilder::BuildBrReg2(Js::OpCode newOpcode, uint32 offset, uint targetOffset, J
}
}


void
IRBuilder::BuildBrReg3(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2)
{
switch (newOpcode)
{
case Js::OpCode::CheckExtends:
{
IR::RegOpnd * opndExtends = BuildSrcOpnd(R2);
// If extends is Null, assign appropriate values to ctorParent and protoParent and jump to target offset.
IR::LabelInstr * labelNotNull = IR::LabelInstr::New(Js::OpCode::Label, m_func);
IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrOnNotNullObj_A, labelNotNull, opndExtends, m_func);
this->AddInstr(branchInstr, offset);

IR::AddrOpnd * opndNullAddr = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetNullAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
IR::RegOpnd * opndProtoParent = BuildDstOpnd(R1);
IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, opndProtoParent, opndNullAddr, m_func);
opndNullAddr->SetValueType(ValueType::Null);
this->AddInstr(instr, offset);

IR::AddrOpnd * opndFuncProto = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetFunctionPrototypeAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
IR::RegOpnd * opndCtorParent = BuildDstOpnd(R0);
instr = IR::Instr::New(Js::OpCode::Ld_A, opndCtorParent, opndFuncProto, m_func);
this->AddInstr(instr, offset);

branchInstr = IR::BranchInstr::New(Js::OpCode::Br, nullptr, m_func);
this->AddBranchInstr(branchInstr, offset, targetOffset);

this->AddInstr(labelNotNull, offset);

IR::LabelInstr * labelIsCtor = IR::LabelInstr::New(Js::OpCode::Label, m_func);
IR::BranchInstr * brIsCtor = IR::BranchInstr::New(Js::OpCode::BrOnConstructor_A, labelIsCtor, opndExtends, m_func);
this->AddInstr(brIsCtor, offset);

instr = IR::Instr::New(Js::OpCode::RuntimeTypeError, m_func);
instr->SetSrc1(IR::IntConstOpnd::New(SCODE_CODE(JSERR_ErrorOnNew), TyInt32, m_func, true));
this->AddInstr(instr, offset);

this->AddInstr(labelIsCtor, offset);

if (R0 == R2 && opndCtorParent->m_sym != opndExtends->m_sym)
{
// The byte code doesn't contain a Ld_A, since the byte code regs are the same, but they've been renumbered in the JIT,
// so we have to assign from one to the other.
instr = IR::Instr::New(Js::OpCode::Ld_A, opndCtorParent, opndExtends, m_func);
this->AddInstr(instr, offset);
}

break;
}

default:
AssertMsg(false, "Unknown BrReg3 opcode");
break;

}
}

void
IRBuilder::BuildEmpty(Js::OpCode newOpcode, uint32 offset)
{
@@ -137,11 +137,18 @@ class IRBuilder
void BuildProfiledReg2(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, Js::ProfileId profileId);
void BuildReg3(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
Js::RegSlot src2RegSlot, Js::ProfileId profileId);
void BuildReg3U(Js::OpCode newOpCode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
Js::RegSlot src2RegSlot, uint slotIndex);
void BuildIsIn(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, Js::ProfileId profileId);
void BuildReg3C(Js::OpCode newOpCode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
Js::RegSlot src2RegSlot, Js::CacheId inlineCacheIndex);
void BuildReg3UC(Js::OpCode newOpCode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
Js::RegSlot src2RegSlot, uint slotIndex, Js::CacheId inlineCacheIndex);
void BuildReg4(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
Js::RegSlot src2RegSlot, Js::RegSlot src3RegSlot);
void BuildReg4U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2, Js::RegSlot R3, uint slotIndex);
void BuildReg5U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2, Js::RegSlot R3, Js::RegSlot R4,
uint slotIndex);
void BuildReg2B1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, byte index);
void BuildReg3B1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot,
Js::RegSlot src2RegSlot, uint8 index);
@@ -151,6 +158,7 @@ class IRBuilder
void BuildReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, int32 C1);
void BuildProfiledReg1Unsigned1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, int32 C1, Js::ProfileId profileId);
void BuildReg2Int1(Js::OpCode newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, int32 value);
void BuildReg2U(Js::OpCode newOpcode, uint32 offset, Js::RegSlot R0, Js::RegSlot R1, uint index);
void BuildElementC(Js::OpCode newOpcode, uint32 offset, Js::RegSlot fieldRegSlot, Js::RegSlot regSlot,
Js::PropertyIdIndexType propertyIdIndex);
void BuildElementScopedC(Js::OpCode newOpcode, uint32 offset, Js::RegSlot regSlot,
@@ -201,9 +209,10 @@ class IRBuilder
Js::ArgSlot argCount, Js::CallIExtendedOptions options, uint32 spreadAuxOffset, Js::CallFlags flags = Js::CallFlags_None);
void BuildCallCommon(IR::Instr *instr, StackSym *symDst, Js::ArgSlot argCount, Js::CallFlags flags = Js::CallFlags_None);
void BuildRegexFromPattern(Js::RegSlot dstRegSlot, uint32 patternIndex, uint32 offset);
void BuildClass(Js::OpCode newOpcode, uint32 offset, Js::RegSlot constructor, Js::RegSlot extends);
void BuildInitClass(uint32 offset, Js::RegSlot constructor, Js::RegSlot proto, IR::Opnd * opndProtoParent, IR::Opnd * opndCtorParent, IR::Opnd * opndEnvironment, uint index);
void BuildBrReg1(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot srcRegSlot);
void BuildBrReg2(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot);
void BuildBrReg3(Js::OpCode newOpcode, uint32 offset, uint targetOffset, Js::RegSlot R0, Js::RegSlot R1, Js::RegSlot R2);
void BuildBrBReturn(Js::OpCode newOpcode, uint32 offset, Js::RegSlot DestRegSlot, uint32 forInLoopLevel, uint32 targetOffset);

IR::IndirOpnd * BuildIndirOpnd(IR::RegOpnd *baseReg, IR::RegOpnd *indexReg);

0 comments on commit 63a27a9

Please sign in to comment.
You can’t perform that action at this time.