Merge: Fast super strings
authorJean Privat <jean@pryen.org>
Sat, 28 Mar 2015 01:34:45 +0000 (08:34 +0700)
committerJean Privat <jean@pryen.org>
Sat, 28 Mar 2015 01:34:45 +0000 (08:34 +0700)
Superstrings, like "a{b}c", are managed in the AST as a special group of sub-expression nodes that are either literal string parts or standard expressions.
The previous example is basically `["a", b, "c"]`

Previously, the compilation of super-strings was direct: the values are grouped in an array and `to_s` is called on it.

So in fact `"a{b}c"` was compiled as `["a", b, "c"].to_s`.

This basic implementation is simple and correct. But it has some drawbacks:

* a new Array[Object] (and a NativeArray[Object]) is allocated each time the super-string is evaluated.
* all elements are to_s-ized in `Array::to_s`, even the literal parts.
* an additional NativeArray[String] is allocated in `Array:to_s` to do the fast concatenation.

Because of the numerous allocations, superstrings caused a lot of work to the GC.

This PR provides a better, but more complex implementation:

* instead of an Array[Object], a NativeArray[String] is directly build and a fast concatenation `native_to_s` is invoked.
* the allocated NativeArray is cached in a static variable so it can be reused in next evaluation.
* the literal string parts are stored in the native array as is, and only once just after the allocation of the native array.

Results for nitc/nitc/nitc:
before: 0m6.076s
after: 0m5.512s (-9% not bad!)

Pull-Request: #1219
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>

lib/standard/exec.nit
lib/standard/file.nit
lib/string_experimentations/utf8_noindex.nit
src/compiler/separate_compiler.nit
src/nit.nit
src/nitvm.nit
src/platform/android.nit
src/vm/variables_numbering.nit [moved from src/variables_numbering.nit with 99% similarity]
src/vm/virtual_machine.nit [moved from src/vm.nit with 99% similarity]
src/vm/vm.nit [new file with mode: 0644]
src/vm/vm_optimizations.nit [moved from src/vm_optimizations.nit with 99% similarity]

index d9a0704..8cd2f70 100644 (file)
@@ -129,7 +129,9 @@ class ProcessWriter
        redef fun execute
        do
                super
-               stream_out = new FileWriter.from_fd(data.in_fd)
+               var out = new FileWriter.from_fd(data.in_fd)
+               out.set_buffering_mode(0, sys.buffer_mode_none)
+               stream_out = out
        end
 end
 
index 4d77955..a2856ae 100644 (file)
@@ -150,7 +150,6 @@ class FileWriter
                else
                        for i in s.substrings do write_native(i.to_cstring, i.length)
                end
-               _file.flush
        end
 
        redef fun close
index 0fa637a..2875a8b 100644 (file)
@@ -231,7 +231,7 @@ class FlatStringIter
 
        private var it: UnicodeChar
 
-       private var is_created: Bool
+       private var is_created = false
 
        init(s: FlatString) do from(s, 0)
 
index 83749b6..ecfcc8e 100644 (file)
@@ -1580,7 +1580,7 @@ class SeparateCompilerVisitor
                        self.add("{res} = {recv}->attrs[{a.const_color}] != NULL; /* {a} on {recv.inspect}*/")
                else
 
-                       if not mtype.is_c_primitive then
+                       if not mtype.is_c_primitive and not mtype.is_tagged then
                                self.add("{res} = {recv}->attrs[{a.const_color}].val != NULL; /* {a} on {recv.inspect} */")
                        else
                                self.add("{res} = 1; /* NOT YET IMPLEMENTED: isset of primitives: {a} on {recv.inspect} */")
@@ -1661,7 +1661,11 @@ class SeparateCompilerVisitor
                self.require_declaration(a.const_color)
                if self.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
                        var attr = "{recv}->attrs[{a.const_color}]"
-                       if mtype.is_c_primitive then
+                       if mtype.is_tagged then
+                               # The attribute is not primitive, thus store it as tagged
+                               var tv = autobox(value, compiler.mainmodule.object_type)
+                               self.add("{attr} = {tv}; /* {a} on {recv.inspect} */")
+                       else if mtype.is_c_primitive then
                                assert mtype isa MClassType
                                # The attribute is primitive, thus we store it in a box
                                # The trick is to create the box the first time then resuse the box
@@ -2320,3 +2324,14 @@ redef class AMethPropdef
                return super
        end
 end
+
+redef class AAttrPropdef
+       redef fun init_expr(v, recv)
+       do
+               super
+               if is_lazy and v.compiler.modelbuilder.toolcontext.opt_no_union_attribute.value then
+                       var guard = self.mlazypropdef.mproperty
+                       v.write_attribute(guard, recv, v.bool_instance(false))
+               end
+       end
+end
index 13f8c59..5a74d48 100644 (file)
@@ -21,8 +21,6 @@ import interpreter
 import frontend
 import parser_util
 import vm
-import vm_optimizations
-import variables_numbering
 
 # Create a tool context to handle options and paths
 var toolcontext = new ToolContext
index 1fef7a4..088cd92 100644 (file)
@@ -18,8 +18,6 @@
 module nitvm
 
 import vm
-import vm_optimizations
-import variables_numbering
 import frontend
 
 # Create a tool context to handle options and paths
index b411225..e2db002 100644 (file)
@@ -227,6 +227,7 @@ $(call import-module,android/native_app_glue)
 </manifest>
 <!-- END_INCLUDE(manifest) -->
 """
+               manifest_file.close
 
                ### Link to png sources
                # libpng is not available on Android NDK
similarity index 99%
rename from src/variables_numbering.nit
rename to src/vm/variables_numbering.nit
index 1190fab..4de0eb4 100644 (file)
@@ -17,7 +17,7 @@
 # Handle all numbering operations related to local variables in the Nit virtual machine
 module variables_numbering
 
-import vm
+import virtual_machine
 
 redef class VirtualMachine
 
similarity index 99%
rename from src/vm.nit
rename to src/vm/virtual_machine.nit
index 97069cf..b33e7f8 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Implementation of the Nit virtual machine
-module vm
+module virtual_machine
 
 import interpreter::naive_interpreter
 import perfect_hashing
@@ -177,7 +177,6 @@ class VirtualMachine super NaiveInterpreter
                recv.vtable = recv.mtype.as(MClassType).mclass.vtable
        end
 
-
        # Initialize the internal representation of an object (its attribute values)
        # `init_instance` is the initial value of attributes
        private fun init_internal_attributes(init_instance: Instance, size: Int): Pointer
diff --git a/src/vm/vm.nit b/src/vm/vm.nit
new file mode 100644 (file)
index 0000000..4027a15
--- /dev/null
@@ -0,0 +1,22 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Copyright 2015 Julien Pagès <julien.pages@lirmm.fr>
+#
+# 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.
+
+# Entry point of all vm components
+module vm
+
+import virtual_machine
+import vm_optimizations
+import variables_numbering
similarity index 99%
rename from src/vm_optimizations.nit
rename to src/vm/vm_optimizations.nit
index f657786..6f3c201 100644 (file)
@@ -17,7 +17,7 @@
 # Optimization of the nitvm
 module vm_optimizations
 
-import vm
+import virtual_machine
 
 redef class VirtualMachine