@@ -4592,35 +4592,14 @@ Inline::SplitConstructorCallCommon(
45924592}
45934593
45944594void
4595- Inline::InsertObjectCheck (IR::RegOpnd * funcOpnd, IR::Instr* insertBeforeInstr, IR::Instr*bailOutIfNotObject )
4595+ Inline::InsertFunctionObjectCheck (IR::RegOpnd * funcOpnd, IR::Instr * insertBeforeInstr, IR::Instr *bailOutInstr, const FunctionJITTimeInfo *funcInfo )
45964596{
4597- // Bailout if 'functionRegOpnd' is not an object.
4598- bailOutIfNotObject->SetSrc1 (funcOpnd);
4599- bailOutIfNotObject->SetByteCodeOffset (insertBeforeInstr);
4600- insertBeforeInstr->InsertBefore (bailOutIfNotObject);
4601- }
4597+ Js::BuiltinFunction index = Js::JavascriptLibrary::GetBuiltInForFuncInfo (funcInfo->GetLocalFunctionId ());
4598+ AssertMsg (index < Js::BuiltinFunction::Count, " Invalid built-in index on a call target marked as built-in" );
46024599
4603- void
4604- Inline::InsertFunctionTypeIdCheck (IR::RegOpnd * funcOpnd, IR::Instr* insertBeforeInstr, IR::Instr* bailOutIfNotJsFunction)
4605- {
4606- // functionTypeRegOpnd = Ld functionRegOpnd->type
4607- IR::IndirOpnd *functionTypeIndirOpnd = IR::IndirOpnd::New (funcOpnd, Js::RecyclableObject::GetOffsetOfType (), TyMachPtr, insertBeforeInstr->m_func );
4608- IR::RegOpnd *functionTypeRegOpnd = IR::RegOpnd::New (TyVar, this ->topFunc );
4609- IR::Instr *instr = IR::Instr::New (Js::OpCode::Ld_A, functionTypeRegOpnd, functionTypeIndirOpnd, insertBeforeInstr->m_func );
4610- if (instr->m_func ->HasByteCodeOffset ())
4611- {
4612- instr->SetByteCodeOffset (insertBeforeInstr);
4613- }
4614- insertBeforeInstr->InsertBefore (instr);
4615-
4616- CompileAssert (sizeof (Js::TypeId) == sizeof (int32));
4617- // if (functionTypeRegOpnd->typeId != TypeIds_Function) goto $noInlineLabel
4618- // BrNeq_I4 $noInlineLabel, functionTypeRegOpnd->typeId, TypeIds_Function
4619- IR::IndirOpnd *functionTypeIdIndirOpnd = IR::IndirOpnd::New (functionTypeRegOpnd, Js::Type::GetOffsetOfTypeId (), TyInt32, insertBeforeInstr->m_func );
4620- IR::IntConstOpnd *typeIdFunctionConstOpnd = IR::IntConstOpnd::New (Js::TypeIds_Function, TyInt32, insertBeforeInstr->m_func );
4621- bailOutIfNotJsFunction->SetSrc1 (functionTypeIdIndirOpnd);
4622- bailOutIfNotJsFunction->SetSrc2 (typeIdFunctionConstOpnd);
4623- insertBeforeInstr->InsertBefore (bailOutIfNotJsFunction);
4600+ bailOutInstr->SetSrc1 (funcOpnd);
4601+ bailOutInstr->SetSrc2 (IR::IntConstOpnd::New (index, TyInt32, insertBeforeInstr->m_func ));
4602+ insertBeforeInstr->InsertBefore (bailOutInstr);
46244603}
46254604
46264605void
@@ -4629,74 +4608,33 @@ Inline::InsertJsFunctionCheck(IR::Instr * callInstr, IR::Instr *insertBeforeInst
46294608 // This function only inserts bailout for tagged int & TypeIds_Function.
46304609 // As of now this is only used for polymorphic inlining.
46314610 Assert (bailOutKind == IR::BailOutOnPolymorphicInlineFunction);
4632-
46334611 Assert (insertBeforeInstr);
46344612 Assert (insertBeforeInstr->m_func == callInstr->m_func );
46354613
4636- IR::RegOpnd * funcOpnd = callInstr->GetSrc1 ()->AsRegOpnd ();
4637-
4638- // bailOutIfNotFunction is primary bailout instruction
4639- IR::Instr* bailOutIfNotFunction = IR::BailOutInstr::New (Js::OpCode::BailOnNotEqual, bailOutKind, insertBeforeInstr, callInstr->m_func );
4640-
4641- IR::Instr *bailOutIfNotObject = IR::BailOutInstr::New (Js::OpCode::BailOnNotObject, bailOutKind, bailOutIfNotFunction->GetBailOutInfo (), callInstr->m_func );
4642- InsertObjectCheck (funcOpnd, insertBeforeInstr, bailOutIfNotObject);
4643-
4644- InsertFunctionTypeIdCheck (funcOpnd, insertBeforeInstr, bailOutIfNotFunction);
4645-
4646- }
4647-
4648- void
4649- Inline::InsertFunctionInfoCheck (IR::RegOpnd * funcOpnd, IR::Instr *insertBeforeInstr, IR::Instr* bailoutInstr, const FunctionJITTimeInfo *funcInfo)
4650- {
4651- // if (VarTo<JavascriptFunction>(r1)->functionInfo != funcInfo) goto noInlineLabel
4652- // BrNeq_I4 noInlineLabel, r1->functionInfo, funcInfo
4653- IR::IndirOpnd* opndFuncInfo = IR::IndirOpnd::New (funcOpnd, Js::JavascriptFunction::GetOffsetOfFunctionInfo (), TyMachPtr, insertBeforeInstr->m_func );
4654- IR::AddrOpnd* inlinedFuncInfo = IR::AddrOpnd::New (funcInfo->GetFunctionInfoAddr (), IR::AddrOpndKindDynamicFunctionInfo, insertBeforeInstr->m_func );
4655- bailoutInstr->SetSrc1 (opndFuncInfo);
4656- bailoutInstr->SetSrc2 (inlinedFuncInfo);
4657-
4658- insertBeforeInstr->InsertBefore (bailoutInstr);
4659- }
4660-
4661- void
4662- Inline::InsertFunctionObjectCheck (IR::RegOpnd * funcOpnd, IR::Instr *insertBeforeInstr, IR::Instr *bailOutInstr, const FunctionJITTimeInfo *funcInfo)
4663- {
4664- Js::BuiltinFunction index = Js::JavascriptLibrary::GetBuiltInForFuncInfo (funcInfo->GetLocalFunctionId ());
4665- AssertMsg (index < Js::BuiltinFunction::Count, " Invalid built-in index on a call target marked as built-in" );
4666-
4667- bailOutInstr->SetSrc1 (funcOpnd);
4668- bailOutInstr->SetSrc2 (IR::IntConstOpnd::New (index, TyInt32, insertBeforeInstr->m_func ));
4669- insertBeforeInstr->InsertBefore (bailOutInstr);
4614+ // Two bailout checks, an object check followed by a function type ID check, are required. These bailout instructions are created
4615+ // when lowering checkFunctionEntryPoint rather than being created here as checkFunctionEntryPoint can be hoisted outside of a loop.
4616+ IR::Instr *checkIsFuncObj = IR::BailOutInstr::New (Js::OpCode::CheckIsFuncObj, bailOutKind, insertBeforeInstr, callInstr->m_func );
4617+ checkIsFuncObj->SetSrc1 (callInstr->GetSrc1 ()->AsRegOpnd ());
4618+ checkIsFuncObj->SetByteCodeOffset (insertBeforeInstr);
4619+ insertBeforeInstr->InsertBefore (checkIsFuncObj);
46704620}
46714621
46724622IR::Instr *
46734623Inline::PrepareInsertionPoint (IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, IR::Instr *insertBeforeInstr)
46744624{
46754625 Assert (insertBeforeInstr);
46764626 Assert (insertBeforeInstr->m_func == callInstr->m_func );
4677- IR::BailOutKind bailOutKind = IR::BailOutOnInlineFunction;
4678-
4679- IR::RegOpnd * funcOpnd = callInstr->GetSrc1 ()->AsRegOpnd ();
46804627
4681- // FunctionBody check is the primary bailout instruction, create it first
4682- IR::BailOutInstr* primaryBailOutInstr = IR::BailOutInstr::New (Js::OpCode::BailOnNotEqual, bailOutKind, insertBeforeInstr, callInstr->m_func );
4683- primaryBailOutInstr->SetByteCodeOffset (insertBeforeInstr);
4628+ IR::Instr *checkFuncInfo = IR::BailOutInstr::New (Js::OpCode::CheckFuncInfo, IR::BailOutOnInlineFunction, insertBeforeInstr, callInstr->m_func );
4629+ checkFuncInfo->SetSrc1 (callInstr->GetSrc1 ()->AsRegOpnd ());
46844630
4685- // 1. Bailout if function object is not an object.
4686- IR::Instr *bailOutIfNotObject = IR::BailOutInstr::New (Js::OpCode::BailOnNotObject,
4687- bailOutKind,
4688- primaryBailOutInstr->GetBailOutInfo (),
4689- callInstr->m_func );
4690- InsertObjectCheck (funcOpnd, insertBeforeInstr, bailOutIfNotObject);
4691-
4692- // 2. Bailout if function object is not a TypeId_Function
4693- IR::Instr* bailOutIfNotJsFunction = IR::BailOutInstr::New (Js::OpCode::BailOnNotEqual, bailOutKind, primaryBailOutInstr->GetBailOutInfo (), callInstr->m_func );
4694- InsertFunctionTypeIdCheck (funcOpnd, insertBeforeInstr, bailOutIfNotJsFunction);
4631+ IR::AddrOpnd* inlinedFuncInfo = IR::AddrOpnd::New (funcInfo->GetFunctionInfoAddr (), IR::AddrOpndKindDynamicFunctionInfo, insertBeforeInstr->m_func );
4632+ checkFuncInfo->SetSrc2 (inlinedFuncInfo);
46954633
4696- // 3. Bailout if function body doesn't match funcInfo
4697- InsertFunctionInfoCheck (funcOpnd, insertBeforeInstr, primaryBailOutInstr, funcInfo );
4634+ checkFuncInfo-> SetByteCodeOffset (insertBeforeInstr);
4635+ insertBeforeInstr-> InsertBefore (checkFuncInfo );
46984636
4699- return primaryBailOutInstr ;
4637+ return checkFuncInfo ;
47004638}
47014639
47024640IR::ByteCodeUsesInstr*
0 commit comments