From f0c8f453b96fdf677ec8010838994e373bc84bbd Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Mon, 10 Aug 2009 15:01:15 -0400 Subject: [PATCH] icode: inline methods with closures Warning, break of closure call cannot be inlined. Signed-off-by: Jean Privat --- src/analysis/inline_methods.nit | 2 +- src/compiling/compiling_global.nit | 2 +- src/icode/icode_tools.nit | 49 ++++++++++++++++++++++++++++-------- src/syntax/icode_generation.nit | 2 +- tests/base_inline_closure.nit | 44 ++++++++++++++++++++++++++++++++ tests/base_inline_closure2.nit | 44 ++++++++++++++++++++++++++++++++ tests/sav/base_inline_closure.sav | 9 +++++++ tests/sav/base_inline_closure2.sav | 9 +++++++ 8 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 tests/base_inline_closure.nit create mode 100644 tests/base_inline_closure2.nit create mode 100644 tests/sav/base_inline_closure.sav create mode 100644 tests/sav/base_inline_closure2.sav diff --git a/src/analysis/inline_methods.nit b/src/analysis/inline_methods.nit index a661452..eafa6d7 100644 --- a/src/analysis/inline_methods.nit +++ b/src/analysis/inline_methods.nit @@ -35,7 +35,7 @@ special ICodeVisitor var old_seq = icb.seq icb.seq = seq current_icode.insert_before(seq) - var e = icb.inline_routine(ir, ic.exprs) + var e = icb.inline_routine(ir, ic.exprs, ic.closure_defs) var r = ic.result if r != null then assert e != null diff --git a/src/compiling/compiling_global.nit b/src/compiling/compiling_global.nit index bdc7e55..49b390f 100644 --- a/src/compiling/compiling_global.nit +++ b/src/compiling/compiling_global.nit @@ -881,7 +881,7 @@ redef class MMLocalClass var ir = p.iroutine if ir == null then continue # FIXME: Not compatible with sep compilation - var e = icb.inline_routine(ir, iselfa).as(not null) + var e = icb.inline_routine(ir, iselfa, null).as(not null) icb.stmt(new IAttrWrite(p, iself, e)) end end diff --git a/src/icode/icode_tools.nit b/src/icode/icode_tools.nit index 3884840..076f125 100644 --- a/src/icode/icode_tools.nit +++ b/src/icode/icode_tools.nit @@ -93,10 +93,14 @@ end 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 @@ -117,6 +121,17 @@ redef class ICodeBuilder #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 @@ -156,6 +171,9 @@ private class ICodeDupContext # 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 @@ -267,16 +285,20 @@ redef class INew 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 @@ -350,6 +372,13 @@ 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 diff --git a/src/syntax/icode_generation.nit b/src/syntax/icode_generation.nit index 9477f2d..64fd0f2 100644 --- a/src/syntax/icode_generation.nit +++ b/src/syntax/icode_generation.nit @@ -1450,7 +1450,7 @@ redef class AClosureCallExpr v.add_assignment(r, r2) end v.seq = iif.else_seq - var r3 = v.inline_routine(closdecl_default, args) + var r3 = v.inline_routine(closdecl_default, args, null) if r != null then assert r3 != null v.add_assignment(r, r3) diff --git a/tests/base_inline_closure.nit b/tests/base_inline_closure.nit new file mode 100644 index 0000000..645fa8c --- /dev/null +++ b/tests/base_inline_closure.nit @@ -0,0 +1,44 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2009 Jean Privat +# +# 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 diff --git a/tests/base_inline_closure2.nit b/tests/base_inline_closure2.nit new file mode 100644 index 0000000..31ef7b9 --- /dev/null +++ b/tests/base_inline_closure2.nit @@ -0,0 +1,44 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Copyright 2009 Jean Privat +# +# 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 diff --git a/tests/sav/base_inline_closure.sav b/tests/sav/base_inline_closure.sav new file mode 100644 index 0000000..52a0ad1 --- /dev/null +++ b/tests/sav/base_inline_closure.sav @@ -0,0 +1,9 @@ +0 +1 +2 +10 +1 +12 +10 +11 +12 diff --git a/tests/sav/base_inline_closure2.sav b/tests/sav/base_inline_closure2.sav new file mode 100644 index 0000000..52a0ad1 --- /dev/null +++ b/tests/sav/base_inline_closure2.sav @@ -0,0 +1,9 @@ +0 +1 +2 +10 +1 +12 +10 +11 +12 -- 1.7.9.5