@@ -110,9 +110,11 @@ class CompilerContext {
110110 .first ->second ;
111111 }
112112 virtual bool loopIsLocal () { return !loops.empty (); }
113+ virtual bool isPromiseContext () { return false ; }
113114 };
114115
115116 class PromiseContext : public CodeContext {
117+
116118 public:
117119 PromiseContext (SEXP ast, FunctionWriter& fun, CodeContext* p)
118120 : CodeContext(ast, fun, p) {}
@@ -123,6 +125,8 @@ class CompilerContext {
123125 }
124126 return true ;
125127 }
128+
129+ bool isPromiseContext () override { return true ; }
126130 };
127131
128132 std::stack<CodeContext*> code;
@@ -163,13 +167,19 @@ class CompilerContext {
163167 new CodeContext (ast, fun, code.empty () ? nullptr : code.top ()));
164168 }
165169
170+ bool isInPromise () { return pushedPromiseContexts > 0 ; }
171+
166172 void pushPromiseContext (SEXP ast) {
173+ pushedPromiseContexts++;
174+
167175 code.push (
168176 new PromiseContext (ast, fun, code.empty () ? nullptr : code.top ()));
169177 }
170178
171179 Code* pop () {
172180 Code* res = cs ().finalize (0 , code.top ()->loadsSlotInCache .size ());
181+ if (code.top ()->isPromiseContext ())
182+ pushedPromiseContexts--;
173183 delete code.top ();
174184 code.pop ();
175185 return res;
@@ -184,6 +194,9 @@ class CompilerContext {
184194 << BC::push (R_FalseValue) << BC::push (Rf_mkString (msg))
185195 << BC::callBuiltin (4 , ast, getBuiltinFun (" warning" )) << BC::pop ();
186196 }
197+
198+ private:
199+ unsigned int pushedPromiseContexts = 0 ;
187200};
188201
189202struct LoadArgsResult {
@@ -1751,19 +1764,55 @@ static LoadArgsResult compileLoadArgs(CompilerContext& ctx, SEXP ast, SEXP fun,
17511764 return res;
17521765}
17531766
1767+
17541768// function application
17551769void compileCall (CompilerContext& ctx, SEXP ast, SEXP fun, SEXP args,
17561770 bool voidContext) {
1771+
17571772 CodeStream& cs = ctx.cs ();
17581773
17591774 // application has the form:
17601775 // LHS ( ARGS )
17611776
17621777 // LHS can either be an identifier or an expression
1778+ bool speculateOnBuiltin = false ;
1779+ BC::Label eager = 0 ;
1780+ BC::Label theEnd = 0 ;
1781+
17631782 if (TYPEOF (fun) == SYMSXP) {
17641783 if (compileSpecialCall (ctx, ast, fun, args, voidContext))
17651784 return ;
17661785
1786+ if (!ctx.isInPromise ()) {
1787+
1788+ auto callHasDots = false ;
1789+ for (RListIter arg = RList (args).begin (); arg != RList::end ();
1790+ ++arg) {
1791+
1792+ if (*arg == R_DotsSymbol) {
1793+ callHasDots = true ;
1794+ break ;
1795+ }
1796+ }
1797+
1798+ if (!callHasDots) {
1799+ auto builtin = Rf_findVar (fun, R_BaseEnv);
1800+ auto likelyBuiltin = TYPEOF (builtin) == BUILTINSXP;
1801+ speculateOnBuiltin = likelyBuiltin;
1802+
1803+ if (speculateOnBuiltin) {
1804+
1805+ eager = cs.mkLabel ();
1806+ theEnd = cs.mkLabel ();
1807+ cs << BC::push (builtin) << BC::dup ()
1808+ << BC::ldvarNoForce (fun) << BC::identicalNoforce ()
1809+ << BC::recordTest () << BC::brtrue (eager);
1810+
1811+ cs << BC::pop ();
1812+ }
1813+ }
1814+ }
1815+
17671816 cs << BC::ldfun (fun);
17681817 } else {
17691818 compileExpr (ctx, fun);
@@ -1773,22 +1822,37 @@ void compileCall(CompilerContext& ctx, SEXP ast, SEXP fun, SEXP args,
17731822 if (Compiler::profile)
17741823 cs << BC::recordCall ();
17751824
1825+ auto compileCall = [&](LoadArgsResult& info) {
1826+ if (info.hasDots ) {
1827+ cs << BC::callDots (info.numArgs , info.names , ast, info.assumptions );
1828+ } else if (info.hasNames ) {
1829+ cs << BC::call (info.numArgs , info.names , ast, info.assumptions );
1830+ } else {
1831+ info.assumptions .add (Assumption::CorrectOrderOfArguments);
1832+ cs << BC::call (info.numArgs , ast, info.assumptions );
1833+ }
1834+ };
1835+
17761836 LoadArgsResult info;
17771837 if (fun == symbol::forceAndCall) {
17781838 // First arg certainly eager
17791839 info = compileLoadArgs (ctx, ast, fun, args, voidContext, 0 , 2 );
17801840 } else {
17811841 info = compileLoadArgs (ctx, ast, fun, args, voidContext);
17821842 }
1843+ compileCall (info);
17831844
1784- if (info.hasDots ) {
1785- cs << BC::callDots (info.numArgs , info.names , ast, info.assumptions );
1786- } else if (info.hasNames ) {
1787- cs << BC::call (info.numArgs , info.names , ast, info.assumptions );
1788- } else {
1789- info.assumptions .add (Assumption::CorrectOrderOfArguments);
1790- cs << BC::call (info.numArgs , ast, info.assumptions );
1845+ if (speculateOnBuiltin) {
1846+ cs << BC::br (theEnd) << eager;
1847+
1848+ auto infoEager = compileLoadArgs (ctx, ast, fun, args, voidContext, 0 ,
1849+ RList (args).length ());
1850+
1851+ compileCall (infoEager);
1852+
1853+ cs << theEnd;
17911854 }
1855+
17921856 if (voidContext)
17931857 cs << BC::pop ();
17941858 else if (Compiler::profile)
0 commit comments