redef class ICodeBuilder
# Inline an iroutine in the current icode sequence
- fun inline_routine(routine: IRoutine, args: Sequence[IRegister]): nullable IRegister
+ fun inline_routine(routine: IRoutine, args: Sequence[IRegister], closdefs: nullable Sequence[nullable IClosureDef]): nullable IRegister
do
var d = new ICodeDupContext(self)
assert args.length == routine.params.length
+ var closdecls = routine.closure_decls
+ var cdefsa = if closdefs != null then closdefs.length else 0
+ var cdeclsa = if closdecls != null then closdecls.length else 0
+ assert cdefsa <= cdeclsa
# Fill register duplicate association
var dico = d._registers
#seq.icodes.add(new IMove(dico[routine.params[i]]), args[i]))
end
+ # Fill closure association
+ if closdecls != null then
+ var cdico = d._closures
+ for i in [0..cdefsa[ do
+ cdico[closdecls[i]] = closdefs[i]
+ end
+ for i in [cdefsa..cdeclsa[ do
+ cdico[closdecls[i]] = null
+ end
+ end
+
# Process inlining
routine.body.dup_with(d)
return res
# Used by dup_ireg
var _registers: Map[IRegister, IRegister] = new HashMap[IRegister, IRegister]
+ # The association between a closure_decl and its closure_def (if any)
+ var _closures: Map[IClosureDecl, nullable IClosureDef] = new ArrayMap[IClosureDecl, nullable IClosureDef]
+
# The current code builder
var _icb: ICodeBuilder
end
redef class IClosCall
- redef fun inner_dup_with(d)
+ redef fun dup_with(d)
do
- var c2 = new IClosCall(closure_decl, d.dup_iregs(exprs))
- var bs = break_seq
- if bs != null then
- var bs2 = new ISeq
- c2.break_seq = bs2
- bs.dup_seq_to(d, bs2)
+ var closdef = d._closures[closure_decl]
+ if closdef == null then
+ # Default is already guarded and inlined
+ return
+ end
+ # Break sequence cannot be inlined :/
+ assert break_seq == null
+ var res = d._icb.inline_routine(closdef, d.dup_iregs(exprs), null)
+ if result != null then
+ assert res != null
+ d._icb.stmt(new IMove(d.dup_ireg(result.as(not null)), res))
end
- return c2
end
end
redef class IHasClos
redef fun inner_dup_with(d)
do
- return new IHasClos(closure_decl)
+ var closdef = d._closures[closure_decl]
+ var res: IRegister
+ if closdef != null then
+ res = d._icb.lit_true_reg
+ else
+ res = d._icb.lit_false_reg
+ end
+ return new IMove(d.dup_ireg(result.as(not null)), res)
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+interface Inline__
+ fun foo
+ !f
+ do
+ 0.output
+ f
+ 2.output
+ end
+
+ fun bar
+ !b do 11.output
+ do
+ 10.output
+ b
+ 12.output
+ end
+end
+
+class A
+special Inline__
+end
+
+var a: A = new A
+a.foo !f do 1.output
+a.bar !b do 1.output
+a.bar
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2009 Jean Privat <jean@pryen.org>
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import kernel
+
+interface Inline__
+ fun foo
+ !f: Int
+ do
+ 0.output
+ f.output
+ 2.output
+ end
+
+ fun bar
+ !b: Int do continue 11
+ do
+ 10.output
+ b.output
+ 12.output
+ end
+end
+
+class A
+special Inline__
+end
+
+var a: A = new A
+a.foo !f do continue 1
+a.bar !b do continue 1
+a.bar