[education/rkward] rkward/rbackend: Start working on a new object modification detection scheme.

Thomas Friedrichsmeier null at kde.org
Thu May 26 10:06:45 BST 2022


Git commit 072be5d5e417031dde18f648c73f0a7ad77cd4ac by Thomas Friedrichsmeier.
Committed on 23/05/2020 at 16:56.
Pushed by tfry into branch 'master'.

Start working on a new object modification detection scheme.

Based on shadow copies, rather than active bindings, as the latter are slow, and broken in R 4.0.0.

M  +5    -0    rkward/rbackend/rkrbackend.cpp
M  +59   -0    rkward/rbackend/rkrsupport.cpp
M  +12   -0    rkward/rbackend/rkrsupport.h

https://invent.kde.org/education/rkward/commit/072be5d5e417031dde18f648c73f0a7ad77cd4ac

diff --git a/rkward/rbackend/rkrbackend.cpp b/rkward/rbackend/rkrbackend.cpp
index f4e36128..11da3242 100644
--- a/rkward/rbackend/rkrbackend.cpp
+++ b/rkward/rbackend/rkrbackend.cpp
@@ -1046,6 +1046,10 @@ SEXP RKD_AdjustSize (SEXP devnum);
 SEXP doWs (SEXP name);
 void doPendingPriorityCommands ();
 
+SEXP checkEnv(SEXP a) {
+	return RKRSupport::StringListToSEXP(RKRShadowEnvironment::environmentFor(a)->diffAndUpdate());
+}
+
 bool RKRBackend::startR () {
 	RK_TRACE (RBACKEND);
 
@@ -1134,6 +1138,7 @@ bool RKRBackend::startR () {
 		{ "rk.capture.output", (DL_FUNC) (void*) &doCaptureOutput, 5 },
 		{ "rk.graphics.device", (DL_FUNC) (void*) &RKStartGraphicsDevice, 7},
 		{ "rk.graphics.device.resize", (DL_FUNC) (void*) &RKD_AdjustSize, 1},
+		{ "rk.check.env", (DL_FUNC) (void*) &checkEnv, 1 },
 		{ 0, 0, 0 }
 	};
 	R_registerRoutines (R_getEmbeddingDllInfo(), NULL, callMethods, NULL, NULL);
diff --git a/rkward/rbackend/rkrsupport.cpp b/rkward/rbackend/rkrsupport.cpp
index ee039454..97a39335 100644
--- a/rkward/rbackend/rkrsupport.cpp
+++ b/rkward/rbackend/rkrsupport.cpp
@@ -248,3 +248,62 @@ RData *RKRSupport::SEXPToRData (SEXP from_exp) {
 
 	return data;
 }
+
+QMap<SEXP, RKRShadowEnvironment*> RKRShadowEnvironment::environments;
+RKRShadowEnvironment* RKRShadowEnvironment::environmentFor(SEXP baseenvir) {
+	if (!environments.contains(baseenvir)) {
+		// TODO: Of course this is still wrong!
+Rprintf("new shadow environment for %p\n", baseenvir);
+	SEXP tr = Rf_allocVector(INTSXP, 1);
+	INTEGER (tr)[0] = TRUE;
+		Rf_defineVar(Rf_install("shadow_hide_me"), RKRSupport::callSimpleFun2(Rf_install("new.env"), tr, R_EmptyEnv, R_GlobalEnv), R_GlobalEnv);
+		SEXP shadowenvir = Rf_findVar(Rf_install("shadow_hide_me"), R_GlobalEnv);
+		environments.insert(baseenvir, new RKRShadowEnvironment(baseenvir, shadowenvir));
+	}
+	return environments[baseenvir];
+}
+
+QStringList RKRShadowEnvironment::diffAndUpdate() {
+	QStringList diffs;
+	QStringList removed;
+
+	Rprintf("%p %p\n", baseenvir, shadowenvir);
+	// find the changed symbols, and copy them to the shadow environment
+	SEXP symbols = R_lsInternal(baseenvir, TRUE);
+	PROTECT(symbols);
+	int count = Rf_length(symbols);
+	for (int i = 0; i < count; ++i) {
+		SEXP name = Rf_installChar(STRING_ELT(symbols, i));
+		PROTECT(name);
+		SEXP main = Rf_findVar(name, baseenvir);
+		SEXP cached = Rf_findVar(name, shadowenvir);
+		if (main != cached) {
+			Rf_defineVar(name, Rf_findVar(name, baseenvir), shadowenvir);
+			diffs.append(RKRSupport::SEXPToString(name));
+		}
+		UNPROTECT(1);
+	}
+
+	// find the symbols only in the shadow environment (those that were removed)
+	SEXP symbols2 = R_lsInternal(shadowenvir, TRUE);
+	PROTECT(symbols2);
+	int count2 = Rf_length (symbols2);
+	for (int i = 0; i < count2; ++i) {
+		bool found = false;
+		for (int j = 0; j < count; ++j) {
+			if (STRING_ELT(symbols, j) == STRING_ELT(symbols2, i)) {
+				found = true;
+				break;
+			}
+		}
+		if (!found) {
+			removed.append(RKRSupport::SEXPToString(Rf_installChar(STRING_ELT(symbols2, i))));
+		}
+	}
+
+	UNPROTECT(2);
+
+	Rprintf("changed %s\n", qPrintable(diffs.join(", ")));
+	Rprintf("removed %s\n", qPrintable(removed.join(", ")));
+	return diffs + removed;
+}
diff --git a/rkward/rbackend/rkrsupport.h b/rkward/rbackend/rkrsupport.h
index d5eb3ac2..c73920ef 100644
--- a/rkward/rbackend/rkrsupport.h
+++ b/rkward/rbackend/rkrsupport.h
@@ -43,4 +43,16 @@ namespace RKRSupport {
 	RData* SEXPToRData (SEXP from_exp);
 };
 
+class RKRShadowEnvironment {
+public:
+	QStringList diffAndUpdate();
+	static RKRShadowEnvironment* environmentFor(SEXP baseenvir);
+private:
+	RKRShadowEnvironment(SEXP baseenvir, SEXP shadowenvir) : baseenvir(baseenvir), shadowenvir(shadowenvir) {};
+	~RKRShadowEnvironment();
+	SEXP baseenvir;
+	SEXP shadowenvir;
+	static QMap<SEXP, RKRShadowEnvironment*> environments;
+};
+
 #endif



More information about the rkward-tracker mailing list