PageRenderTime 46ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/Languages/IronPython/Scripts/generate_calls.py

http://github.com/IronLanguages/main
Python | 607 lines | 585 code | 8 blank | 14 comment | 6 complexity | f6bc858f6065743f52f3a4666e858b52 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. #####################################################################################
  2. #
  3. # Copyright (c) Microsoft Corporation. All rights reserved.
  4. #
  5. # This source code is subject to terms and conditions of the Apache License, Version 2.0. A
  6. # copy of the license can be found in the License.html file at the root of this distribution. If
  7. # you cannot locate the Apache License, Version 2.0, please send an email to
  8. # ironpy@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
  9. # by the terms of the Apache License, Version 2.0.
  10. #
  11. # You must not remove this notice, or any other, from this software.
  12. #
  13. #
  14. #####################################################################################
  15. import sys
  16. from generate import generate
  17. MAX_ARGS = 16
  18. def make_params(nargs, *prefix):
  19. params = ["object arg%d" % i for i in range(nargs)]
  20. return ", ".join(list(prefix) + params)
  21. def make_params1(nargs, prefix=("CodeContext context",)):
  22. params = ["object arg%d" % i for i in range(nargs)]
  23. return ", ".join(list(prefix) + params)
  24. def make_args(nargs, *prefix):
  25. params = ["arg%d" % i for i in range(nargs)]
  26. return ", ".join(list(prefix) + params)
  27. def make_args1(nargs, prefix, start=0):
  28. args = ["arg%d" % i for i in range(start, nargs)]
  29. return ", ".join(list(prefix) + args)
  30. def make_calltarget_type_args(nargs):
  31. return ', '.join(['PythonFunction'] + ['object'] * (nargs + 1))
  32. def gen_args_comma(nparams, comma):
  33. args = ""
  34. for i in xrange(nparams):
  35. args = args + comma + ("object arg%d" % i)
  36. comma = ", "
  37. return args
  38. def gen_args(nparams):
  39. return gen_args_comma(nparams, "")
  40. def gen_args_call(nparams, *prefix):
  41. args = ""
  42. comma = ""
  43. for i in xrange(nparams):
  44. args = args + comma +("arg%d" % i)
  45. comma = ", "
  46. if prefix:
  47. if args:
  48. args = prefix[0] + ', ' + args
  49. else:
  50. args = prefix[0]
  51. return args
  52. def gen_args_array(nparams):
  53. args = gen_args_call(nparams)
  54. if args: return "{ " + args + " }"
  55. else: return "{ }"
  56. def gen_callargs(nparams):
  57. args = ""
  58. comma = ""
  59. for i in xrange(nparams):
  60. args = args + comma + ("callArgs[%d]" % i)
  61. comma = ","
  62. return args
  63. def gen_args_paramscall(nparams):
  64. args = ""
  65. comma = ""
  66. for i in xrange(nparams):
  67. args = args + comma + ("args[%d]" % i)
  68. comma = ","
  69. return args
  70. method_caller_template = """
  71. class MethodBinding<%(typeParams)s> : BaseMethodBinding {
  72. private CallSite<Func<CallSite, CodeContext, object, object, %(typeParams)s, object>> _site;
  73. public MethodBinding(PythonInvokeBinder binder) {
  74. _site = CallSite<Func<CallSite, CodeContext, object, object, %(typeParams)s, object>>.Create(binder);
  75. }
  76. public object SelfTarget(CallSite site, CodeContext context, object target, %(callParams)s) {
  77. Method self = target as Method;
  78. if (self != null && self._inst != null) {
  79. return _site.Target(_site, context, self._func, self._inst, %(callArgs)s);
  80. }
  81. return ((CallSite<Func<CallSite, CodeContext, object, %(typeParams)s, object>>)site).Update(site, context, target, %(callArgs)s);
  82. }
  83. public object SelflessTarget(CallSite site, CodeContext context, object target, object arg0, %(callParamsSelfless)s) {
  84. Method self = target as Method;
  85. if (self != null && self._inst == null) {
  86. return _site.Target(_site, context, self._func, PythonOps.MethodCheckSelf(context, self, arg0), %(callArgsSelfless)s);
  87. }
  88. return ((CallSite<Func<CallSite, CodeContext, object, object, %(typeParams)s, object>>)site).Update(site, context, target, arg0, %(callArgsSelfless)s);
  89. }
  90. public override Delegate GetSelfTarget() {
  91. return new Func<CallSite, CodeContext, object, %(typeParams)s, object>(SelfTarget);
  92. }
  93. public override Delegate GetSelflessTarget() {
  94. return new Func<CallSite, CodeContext, object, object, %(typeParams)s, object>(SelflessTarget);
  95. }
  96. }"""
  97. def method_callers(cw):
  98. for nparams in range(1, MAX_ARGS-3):
  99. cw.write(method_caller_template % {
  100. 'typeParams' : ', '.join(('T%d' % d for d in xrange(nparams))),
  101. 'callParams': ', '.join(('T%d arg%d' % (d,d) for d in xrange(nparams))),
  102. 'callParamsSelfless': ', '.join(('T%d arg%d' % (d,d+1) for d in xrange(nparams))),
  103. 'callArgsSelfless' : ', '.join(('arg%d' % (d+1) for d in xrange(nparams))),
  104. 'argCount' : nparams,
  105. 'callArgs': ', '.join(('arg%d' % d for d in xrange(nparams))),
  106. 'genFuncArgs' : make_calltarget_type_args(nparams),
  107. })
  108. def selfless_method_caller_switch(cw):
  109. cw.enter_block('switch (typeArgs.Length)')
  110. for i in range(1, MAX_ARGS-3):
  111. cw.write('case %d: binding = (BaseMethodBinding)Activator.CreateInstance(typeof(MethodBinding<%s>).MakeGenericType(typeArgs), binder); break;' % (i, ',' * (i-1)))
  112. cw.exit_block()
  113. function_caller_template = """
  114. public sealed class FunctionCaller<%(typeParams)s> : FunctionCaller {
  115. public FunctionCaller(int compat) : base(compat) { }
  116. public object Call%(argCount)d(CallSite site, CodeContext context, object func, %(callParams)s) {
  117. PythonFunction pyfunc = func as PythonFunction;
  118. if (pyfunc != null && pyfunc._compat == _compat) {
  119. return ((Func<%(genFuncArgs)s>)pyfunc.func_code.Target)(pyfunc, %(callArgs)s);
  120. }
  121. return ((CallSite<Func<CallSite, CodeContext, object, %(typeParams)s, object>>)site).Update(site, context, func, %(callArgs)s);
  122. }"""
  123. defaults_template = """
  124. public object Default%(defaultCount)dCall%(argCount)d(CallSite site, CodeContext context, object func, %(callParams)s) {
  125. PythonFunction pyfunc = func as PythonFunction;
  126. if (pyfunc != null && pyfunc._compat == _compat) {
  127. int defaultIndex = pyfunc.Defaults.Length - pyfunc.NormalArgumentCount + %(argCount)d;
  128. return ((Func<%(genFuncArgs)s>)pyfunc.func_code.Target)(pyfunc, %(callArgs)s, %(defaultArgs)s);
  129. }
  130. return ((CallSite<Func<CallSite, CodeContext, object, %(typeParams)s, object>>)site).Update(site, context, func, %(callArgs)s);
  131. }"""
  132. defaults_template_0 = """
  133. public object Default%(argCount)dCall0(CallSite site, CodeContext context, object func) {
  134. PythonFunction pyfunc = func as PythonFunction;
  135. if (pyfunc != null && pyfunc._compat == _compat) {
  136. int defaultIndex = pyfunc.Defaults.Length - pyfunc.NormalArgumentCount;
  137. return ((Func<%(genFuncArgs)s>)pyfunc.func_code.Target)(pyfunc, %(defaultArgs)s);
  138. }
  139. return ((CallSite<Func<CallSite, CodeContext, object, object>>)site).Update(site, context, func);
  140. }"""
  141. def function_callers(cw):
  142. cw.write('''class FunctionCallerProperties {
  143. internal const int MaxGeneratedFunctionArgs = %d;
  144. }''' % (MAX_ARGS-2))
  145. cw.write('')
  146. for nparams in range(1, MAX_ARGS-2):
  147. cw.write(function_caller_template % {
  148. 'typeParams' : ', '.join(('T%d' % d for d in xrange(nparams))),
  149. 'callParams': ', '.join(('T%d arg%d' % (d,d) for d in xrange(nparams))),
  150. 'argCount' : nparams,
  151. 'callArgs': ', '.join(('arg%d' % d for d in xrange(nparams))),
  152. 'genFuncArgs' : make_calltarget_type_args(nparams),
  153. })
  154. for i in xrange(nparams + 1, MAX_ARGS - 2):
  155. cw.write(defaults_template % {
  156. 'typeParams' : ', '.join(('T%d' % d for d in xrange(nparams))),
  157. 'callParams': ', '.join(('T%d arg%d' % (d,d) for d in xrange(nparams))),
  158. 'argCount' : nparams,
  159. 'totalParamCount' : i,
  160. 'callArgs': ', '.join(('arg%d' % d for d in xrange(nparams))),
  161. 'defaultCount' : i - nparams,
  162. 'defaultArgs' : ', '.join(('pyfunc.Defaults[defaultIndex + %d]' % curDefault for curDefault in xrange(i - nparams))),
  163. 'genFuncArgs' : make_calltarget_type_args(i),
  164. })
  165. cw.write('}')
  166. def function_callers_0(cw):
  167. for i in xrange(1, MAX_ARGS - 2):
  168. cw.write(defaults_template_0 % {
  169. 'argCount' : i,
  170. 'defaultArgs' : ', '.join(('pyfunc.Defaults[defaultIndex + %d]' % curDefault for curDefault in xrange(i))),
  171. 'genFuncArgs' : make_calltarget_type_args(i),
  172. })
  173. function_caller_switch_template = """case %(argCount)d:
  174. callerType = typeof(FunctionCaller<%(arity)s>).MakeGenericType(typeParams);
  175. mi = callerType.GetMethod(baseName + "Call%(argCount)d");
  176. Debug.Assert(mi != null);
  177. fc = GetFunctionCaller(callerType, funcCompat);
  178. funcType = typeof(Func<,,,,%(arity)s>).MakeGenericType(allParams);
  179. return new Binding.FastBindResult<T>((T)(object)mi.CreateDelegate(funcType, fc), true);"""
  180. def function_caller_switch(cw):
  181. for nparams in range(1, MAX_ARGS-2):
  182. cw.write(function_caller_switch_template % {
  183. 'arity' : ',' * (nparams - 1),
  184. 'argCount' : nparams,
  185. })
  186. def gen_lazy_call_targets(cw):
  187. for nparams in range(MAX_ARGS):
  188. cw.enter_block("public static object OriginalCallTarget%d(%s)" % (nparams, make_params(nparams, "PythonFunction function")))
  189. cw.write("function.func_code.LazyCompileFirstTarget(function);")
  190. cw.write("return ((Func<%s>)function.func_code.Target)(%s);" % (make_calltarget_type_args(nparams), gen_args_call(nparams, 'function')))
  191. cw.exit_block()
  192. cw.write('')
  193. def gen_recursion_checks(cw):
  194. for nparams in range(MAX_ARGS):
  195. cw.enter_block("internal class PythonFunctionRecursionCheck%d" % (nparams, ))
  196. cw.write("private readonly Func<%s> _target;" % (make_calltarget_type_args(nparams), ))
  197. cw.write('')
  198. cw.enter_block('public PythonFunctionRecursionCheck%d(Func<%s> target)' % (nparams, make_calltarget_type_args(nparams)))
  199. cw.write('_target = target;')
  200. cw.exit_block()
  201. cw.write('')
  202. cw.enter_block('public object CallTarget(%s)' % (make_params(nparams, "PythonFunction/*!*/ function"), ))
  203. cw.write('PythonOps.FunctionPushFrame((PythonContext)function.Context.LanguageContext);')
  204. cw.enter_block('try')
  205. cw.write('return _target(%s);' % (gen_args_call(nparams, 'function'), ))
  206. cw.finally_block()
  207. cw.write('PythonOps.FunctionPopFrame();')
  208. cw.exit_block()
  209. cw.exit_block()
  210. cw.exit_block()
  211. cw.write('')
  212. def gen_recursion_delegate_switch(cw):
  213. for nparams in range(MAX_ARGS):
  214. cw.case_label('case %d:' % nparams)
  215. cw.write('finalTarget = new Func<%s>(new PythonFunctionRecursionCheck%d((Func<%s>)finalTarget).CallTarget);' % (make_calltarget_type_args(nparams), nparams, make_calltarget_type_args(nparams)))
  216. cw.write('break;')
  217. cw.dedent()
  218. def get_call_type(postfix):
  219. if postfix == "": return "CallType.None"
  220. else: return "CallType.ImplicitInstance"
  221. def make_call_to_target(cw, index, postfix, extraArg):
  222. cw.enter_block("public override object Call%(postfix)s(%(params)s)", postfix=postfix,
  223. params=make_params1(index))
  224. cw.write("if (target%(index)d != null) return target%(index)d(%(args)s);", index=index,
  225. args = make_args1(index, extraArg))
  226. cw.write("throw BadArgumentError(%(callType)s, %(nargs)d);", callType=get_call_type(postfix), nargs=index)
  227. cw.exit_block()
  228. def make_call_to_targetX(cw, index, postfix, extraArg):
  229. cw.enter_block("public override object Call%(postfix)s(%(params)s)", postfix=postfix,
  230. params=make_params1(index))
  231. cw.write("return target%(index)d(%(args)s);", index=index, args = make_args1(index, extraArg))
  232. cw.exit_block()
  233. def make_error_calls(cw, index):
  234. cw.enter_block("public override object Call(%(params)s)", params=make_params1(index))
  235. cw.write("throw BadArgumentError(CallType.None, %(nargs)d);", nargs=index)
  236. cw.exit_block()
  237. if index > 0:
  238. cw.enter_block("public override object CallInstance(%(params)s)", params=make_params1(index))
  239. cw.write("throw BadArgumentError(CallType.ImplicitInstance, %(nargs)d);", nargs=index)
  240. cw.exit_block()
  241. def gen_call(nargs, nparams, cw, extra=[]):
  242. args = extra + ["arg%d" % i for i in range(nargs)]
  243. cw.enter_block("public override object Call(%s)" % make_params1(nargs))
  244. # first emit error checking...
  245. ndefaults = nparams-nargs
  246. if nargs != nparams:
  247. cw.write("if (Defaults.Length < %d) throw BadArgumentError(%d);" % (ndefaults,nargs))
  248. # emit the common case of no recursion check
  249. if (nargs == nparams):
  250. cw.write("if (!EnforceRecursion) return target(%s);" % ", ".join(args))
  251. else:
  252. dargs = args + ["Defaults[Defaults.Length - %d]" % i for i in range(ndefaults, 0, -1)]
  253. cw.write("if (!EnforceRecursion) return target(%s);" % ", ".join(dargs))
  254. # emit non-common case of recursion check
  255. cw.write("PushFrame();")
  256. cw.enter_block("try")
  257. # make function body
  258. if (nargs == nparams):
  259. cw.write("return target(%s);" % ", ".join(args))
  260. else:
  261. dargs = args + ["Defaults[Defaults.Length - %d]" % i for i in range(ndefaults, 0, -1)]
  262. cw.write("return target(%s);" % ", ".join(dargs))
  263. cw.finally_block()
  264. cw.write("PopFrame();")
  265. cw.exit_block()
  266. cw.exit_block()
  267. def gen_params_callN(cw, any):
  268. cw.enter_block("public override object Call(CodeContext context, params object[] args)")
  269. cw.write("if (!IsContextAware) return Call(args);")
  270. cw.write("")
  271. cw.enter_block("if (Instance == null)")
  272. cw.write("object[] newArgs = new object[args.Length + 1];")
  273. cw.write("newArgs[0] = context;")
  274. cw.write("Array.Copy(args, 0, newArgs, 1, args.Length);")
  275. cw.write("return Call(newArgs);")
  276. cw.else_block()
  277. # need to call w/ Context, Instance, *args
  278. if any:
  279. cw.enter_block("switch (args.Length)")
  280. for i in xrange(MAX_ARGS-1):
  281. if i == 0:
  282. cw.write(("case %d: if(target2 != null) return target2(context, Instance); break;") % (i))
  283. else:
  284. cw.write(("case %d: if(target%d != null) return target%d(context, Instance, " + gen_args_paramscall(i) + "); break;") % (i, i+2, i+2))
  285. cw.exit_block()
  286. cw.enter_block("if (targetN != null)")
  287. cw.write("object [] newArgs = new object[args.Length+2];")
  288. cw.write("newArgs[0] = context;")
  289. cw.write("newArgs[1] = Instance;")
  290. cw.write("Array.Copy(args, 0, newArgs, 2, args.Length);")
  291. cw.write("return targetN(newArgs);")
  292. cw.exit_block()
  293. cw.write("throw BadArgumentError(args.Length);")
  294. cw.exit_block()
  295. else:
  296. cw.write("object [] newArgs = new object[args.Length+2];")
  297. cw.write("newArgs[0] = context;")
  298. cw.write("newArgs[1] = Instance;")
  299. cw.write("Array.Copy(args, 0, newArgs, 2, args.Length);")
  300. cw.write("return target(newArgs);")
  301. cw.exit_block()
  302. cw.exit_block()
  303. cw.write("")
  304. CODE = """
  305. public static object Call(%(params)s) {
  306. FastCallable fc = func as FastCallable;
  307. if (fc != null) return fc.Call(%(args)s);
  308. return PythonCalls.Call(func, %(argsArray)s);
  309. }"""
  310. def gen_python_switch(cw):
  311. for nparams in range(MAX_ARGS):
  312. genArgs = make_calltarget_type_args(nparams)
  313. cw.write("""case %d:
  314. originalTarget = (Func<%s>)OriginalCallTarget%d;
  315. return typeof(Func<%s>);""" % (nparams, genArgs, nparams, genArgs))
  316. fast_type_call_template = """
  317. class FastBindingBuilder<%(typeParams)s> : FastBindingBuilderBase {
  318. public FastBindingBuilder(CodeContext context, PythonType type, PythonInvokeBinder binder, Type siteType, Type[] genTypeArgs) :
  319. base(context, type, binder, siteType, genTypeArgs) {
  320. }
  321. protected override Delegate GetNewSiteDelegate(PythonInvokeBinder binder, object func) {
  322. return new Func<%(newInitDlgParams)s>(new NewSite<%(typeParams)s>(binder, func).Call);
  323. }
  324. protected override Delegate MakeDelegate(int version, Delegate newDlg, LateBoundInitBinder initBinder) {
  325. return new Func<%(funcParams)s>(
  326. new FastTypeSite<%(typeParams)s>(
  327. version,
  328. (Func<%(newInitDlgParams)s>)newDlg,
  329. initBinder
  330. ).CallTarget
  331. );
  332. }
  333. }
  334. class FastTypeSite<%(typeParams)s> {
  335. private readonly int _version;
  336. private readonly Func<%(newInitDlgParams)s> _new;
  337. private readonly CallSite<Func<%(nestedSlowSiteParams)s>> _initSite;
  338. public FastTypeSite(int version, Func<%(newInitDlgParams)s> @new, LateBoundInitBinder initBinder) {
  339. _version = version;
  340. _new = @new;
  341. _initSite = CallSite<Func<%(nestedSlowSiteParams)s>>.Create(initBinder);
  342. }
  343. public object CallTarget(CallSite site, CodeContext context, object type, %(callTargetArgs)s) {
  344. PythonType pt = type as PythonType;
  345. if (pt != null && pt.Version == _version) {
  346. object res = _new(context, type, %(callTargetPassedArgs)s);
  347. _initSite.Target(_initSite, context, res, %(callTargetPassedArgs)s);
  348. return res;
  349. }
  350. return ((CallSite<Func<%(funcParams)s>>)site).Update(site, context, type, %(callTargetPassedArgs)s);
  351. }
  352. }
  353. class NewSite<%(typeParams)s> {
  354. private readonly CallSite<Func<%(nestedSiteParams)s>> _site;
  355. private readonly object _target;
  356. public NewSite(PythonInvokeBinder binder, object target) {
  357. _site = CallSite<Func<%(nestedSiteParams)s>>.Create(binder);
  358. _target = target;
  359. }
  360. public object Call(CodeContext context, object typeOrInstance, %(callTargetArgs)s) {
  361. return _site.Target(_site, context, _target, typeOrInstance, %(callTargetPassedArgs)s);
  362. }
  363. }
  364. """
  365. def gen_fast_type_callers(cw):
  366. for nparams in range(1, 6):
  367. funcParams = 'CallSite, CodeContext, object, ' + ', '.join(('T%d' % d for d in xrange(nparams))) + ', object'
  368. newInitDlgParams = 'CodeContext, object, ' + ', '.join(('T%d' % d for d in xrange(nparams))) + ', object'
  369. callTargetArgs = ', '.join(('T%d arg%d' % (d, d) for d in xrange(nparams)))
  370. callTargetPassedArgs = ', '.join(('arg%d' % (d, ) for d in xrange(nparams)))
  371. nestedSiteParams = 'CallSite, CodeContext, object, object, ' + ', '.join(('T%d' % d for d in xrange(nparams))) + ', object'
  372. nestedSlowSiteParams = 'CallSite, CodeContext, object, ' + ', '.join(('T%d' % d for d in xrange(nparams))) + ', object'
  373. cw.write(fast_type_call_template % {
  374. 'typeParams' : ', '.join(('T%d' % d for d in xrange(nparams))),
  375. 'funcParams' : funcParams,
  376. 'newInitDlgParams' : newInitDlgParams,
  377. 'callTargetArgs' : callTargetArgs,
  378. 'callTargetPassedArgs': callTargetPassedArgs,
  379. 'nestedSiteParams' : nestedSiteParams,
  380. 'nestedSlowSiteParams' : nestedSlowSiteParams,
  381. })
  382. def gen_fast_type_caller_switch(cw):
  383. for nparams in range(1, 6):
  384. cw.write('case %d: baseType = typeof(FastBindingBuilder<%s>); break;' % (nparams, (',' * (nparams - 1))))
  385. fast_init_template = """
  386. class FastInitSite<%(typeParams)s> {
  387. private readonly int _version;
  388. private readonly PythonFunction _slot;
  389. private readonly CallSite<Func<CallSite, CodeContext, PythonFunction, object, %(typeParams)s, object>> _initSite;
  390. public FastInitSite(int version, PythonInvokeBinder binder, PythonFunction target) {
  391. _version = version;
  392. _slot = target;
  393. _initSite = CallSite<Func<CallSite, CodeContext, PythonFunction, object, %(typeParams)s, object>>.Create(binder);
  394. }
  395. public object CallTarget(CallSite site, CodeContext context, object inst, %(callParams)s) {
  396. IPythonObject pyObj = inst as IPythonObject;
  397. if (pyObj != null && pyObj.PythonType.Version == _version) {
  398. _initSite.Target(_initSite, context, _slot, inst, %(callArgs)s);
  399. return inst;
  400. }
  401. return ((CallSite<Func<CallSite, CodeContext, object, %(typeParams)s, object>>)site).Update(site, context, inst, %(callArgs)s);
  402. }
  403. public object EmptyCallTarget(CallSite site, CodeContext context, object inst, %(callParams)s) {
  404. IPythonObject pyObj = inst as IPythonObject;
  405. if ((pyObj != null && pyObj.PythonType.Version == _version) || DynamicHelpers.GetPythonType(inst).Version == _version) {
  406. return inst;
  407. }
  408. return ((CallSite<Func<CallSite, CodeContext, object, %(typeParams)s, object>>)site).Update(site, context, inst, %(callArgs)s);
  409. }
  410. }
  411. """
  412. MAX_FAST_INIT_ARGS = 6
  413. def gen_fast_init_callers(cw):
  414. for nparams in range(1, MAX_FAST_INIT_ARGS):
  415. callParams = ', '.join(('T%d arg%d' % (d, d) for d in xrange(nparams)))
  416. callArgs = ', '.join(('arg%d' % (d, ) for d in xrange(nparams)))
  417. cw.write(fast_init_template % {
  418. 'typeParams' : ', '.join(('T%d' % d for d in xrange(nparams))),
  419. 'callParams' : callParams,
  420. 'callArgs': callArgs,
  421. })
  422. def gen_fast_init_switch(cw):
  423. for nparams in range(1, MAX_FAST_INIT_ARGS):
  424. cw.write("case %d: initSiteType = typeof(FastInitSite<%s>); break;" % (nparams, ',' * (nparams-1), ))
  425. def gen_fast_init_max_args(cw):
  426. cw.write("public const int MaxFastLateBoundInitArgs = %d;" % MAX_FAST_INIT_ARGS)
  427. MAX_INSTRUCTION_PROVIDED_CALLS = 7
  428. def gen_call_expression_instruction_switch(cw):
  429. for i in xrange(MAX_INSTRUCTION_PROVIDED_CALLS):
  430. cw.case_label('case %d:' % i)
  431. cw.write('compiler.Compile(Parent.LocalContext);')
  432. cw.write('compiler.Compile(_target);')
  433. for j in xrange(i):
  434. cw.write('compiler.Compile(_args[%d].Expression);' % j)
  435. cw.write('compiler.Instructions.Emit(new Invoke%dInstruction(Parent.PyContext));' % i)
  436. cw.write('return;')
  437. cw.dedent()
  438. def gen_call_expression_instructions(cw):
  439. for i in xrange(MAX_INSTRUCTION_PROVIDED_CALLS):
  440. siteargs = 'object, ' * (i + 1)
  441. argfetch = '\n'.join([' var arg%d = frame.Pop();' % (j-1) for j in xrange(i, 0, -1)])
  442. callargs = ', '.join(['target'] + ['arg%d' % j for j in xrange(i)])
  443. cw.write("""
  444. class Invoke%(argcount)dInstruction : InvokeInstruction {
  445. private readonly CallSite<Func<CallSite, CodeContext, %(siteargs)sobject>> _site;
  446. public Invoke%(argcount)dInstruction(PythonContext context) {
  447. _site = context.CallSite%(argcount)d;
  448. }
  449. public override int ConsumedStack {
  450. get {
  451. return %(consumedCount)d;
  452. }
  453. }
  454. public override int Run(InterpretedFrame frame) {
  455. %(argfetch)s
  456. var target = frame.Pop();
  457. frame.Push(_site.Target(_site, (CodeContext)frame.Pop(), %(callargs)s));
  458. return +1;
  459. }
  460. }""" % {'siteargs': siteargs, 'argfetch' : argfetch, 'callargs' : callargs, 'argcount' : i, 'consumedCount' : i + 2 })
  461. def gen_shared_call_sites_storage(cw):
  462. for i in xrange(MAX_INSTRUCTION_PROVIDED_CALLS):
  463. siteargs = 'object, ' * (i + 1)
  464. cw.writeline('private CallSite<Func<CallSite, CodeContext, %sobject>> _callSite%d;' % (siteargs, i))
  465. def gen_shared_call_sites_properties(cw):
  466. for i in xrange(MAX_INSTRUCTION_PROVIDED_CALLS):
  467. siteargs = 'object, ' * (i + 1)
  468. cw.enter_block('internal CallSite<Func<CallSite, CodeContext, %sobject>> CallSite%d' % (siteargs, i))
  469. cw.enter_block('get')
  470. cw.writeline('EnsureCall%dSite();' % i)
  471. cw.writeline('return _callSite%d;' % i)
  472. cw.exit_block()
  473. cw.exit_block()
  474. cw.writeline('')
  475. cw.enter_block('private void EnsureCall%dSite()' % i)
  476. cw.enter_block('if (_callSite%d == null)' % i)
  477. cw.writeline('Interlocked.CompareExchange(')
  478. cw.indent()
  479. cw.writeline('ref _callSite%d,' % i)
  480. cw.writeline('CallSite<Func<CallSite, CodeContext, %sobject>>.Create(Invoke(new CallSignature(%d))),' % (siteargs, i))
  481. cw.writeline('null')
  482. cw.dedent()
  483. cw.writeline(');')
  484. cw.exit_block()
  485. cw.exit_block()
  486. cw.writeline('')
  487. def main():
  488. return generate(
  489. ("Python Selfless Method Caller Switch", selfless_method_caller_switch),
  490. ("Python Method Callers", method_callers),
  491. ("Python Shared Call Sites Properties", gen_shared_call_sites_properties),
  492. ("Python Shared Call Sites Storage", gen_shared_call_sites_storage),
  493. ("Python Call Expression Instructions", gen_call_expression_instructions),
  494. ("Python Call Expression Instruction Switch", gen_call_expression_instruction_switch),
  495. ("Python Fast Init Max Args", gen_fast_init_max_args),
  496. ("Python Fast Init Switch", gen_fast_init_switch),
  497. ("Python Fast Init Callers", gen_fast_init_callers),
  498. ("Python Fast Type Caller Switch", gen_fast_type_caller_switch),
  499. ("Python Fast Type Callers", gen_fast_type_callers),
  500. ("Python Recursion Enforcement", gen_recursion_checks),
  501. ("Python Recursion Delegate Switch", gen_recursion_delegate_switch),
  502. ("Python Lazy Call Targets", gen_lazy_call_targets),
  503. ("Python Zero Arg Function Callers", function_callers_0),
  504. ("Python Function Callers", function_callers),
  505. ("Python Function Caller Switch", function_caller_switch),
  506. ("Python Call Target Switch", gen_python_switch),
  507. )
  508. if __name__ == "__main__":
  509. main()