@@ -4592,35 +4592,14 @@ Inline::SplitConstructorCallCommon(
4592
4592
}
4593
4593
4594
4594
void
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 )
4596
4596
{
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" );
4602
4599
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);
4624
4603
}
4625
4604
4626
4605
void
@@ -4629,74 +4608,33 @@ Inline::InsertJsFunctionCheck(IR::Instr * callInstr, IR::Instr *insertBeforeInst
4629
4608
// This function only inserts bailout for tagged int & TypeIds_Function.
4630
4609
// As of now this is only used for polymorphic inlining.
4631
4610
Assert (bailOutKind == IR::BailOutOnPolymorphicInlineFunction);
4632
-
4633
4611
Assert (insertBeforeInstr);
4634
4612
Assert (insertBeforeInstr->m_func == callInstr->m_func );
4635
4613
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);
4670
4620
}
4671
4621
4672
4622
IR::Instr *
4673
4623
Inline::PrepareInsertionPoint (IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, IR::Instr *insertBeforeInstr)
4674
4624
{
4675
4625
Assert (insertBeforeInstr);
4676
4626
Assert (insertBeforeInstr->m_func == callInstr->m_func );
4677
- IR::BailOutKind bailOutKind = IR::BailOutOnInlineFunction;
4678
-
4679
- IR::RegOpnd * funcOpnd = callInstr->GetSrc1 ()->AsRegOpnd ();
4680
4627
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 ());
4684
4630
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);
4695
4633
4696
- // 3. Bailout if function body doesn't match funcInfo
4697
- InsertFunctionInfoCheck (funcOpnd, insertBeforeInstr, primaryBailOutInstr, funcInfo );
4634
+ checkFuncInfo-> SetByteCodeOffset (insertBeforeInstr);
4635
+ insertBeforeInstr-> InsertBefore (checkFuncInfo );
4698
4636
4699
- return primaryBailOutInstr ;
4637
+ return checkFuncInfo ;
4700
4638
}
4701
4639
4702
4640
IR::ByteCodeUsesInstr*
0 commit comments