Re: [Vala] how to *not* automagically copy arrays passed to methods?



On 12/20/11 22:53, Luca Bruno wrote:
On Wed, Dec 21, 2011 at 6:18 AM, Matto Marjanovic<maddog mir com>  wrote:

Ok, another bonus question (see revised subject) --- and I think this
issue was the root of the misfire with my earlier experiments with slices:

How does one tell valac to *not* copy arrays that are passed to methods?

For example:

   public void foo(uint8[] x) {
     ...
     x[0] = 7;
     ...
   }

The generated C code for the method duplicates the array x before executing
the body of the method; hence the common case of a method which modifies a
buffer, returning with side-effects, doesn't work.


What are you talking about? It's not copied.

You're right... it is not copied in the example I gave above.  However,
it is copied if the method body produces a closure --- I didn't realize
that that detail changed the behavior (until just now).

Compiling this with "valac -C":

    void foo(uint8[] x) {
      x[0] = 7;
    }
delegate void Callback(); void baz(Callback callback) {
      callback();
    }
void bar(uint8[] buffer) {
      buffer[0] = 77;
      baz(() => { buffer[0] = 23; });
    }

yields the following C code:
    ...
    void foo (guint8* x, int x_length1) {
        guint8* _tmp0_;
        gint _tmp0__length1;
        guint8 _tmp1_;
        _tmp0_ = x;
        _tmp0__length1 = x_length1;
        _tmp0_[0] = (guint8) 7;
        _tmp1_ = _tmp0_[0];
    }
    ...
    void bar (guint8* x, int x_length1) {
        Block1Data* _data1_;
        guint8* _tmp0_;
        gint _tmp0__length1;
        guint8* _tmp1_;
        gint _tmp1__length1;
        guint8* _tmp2_;
        gint _tmp2__length1;
        guint8 _tmp3_;
        _data1_ = g_slice_new0 (Block1Data);
        _data1_->_ref_count_ = 1;
        _tmp0_ = x;
        _tmp0__length1 = x_length1;
        _tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup1 (_tmp0_, _tmp0__length1) : ((gpointer) _tmp0_);
        _tmp1__length1 = _tmp0__length1;
        _data1_->x = _tmp1_;
        _data1_->x_length1 = _tmp1__length1;
        _tmp2_ = _data1_->x;
        _tmp2__length1 = _data1_->x_length1;
        _tmp2_[0] = (guint8) 7;
        _tmp3_ = _tmp2_[0];
        baz (___lambda0__callback, _data1_);
        block1_data_unref (_data1_);
        _data1_ = NULL;
    }

It looks like the presence of the closure is causing the array to get
dup'ed, and it's being dup'd even before the assignment that occurs
before the closure is constructed.

-m



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]