@@ -4443,35 +4443,14 @@ Inline::SplitConstructorCallCommon(
44434443}
44444444
44454445void
4446- Inline::InsertObjectCheck (IR::RegOpnd * funcOpnd, IR::Instr* insertBeforeInstr, IR::Instr*bailOutIfNotObject )
4446+ Inline::InsertFunctionObjectCheck (IR::RegOpnd * funcOpnd, IR::Instr * insertBeforeInstr, IR::Instr *bailOutInstr, const FunctionJITTimeInfo *funcInfo )
44474447{
4448- // Bailout if 'functionRegOpnd' is not an object.
4449- bailOutIfNotObject->SetSrc1 (funcOpnd);
4450- bailOutIfNotObject->SetByteCodeOffset (insertBeforeInstr);
4451- insertBeforeInstr->InsertBefore (bailOutIfNotObject);
4452- }
4448+ Js::BuiltinFunction index = Js::JavascriptLibrary::GetBuiltInForFuncInfo (funcInfo->GetLocalFunctionId ());
4449+ AssertMsg (index < Js::BuiltinFunction::Count, " Invalid built-in index on a call target marked as built-in" );
44534450
4454- void
4455- Inline::InsertFunctionTypeIdCheck (IR::RegOpnd * funcOpnd, IR::Instr* insertBeforeInstr, IR::Instr* bailOutIfNotJsFunction)
4456- {
4457- // functionTypeRegOpnd = Ld functionRegOpnd->type
4458- IR::IndirOpnd *functionTypeIndirOpnd = IR::IndirOpnd::New (funcOpnd, Js::RecyclableObject::GetOffsetOfType (), TyMachPtr, insertBeforeInstr->m_func );
4459- IR::RegOpnd *functionTypeRegOpnd = IR::RegOpnd::New (TyVar, this ->topFunc );
4460- IR::Instr *instr = IR::Instr::New (Js::OpCode::Ld_A, functionTypeRegOpnd, functionTypeIndirOpnd, insertBeforeInstr->m_func );
4461- if (instr->m_func ->HasByteCodeOffset ())
4462- {
4463- instr->SetByteCodeOffset (insertBeforeInstr);
4464- }
4465- insertBeforeInstr->InsertBefore (instr);
4466-
4467- CompileAssert (sizeof (Js::TypeId) == sizeof (int32));
4468- // if (functionTypeRegOpnd->typeId != TypeIds_Function) goto $noInlineLabel
4469- // BrNeq_I4 $noInlineLabel, functionTypeRegOpnd->typeId, TypeIds_Function
4470- IR::IndirOpnd *functionTypeIdIndirOpnd = IR::IndirOpnd::New (functionTypeRegOpnd, Js::Type::GetOffsetOfTypeId (), TyInt32, insertBeforeInstr->m_func );
4471- IR::IntConstOpnd *typeIdFunctionConstOpnd = IR::IntConstOpnd::New (Js::TypeIds_Function, TyInt32, insertBeforeInstr->m_func );
4472- bailOutIfNotJsFunction->SetSrc1 (functionTypeIdIndirOpnd);
4473- bailOutIfNotJsFunction->SetSrc2 (typeIdFunctionConstOpnd);
4474- insertBeforeInstr->InsertBefore (bailOutIfNotJsFunction);
4451+ bailOutInstr->SetSrc1 (funcOpnd);
4452+ bailOutInstr->SetSrc2 (IR::IntConstOpnd::New (index, TyInt32, insertBeforeInstr->m_func ));
4453+ insertBeforeInstr->InsertBefore (bailOutInstr);
44754454}
44764455
44774456void
@@ -4480,74 +4459,33 @@ Inline::InsertJsFunctionCheck(IR::Instr * callInstr, IR::Instr *insertBeforeInst
44804459 // This function only inserts bailout for tagged int & TypeIds_Function.
44814460 // As of now this is only used for polymorphic inlining.
44824461 Assert (bailOutKind == IR::BailOutOnPolymorphicInlineFunction);
4483-
44844462 Assert (insertBeforeInstr);
44854463 Assert (insertBeforeInstr->m_func == callInstr->m_func );
44864464
4487- IR::RegOpnd * funcOpnd = callInstr->GetSrc1 ()->AsRegOpnd ();
4488-
4489- // bailOutIfNotFunction is primary bailout instruction
4490- IR::Instr* bailOutIfNotFunction = IR::BailOutInstr::New (Js::OpCode::BailOnNotEqual, bailOutKind, insertBeforeInstr, callInstr->m_func );
4491-
4492- IR::Instr *bailOutIfNotObject = IR::BailOutInstr::New (Js::OpCode::BailOnNotObject, bailOutKind, bailOutIfNotFunction->GetBailOutInfo (), callInstr->m_func );
4493- InsertObjectCheck (funcOpnd, insertBeforeInstr, bailOutIfNotObject);
4494-
4495- InsertFunctionTypeIdCheck (funcOpnd, insertBeforeInstr, bailOutIfNotFunction);
4496-
4497- }
4498-
4499- void
4500- Inline::InsertFunctionInfoCheck (IR::RegOpnd * funcOpnd, IR::Instr *insertBeforeInstr, IR::Instr* bailoutInstr, const FunctionJITTimeInfo *funcInfo)
4501- {
4502- // if (VarTo<JavascriptFunction>(r1)->functionInfo != funcInfo) goto noInlineLabel
4503- // BrNeq_I4 noInlineLabel, r1->functionInfo, funcInfo
4504- IR::IndirOpnd* opndFuncInfo = IR::IndirOpnd::New (funcOpnd, Js::JavascriptFunction::GetOffsetOfFunctionInfo (), TyMachPtr, insertBeforeInstr->m_func );
4505- IR::AddrOpnd* inlinedFuncInfo = IR::AddrOpnd::New (funcInfo->GetFunctionInfoAddr (), IR::AddrOpndKindDynamicFunctionInfo, insertBeforeInstr->m_func );
4506- bailoutInstr->SetSrc1 (opndFuncInfo);
4507- bailoutInstr->SetSrc2 (inlinedFuncInfo);
4508-
4509- insertBeforeInstr->InsertBefore (bailoutInstr);
4510- }
4511-
4512- void
4513- Inline::InsertFunctionObjectCheck (IR::RegOpnd * funcOpnd, IR::Instr *insertBeforeInstr, IR::Instr *bailOutInstr, const FunctionJITTimeInfo *funcInfo)
4514- {
4515- Js::BuiltinFunction index = Js::JavascriptLibrary::GetBuiltInForFuncInfo (funcInfo->GetLocalFunctionId ());
4516- AssertMsg (index < Js::BuiltinFunction::Count, " Invalid built-in index on a call target marked as built-in" );
4517-
4518- bailOutInstr->SetSrc1 (funcOpnd);
4519- bailOutInstr->SetSrc2 (IR::IntConstOpnd::New (index, TyInt32, insertBeforeInstr->m_func ));
4520- insertBeforeInstr->InsertBefore (bailOutInstr);
4465+ // Two bailout checks, an object check followed by a function type ID check, are required. These bailout instructions are created
4466+ // when lowering checkFunctionEntryPoint rather than being created here as checkFunctionEntryPoint can be hoisted outside of a loop.
4467+ IR::Instr *checkIsFuncObj = IR::BailOutInstr::New (Js::OpCode::CheckIsFuncObj, bailOutKind, insertBeforeInstr, callInstr->m_func );
4468+ checkIsFuncObj->SetSrc1 (callInstr->GetSrc1 ()->AsRegOpnd ());
4469+ checkIsFuncObj->SetByteCodeOffset (insertBeforeInstr);
4470+ insertBeforeInstr->InsertBefore (checkIsFuncObj);
45214471}
45224472
45234473IR::Instr *
45244474Inline::PrepareInsertionPoint (IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, IR::Instr *insertBeforeInstr)
45254475{
45264476 Assert (insertBeforeInstr);
45274477 Assert (insertBeforeInstr->m_func == callInstr->m_func );
4528- IR::BailOutKind bailOutKind = IR::BailOutOnInlineFunction;
4529-
4530- IR::RegOpnd * funcOpnd = callInstr->GetSrc1 ()->AsRegOpnd ();
45314478
4532- // FunctionBody check is the primary bailout instruction, create it first
4533- IR::BailOutInstr* primaryBailOutInstr = IR::BailOutInstr::New (Js::OpCode::BailOnNotEqual, bailOutKind, insertBeforeInstr, callInstr->m_func );
4534- primaryBailOutInstr->SetByteCodeOffset (insertBeforeInstr);
4479+ IR::Instr *checkFuncInfo = IR::BailOutInstr::New (Js::OpCode::CheckFuncInfo, IR::BailOutOnInlineFunction, insertBeforeInstr, callInstr->m_func );
4480+ checkFuncInfo->SetSrc1 (callInstr->GetSrc1 ()->AsRegOpnd ());
45354481
4536- // 1. Bailout if function object is not an object.
4537- IR::Instr *bailOutIfNotObject = IR::BailOutInstr::New (Js::OpCode::BailOnNotObject,
4538- bailOutKind,
4539- primaryBailOutInstr->GetBailOutInfo (),
4540- callInstr->m_func );
4541- InsertObjectCheck (funcOpnd, insertBeforeInstr, bailOutIfNotObject);
4542-
4543- // 2. Bailout if function object is not a TypeId_Function
4544- IR::Instr* bailOutIfNotJsFunction = IR::BailOutInstr::New (Js::OpCode::BailOnNotEqual, bailOutKind, primaryBailOutInstr->GetBailOutInfo (), callInstr->m_func );
4545- InsertFunctionTypeIdCheck (funcOpnd, insertBeforeInstr, bailOutIfNotJsFunction);
4482+ IR::AddrOpnd* inlinedFuncInfo = IR::AddrOpnd::New (funcInfo->GetFunctionInfoAddr (), IR::AddrOpndKindDynamicFunctionInfo, insertBeforeInstr->m_func );
4483+ checkFuncInfo->SetSrc2 (inlinedFuncInfo);
45464484
4547- // 3. Bailout if function body doesn't match funcInfo
4548- InsertFunctionInfoCheck (funcOpnd, insertBeforeInstr, primaryBailOutInstr, funcInfo );
4485+ checkFuncInfo-> SetByteCodeOffset (insertBeforeInstr);
4486+ insertBeforeInstr-> InsertBefore (checkFuncInfo );
45494487
4550- return primaryBailOutInstr ;
4488+ return checkFuncInfo ;
45514489}
45524490
45534491IR::ByteCodeUsesInstr*
0 commit comments