From 94162771a1924e4706dcb9a276fd0a10f34c546d Mon Sep 17 00:00:00 2001 From: Jean Privat Date: Mon, 17 Aug 2009 10:29:05 -0400 Subject: [PATCH] icode: do no do recursive inline Signed-off-by: Jean Privat --- src/analysis/inline_methods.nit | 40 ++++++++++++------- src/icode/icode_tools.nit | 14 +++++++ tests/base_inline_closure_nested.nit | 64 ++++++++++++++++++++++++++++++ tests/base_inline_nested.nit | 34 ++++++++++++++++ tests/base_inline_nested2.nit | 52 ++++++++++++++++++++++++ tests/sav/base_inline_closure_nested.sav | 16 ++++++++ tests/sav/base_inline_nested.sav | 3 ++ tests/sav/base_inline_nested2.sav | 22 ++++++++++ 8 files changed, 230 insertions(+), 15 deletions(-) create mode 100644 tests/base_inline_closure_nested.nit create mode 100644 tests/base_inline_nested.nit create mode 100644 tests/base_inline_nested2.nit create mode 100644 tests/sav/base_inline_closure_nested.sav create mode 100644 tests/sav/base_inline_nested.sav create mode 100644 tests/sav/base_inline_nested2.sav diff --git a/src/analysis/inline_methods.nit b/src/analysis/inline_methods.nit index eafa6d7..1b06b0d 100644 --- a/src/analysis/inline_methods.nit +++ b/src/analysis/inline_methods.nit @@ -24,26 +24,35 @@ special ICodeVisitor var _pass: Int = 0 var _icb: ICodeBuilder + var _current_inlining: Array[IRoutine] + redef fun visit_icode(ic) do if ic isa ICall then var m = ic.property - if m.iroutine != null and ic.is_inlinable then - var icb = _icb - var ir = m.iroutine.as(not null) - var seq = new ISeq - var old_seq = icb.seq - icb.seq = seq - current_icode.insert_before(seq) - var e = icb.inline_routine(ir, ic.exprs, ic.closure_defs) - var r = ic.result - if r != null then - assert e != null - current_icode.insert_before(new IMove(r, e)) + var ir = m.iroutine + if ir != null and ic.is_inlinable then + if _current_inlining.has(ir) then + # We cannot inline ir + # FIXME: what we want is a static call + else + var icb = _icb + _current_inlining.push(ir) + var seq = new ISeq + var old_seq = icb.seq + icb.seq = seq + current_icode.insert_before(seq) + var e = icb.inline_routine(ir, ic.exprs, ic.closure_defs) + var r = ic.result + if r != null then + assert e != null + current_icode.insert_before(new IMove(r, e)) + end + current_icode.delete + icb.seq = old_seq + visit_icode(seq) + _current_inlining.pop end - current_icode.delete - icb.seq = old_seq - visit_icode(seq) end end super @@ -51,6 +60,7 @@ special ICodeVisitor init(m: MMModule, r: IRoutine) do + _current_inlining = [r] _icb = new ICodeBuilder(m, r) end end diff --git a/src/icode/icode_tools.nit b/src/icode/icode_tools.nit index 076f125..7c38798 100644 --- a/src/icode/icode_tools.nit +++ b/src/icode/icode_tools.nit @@ -92,9 +92,22 @@ class ICodeVisitor end redef class ICodeBuilder + # IRoutine currently inlining + # Used to avoid recursive inlining + var _current_inlining: Array[IRoutine] = new Array[IRoutine] + + # Return false if routine can be saflely inlined + fun is_currently_inlining_routine(routine: IRoutine): Bool + do + return routine == iroutine or _current_inlining.has(routine) + end + # Inline an iroutine in the current icode sequence + # Require not is_currently_inlining fun inline_routine(routine: IRoutine, args: Sequence[IRegister], closdefs: nullable Sequence[nullable IClosureDef]): nullable IRegister do + assert not is_currently_inlining_routine(routine) + _current_inlining.add(routine) var d = new ICodeDupContext(self) assert args.length == routine.params.length var closdecls = routine.closure_decls @@ -134,6 +147,7 @@ redef class ICodeBuilder # Process inlining routine.body.dup_with(d) + _current_inlining.pop return res end end diff --git a/tests/base_inline_closure_nested.nit b/tests/base_inline_closure_nested.nit new file mode 100644 index 0000000..351dedc --- /dev/null +++ b/tests/base_inline_closure_nested.nit @@ -0,0 +1,64 @@ +# 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 + +fun test1 +do + var a: A = new A + 5.output + a.bar !b do + 15.output + a.bar + end +end + +fun test2 +do + var a: A = new A + a.foo !f do + 5.output + a.bar !b do + 15.output + a.bar + end + end +end + +test1 +test2 diff --git a/tests/base_inline_nested.nit b/tests/base_inline_nested.nit new file mode 100644 index 0000000..f25b454 --- /dev/null +++ b/tests/base_inline_nested.nit @@ -0,0 +1,34 @@ +# 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 do bar.output + fun bar: Int = 2 + fun baz is abstract +end + +class A +special Inline__ + redef fun bar do return 20 + redef fun baz do bar.output +end + +var a: A = new A +a.foo +a.bar.output +a.baz diff --git a/tests/base_inline_nested2.nit b/tests/base_inline_nested2.nit new file mode 100644 index 0000000..ef70646 --- /dev/null +++ b/tests/base_inline_nested2.nit @@ -0,0 +1,52 @@ +# 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(i: Int) + do + 'F'.output + i.output + if i > 0 then + bar(i-1) + end + end + fun bar(i: Int) + do + 'B'.output + i.output + if i > 0 then + foo(i-1) + end + end +end + +class A +special Inline__ + redef fun foo(i: Int) + do + 'A'.output + i.output + if i > 0 then + bar(i-1) + end + end +end + +var a: A = new A +a.foo(10) +a.bar(10) diff --git a/tests/sav/base_inline_closure_nested.sav b/tests/sav/base_inline_closure_nested.sav new file mode 100644 index 0000000..6d8b859 --- /dev/null +++ b/tests/sav/base_inline_closure_nested.sav @@ -0,0 +1,16 @@ +5 +10 +15 +10 +11 +12 +12 +0 +5 +10 +15 +10 +11 +12 +12 +2 diff --git a/tests/sav/base_inline_nested.sav b/tests/sav/base_inline_nested.sav new file mode 100644 index 0000000..19f9935 --- /dev/null +++ b/tests/sav/base_inline_nested.sav @@ -0,0 +1,3 @@ +2 +20 +20 diff --git a/tests/sav/base_inline_nested2.sav b/tests/sav/base_inline_nested2.sav new file mode 100644 index 0000000..c749215 --- /dev/null +++ b/tests/sav/base_inline_nested2.sav @@ -0,0 +1,22 @@ +A10 +B9 +F8 +B7 +F6 +B5 +F4 +B3 +A2 +B1 +F0 +B10 +F9 +B8 +F7 +B6 +A5 +B4 +F3 +B2 +F1 +B0 -- 1.7.9.5