Closed biboudis closed 9 years ago
This is because calling
unit(new ArrayBuffer[Int]())
does not crate an IR Def which corresponds to creation of a new array buffer, instead it creates a const of the Scala ArrayBuffer that is created by new
. To avoid this, try:
def toArrayTest (xs : Rep[Array[Int]]) : Rep[Array[Int]] = {
val buffer = ArrayBuffer[Int]()
buffer += xs(0)
buffer += xs(1)
buffer.toArray
}
Indeed. Thank you!
Regarding the following, I managed to avoid it by implementing the toArray
method (in my streaming library) by an explicit loop function instead of foldingLeft (foldLeft(buf)((b, v) => { b += v; b })
), but what is the general advise here? Avoid aliasing of mutable references in general? BTW, the code compiles and runs, despite the illegal sharing error.
error: illegal sharing of mutable objects Sym(64)
at Sym(65)=Reflect(NewVar(Sym(64)),Summary(false,false,false,false,true,false,List(Sym(64)),List(Sym(64)),List(),List()),List(Sym(64)))
/*****************************************
Emitting Generated Code
*******************************************/
class toArrayTest extends ((Array[Int])=>(Array[Int])) {
def apply(x63:Array[Int]): Array[Int] = {
val x64 = scala.collection.mutable.ArrayBuffer[Int]()
var x65: scala.collection.mutable.ArrayBuffer[Int] = x64
var x66: Int = 0
var x67: Boolean = true
val x68 = x63.length
val x100 = while ({val x90 = x66
val x91 = x90 < x68
val x92 = x91 && true
x92}) {
val x95 = x66
val x96 = x63(x95)
val x97 = x64 += x96
val x98 = x66 += 1
()
}
val x101 = x64.toArray
x101
}
}
/*****************************************
End of Generated Code
*******************************************/
error: illegal sharing of mutable objects Sym(1)
at Sym(2)=Reflect(NewVar(Sym(1)),Summary(false,false,false,false,true,false,List(Sym(1)),List(Sym(1)),List(),List()),List(Sym(1)))
Thank you @astojanov
Yes, the general advice is to avoid sharing and nesting of mutable objects. So instead of putting the ArrayBuffer into a var, it is better to bind it using a val, and update it directly.
Btw, in your original snippet you were using unit(new ArrayBuffer())
. Semantically, this would mean that you are creating an ArrayBuffer
at code generation time, and then having it filled when the generated code is run. Sometimes this is indeed useful, but you'd have to use staticData
instead of unit
, because unit
only works with primitives, not heap-allocated objects.
Thank you for the tips @TiarkRompf and @astojanov!!! Tiark, especially your second comment made the semantics of unit
more clear to me!
When trying to emit (dynamically compile) the following snippet/test (static compile passes)
with the following configuration:
I get this exception:
java.lang.ClassCastException: scala.virtualization.lms.internal.Expressions$Const cannot be cast to scala.virtualization.lms.internal.Expressions$Sym
Is there something that I can fix to avoid this behavior? The full log follows.
ping @TiarkRompf