3232import com .oracle .truffle .r .runtime .RRuntime ;
3333import com .oracle .truffle .r .runtime .RType ;
3434import com .oracle .truffle .r .runtime .Utils ;
35+ import com .oracle .truffle .r .runtime .context .RContext ;
3536import com .oracle .truffle .r .runtime .data .closures .RClosures ;
3637import com .oracle .truffle .r .runtime .data .model .RAbstractContainer ;
3738import com .oracle .truffle .r .runtime .data .model .RAbstractStringVector ;
4344
4445public final class RStringVector extends RVector <Object []> implements RAbstractStringVector {
4546
46- private static volatile int fence ;
4747 private static final Assumption noWrappedStrings = Truffle .getRuntime ().createAssumption ();
4848
4949 private long nativeContentsAddr ;
@@ -85,7 +85,7 @@ public Object[] getInternalStore() {
8585
8686 @ Override
8787 public void setDataAt (Object store , int index , String value ) {
88- assert data == store ;
88+ assert canBeValidStore ( store , data ) ;
8989 if (noWrappedStrings .isValid () || store instanceof String []) {
9090 ((String []) store )[index ] = value ;
9191 } else {
@@ -96,7 +96,7 @@ public void setDataAt(Object store, int index, String value) {
9696
9797 @ Override
9898 public String getDataAt (Object store , int index ) {
99- assert data == store ;
99+ assert canBeValidStore ( store , data ) ;
100100 if (noWrappedStrings .isValid () || store instanceof String []) {
101101 return ((String []) store )[index ];
102102 }
@@ -106,7 +106,8 @@ public String getDataAt(Object store, int index) {
106106
107107 @ Override
108108 protected RStringVector internalCopy () {
109- return new RStringVector (Arrays .copyOf (data , data .length ), isComplete ());
109+ Object [] localData = data ;
110+ return new RStringVector (Arrays .copyOf (localData , localData .length ), isComplete ());
110111 }
111112
112113 @ Override
@@ -116,8 +117,9 @@ public int getLength() {
116117
117118 @ Override
118119 public String [] getDataCopy () {
119- String [] copy = new String [data .length ];
120- System .arraycopy (data , 0 , copy , 0 , data .length );
120+ Object [] localData = data ;
121+ String [] copy = new String [localData .length ];
122+ System .arraycopy (localData , 0 , copy , 0 , localData .length );
121123 return copy ;
122124 }
123125
@@ -131,11 +133,12 @@ public Object[] getReadonlyData() {
131133 * wrapped in {@link CharSXPWrapper}, then it unwraps them to a newly allocated array.
132134 */
133135 public String [] getReadonlyStringData () {
134- if (noWrappedStrings .isValid () || data instanceof String []) {
135- return (String []) data ;
136+ Object [] localData = data ;
137+ if (noWrappedStrings .isValid () || localData instanceof String []) {
138+ return (String []) localData ;
136139 }
137- assert data instanceof CharSXPWrapper [] : data ;
138- return createStringArray ((CharSXPWrapper []) data );
140+ assert localData instanceof CharSXPWrapper [] : localData ;
141+ return createStringArray ((CharSXPWrapper []) localData );
139142 }
140143
141144 @ TruffleBoundary
@@ -149,22 +152,24 @@ private static String[] createStringArray(CharSXPWrapper[] data) {
149152
150153 @ Override
151154 public String getDataAt (int i ) {
152- if (noWrappedStrings .isValid () || data instanceof String []) {
153- return ((String []) data )[i ];
155+ Object [] localData = data ;
156+ if (noWrappedStrings .isValid () || localData instanceof String []) {
157+ return ((String []) localData )[i ];
154158 }
155- assert data instanceof CharSXPWrapper [] : data ;
156- return ((CharSXPWrapper []) data )[i ].getContents ();
159+ assert data instanceof CharSXPWrapper [] : localData ;
160+ return ((CharSXPWrapper []) localData )[i ].getContents ();
157161 }
158162
159163 private RStringVector updateDataAt (int i , String right , NACheck rightNACheck ) {
160164 if (this .isShared ()) {
161165 throw RInternalError .shouldNotReachHere ("update shared vector" );
162166 }
163- if (noWrappedStrings .isValid () || data instanceof String []) {
164- data [i ] = right ;
167+ Object [] localData = data ;
168+ if (noWrappedStrings .isValid () || localData instanceof String []) {
169+ localData [i ] = right ;
165170 } else {
166- assert data instanceof CharSXPWrapper [] : data ;
167- ((CharSXPWrapper []) data )[i ] = CharSXPWrapper .create (right );
171+ assert localData instanceof CharSXPWrapper [] : localData ;
172+ ((CharSXPWrapper []) localData )[i ] = CharSXPWrapper .create (right );
168173 }
169174 if (rightNACheck .check (right )) {
170175 setComplete (false );
@@ -217,11 +222,12 @@ public RStringVector createEmptySameType(int newLength, boolean newIsComplete) {
217222
218223 @ Override
219224 public void transferElementSameType (int toIndex , RAbstractVector fromVector , int fromIndex ) {
225+ Object [] localData = getReadonlyData ();
220226 RAbstractStringVector other = (RAbstractStringVector ) fromVector ;
221227 if (noWrappedStrings .isValid ()) {
222- data [toIndex ] = other .getDataAt (fromIndex );
228+ localData [toIndex ] = other .getDataAt (fromIndex );
223229 } else {
224- setDataAt (data , toIndex , other .getDataAt (fromIndex ));
230+ setDataAt (localData , toIndex , other .getDataAt (fromIndex ));
225231 }
226232 }
227233
@@ -242,6 +248,7 @@ public Object getDataAtAsObject(int index) {
242248
243249 @ Override
244250 public void setElement (int i , Object value ) {
251+ // Note: any writes should create a local copy of the vector
245252 data [i ] = (String ) value ;
246253 }
247254
@@ -251,11 +258,8 @@ public void setElement(int i, Object value) {
251258 * vector contains plain Strings, they will be first wrapped to {@link CharSXPWrapper}s.
252259 */
253260 public long allocateNativeContents () {
254- if (nativeContentsAddr == 0 ) {
255- wrapStrings ();
256- nativeContentsAddr = NativeDataAccess .allocateNativeContents (this , (CharSXPWrapper []) data );
257- }
258- return nativeContentsAddr ;
261+ wrapStrings ();
262+ return NativeDataAccess .allocateNativeContents (this , (CharSXPWrapper []) data );
259263 }
260264
261265 /**
@@ -273,8 +277,8 @@ public void wrapStrings() {
273277 for (int i = 0 ; i < oldData .length ; i ++) {
274278 newData [i ] = CharSXPWrapper .create (oldStrings [i ]);
275279 }
280+ fence = 42 ; // make sure the array is really initialized before we set it to this.data
276281 this .data = newData ;
277- fence = 42 ;
278282 }
279283
280284 public CharSXPWrapper getWrappedDataAt (int index ) {
0 commit comments