@@ -347,11 +347,53 @@ class IREmitterImpl : public IREmitter {
347347 llvm::BasicBlock*& curblock;
348348 IRGenerator* irgenerator;
349349
350+ void emitPendingCallsCheck (llvm::BasicBlock* exc_dest) {
351+ auto && builder = *getBuilder ();
352+
353+ llvm::GlobalVariable* pendingcalls_to_do_gv = g.cur_module ->getGlobalVariable (" _pendingcalls_to_do" );
354+ if (!pendingcalls_to_do_gv) {
355+ static_assert (sizeof (_pendingcalls_to_do) == 4 , " " );
356+ pendingcalls_to_do_gv = new llvm::GlobalVariable (
357+ *g.cur_module , g.i32 , false , llvm::GlobalValue::ExternalLinkage, 0 , " _pendingcalls_to_do" );
358+ pendingcalls_to_do_gv->setAlignment (4 );
359+ }
360+
361+ llvm::BasicBlock* cur_block = builder.GetInsertBlock ();
362+
363+ llvm::BasicBlock* pendingcalls_set = createBasicBlock (" _pendingcalls_set" );
364+ pendingcalls_set->moveAfter (cur_block);
365+ llvm::BasicBlock* join_block = createBasicBlock (" continue_after_pendingcalls_check" );
366+ join_block->moveAfter (pendingcalls_set);
367+
368+ llvm::Value* pendingcalls_to_do_val = builder.CreateLoad (pendingcalls_to_do_gv, true /* volatile */ );
369+ llvm::Value* is_zero
370+ = builder.CreateICmpEQ (pendingcalls_to_do_val, getConstantInt (0 , pendingcalls_to_do_val->getType ()));
371+
372+ llvm::Metadata* md_vals[]
373+ = { llvm::MDString::get (g.context , " branch_weights" ), llvm::ConstantAsMetadata::get (getConstantInt (1000 )),
374+ llvm::ConstantAsMetadata::get (getConstantInt (1 )) };
375+ llvm::MDNode* branch_weights = llvm::MDNode::get (g.context , llvm::ArrayRef<llvm::Metadata*>(md_vals));
376+
377+
378+ builder.CreateCondBr (is_zero, join_block, pendingcalls_set, branch_weights);
379+ {
380+ setCurrentBasicBlock (pendingcalls_set);
381+
382+ if (exc_dest) {
383+ builder.CreateInvoke (g.funcs .makePendingCalls , join_block, exc_dest);
384+ } else {
385+ builder.CreateCall (g.funcs .makePendingCalls );
386+ builder.CreateBr (join_block);
387+ }
388+ }
389+
390+ cur_block = join_block;
391+ setCurrentBasicBlock (join_block);
392+ }
393+
350394 llvm::CallSite emitCall (const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
351395 ExceptionStyle target_exception_style) {
352- llvm::Value* stmt = unw_info.current_stmt ? embedRelocatablePtr (unw_info.current_stmt , g.llvm_aststmt_type_ptr )
353- : getNullPtr (g.llvm_aststmt_type_ptr );
354- getBuilder ()->CreateStore (stmt, irstate->getStmtVar ());
396+ emitSetCurrentStmt (unw_info.current_stmt );
355397
356398 if (target_exception_style == CXX && (unw_info.hasHandler () || irstate->getExceptionStyle () == CAPI)) {
357399 // Create the invoke:
@@ -375,9 +417,13 @@ class IREmitterImpl : public IREmitter {
375417 // Normal case:
376418 getBuilder ()->SetInsertPoint (normal_dest);
377419 curblock = normal_dest;
420+ emitPendingCallsCheck (exc_dest);
378421 return rtn;
379422 } else {
423+
380424 llvm::CallInst* cs = getBuilder ()->CreateCall (callee, args);
425+ if (target_exception_style == CXX)
426+ emitPendingCallsCheck (NULL );
381427 return cs;
382428 }
383429 }
@@ -479,6 +525,15 @@ class IREmitterImpl : public IREmitter {
479525 return llvm::BasicBlock::Create (g.context , name, irstate->getLLVMFunction ());
480526 }
481527
528+ // Our current frame introspection approach requires that we update the currently executed stmt before doing a call
529+ // to a function which could throw an exception, inspect the python call frame,...
530+ // Only patchpoint don't need to set the current statement because the stmt will be inluded in the stackmap args.
531+ void emitSetCurrentStmt (AST_stmt* stmt) {
532+ getBuilder ()->CreateStore (stmt ? embedRelocatablePtr (stmt, g.llvm_aststmt_type_ptr )
533+ : getNullPtr (g.llvm_aststmt_type_ptr ),
534+ irstate->getStmtVar ());
535+ }
536+
482537 llvm::Value* createCall (const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
483538 ExceptionStyle target_exception_style = CXX) override {
484539#ifndef NDEBUG
@@ -2137,7 +2192,7 @@ class IRGeneratorImpl : public IRGenerator {
21372192
21382193 // Don't call deinitFrame when this is a OSR function because the interpreter will call it
21392194 if (!irstate->getCurFunction ()->entry_descriptor )
2140- emitter.createCall (unw_info, g.funcs .deinitFrame , irstate->getFrameInfoVar ());
2195+ emitter.getBuilder ()-> CreateCall ( g.funcs .deinitFrame , irstate->getFrameInfoVar ());
21412196
21422197 for (auto & p : symbol_table) {
21432198 p.second ->decvref (emitter);
@@ -2878,9 +2933,10 @@ class IRGeneratorImpl : public IRGenerator {
28782933 }
28792934
28802935 void doSafePoint (AST_stmt* next_statement) override {
2881- // Unwind info is always needed in allowGLReadPreemption if it has any chance of
2882- // running arbitrary code like finalizers.
2883- emitter.createCall (UnwindInfo (next_statement, NULL ), g.funcs .allowGLReadPreemption );
2936+ // We need to setup frame introspection by updating the current stmt because we can run can run arbitrary code
2937+ // like finalizers inside allowGLReadPreemption.
2938+ emitter.emitSetCurrentStmt (next_statement);
2939+ emitter.getBuilder ()->CreateCall (g.funcs .allowGLReadPreemption );
28842940 }
28852941
28862942 // Create a (or reuse an existing) block that will catch a CAPI exception, and then forward
@@ -2902,16 +2958,17 @@ class IRGeneratorImpl : public IRGenerator {
29022958 assert (!phi_node);
29032959 phi_node = emitter.getBuilder ()->CreatePHI (g.llvm_aststmt_type_ptr , 0 );
29042960
2905- emitter.createCall (UnwindInfo (current_stmt, NULL ), g.funcs .caughtCapiException ,
2906- { phi_node, embedRelocatablePtr (irstate->getSourceInfo (), g.i8_ptr ) });
2961+ emitter.emitSetCurrentStmt (current_stmt);
2962+ emitter.getBuilder ()->CreateCall (g.funcs .caughtCapiException ,
2963+ { phi_node, embedRelocatablePtr (irstate->getSourceInfo (), g.i8_ptr ) });
29072964
29082965 if (!final_dest) {
29092966 // Propagate the exception out of the function:
29102967 if (irstate->getExceptionStyle () == CXX) {
29112968 emitter.getBuilder ()->CreateCall (g.funcs .reraiseCapiExcAsCxx );
29122969 emitter.getBuilder ()->CreateUnreachable ();
29132970 } else {
2914- emitter.createCall ( UnwindInfo (current_stmt, NULL ), g.funcs .deinitFrame , irstate->getFrameInfoVar ());
2971+ emitter.getBuilder ()-> CreateCall ( g.funcs .deinitFrame , irstate->getFrameInfoVar ());
29152972 emitter.getBuilder ()->CreateRet (getNullPtr (g.llvm_value_type_ptr ));
29162973 }
29172974 } else {
0 commit comments