Skip to content

Commit d055a9e

Browse files
committed
Make sure RStringVector methods work with local copy of the data field
1 parent 5a4f074 commit d055a9e

File tree

2 files changed

+47
-26
lines changed

2 files changed

+47
-26
lines changed

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.oracle.truffle.r.runtime.RRuntime;
3333
import com.oracle.truffle.r.runtime.RType;
3434
import com.oracle.truffle.r.runtime.Utils;
35+
import com.oracle.truffle.r.runtime.context.RContext;
3536
import com.oracle.truffle.r.runtime.data.closures.RClosures;
3637
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
3738
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -43,7 +44,6 @@
4344

4445
public 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) {

com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.oracle.truffle.r.runtime.RInternalError;
3333
import com.oracle.truffle.r.runtime.RRuntime;
3434
import com.oracle.truffle.r.runtime.SuppressFBWarnings;
35+
import com.oracle.truffle.r.runtime.context.RContext;
3536
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
3637
import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
3738
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -58,6 +59,11 @@
5859
*/
5960
public abstract class RVector<ArrayT> extends RSharingAttributeStorage implements RAbstractVector, RFFIAccess {
6061

62+
/**
63+
* Dummy volatile field that can be used to create memory barrier.
64+
*/
65+
protected static volatile int fence;
66+
6167
protected boolean complete; // "complete" means: does not contain NAs
6268

6369
protected RVector(boolean complete) {
@@ -783,4 +789,15 @@ public final String toString() {
783789
}
784790
return str.append(']').toString();
785791
}
792+
793+
protected boolean canBeValidStore(Object store, Object data) {
794+
RContext ctx;
795+
try {
796+
ctx = RContext.getInstance();
797+
} catch (IllegalStateException ex) {
798+
return true; // no context, we cannot check anything
799+
}
800+
// We can be only sure if there is only one thread
801+
return !ctx.isSingle() || store == data;
802+
}
786803
}

0 commit comments

Comments
 (0)