icode: inline foreign icloscall and ihasclos
authorJean Privat <jean@pryen.org>
Tue, 15 Sep 2009 15:22:37 +0000 (11:22 -0400)
committerJean Privat <jean@pryen.org>
Tue, 15 Sep 2009 15:22:37 +0000 (11:22 -0400)
Signed-off-by: Jean Privat <jean@pryen.org>

src/icode/icode_tools.nit
tests/base_inline_closurecall.nit [new file with mode: 0644]
tests/sav/base_inline_closurecall.sav [new file with mode: 0644]

index 87d5c16..56a6f13 100644 (file)
@@ -366,19 +366,31 @@ end
 redef class IClosCall
        redef fun dup_with(d)
        do
-               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))
+               if d._closures.has_key(closure_decl) then
+                       # The icloscall need to be replaced with an inlined closdef
+                       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
+                       # Inline the closdef
+                       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
+               else
+                       # Standard icloscall duplication
+                       super
                end
        end
+
+       redef fun inner_dup_with(d)
+       do
+               return new IClosCall(closure_decl, exprs)
+       end
 end
 
 redef class INative
@@ -451,13 +463,18 @@ end
 redef class IHasClos
        redef fun inner_dup_with(d)
        do
-               var closdef = d._closures[closure_decl]
-               var res: IRegister
-               if closdef != null then
-                       res = d._icb.lit_true_reg
+               if d._closures.has_key(closure_decl) then
+                       # closdef will be inlined
+                       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)
                else
-                       res = d._icb.lit_false_reg
+                       return new IHasClos(closure_decl)
                end
-               return new IMove(d.dup_ireg(result.as(not null)), res)
        end
 end
diff --git a/tests/base_inline_closurecall.nit b/tests/base_inline_closurecall.nit
new file mode 100644 (file)
index 0000000..9f4e64c
--- /dev/null
@@ -0,0 +1,65 @@
+# 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
+
+class 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
+       fun baz
+               !b
+       do
+               var inl = new Inline__
+               inl.foo !f do b
+               inl.bar !b do b
+               inl.bar
+               inl.foo !f do inl.bar !b do b
+       end
+
+       fun baz2
+               !b do 22.output
+       do
+               var inl = new Inline__
+               inl.foo !f do b
+               inl.bar !b do b
+               inl.bar
+               inl.foo !f do inl.bar !b do b
+       end
+end
+
+
+var a = new A
+a.baz !b do 20.output
+'\n'.output
+a.baz2 !b do 21.output
+'\n'.output
+a.baz2
diff --git a/tests/sav/base_inline_closurecall.sav b/tests/sav/base_inline_closurecall.sav
new file mode 100644 (file)
index 0000000..7cf7772
--- /dev/null
@@ -0,0 +1,44 @@
+0
+20
+2
+10
+20
+12
+10
+11
+12
+0
+10
+20
+12
+2
+
+0
+21
+2
+10
+21
+12
+10
+11
+12
+0
+10
+21
+12
+2
+
+0
+22
+2
+10
+22
+12
+10
+11
+12
+0
+10
+22
+12
+2