@@ -4443,35 +4443,14 @@ Inline::SplitConstructorCallCommon(
4443
4443
}
4444
4444
4445
4445
void
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 )
4447
4447
{
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" );
4453
4450
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);
4475
4454
}
4476
4455
4477
4456
void
@@ -4480,74 +4459,33 @@ Inline::InsertJsFunctionCheck(IR::Instr * callInstr, IR::Instr *insertBeforeInst
4480
4459
// This function only inserts bailout for tagged int & TypeIds_Function.
4481
4460
// As of now this is only used for polymorphic inlining.
4482
4461
Assert (bailOutKind == IR::BailOutOnPolymorphicInlineFunction);
4483
-
4484
4462
Assert (insertBeforeInstr);
4485
4463
Assert (insertBeforeInstr->m_func == callInstr->m_func );
4486
4464
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);
4521
4471
}
4522
4472
4523
4473
IR::Instr *
4524
4474
Inline::PrepareInsertionPoint (IR::Instr *callInstr, const FunctionJITTimeInfo *funcInfo, IR::Instr *insertBeforeInstr)
4525
4475
{
4526
4476
Assert (insertBeforeInstr);
4527
4477
Assert (insertBeforeInstr->m_func == callInstr->m_func );
4528
- IR::BailOutKind bailOutKind = IR::BailOutOnInlineFunction;
4529
-
4530
- IR::RegOpnd * funcOpnd = callInstr->GetSrc1 ()->AsRegOpnd ();
4531
4478
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 ());
4535
4481
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);
4546
4484
4547
- // 3. Bailout if function body doesn't match funcInfo
4548
- InsertFunctionInfoCheck (funcOpnd, insertBeforeInstr, primaryBailOutInstr, funcInfo );
4485
+ checkFuncInfo-> SetByteCodeOffset (insertBeforeInstr);
4486
+ insertBeforeInstr-> InsertBefore (checkFuncInfo );
4549
4487
4550
- return primaryBailOutInstr ;
4488
+ return checkFuncInfo ;
4551
4489
}
4552
4490
4553
4491
IR::ByteCodeUsesInstr*
0 commit comments