| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft Corporation and contributors. 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_isInt64Const = false;
- stackSym->m_isStrConst = false;
- stackSym->m_isStrEmpty = false;
- stackSym->m_allocated = false;
- stackSym->m_isTypeSpec = false;
- stackSym->m_isArgSlotSym = false;
- stackSym->m_isArgSlotRegSym = false;
- stackSym->m_isParamSym = false;
- stackSym->m_isImplicitParamSym = 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_slotNum = 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::NewImplicitParamSym(Js::ArgSlot paramSlotNum, Func * func)
- {
- return func->m_symTable->GetImplicitParam(paramSlotNum);
- }
- StackSym *
- StackSym::NewParamSlotSym(Js::ArgSlot paramSlotNum, Func * func)
- {
- return NewParamSlotSym(paramSlotNum, func, TyVar);
- }
- StackSym *
- StackSym::NewParamSlotSym(Js::ArgSlot paramSlotNum, Func * func, IRType type)
- {
- StackSym * stackSym = StackSym::New(type, func);
- stackSym->m_isParamSym = true;
- stackSym->m_slotNum = 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_isArgSlotRegSym = true;
- stackSym->m_slotNum = 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_slotNum = argSlotNum;
- #if defined(_M_X64)
- stackSym->m_argPosition = 0;
- #endif
- return stackSym;
- }
- bool
- StackSym::IsTempReg(Func *const func) const
- {
- return !HasByteCodeRegSlot() || GetByteCodeRegSlot() >= func->GetJITFunctionBody()->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::IsInt64Const() const
- {
- #if DBG
- VerifyConstFlags();
- #endif
- return m_isInt64Const;
- }
- 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->IsInt64ConstOpnd())
- {
- Assert(this->m_instrDef->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(this->m_instrDef));
- this->SetIsInt64Const();
- }
- 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)
- {
- #if !FLOATVAR
- if (JITManager::GetJITManager()->IsOOPJITEnabled())
- {
- if (addrOpnd->m_localAddress && Js::JavascriptNumber::Is(addrOpnd->m_localAddress) && Js::JavascriptNumber::IsInt32_NoChecks(addrOpnd->m_localAddress))
- {
- this->m_isIntConst = true;
- }
- }
- else
- #endif
- {
- if (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::SetIsInt64Const()
- {
- Assert(this->m_isSingleDef);
- Assert(this->m_instrDef);
- this->m_isConst = true;
- this->m_isInt64Const = true;
- this->m_isIntConst = false;
- this->m_isTaggableIntConst = false;
- 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_slotNum++;
- }
- void
- StackSym::DecrementArgSlotNum()
- {
- Assert(IsArgSlotSym());
- m_slotNum--;
- }
- 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_isArgSlotRegSym = m_isArgSlotRegSym;
- newSym->m_isParamSym = m_isParamSym;
- newSym->m_isImplicitParamSym = m_isImplicitParamSym;
- newSym->m_isArgCaptured = m_isArgCaptured;
- newSym->m_isBailOutReferenced = m_isBailOutReferenced;
- newSym->m_slotNum = m_slotNum;
- #if defined(_M_X64)
- newSym->m_argPosition = m_argPosition;
- #endif
- 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 || 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(addrOpnd->m_localAddress? addrOpnd->m_localAddress: addrOpnd->m_address));
- return address;
- }
- void *StackSym::GetConstAddress(bool useLocal /*= false*/) 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 useLocal ? src1->AsAddrOpnd()->m_localAddress : 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->IsInt64ConstOpnd())
- {
- Assert(this->m_isInt64Const);
- Assert(defInstr->m_opcode == Js::OpCode::Ld_I4 || LowererMD::IsAssign(defInstr));
- }
- 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 TySimd128I16:
- return this->GetSimd128I16EquivSym(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::GetSimd128I16EquivSym(Func *func)
- {
- return this->GetTypeEquivSym(TySimd128I16, 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, simd128D2
- 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);
- }
- #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(_u("arg "));
- }
- else if (this->IsStackSym() && this->AsStackSym()->IsParamSlotSym())
- {
- Output::Print(_u("param "));
- }
- }
- else if (this->IsStackSym())
- {
- StackSym *stackSym = this->AsStackSym();
- if (stackSym->IsArgSlotSym())
- {
- if (stackSym->m_isInlinedArgSlot)
- {
- Output::Print(_u("iarg%d"), stackSym->GetArgSlotNum());
- }
- else
- {
- Output::Print(_u("arg%d"), stackSym->GetArgSlotNum());
- }
- Output::Print(_u("(s%d)"), m_id);
- }
- else if (stackSym->IsParamSlotSym())
- {
- if (stackSym->IsImplicitParamSym())
- {
- switch (stackSym->GetParamSlotNum())
- {
- case 1:
- Output::Print(_u("callInfo"));
- break;
- case 2:
- Output::Print(_u("funcInfo"));
- break;
- case 3:
- Output::Print(_u("genObj"));
- break;
- case 4:
- Output::Print(_u("genFrame"));
- break;
- default:
- Output::Print(_u("implPrm%d"), stackSym->GetParamSlotNum());
- }
- }
- else
- {
- Output::Print(_u("prm%d"), stackSym->GetParamSlotNum());
- }
- }
- else
- {
- Output::Print(_u("s%d"), m_id);
- if (Js::Configuration::Global.flags.Debug && stackSym->HasByteCodeRegSlot())
- {
- if (!JITManager::GetJITManager()->IsOOPJITEnabled())
- {
- Js::FunctionBody* functionBody = (Js::FunctionBody*)stackSym->GetByteCodeFunc()->GetJITFunctionBody()->GetAddr();
- if (functionBody->GetPropertyIdOnRegSlotsContainer())
- {
- if (functionBody->IsNonTempLocalVar(stackSym->GetByteCodeRegSlot()))
- {
- uint index = stackSym->GetByteCodeRegSlot() - stackSym->GetByteCodeFunc()->GetJITFunctionBody()->GetConstCount();
- Js::PropertyId propertyId = functionBody->GetPropertyIdOnRegSlotsContainer()->propertyIdsForRegSlots[index];
- Output::Print(_u("(%s)"), stackSym->GetByteCodeFunc()->GetInProcThreadContext()->GetPropertyRecord(propertyId)->GetBuffer());
- }
- }
- }
- }
- if (stackSym->IsVar())
- {
- if (stackSym->HasObjectTypeSym() && !SimpleForm)
- {
- Output::Print(_u("<s%d>"), stackSym->GetObjectTypeSym()->m_id);
- }
- }
- else
- {
- StackSym *varSym = stackSym->GetVarEquivSym(nullptr);
- if (varSym)
- {
- Output::Print(_u("(s%d)"), varSym->m_id);
- }
- }
- if (!SimpleForm)
- {
- if (stackSym->m_builtInIndex != Js::BuiltinFunction::None)
- {
- Output::Print(_u("[ffunc]"));
- }
- }
- IR::Opnd::DumpValueType(valueType);
- }
- }
- else if (this->IsPropertySym())
- {
- PropertySym *propertySym = this->AsPropertySym();
- if (!SimpleForm)
- {
- Output::Print(_u("s%d("), m_id);
- }
- switch (propertySym->m_fieldKind)
- {
- case PropertyKindData:
- propertySym->m_stackSym->Dump(flags, valueType);
- if (JITManager::GetJITManager()->IsOOPJITEnabled())
- {
- Output::Print(_u("->#%d"), propertySym->m_propertyId);
- }
- else
- {
- Js::PropertyRecord const* fieldName = propertySym->m_func->GetInProcThreadContext()->GetPropertyRecord(propertySym->m_propertyId);
- Output::Print(_u("->%s"), fieldName->GetBuffer());
- }
- break;
- case PropertyKindSlots:
- case PropertyKindSlotArray:
- propertySym->m_stackSym->Dump(flags, valueType);
- Output::Print(_u("[%d]"), propertySym->m_propertyId);
- break;
- case PropertyKindLocalSlots:
- propertySym->m_stackSym->Dump(flags, valueType);
- Output::Print(_u("l[%d]"), propertySym->m_propertyId);
- break;
- default:
- AssertMsg(0, "Unknown field kind");
- break;
- }
- if (!SimpleForm)
- {
- Output::Print(_u(")"));
- }
- }
- }
- void
- Sym::Dump(const ValueType valueType)
- {
- this->Dump(IRDumpFlags_None, valueType);
- }
- void
- Sym::DumpSimple()
- {
- this->Dump(IRDumpFlags_SimpleForm);
- }
- #endif // DBG_DUMP
|