| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #include "BackEnd.h"
- const Js::ArgSlot StackSym::InvalidSlot = (Js::ArgSlot)-1;
- ///----------------------------------------------------------------------------
- ///
- /// StackSym::New
- ///
- /// Creates a StackSym
- ///
- ///----------------------------------------------------------------------------
- StackSym *
- StackSym::New(SymID id, IRType type, Js::RegSlot byteCodeRegSlot, Func *func)
- {
- StackSym * stackSym;
- if (byteCodeRegSlot != Js::Constants::NoRegister)
- {
- stackSym = AnewZ(func->m_alloc, ByteCodeStackSym, byteCodeRegSlot, func);
- stackSym->m_hasByteCodeRegSlot = true;
- }
- else
- {
- stackSym = AnewZ(func->m_alloc, StackSym);
- }
- stackSym->m_id = id;
- stackSym->m_kind = SymKindStack;
- // Assume SingleDef until proven false.
- stackSym->m_isConst = false;
- stackSym->m_isIntConst = false;
- stackSym->m_isTaggableIntConst = false;
- stackSym->m_isSingleDef = true;
- stackSym->m_isEncodedConstant = false;
- stackSym->m_isFltConst = false;
- stackSym->m_isStrConst = false;
- stackSym->m_isStrEmpty = false;
- stackSym->m_allocated = false;
- stackSym->m_isTypeSpec = false;
- stackSym->m_isArgSlotSym = false;
- stackSym->m_isBailOutReferenced = false;
- stackSym->m_isArgCaptured = false;
- stackSym->m_requiresBailOnNotNumber = false;
- stackSym->m_isCatchObjectSym = false;
- stackSym->m_builtInIndex = Js::BuiltinFunction::None;
- stackSym->m_paramSlotNum = StackSym::InvalidSlot;
- stackSym->m_type = type;
- stackSym->m_equivNext = stackSym;
- stackSym->m_objectInfo = nullptr;
- AssertMsg(func->m_symTable->Find(id) == nullptr, "Trying to add new symbol which already exists.");
- func->m_symTable->Add(stackSym);
- return stackSym;
- }
- ObjectSymInfo *
- ObjectSymInfo::New(Func * func)
- {
- ObjectSymInfo * objSymInfo = JitAnewZ(func->m_alloc, ObjectSymInfo);
- return objSymInfo;
- }
- ObjectSymInfo *
- ObjectSymInfo::New(StackSym * typeSym, Func * func)
- {
- ObjectSymInfo * objSymInfo = ObjectSymInfo::New(func);
- objSymInfo->m_typeSym = typeSym;
- return objSymInfo;
- }
- ObjectSymInfo *
- StackSym::EnsureObjectInfo(Func * func)
- {
- if (this->m_objectInfo == nullptr)
- {
- this->m_objectInfo = ObjectSymInfo::New(func);
- }
- return this->m_objectInfo;
- }
- ///----------------------------------------------------------------------------
- ///
- /// StackSym::New
- ///
- /// Creates a StackSym
- ///
- ///----------------------------------------------------------------------------
- StackSym *
- StackSym::New(Func *func)
- {
- return StackSym::New(func->m_symTable->NewID(), TyVar, Js::Constants::NoRegister, func);
- }
- StackSym *
- StackSym::New(IRType type, Func *func)
- {
- return StackSym::New(func->m_symTable->NewID(), type, Js::Constants::NoRegister, func);
- }
- StackSym *
- StackSym::NewParamSlotSym(Js::ArgSlot paramSlotNum, Func * func)
- {
- StackSym * stackSym = StackSym::New(func);
- stackSym->m_paramSlotNum = paramSlotNum;
- return stackSym;
- }
- StackSym *
- StackSym::NewParamSlotSym(Js::ArgSlot paramSlotNum, Func * func, IRType type)
- {
- StackSym * stackSym = StackSym::New(type, func);
- stackSym->m_paramSlotNum = paramSlotNum;
- return stackSym;
- }
- // Represents a temporary sym which is a copy of an arg slot sym.
- StackSym *
- StackSym::NewArgSlotRegSym(Js::ArgSlot argSlotNum, Func * func, IRType type /* = TyVar */)
- {
- StackSym * stackSym = StackSym::New(type, func);
- stackSym->m_isArgSlotSym = false;
- stackSym->m_argSlotNum = argSlotNum;
- #if defined(_M_X64)
- stackSym->m_argPosition = 0;
- #endif
- return stackSym;
- }
- StackSym *
- StackSym::NewArgSlotSym(Js::ArgSlot argSlotNum, Func * func, IRType type /* = TyVar */)
- {
- StackSym * stackSym = StackSym::New(type, func);
- stackSym->m_isArgSlotSym = true;
- stackSym->m_argSlotNum = argSlotNum;
- #if defined(_M_X64)
- stackSym->m_argPosition = 0;
- #endif
- return stackSym;
- }
- bool
- StackSym::IsTempReg(Func *const func) const
- {
- return !HasByteCodeRegSlot() || GetByteCodeRegSlot() >= func->GetJnFunction()->GetFirstTmpReg();
- }
- #if DBG
- void
- StackSym::VerifyConstFlags() const
- {
- if (m_isConst)
- {
- Assert(this->m_isSingleDef);
- Assert(this->m_instrDef);
- if (m_isIntConst)
- {
- Assert(!m_isFltConst);
- }
- else
- {
- Assert(!m_isTaggableIntConst);
- }
- }
- else
- {
- Assert(!m_isIntConst);
- Assert(!m_isTaggableIntConst);
- Assert(!m_isFltConst);
- }
- }
- #endif
- bool
- StackSym::IsConst() const
- {
- #if DBG
- VerifyConstFlags();
- #endif
- return m_isConst;
- }
- bool
- StackSym::IsIntConst() const
- {
- #if DBG
- VerifyConstFlags();
- #endif
- return m_isIntConst;
- }
- bool
- StackSym::IsTaggableIntConst() const
- {
- #if DBG
- VerifyConstFlags();
- #endif
- return m_isTaggableIntConst;
- }
- bool
- StackSym::IsFloatConst() const
- {
- #if DBG
- VerifyConstFlags();
- #endif
- return m_isFltConst;
- }
- bool
- StackSym::IsSimd128Const() const
- {
- #if DBG
- VerifyConstFlags();
- #endif
- return m_isSimd128Const;
- }
- void
- StackSym::SetIsConst()
- {
- Assert(this->m_isSingleDef);
- Assert(this->m_instrDef);
- IR::Opnd * src = this->m_instrDef->GetSrc1();
- Assert(src->IsImmediateOpnd() || src->IsFloatConstOpnd() || src->IsSimd128ConstOpnd());
- if (src->IsIntConstOpnd())
- {
- Assert(this->m_instrDef->m_opcode == Js::OpCode::Ld_I4 || this->m_instrDef->m_opcode == Js::OpCode::LdC_A_I4 || LowererMD::IsAssign(this->m_instrDef));
- this->SetIsIntConst(src->AsIntConstOpnd()->GetValue());
- }
- else if (src->IsFloatConstOpnd())
- {
- Assert(this->m_instrDef->m_opcode == Js::OpCode::LdC_A_R8);
- this->SetIsFloatConst();
- }
- else if (src->IsSimd128ConstOpnd()){
- Assert(this->m_instrDef->m_opcode == Js::OpCode::Simd128_LdC);
- this->SetIsSimd128Const();
- }
- else
- {
- Assert(this->m_instrDef->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(this->m_instrDef));
- Assert(src->IsAddrOpnd());
- IR::AddrOpnd * addrOpnd = src->AsAddrOpnd();
- this->m_isConst = true;
- if (addrOpnd->IsVar())
- {
- Js::Var var = addrOpnd->m_address;
- if (Js::TaggedInt::Is(var))
- {
- this->m_isIntConst = true;
- this->m_isTaggableIntConst = true;
- }
- else if (var && Js::JavascriptNumber::Is(var) && Js::JavascriptNumber::IsInt32_NoChecks(var))
- {
- this->m_isIntConst = true;
- }
- }
- }
- }
- void
- StackSym::SetIsIntConst(IntConstType value)
- {
- Assert(this->m_isSingleDef);
- Assert(this->m_instrDef);
- this->m_isConst = true;
- this->m_isIntConst = true;
- this->m_isTaggableIntConst = !Js::TaggedInt::IsOverflow(value);
- this->m_isFltConst = false;
- }
- void
- StackSym::SetIsFloatConst()
- {
- Assert(this->m_isSingleDef);
- Assert(this->m_instrDef);
- this->m_isConst = true;
- this->m_isIntConst = false;
- this->m_isTaggableIntConst = false;
- this->m_isFltConst = true;
- }
- void
- StackSym::SetIsSimd128Const()
- {
- Assert(this->m_isSingleDef);
- Assert(this->m_instrDef);
- this->m_isConst = true;
- this->m_isIntConst = false;
- this->m_isTaggableIntConst = false;
- this->m_isFltConst = false;
- this->m_isSimd128Const = true;
- }
- Js::RegSlot
- StackSym::GetByteCodeRegSlot() const
- {
- Assert(HasByteCodeRegSlot());
- return ((ByteCodeStackSym *)this)->byteCodeRegSlot;
- }
- Func *
- StackSym::GetByteCodeFunc() const
- {
- Assert(HasByteCodeRegSlot());
- return ((ByteCodeStackSym *)this)->byteCodeFunc;
- }
- void
- StackSym::IncrementArgSlotNum()
- {
- Assert(IsArgSlotSym());
- m_argSlotNum++;
- }
- void
- StackSym::DecrementArgSlotNum()
- {
- Assert(IsArgSlotSym());
- m_argSlotNum--;
- }
- void
- StackSym::FixupStackOffset(Func * currentFunc)
- {
- int offsetFixup = 0;
- Func * parentFunc = currentFunc->GetParentFunc();
- while (parentFunc)
- {
- if (parentFunc->callSiteToArgumentsOffsetFixupMap)
- {
- parentFunc->callSiteToArgumentsOffsetFixupMap->TryGetValue(currentFunc->callSiteIdInParentFunc, &offsetFixup);
- this->m_offset += offsetFixup * MachPtr;
- }
- parentFunc = parentFunc->GetParentFunc();
- currentFunc = currentFunc->GetParentFunc();
- offsetFixup = 0;
- }
- }
- ///----------------------------------------------------------------------------
- ///
- /// StackSym::FindOrCreate
- ///
- /// Look for a StackSym with the given ID. If not found, create it.
- ///
- ///----------------------------------------------------------------------------
- StackSym *
- StackSym::FindOrCreate(SymID id, Js::RegSlot byteCodeRegSlot, Func *func, IRType type)
- {
- StackSym * stackSym;
- stackSym = func->m_symTable->FindStackSym(id);
- if (stackSym)
- {
- Assert(!stackSym->HasByteCodeRegSlot() ||
- (stackSym->GetByteCodeRegSlot() == byteCodeRegSlot && stackSym->GetByteCodeFunc() == func));
- Assert(stackSym->GetType() == type);
- return stackSym;
- }
- return StackSym::New(id, type, byteCodeRegSlot, func);
- }
- StackSym *
- StackSym::CloneDef(Func *func)
- {
- Cloner * cloner = func->GetCloner();
- StackSym * newSym = nullptr;
- AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
- if (!this->m_isSingleDef)
- {
- return this;
- }
- switch (this->m_instrDef->m_opcode)
- {
- // Note: we were cloning single-def load constant instr's, but couldn't guarantee
- // that we were cloning all the uses.
- case Js::OpCode::ArgOut_A:
- case Js::OpCode::ArgOut_A_Dynamic:
- case Js::OpCode::ArgOut_A_InlineBuiltIn:
- case Js::OpCode::ArgOut_A_SpreadArg:
- case Js::OpCode::StartCall:
- case Js::OpCode::InlineeMetaArg:
- // Go ahead and clone: we need a single-def sym.
- // Arg/StartCall trees must be single-def.
- // Uses of int-const syms may need to find their defining instr's.
- break;
- default:
- return this;
- }
- if (cloner->symMap == nullptr)
- {
- cloner->symMap = HashTable<StackSym*>::New(cloner->alloc, 7);
- }
- else
- {
- StackSym **entry = cloner->symMap->Get(m_id);
- if (entry)
- {
- newSym = *entry;
- }
- }
- if (newSym == nullptr)
- {
- // NOTE: We don't care about the bytecode register information for cloned symbol
- // As those are the float sym that we will convert back to Var before jumping back
- // to the slow path's bailout. The bailout can just track the original symbol.
- newSym = StackSym::New(func);
- newSym->m_isConst = m_isConst;
- newSym->m_isIntConst = m_isIntConst;
- newSym->m_isTaggableIntConst = m_isTaggableIntConst;
- newSym->m_isArgSlotSym = m_isArgSlotSym;
- newSym->m_isArgCaptured = m_isArgCaptured;
- newSym->m_isBailOutReferenced = m_isBailOutReferenced;
- newSym->m_argSlotNum = m_argSlotNum;
- #if defined(_M_X64)
- newSym->m_argPosition = m_argPosition;
- #endif
- newSym->m_paramSlotNum = m_paramSlotNum;
- newSym->m_offset = m_offset;
- newSym->m_allocated = m_allocated;
- newSym->m_isInlinedArgSlot = m_isInlinedArgSlot;
- newSym->m_isCatchObjectSym = m_isCatchObjectSym;
- newSym->m_type = m_type;
- newSym->CopySymAttrs(this);
- // NOTE: It is not clear what the right thing to do is here...
- newSym->m_equivNext = newSym;
- cloner->symMap->FindOrInsert(newSym, m_id);
- }
- return newSym;
- }
- StackSym *
- StackSym::CloneUse(Func *func)
- {
- Cloner * cloner = func->GetCloner();
- StackSym ** newSym;
- AssertMsg(cloner, "Use Func::BeginClone to initialize cloner");
- if (cloner->symMap == nullptr)
- {
- return this;
- }
- newSym = cloner->symMap->Get(m_id);
- if (newSym == nullptr)
- {
- return this;
- }
- return *newSym;
- }
- void
- StackSym::CopySymAttrs(StackSym *symSrc)
- {
- m_isNotInt = symSrc->m_isNotInt;
- m_isSafeThis = symSrc->m_isSafeThis;
- m_builtInIndex = symSrc->m_builtInIndex;
- }
- // StackSym::GetIntConstValue
- int32
- StackSym::GetIntConstValue() const
- {
- Assert(this->IsIntConst());
- IR::Instr *defInstr = this->m_instrDef;
- IR::Opnd *src1 = defInstr->GetSrc1();
- if (src1->IsIntConstOpnd())
- {
- Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || defInstr->m_opcode == Js::OpCode::LdC_A_I4 || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
- return src1->AsIntConstOpnd()->AsInt32();
- }
- if (src1->IsAddrOpnd())
- {
- Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
- IR::AddrOpnd *addr = src1->AsAddrOpnd();
- Assert(addr->IsVar());
- Js::Var var = src1->AsAddrOpnd()->m_address;
- if (Js::TaggedInt::Is(var))
- {
- return Js::TaggedInt::ToInt32(var);
- }
- int32 value;
- const bool isInt32 = Js::JavascriptNumber::TryGetInt32Value(Js::JavascriptNumber::GetValue(var), &value);
- Assert(isInt32);
- return value;
- }
- Assert(src1->IsRegOpnd());
- return src1->AsRegOpnd()->m_sym->GetIntConstValue();
- }
- Js::Var StackSym::GetFloatConstValueAsVar_PostGlobOpt() const
- {
- Assert(this->IsConst());
- IR::Instr *defInstr = this->m_instrDef;
- IR::Opnd *src1 = defInstr->GetSrc1();
- StackSym * stackSym = nullptr;
- if (src1->IsRegOpnd())
- {
- stackSym = src1->AsRegOpnd()->m_sym;
- Assert(!stackSym->m_isEncodedConstant);
- if (stackSym->m_isSingleDef)
- {
- //In ARM constant load is always legalized. Try to get the constant from src def
- defInstr = stackSym->m_instrDef;
- src1 = defInstr->GetSrc1();
- }
- }
- Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
- IR::AddrOpnd *addrOpnd;
- if (src1->IsAddrOpnd())
- {
- Assert(defInstr->m_opcode == Js::OpCode::Ld_A);
- addrOpnd = src1->AsAddrOpnd();
- }
- else
- {
- Assert(src1->IsFloatConstOpnd());
- Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
- addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
- // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
- // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
- defInstr->ReplaceSrc1(addrOpnd);
- defInstr->m_opcode = Js::OpCode::Ld_A;
- }
- const Js::Var address = addrOpnd->m_address;
- Assert(Js::JavascriptNumber::Is(address));
- return address;
- }
- void *StackSym::GetConstAddress() const
- {
- Assert(this->IsConst());
- IR::Instr *defInstr = this->m_instrDef;
- IR::Opnd *src1 = defInstr->GetSrc1();
- StackSym * stackSym = nullptr;
- if (src1->IsRegOpnd())
- {
- stackSym = src1->AsRegOpnd()->m_sym;
- Assert(!stackSym->m_isEncodedConstant);
- if (stackSym->m_isSingleDef)
- {
- //In ARM constant load is always legalized. Try to get the constant from src def
- defInstr = stackSym->m_instrDef;
- src1 = defInstr->GetSrc1();
- }
- }
- Assert(src1->IsAddrOpnd());
- Assert(defInstr->m_opcode == Js::OpCode::Ld_A || defInstr->m_opcode == Js::OpCode::LdStr || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
- return src1->AsAddrOpnd()->m_address;
- }
- intptr_t StackSym::GetLiteralConstValue_PostGlobOpt() const
- {
- Assert(this->IsConst());
- IR::Instr *defInstr = this->m_instrDef;
- IR::Opnd *src1 = defInstr->GetSrc1();
- StackSym * stackSym = nullptr;
- if (src1->IsRegOpnd())
- {
- stackSym = src1->AsRegOpnd()->m_sym;
- if (stackSym->m_isEncodedConstant)
- {
- Assert(!stackSym->m_isSingleDef);
- Assert(LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
- return stackSym->constantValue;
- }
- if (stackSym->m_isSingleDef)
- {
- //In ARM constant load is always legalized. Try to get the constant from src def
- defInstr = stackSym->m_instrDef;
- src1 = defInstr->GetSrc1();
- }
- }
- if (src1->IsAddrOpnd())
- {
- Assert(defInstr->m_opcode == Js::OpCode::Ld_A || defInstr->m_opcode == Js::OpCode::LdStr || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn || LowererMD::IsAssign(defInstr));
- return reinterpret_cast<intptr_t>(src1->AsAddrOpnd()->m_address);
- }
- if (src1->IsIntConstOpnd())
- {
- Assert(this->IsIntConst() || (stackSym && stackSym->IsIntConst()));
- if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
- {
- IR::AddrOpnd *const addrOpnd = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
- const Js::Var address = addrOpnd->m_address;
- // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
- // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
- defInstr->ReplaceSrc1(addrOpnd);
- defInstr->m_opcode = Js::OpCode::Ld_A;
- return reinterpret_cast<intptr_t>(address);
- }
- Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
- return src1->AsIntConstOpnd()->GetValue();
- }
- if (src1->IsFloatConstOpnd())
- {
- Assert(this->IsFloatConst() || (stackSym && stackSym->IsFloatConst()));
- Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
- IR::AddrOpnd *const addrOpnd = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
- const Js::Var address = addrOpnd->m_address;
- // This is just to prevent creating multiple numbers when the sym is used multiple times. We can only do this
- // post-GlobOpt, as otherwise it violates some invariants assumed in GlobOpt.
- defInstr->ReplaceSrc1(addrOpnd);
- defInstr->m_opcode = Js::OpCode::Ld_A;
- return reinterpret_cast<intptr_t>(address);
- }
- AssertMsg(UNREACHED, "Unknown const value");
- return 0;
- }
- IR::Opnd *
- StackSym::GetConstOpnd() const
- {
- Assert(IsConst());
- IR::Instr *defInstr = this->m_instrDef;
- IR::Opnd *src1 = defInstr->GetSrc1();
- if (!src1)
- {
- #if defined(_M_IX86) || defined(_M_X64)
- Assert(defInstr->m_opcode == Js::OpCode::MOVSD_ZERO);
- #else
- Assert(UNREACHED);
- #endif
- }
- else if (src1->IsIntConstOpnd())
- {
- Assert(this->IsIntConst());
- if (defInstr->m_opcode == Js::OpCode::LdC_A_I4)
- {
- src1 = IR::AddrOpnd::NewFromNumber(src1->AsIntConstOpnd()->GetValue(), defInstr->m_func);
- defInstr->ReplaceSrc1(src1);
- defInstr->m_opcode = Js::OpCode::Ld_A;
- }
- else
- {
- Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
- }
- }
- else if (src1->IsFloatConstOpnd())
- {
- Assert(this->IsFloatConst());
- Assert(defInstr->m_opcode == Js::OpCode::LdC_A_R8);
- src1 = src1->AsFloatConstOpnd()->GetAddrOpnd(defInstr->m_func);
- defInstr->ReplaceSrc1(src1);
- defInstr->m_opcode = Js::OpCode::Ld_A;
- }
- else if (src1->IsAddrOpnd())
- {
- Assert(defInstr->m_opcode == Js::OpCode::Ld_A || LowererMD::IsAssign(defInstr) || defInstr->m_opcode == Js::OpCode::ArgOut_A_InlineBuiltIn);
- }
- else if (src1->IsMemRefOpnd())
- {
- Assert(this->IsFloatConst() || this->IsSimd128Const());
- }
- else
- {
- AssertMsg(UNREACHED, "Invalid const value");
- }
- return src1;
- }
- BailoutConstantValue StackSym::GetConstValueForBailout() const
- {
- Assert(this->IsConst());
- IR::Instr *defInstr = this->m_instrDef;
- IR::Opnd *src1 = defInstr->GetSrc1();
- return src1->GetConstValue();
- }
- // SIMD_JS
- StackSym *
- StackSym::GetSimd128EquivSym(IRType type, Func *func)
- {
- switch (type)
- {
- case TySimd128F4:
- return this->GetSimd128F4EquivSym(func);
- break;
- case TySimd128I4:
- return this->GetSimd128I4EquivSym(func);
- break;
- case TySimd128D2:
- return this->GetSimd128D2EquivSym(func);
- break;
- default:
- Assert(UNREACHED);
- return nullptr;
- }
- }
- StackSym *
- StackSym::GetSimd128F4EquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TySimd128F4, func);
- }
- StackSym *
- StackSym::GetSimd128I4EquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TySimd128I4, func);
- }
- StackSym *
- StackSym::GetSimd128D2EquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TySimd128D2, func);
- }
- StackSym *
- StackSym::GetFloat64EquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TyFloat64, func);
- }
- StackSym *
- StackSym::GetInt32EquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TyInt32, func);
- }
- StackSym *
- StackSym::GetVarEquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TyVar, func);
- }
- StackSym *
- StackSym::GetTypeEquivSym(IRType type, Func *func)
- {
- Assert(this->m_type != type);
- StackSym *sym = this->m_equivNext;
- int i = 1;
- while (sym != this)
- {
- Assert(i <= 5); // circular of at most 6 syms : var, f64, i32, simd128I4, simd128F4, simd12D2
- if (sym->m_type == type)
- {
- return sym;
- }
- sym = sym->m_equivNext;
- i++;
- }
- // Don't allocate if func wasn't passed in.
- if (func == nullptr)
- {
- return nullptr;
- }
- if (this->HasByteCodeRegSlot())
- {
- sym = StackSym::New(func->m_symTable->NewID(), type,
- this->GetByteCodeRegSlot(), this->GetByteCodeFunc());
- }
- else
- {
- sym = StackSym::New(type, func);
- }
- sym->m_equivNext = this->m_equivNext;
- this->m_equivNext = sym;
- if (type != TyVar)
- {
- sym->m_isTypeSpec = true;
- }
- return sym;
- }
- StackSym *StackSym::GetVarEquivStackSym_NoCreate(Sym *const sym)
- {
- Assert(sym);
- if(!sym->IsStackSym())
- {
- return nullptr;
- }
- StackSym *stackSym = sym->AsStackSym();
- if(stackSym->IsTypeSpec())
- {
- stackSym = stackSym->GetVarEquivSym(nullptr);
- }
- return stackSym;
- }
- ///----------------------------------------------------------------------------
- ///
- /// PropertySym::New
- ///
- /// Creates a PropertySym
- ///
- ///----------------------------------------------------------------------------
- PropertySym *
- PropertySym::New(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
- {
- StackSym * stackSym;
- stackSym = func->m_symTable->FindStackSym(stackSymID);
- AssertMsg(stackSym != nullptr, "Adding propertySym to non-existing stackSym... Can this happen??");
- return PropertySym::New(stackSym, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
- }
- PropertySym *
- PropertySym::New(StackSym *stackSym, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
- {
- PropertySym * propertySym;
- propertySym = JitAnewZ(func->m_alloc, PropertySym);
- propertySym->m_func = func;
- propertySym->m_id = func->m_symTable->NewID();
- propertySym->m_kind = SymKindProperty;
- propertySym->m_propertyId = propertyId;
- propertyIdIndex = (uint)-1;
- inlineCacheIndex = (uint)-1;
- propertySym->m_propertyIdIndex = propertyIdIndex;
- propertySym->m_inlineCacheIndex = inlineCacheIndex;
- Assert(propertyIdIndex == (uint)-1 || inlineCacheIndex == (uint)-1);
- propertySym->m_loadInlineCacheIndex = (uint)-1;
- propertySym->m_loadInlineCacheFunc = nullptr;
- propertySym->m_fieldKind = fieldKind;
- propertySym->m_stackSym = stackSym;
- propertySym->m_propertyEquivSet = nullptr;
- // Add to list
- func->m_symTable->Add(propertySym);
- // Keep track of all the property we use from this sym so we can invalidate
- // the value in glob opt
- ObjectSymInfo * objectSymInfo = stackSym->EnsureObjectInfo(func);
- propertySym->m_nextInStackSymList = objectSymInfo->m_propertySymList;
- objectSymInfo->m_propertySymList = propertySym;
- return propertySym;
- }
- ///----------------------------------------------------------------------------
- ///
- /// PropertySym::FindOrCreate
- ///
- /// Look for a PropertySym with the given ID/propertyId.
- ///
- ///----------------------------------------------------------------------------
- PropertySym *
- PropertySym::Find(SymID stackSymID, int32 propertyId, Func *func)
- {
- return func->m_symTable->FindPropertySym(stackSymID, propertyId);
- }
- ///----------------------------------------------------------------------------
- ///
- /// PropertySym::FindOrCreate
- ///
- /// Look for a PropertySym with the given ID/propertyId. If not found,
- /// create it.
- ///
- ///----------------------------------------------------------------------------
- PropertySym *
- PropertySym::FindOrCreate(SymID stackSymID, int32 propertyId, uint32 propertyIdIndex, uint inlineCacheIndex, PropertyKind fieldKind, Func *func)
- {
- PropertySym * propertySym;
- propertySym = Find(stackSymID, propertyId, func);
- if (propertySym)
- {
- return propertySym;
- }
- return PropertySym::New(stackSymID, propertyId, propertyIdIndex, inlineCacheIndex, fieldKind, func);
- }
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- const wchar_t* PropertySym::GetName() const
- {
- if (this->m_fieldKind == PropertyKindData)
- {
- return m_func->GetJnFunction()->GetScriptContext()->GetPropertyNameLocked(this->m_propertyId)->GetBuffer();
- }
- Assert(false);
- return L"";
- }
- #endif
- #if DBG_DUMP || defined(ENABLE_IR_VIEWER)
- ///----------------------------------------------------------------------------
- ///
- /// Sym::Dump
- ///
- ///----------------------------------------------------------------------------
- void
- Sym::Dump(IRDumpFlags flags, const ValueType valueType)
- {
- bool const AsmDumpMode = flags & IRDumpFlags_AsmDumpMode;
- bool const SimpleForm = !!(flags & IRDumpFlags_SimpleForm);
- if (AsmDumpMode)
- {
- if (this->IsStackSym() && this->AsStackSym()->IsArgSlotSym())
- {
- Output::Print(L"arg ");
- }
- else if (this->IsStackSym() && this->AsStackSym()->IsParamSlotSym())
- {
- Output::Print(L"param ");
- }
- }
- else
- {
- if (this->IsStackSym() && this->AsStackSym()->IsArgSlotSym())
- {
- if (this->AsStackSym()->m_isInlinedArgSlot)
- {
- Output::Print(L"iarg%d", this->AsStackSym()->GetArgSlotNum());
- }
- else
- {
- Output::Print(L"arg%d", this->AsStackSym()->GetArgSlotNum());
- }
- Output::Print(L"(s%d)", m_id);
- }
- else if (this->IsStackSym() && this->AsStackSym()->IsParamSlotSym())
- {
- Output::Print(L"prm%d", this->AsStackSym()->GetParamSlotNum());
- }
- else
- {
- if (!this->IsPropertySym() || !SimpleForm)
- {
- Output::Print(L"s%d", m_id);
- }
- if (this->IsStackSym())
- {
- if(Js::Configuration::Global.flags.Debug && this->AsStackSym()->HasByteCodeRegSlot())
- {
- StackSym* sym = this->AsStackSym();
- Js::FunctionBody* functionBody = sym->GetByteCodeFunc()->GetJnFunction();
- if(functionBody->GetPropertyIdOnRegSlotsContainer())
- {
- if(functionBody->IsNonTempLocalVar(sym->GetByteCodeRegSlot()))
- {
- uint index = sym->GetByteCodeRegSlot() - functionBody->GetConstantCount();
- Js::PropertyId propertyId = functionBody->GetPropertyIdOnRegSlotsContainer()->propertyIdsForRegSlots[index];
- Output::Print(L"(%s)", functionBody->GetScriptContext()->GetPropertyNameLocked(propertyId)->GetBuffer());
- }
- }
- }
- if (this->AsStackSym()->IsVar())
- {
- if (this->AsStackSym()->HasObjectTypeSym() && !SimpleForm)
- {
- Output::Print(L"<s%d>", this->AsStackSym()->GetObjectTypeSym()->m_id);
- }
- }
- else
- {
- StackSym *varSym = this->AsStackSym()->GetVarEquivSym(nullptr);
- if (varSym)
- {
- Output::Print(L"(s%d)", varSym->m_id);
- }
- }
- if (!SimpleForm)
- {
- if (this->AsStackSym()->m_builtInIndex != Js::BuiltinFunction::None)
- {
- Output::Print(L"[ffunc]");
- }
- }
- }
- }
- if(IsStackSym())
- {
- IR::Opnd::DumpValueType(valueType);
- }
- }
- if (this->IsPropertySym())
- {
- PropertySym *propertySym = this->AsPropertySym();
- if (!SimpleForm)
- {
- Output::Print(L"(");
- }
- Js::ScriptContext* scriptContext;
- switch (propertySym->m_fieldKind)
- {
- case PropertyKindData:
- {
- propertySym->m_stackSym->Dump(flags, valueType);
- scriptContext = propertySym->m_func->GetScriptContext();
- Js::PropertyRecord const* fieldName = scriptContext->GetPropertyNameLocked(propertySym->m_propertyId);
- Output::Print(L"->%s", fieldName->GetBuffer());
- break;
- }
- case PropertyKindSlots:
- case PropertyKindSlotArray:
- propertySym->m_stackSym->Dump(flags, valueType);
- Output::Print(L"[%d]", propertySym->m_propertyId);
- break;
- case PropertyKindLocalSlots:
- propertySym->m_stackSym->Dump(flags, valueType);
- Output::Print(L"l[%d]", propertySym->m_propertyId);
- break;
- default:
- AssertMsg(0, "Unknown field kind");
- break;
- }
- if (!SimpleForm)
- {
- Output::Print(L")");
- }
- }
- }
- void
- Sym::Dump(const ValueType valueType)
- {
- this->Dump(IRDumpFlags_None, valueType);
- }
- void
- Sym::DumpSimple()
- {
- this->Dump(IRDumpFlags_SimpleForm);
- }
- #endif // DBG_DUMP
|