From c861357b86fada061e9bf45eca776d73857f90c7 Mon Sep 17 00:00:00 2001 From: mattdowle Date: Sat, 31 Aug 2019 02:42:21 -0700 Subject: [PATCH 1/2] duplicate()=>copyAsPlain() due to some ALTREP 'wrappers' now percolating up in 4 revdeps: corpustools, mlr, tcpl, VIM --- src/assign.c | 10 ++++---- src/coalesce.c | 2 +- src/data.table.h | 1 + src/fmelt.c | 2 +- src/reorder.c | 4 ++-- src/subset.c | 2 +- src/transpose.c | 2 +- src/utils.c | 59 +++++++++++++++++++++++++++++++++++++++++------- src/wrappers.c | 2 +- 9 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/assign.c b/src/assign.c index ef3542f770..42a4022b27 100644 --- a/src/assign.c +++ b/src/assign.c @@ -475,7 +475,7 @@ SEXP assign(SEXP dt, SEXP rows, SEXP cols, SEXP newcolnames, SEXP values) Rprintf("RHS for item %d has been duplicated because NAMED==%d MAYBE_SHARED==%d, but then is being plonked. length(values)==%d; length(cols)==%d)\n", i+1, NAMED(thisvalue), MAYBE_SHARED(thisvalue), length(values), length(cols)); } - thisvalue = duplicate(thisvalue); // PROTECT not needed as assigned as element to protected list below. + thisvalue = copyAsPlain(thisvalue); // PROTECT not needed as assigned as element to protected list below. } else { if (verbose) Rprintf("Direct plonk of unnamed RHS, no copy. NAMED==%d, MAYBE_SHARED==%d\n", NAMED(thisvalue), MAYBE_SHARED(thisvalue)); // e.g. DT[,a:=as.character(a)] as tested by 754.5 } @@ -564,7 +564,7 @@ SEXP assign(SEXP dt, SEXP rows, SEXP cols, SEXP newcolnames, SEXP values) if (iRHS[0] != NA_INTEGER) warning("Coerced '%s' RHS to 'integer' to match the factor column's underlying type. Character columns are now recommended (can be in keys), or coerce RHS to integer or character first.", type2char(TYPEOF(thisvalue))); } else { // thisvalue is integer // make sure to copy thisvalue. May be modified below. See #2984 - RHS = PROTECT(duplicate(thisvalue)); thisprotecti++; + RHS = PROTECT(copyAsPlain(thisvalue)); thisprotecti++; iRHS = INTEGER(RHS); } for (int j=0; j maxSize) maxSize=SIZEOF(v); - if (ALTREP(v)) SET_VECTOR_ELT(x,i,duplicate(v)); // expand compact vector in place ready for reordering by reference + if (ALTREP(v)) SET_VECTOR_ELT(x, i, copyAsPlain(v)); } copySharedColumns(x); // otherwise two columns which point to the same vector would be reordered and then re-reordered, issues linked in PR#3768 } else { @@ -33,7 +33,7 @@ SEXP reorder(SEXP x, SEXP order) if (!isInteger(order)) error("order must be an integer vector"); if (length(order) != nrow) error("nrow(x)[%d]!=length(order)[%d]",nrow,length(order)); int nprotect = 0; - if (ALTREP(order)) { order=PROTECT(duplicate(order)); nprotect++; } // TODO: how to fetch range of ALTREP compact vector + if (ALTREP(order)) { order=PROTECT(copyAsPlain(order)); nprotect++; } // TODO: if it's an ALTREP sequence some optimizations are possible rather than expand const int *restrict idx = INTEGER(order); int i=0; diff --git a/src/subset.c b/src/subset.c index 7891a36dd5..f9426bb402 100644 --- a/src/subset.c +++ b/src/subset.c @@ -281,7 +281,7 @@ SEXP subsetDT(SEXP x, SEXP rows, SEXP cols) { for (int i=0; i make.levels -> rbindlist -> [ -> [.data.table + // Perhaps related to row names and the copyMostAttrib() below is not quite sufficient + + size_t n = XLENGTH(x); + SEXP ans = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); + switch (TYPEOF(ans)) { + case RAWSXP: + memcpy(RAW(ans), RAW(x), n*sizeof(Rbyte)); break; + case LGLSXP: + memcpy(LOGICAL(ans), LOGICAL(x), n*sizeof(Rboolean)); break; + case INTSXP: + memcpy(INTEGER(ans), INTEGER(x), n*sizeof(int)); break; + case REALSXP: + memcpy(REAL(ans), REAL(x), n*sizeof(double)); break; + case CPLXSXP: + memcpy(COMPLEX(ans), COMPLEX(x), n*sizeof(Rcomplex)); break; + case STRSXP: + { const SEXP *xp=STRING_PTR(x); for (R_xlen_t i=0; i1?"s":""); // GetVerbose() (slightly expensive call of all options) called here only when needed diff --git a/src/wrappers.c b/src/wrappers.c index 2dc98264ac..928be0c05a 100644 --- a/src/wrappers.c +++ b/src/wrappers.c @@ -93,7 +93,7 @@ SEXP expandAltRep(SEXP x) for (int i=0; i Date: Sat, 31 Aug 2019 18:21:23 -0700 Subject: [PATCH 2/2] coverage --- src/utils.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/utils.c b/src/utils.c index b5a7c5c072..c6b0dc52c7 100644 --- a/src/utils.c +++ b/src/utils.c @@ -194,19 +194,28 @@ SEXP copyAsPlain(SEXP x) { SEXP ans = PROTECT(allocVector(TYPEOF(x), XLENGTH(x))); switch (TYPEOF(ans)) { case RAWSXP: - memcpy(RAW(ans), RAW(x), n*sizeof(Rbyte)); break; + memcpy(RAW(ans), RAW(x), n*sizeof(Rbyte)); // # nocov; add coverage when ALTREP is turned on for all types + break; // # nocov case LGLSXP: - memcpy(LOGICAL(ans), LOGICAL(x), n*sizeof(Rboolean)); break; + memcpy(LOGICAL(ans), LOGICAL(x), n*sizeof(Rboolean)); // # nocov + break; // # nocov case INTSXP: - memcpy(INTEGER(ans), INTEGER(x), n*sizeof(int)); break; + memcpy(INTEGER(ans), INTEGER(x), n*sizeof(int)); // covered by 10:1 after test 178 + break; case REALSXP: - memcpy(REAL(ans), REAL(x), n*sizeof(double)); break; + memcpy(REAL(ans), REAL(x), n*sizeof(double)); // covered by as.Date("2013-01-01")+seq(1,1000,by=10) after test 1075 + break; case CPLXSXP: - memcpy(COMPLEX(ans), COMPLEX(x), n*sizeof(Rcomplex)); break; - case STRSXP: - { const SEXP *xp=STRING_PTR(x); for (R_xlen_t i=0; i