diff --git a/lib/Slic3r.pm b/lib/Slic3r.pm
index 2f10a9fe6..2058a6e07 100644
--- a/lib/Slic3r.pm
+++ b/lib/Slic3r.pm
@@ -114,6 +114,7 @@ sub thread_cleanup {
     *Slic3r::ExPolygon::Collection::DESTROY = sub {};
     *Slic3r::ExtrusionLoop::DESTROY         = sub {};
     *Slic3r::ExtrusionPath::DESTROY         = sub {};
+    *Slic3r::ExtrusionPath::Collection::DESTROY = sub {};
     *Slic3r::Line::DESTROY                  = sub {};
     *Slic3r::Point::DESTROY                 = sub {};
     *Slic3r::Polygon::DESTROY               = sub {};
diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm
index 4577d3b7b..3354efaee 100644
--- a/lib/Slic3r/ExtrusionPath/Collection.pm
+++ b/lib/Slic3r/ExtrusionPath/Collection.pm
@@ -42,12 +42,15 @@ sub cleanup {
     my $self = shift;
     
     # split paths at angles that are too acute to be printed as they will cause blobs
-    @{$self->paths} = map $_->split_at_acute_angles, @{$self->paths};
+    my @paths = map $_->split_at_acute_angles, @$self;
+    $self->clear;
+    $self->append(@paths);
 }
 
 sub detect_arcs {
     my $self = shift;
-    @{$self->paths} = map $_->detect_arcs(@_), @{$self->paths};
+    
+    return map $_->detect_arcs(@_), @$self;
 }
 
 1;
diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm
index 94762a7cc..5a172776b 100644
--- a/lib/Slic3r/GCode.pm
+++ b/lib/Slic3r/GCode.pm
@@ -211,11 +211,7 @@ sub extrude_loop {
             $extrusion_path->intersect_expolygons($self->_layer_overhangs);
         
         # reapply the nearest point search for starting point
-        {
-            my $collection = Slic3r::ExtrusionPath::Collection->new;
-            $collection->append(@paths);
-            @paths = $collection->chained_path($start_at, 1);
-        }
+        @paths = Slic3r::ExtrusionPath::Collection->new(@paths)->chained_path($start_at, 1);
     } else {
         push @paths, $extrusion_path;
     }
diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm
index 3b70e3f25..19c9b18eb 100644
--- a/lib/Slic3r/Layer/Region.pm
+++ b/lib/Slic3r/Layer/Region.pm
@@ -29,19 +29,19 @@ has 'slices' => (is => 'rw', default => sub { Slic3r::Surface::Collection->new }
 
 # collection of polygons or polylines representing thin walls contained 
 # in the original geometry
-has 'thin_walls' => (is => 'rw', default => sub { [] });
+has 'thin_walls' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new });
 
 # collection of extrusion paths/loops filling gaps
-has 'thin_fills' => (is => 'rw', default => sub { [] });
+has 'thin_fills' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new });
 
 # collection of surfaces for infill generation
 has 'fill_surfaces' => (is => 'rw', default => sub { Slic3r::Surface::Collection->new });
 
 # ordered collection of extrusion paths/loops to build all perimeters
-has 'perimeters' => (is => 'rw', default => sub { [] });
+has 'perimeters' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new });
 
 # ordered collection of extrusion paths to fill surfaces
-has 'fills' => (is => 'rw', default => sub { [] });
+has 'fills' => (is => 'rw', default => sub { Slic3r::ExtrusionPath::Collection->new });
 
 sub BUILD {
     my $self = shift;
@@ -100,13 +100,11 @@ sub make_surfaces {
             1,
         );
         
-        $self->thin_walls([]);
+        $self->thin_walls->clear;
         if (@$diff) {
             my $area_threshold = $self->perimeter_flow->scaled_spacing ** 2;
             @$diff = grep $_->area > ($area_threshold), @$diff;
-            
-            @{$self->thin_walls} = map $_->medial_axis($self->perimeter_flow->scaled_width), @$diff;
-            
+            $self->thin_walls->append(map $_->medial_axis($self->perimeter_flow->scaled_width), @$diff);
             Slic3r::debugf "  %d thin walls detected\n", scalar(@{$self->thin_walls}) if @{$self->thin_walls};
         }
     }
@@ -156,9 +154,9 @@ sub make_perimeters {
     my $infill_spacing      = $self->solid_infill_flow->scaled_spacing;
     my $gap_area_threshold  = $self->perimeter_flow->scaled_width ** 2;
     
-    $self->perimeters([]);
+    $self->perimeters->clear;
     $self->fill_surfaces->clear;
-    $self->thin_fills([]);
+    $self->thin_fills->clear;
     
     my @contours    = ();    # array of Polygons with ccw orientation
     my @holes       = ();    # array of Polygons with cw orientation
@@ -278,7 +276,7 @@ sub make_perimeters {
             || ($self->layer->id == 0 && $Slic3r::Config->brim_width > 0);
     
     # append perimeters
-    push @{ $self->perimeters }, @loops;
+    $self->perimeters->append(@loops);
     
     # add thin walls as perimeters
     push @{ $self->perimeters }, Slic3r::ExtrusionPath::Collection->new(
@@ -333,11 +331,11 @@ sub _fill_gaps {
                 role            => EXTR_ROLE_SOLIDFILL,
                 flow_spacing    => $flow->spacing,
             );
-            push @{ $self->thin_fills }, map {
+            $self->thin_fills->append(map {
                 $_->isa('Slic3r::Polygon')
                     ? Slic3r::ExtrusionLoop->new(polygon => $_, %path_args)->split_at_first_point  # we should keep these as loops
                     : Slic3r::ExtrusionPath->new(polyline => $_, %path_args),
-            } map $_->medial_axis($flow->scaled_width), @this_width;
+            } map $_->medial_axis($flow->scaled_width), @this_width);
         
             Slic3r::debugf "  %d gaps filled with extrusion width = %s\n", scalar @this_width, $width
                 if @{ $self->thin_fills };
diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm
index 23a7099d9..4358f47cb 100644
--- a/lib/Slic3r/Print.pm
+++ b/lib/Slic3r/Print.pm
@@ -395,33 +395,17 @@ sub export_gcode {
             thread_cb => sub {
                 my $q = shift;
                 $Slic3r::Geometry::Clipper::clipper = Math::Clipper->new;
-                my $fills = {};
                 while (defined (my $obj_layer = $q->dequeue)) {
                     my ($obj_idx, $layer_id, $region_id) = @$obj_layer;
                     my $object = $self->objects->[$obj_idx];
-                    $fills->{$obj_idx} ||= {};
-                    $fills->{$obj_idx}{$layer_id} ||= {};
-                    $fills->{$obj_idx}{$layer_id}{$region_id} = [
-                        $object->fill_maker->make_fill($object->layers->[$layer_id]->regions->[$region_id]),
-                    ];
-                }
-                return $fills;
-            },
-            collect_cb => sub {
-                my $fills = shift;
-                foreach my $obj_idx (keys %$fills) {
-                    my $object = $self->objects->[$obj_idx];
-                    foreach my $layer_id (keys %{$fills->{$obj_idx}}) {
-                        my $layer = $object->layers->[$layer_id];
-                        foreach my $region_id (keys %{$fills->{$obj_idx}{$layer_id}}) {
-                            $layer->regions->[$region_id]->fills($fills->{$obj_idx}{$layer_id}{$region_id});
-                        }
-                    }
+                    my $layerm = $object->layers->[$layer_id]->regions->[$region_id];
+                    $layerm->fills->append( $object->fill_maker->make_fill($layerm) );
                 }
             },
+            collect_cb => sub {},
             no_threads_cb => sub {
                 foreach my $layerm (map @{$_->regions}, map @{$_->layers}, @{$self->objects}) {
-                    $layerm->fills([ $layerm->layer->object->fill_maker->make_fill($layerm) ]);
+                    $layerm->fills->append($layerm->layer->object->fill_maker->make_fill($layerm));
                 }
             },
         );
@@ -587,7 +571,7 @@ sub make_skirt {
         my @layer_points = (
             (map @$_, map @$_, map @{$_->slices}, @layers),
             (map @$_, map @{$_->thin_walls}, map @{$_->regions}, @layers),
-            (map @{$_->polyline}, map @{$_->support_fills->paths}, grep $_->support_fills, @layers),
+            (map @{$_->polyline}, map @{$_->support_fills}, grep $_->support_fills, @layers),
         );
         push @points, map move_points($_, @layer_points), @{$self->objects->[$obj_idx]->copies};
     }
@@ -647,7 +631,7 @@ sub make_brim {
         my @object_islands = (
             (map $_->contour, @{$layer0->slices}),
             (map { $_->isa('Slic3r::Polygon') ? $_ : $_->grow($grow_distance) } map @{$_->thin_walls}, @{$layer0->regions}),
-            (map $_->polyline->grow($grow_distance), map @{$_->support_fills->paths}, grep $_->support_fills, $layer0),
+            (map $_->polyline->grow($grow_distance), map @{$_->support_fills}, grep $_->support_fills, $layer0),
         );
         foreach my $copy (@{$self->objects->[$obj_idx]->copies}) {
             push @islands, map $_->clone->translate(@$copy), @object_islands;
diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm
index 7b76ba7da..da41b36a0 100644
--- a/lib/Slic3r/Print/Object.pm
+++ b/lib/Slic3r/Print/Object.pm
@@ -315,31 +315,11 @@ sub make_perimeters {
         thread_cb => sub {
             my $q = shift;
             $Slic3r::Geometry::Clipper::clipper = Math::Clipper->new;
-            my $result = {};
             while (defined (my $layer_id = $q->dequeue)) {
-                my $layer = $self->layers->[$layer_id];
-                $layer->make_perimeters;
-                $result->{$layer_id} ||= {};
-                foreach my $region_id (0 .. $#{$layer->regions}) {
-                    my $layerm = $layer->regions->[$region_id];
-                    $result->{$layer_id}{$region_id} = {
-                        perimeters      => $layerm->perimeters,
-                        fill_surfaces   => $layerm->fill_surfaces,
-                        thin_fills      => $layerm->thin_fills,
-                    };
-                }
-            }
-            return $result;
-        },
-        collect_cb => sub {
-            my $result = shift;
-            foreach my $layer_id (keys %$result) {
-                foreach my $region_id (keys %{$result->{$layer_id}}) {
-                    $self->layers->[$layer_id]->regions->[$region_id]->$_($result->{$layer_id}{$region_id}{$_})
-                        for qw(perimeters fill_surfaces thin_fills);
-                }
+                $self->layers->[$layer_id]->make_perimeters;
             }
         },
+        collect_cb => sub {},
         no_threads_cb => sub {
             $_->make_perimeters for @{$self->layers};
         },
@@ -988,9 +968,6 @@ sub generate_support_material {
             };
             return @paths;
         };
-        my %layer_paths             = ();
-        my %layer_contact_paths     = ();
-        my %layer_islands           = ();
         my $process_layer = sub {
             my ($layer_id) = @_;
             my $layer = $self->layers->[$layer_id];
@@ -1026,6 +1003,9 @@ sub generate_support_material {
             }
             return ($paths, $contact_paths, $islands);
         };
+        my %layer_paths             = ();
+        my %layer_contact_paths     = ();
+        my %layer_islands           = ();
         Slic3r::parallelize(
             items => [ keys %layers ],
             thread_cb => sub {
@@ -1051,8 +1031,8 @@ sub generate_support_material {
             $layer->support_islands($layer_islands{$layer_id});
             $layer->support_fills(Slic3r::ExtrusionPath::Collection->new);
             $layer->support_contact_fills(Slic3r::ExtrusionPath::Collection->new);
-            push @{$layer->support_fills->paths}, @{$layer_paths{$layer_id}};
-            push @{$layer->support_contact_fills->paths}, @{$layer_contact_paths{$layer_id}};
+            $layer->support_fills->append(@{$layer_paths{$layer_id}});
+            $layer->support_contact_fills->append(@{$layer_contact_paths{$layer_id}});
         }
     }
 }
diff --git a/t/arcs.t b/t/arcs.t
index 3b14903c8..7d15b63f8 100644
--- a/t/arcs.t
+++ b/t/arcs.t
@@ -22,11 +22,10 @@ use Slic3r::Geometry qw(scaled_epsilon scale X Y);
         [86948.77,175149.09], [119825.35,100585],
     ), role => EXTR_ROLE_FILL, flow_spacing => 0.5);
     
-    my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [$path]);
-    $collection->detect_arcs(30);
+    my @paths = $path->detect_arcs(30);
     
-    is scalar(@{$collection->paths}), 3, 'path collection now contains three paths';
-    isa_ok $collection->paths->[1], 'Slic3r::ExtrusionPath::Arc', 'second one';
+    is scalar(@paths), 3, 'path collection now contains three paths';
+    isa_ok $paths[1], 'Slic3r::ExtrusionPath::Arc', 'second one';
 }
 
 #==========================================================
@@ -50,30 +49,27 @@ use Slic3r::Geometry qw(scaled_epsilon scale X Y);
         flow_spacing => 0.5,
     );
     
-    my $collection1 = Slic3r::ExtrusionPath::Collection->new(paths => [$path1]);
-    my $collection2 = Slic3r::ExtrusionPath::Collection->new(paths => [$path2]);
+    my @paths1 = $path1->detect_arcs(10, scale 1);
+    my @paths2 = $path2->detect_arcs(10, scale 1);
     
-    $collection1->detect_arcs(10, scale 1);
-    $collection2->detect_arcs(10, scale 1);
+    is scalar(@paths1), 1, 'path collection now contains one path';
+    is scalar(@paths2), 1, 'path collection now contains one path';
     
-    is scalar(@{$collection1->paths}), 1, 'path collection now contains one path';
-    is scalar(@{$collection2->paths}), 1, 'path collection now contains one path';
-    
-    isa_ok $collection1->paths->[0], 'Slic3r::ExtrusionPath::Arc', 'path';
-    isa_ok $collection2->paths->[0], 'Slic3r::ExtrusionPath::Arc', 'path';
+    isa_ok $paths1[0], 'Slic3r::ExtrusionPath::Arc', 'path';
+    isa_ok $paths2[0], 'Slic3r::ExtrusionPath::Arc', 'path';
     
     my $expected_length = scale 7.06858347057701;
-    ok abs($collection1->paths->[0]->length - $expected_length) < scaled_epsilon, 'cw oriented arc has correct length';
-    ok abs($collection2->paths->[0]->length - $expected_length) < scaled_epsilon, 'ccw oriented arc has correct length';
+    ok abs($paths1[0]->length - $expected_length) < scaled_epsilon, 'cw oriented arc has correct length';
+    ok abs($paths2[0]->length - $expected_length) < scaled_epsilon, 'ccw oriented arc has correct length';
 
-    is $collection1->paths->[0]->orientation, 'cw', 'cw orientation was correctly detected';
-    is $collection2->paths->[0]->orientation, 'ccw', 'ccw orientation was correctly detected';
-    is $collection1->paths->[0]->flow_spacing, $path1->flow_spacing, 'flow spacing was correctly preserved';
+    is $paths1[0]->orientation, 'cw', 'cw orientation was correctly detected';
+    is $paths2[0]->orientation, 'ccw', 'ccw orientation was correctly detected';
+    is $paths1[0]->flow_spacing, $path1->flow_spacing, 'flow spacing was correctly preserved';
     
-    my $center1 = [ map sprintf('%.0f', $_), @{ $collection1->paths->[0]->center } ];
+    my $center1 = [ map sprintf('%.0f', $_), @{ $paths1[0]->center } ];
     ok abs($center1->[X] - scale 10) < scaled_epsilon && abs($center1->[Y] - scale 10) < scaled_epsilon, 'center was correctly detected';
     
-    my $center2 = [ map sprintf('%.0f', $_), @{ $collection2->paths->[0]->center } ];
+    my $center2 = [ map sprintf('%.0f', $_), @{ $paths2[0]->center } ];
     ok abs($center2->[X] - scale 10) < scaled_epsilon && abs($center1->[Y] - scale 10) < scaled_epsilon, 'center was correctly detected';
 }
 
diff --git a/t/fill.t b/t/fill.t
index ed0505c89..690b0ba25 100644
--- a/t/fill.t
+++ b/t/fill.t
@@ -71,11 +71,11 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
 }
 
 {
-    my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [
+    my $collection = Slic3r::ExtrusionPath::Collection->new(
         map Slic3r::ExtrusionPath->new(polyline => $_, role => 0),
             Slic3r::Polyline->new([0,15], [0,18], [0,20]),
             Slic3r::Polyline->new([0,10], [0,8], [0,5]),
-    ]);
+    );
     is_deeply
         [ map $_->[Y], map @{$_->polyline}, $collection->chained_path(Slic3r::Point->new(0,30)) ],
         [20, 18, 15, 10, 8, 5],
@@ -83,11 +83,11 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
 }
 
 {
-    my $collection = Slic3r::ExtrusionPath::Collection->new(paths => [
+    my $collection = Slic3r::ExtrusionPath::Collection->new(
         map Slic3r::ExtrusionPath->new(polyline => $_, role => 0),
             Slic3r::Polyline->new([15,0], [10,0], [4,0]),
             Slic3r::Polyline->new([10,5], [15,5], [20,5]),
-    ]);
+    );
     is_deeply
         [ map $_->[X], map @{$_->polyline}, $collection->chained_path(Slic3r::Point->new(30,0)) ],
         [reverse 4, 10, 15, 10, 15, 20],
diff --git a/xs/lib/Slic3r/XS.pm b/xs/lib/Slic3r/XS.pm
index 174e72e44..ebe2b59fb 100644
--- a/xs/lib/Slic3r/XS.pm
+++ b/xs/lib/Slic3r/XS.pm
@@ -43,6 +43,14 @@ use overload
     '@{}' => sub { $_[0]->arrayref },
     'fallback' => 1;
 
+sub new {
+    my ($class, @paths) = @_;
+    
+    my $self = $class->_new;
+    $self->append(@paths);
+    return $self;
+}
+
 package Slic3r::ExtrusionLoop;
 use overload
     '@{}' => sub { $_[0]->arrayref },
diff --git a/xs/src/ExtrusionEntityCollection.hpp b/xs/src/ExtrusionEntityCollection.hpp
index ef36cd136..7ffe8a454 100644
--- a/xs/src/ExtrusionEntityCollection.hpp
+++ b/xs/src/ExtrusionEntityCollection.hpp
@@ -6,7 +6,7 @@
 
 namespace Slic3r {
 
-class ExtrusionEntityCollection
+class ExtrusionEntityCollection : public ExtrusionEntity
 {
     public:
     ExtrusionEntitiesPtr entities;
diff --git a/xs/t/12_extrusionpathcollection.t b/xs/t/12_extrusionpathcollection.t
index 97be65772..53d315856 100644
--- a/xs/t/12_extrusionpathcollection.t
+++ b/xs/t/12_extrusionpathcollection.t
@@ -4,7 +4,7 @@ use strict;
 use warnings;
 
 use Slic3r::XS;
-use Test::More tests => 5;
+use Test::More tests => 8;
 
 my $points = [
     [100, 100],
@@ -22,16 +22,23 @@ my $loop = Slic3r::ExtrusionLoop->new(
     role     => Slic3r::ExtrusionPath::EXTR_ROLE_FILL,
 );
 
-my $collection = Slic3r::ExtrusionPath::Collection->new;
-isa_ok $collection, 'Slic3r::ExtrusionPath::Collection', 'collection object';
+my $collection = Slic3r::ExtrusionPath::Collection->new($path);
+isa_ok $collection, 'Slic3r::ExtrusionPath::Collection', 'collection object with items in constructor';
+
+$collection->append($collection);
+is scalar(@$collection), 2, 'append ExtrusionPath::Collection';
 
 $collection->append($path);
-is scalar(@$collection), 1, 'append ExtrusionPath';
+is scalar(@$collection), 3, 'append ExtrusionPath';
 
 $collection->append($loop);
-is scalar(@$collection), 2, 'append ExtrusionLoop';
+is scalar(@$collection), 4, 'append ExtrusionLoop';
+
+isa_ok $collection->[1], 'Slic3r::ExtrusionPath::Collection', 'correct object returned for collection';
+isa_ok $collection->[2], 'Slic3r::ExtrusionPath', 'correct object returned for path';
+isa_ok $collection->[3], 'Slic3r::ExtrusionLoop', 'correct object returned for loop';
+
+is scalar(@{$collection->[1]}), 1, 'appended collection was duplicated';
 
-isa_ok $collection->[0], 'Slic3r::ExtrusionPath', 'correct object returned for path';
-isa_ok $collection->[1], 'Slic3r::ExtrusionLoop', 'correct object returned for loop';
 
 __END__
diff --git a/xs/xsp/ExtrusionEntityCollection.xsp b/xs/xsp/ExtrusionEntityCollection.xsp
index 5715f1899..89c84f57f 100644
--- a/xs/xsp/ExtrusionEntityCollection.xsp
+++ b/xs/xsp/ExtrusionEntityCollection.xsp
@@ -6,7 +6,7 @@
 %}
 
 %name{Slic3r::ExtrusionPath::Collection} class ExtrusionEntityCollection {
-    ExtrusionEntityCollection();
+    %name{_new} ExtrusionEntityCollection();
     ~ExtrusionEntityCollection();
     void clear()
         %code{% THIS->entities.clear(); %};
@@ -23,8 +23,10 @@ ExtrusionEntityCollection::arrayref()
             // return COPIES
             if (ExtrusionPath* path = dynamic_cast<ExtrusionPath*>(*it)) {
                 sv_setref_pv( sv, "Slic3r::ExtrusionPath", new ExtrusionPath(*(ExtrusionPath*)*it) );
-            } else {
+            } else if (ExtrusionLoop* path = dynamic_cast<ExtrusionLoop*>(*it)) {
                 sv_setref_pv( sv, "Slic3r::ExtrusionLoop", new ExtrusionLoop(*(ExtrusionLoop*)*it) );
+            } else {
+                sv_setref_pv( sv, "Slic3r::ExtrusionPath::Collection", new ExtrusionEntityCollection(*(ExtrusionEntityCollection*)*it) );
             }
             av_store(av, i++, sv);
         }
@@ -40,8 +42,10 @@ ExtrusionEntityCollection::append(...)
             // append COPIES
             if (ExtrusionPath* path = dynamic_cast<ExtrusionPath*>(entity)) {
                 THIS->entities.push_back( new ExtrusionPath(*path) );
+            } else if (ExtrusionLoop* loop = dynamic_cast<ExtrusionLoop*>(entity)) {
+                THIS->entities.push_back( new ExtrusionLoop(*loop) );
             } else {
-                THIS->entities.push_back( new ExtrusionLoop(*(ExtrusionLoop*)entity) );
+                THIS->entities.push_back( new ExtrusionEntityCollection(*(ExtrusionEntityCollection*)entity) );
             }
         }