Closed mllg closed 7 years ago
It looks like this happens because when you change the environment of a compiled function, it loses the BCODESXP. It would be nice if there were a way to change the environment without losing that.
For example:
# Compile function in a local env because if CLOENV is the global env, it
# appears a bit differently with .Internal(inspect()).
f <- local({
compiler::cmpfun(function(x) x^2))
})
# Duplicate compiled function and assign new env
f2 <- f
environment(f2) <- new.env()
.Internal(inspect(f))
.Internal(inspect(f2))
The resulting output for f
and f2
:
> .Internal(inspect(f))
@10dedec98 03 CLOSXP g0c0 [NAM(2),ATT]
FORMALS:
@10dedf3f0 02 LISTSXP g0c0 []
TAG: @1028716d0 01 SYMSXP g1c0 [MARK,NAM(2)] "x"
@10281bf08 01 SYMSXP g1c0 [MARK,NAM(2)] "" (has value)
BODY:
@10dedf188 21 BCODESXP g0c0 [NAM(2)]
CLOENV:
@10ccc9320 04 ENVSXP g0c0 [NAM(2)] <0x10ccc9320>
ATTRIB:
@10deded08 02 LISTSXP g0c0 []
TAG: @102825390 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "srcref" (has value)
@10bf511b8 13 INTSXP g0c3 [OBJ,NAM(2),ATT] (len=8, tl=0) 1,29,1,43,29,...
ATTRIB:
@10cccac70 02 LISTSXP g0c0 []
TAG: @102825400 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "srcfile" (has value)
@10cccaa78 04 ENVSXP g0c0 [OBJ,ATT] <0x10cccaa78>
FRAME:
@10cccb178 02 LISTSXP g0c0 []
TAG: @104aa4508 01 SYMSXP g1c0 [MARK,NAM(2)] "lines"
@10cf14598 16 STRSXP g0c1 [] (len=1, tl=0)
@10ce738d8 09 CHARSXP g0c4 [gp=0x60,ATT] [ASCII] [cached] "f <- local(compiler::cmpfun(function(x) x^2))
"
TAG: @104aad508 01 SYMSXP g1c0 [MARK] "filename"
@10cf14568 16 STRSXP g0c1 [] (len=1, tl=0)
@10281c6c8 09 CHARSXP g1c1 [MARK,gp=0x60] [ASCII] [cached] ""
ENCLOS:
@1028552d8 04 ENVSXP g1c0 [MARK,NAM(2)] <R_EmptyEnv>
ATTRIB:
@10ccca208 02 LISTSXP g0c0 []
TAG: @10281bd48 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "class" (has value)
@10bf52ae0 16 STRSXP g0c2 [NAM(2)] (len=2, tl=0)
@104831f50 09 CHARSXP g1c2 [MARK,gp=0x61] [ASCII] [cached] "srcfilecopy"
@10281c278 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "srcfile"
TAG: @10281bd48 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "class" (has value)
@10cf14508 16 STRSXP g0c1 [] (len=1, tl=0)
@10281c248 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "srcref"
> .Internal(inspect(f2))
@10cc4af48 03 CLOSXP g0c0 [NAM(2),ATT]
FORMALS:
@10dedf3f0 02 LISTSXP g0c0 []
TAG: @1028716d0 01 SYMSXP g1c0 [MARK,NAM(2)] "x"
@10281bf08 01 SYMSXP g1c0 [MARK,NAM(2)] "" (has value)
BODY:
@10db2d6d8 06 LANGSXP g0c0 [NAM(2)]
@10282bdf8 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x5000] "^" (has value)
@1028716d0 01 SYMSXP g1c0 [MARK,NAM(2)] "x"
@10cf0dac8 14 REALSXP g0c1 [NAM(2)] (len=1, tl=0) 2
CLOENV:
@10cc4aed8 04 ENVSXP g0c0 [NAM(1)] <0x10cc4aed8>
ATTRIB:
@10cc4af80 02 LISTSXP g0c0 []
TAG: @102825390 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "srcref" (has value)
@10bf511b8 13 INTSXP g0c3 [OBJ,NAM(2),ATT] (len=8, tl=0) 1,29,1,43,29,...
ATTRIB:
@10cccac70 02 LISTSXP g0c0 []
TAG: @102825400 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "srcfile" (has value)
@10cccaa78 04 ENVSXP g0c0 [OBJ,ATT] <0x10cccaa78>
FRAME:
@10cccb178 02 LISTSXP g0c0 []
TAG: @104aa4508 01 SYMSXP g1c0 [MARK,NAM(2)] "lines"
@10cf14598 16 STRSXP g0c1 [] (len=1, tl=0)
@10ce738d8 09 CHARSXP g0c4 [gp=0x60,ATT] [ASCII] [cached] "f <- local(compiler::cmpfun(function(x) x^2))
"
TAG: @104aad508 01 SYMSXP g1c0 [MARK] "filename"
@10cf14568 16 STRSXP g0c1 [] (len=1, tl=0)
@10281c6c8 09 CHARSXP g1c1 [MARK,gp=0x60] [ASCII] [cached] ""
ENCLOS:
@1028552d8 04 ENVSXP g1c0 [MARK,NAM(2)] <R_EmptyEnv>
ATTRIB:
@10ccca208 02 LISTSXP g0c0 []
TAG: @10281bd48 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "class" (has value)
@10bf52ae0 16 STRSXP g0c2 [NAM(2)] (len=2, tl=0)
@104831f50 09 CHARSXP g1c2 [MARK,gp=0x61] [ASCII] [cached] "srcfilecopy"
@10281c278 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "srcfile"
TAG: @10281bd48 01 SYMSXP g1c0 [MARK,NAM(2),LCK,gp=0x4000] "class" (has value)
@10cf14508 16 STRSXP g0c1 [] (len=1, tl=0)
@10281c248 09 CHARSXP g1c1 [MARK,gp=0x61] [ASCII] [cached] "srcref"
It could be an option to compile functions in R6 objects.
There's no way to preserve, but you could check for the presence of bytecode, and re-compile if found.
@hadley I don't know much about how the compiled code works, but it seems to me that if you reassign the environment of a function, it shouldn't be necessary to remove the compiled version. But that would require a change in R itself.
I suspect the overhead of re-compiling on instantiation wouldn't generally be worth it, especially because R's JIT is now enabled by default.
@wch it has to be recompiled because you've potentially changed the lookup of objects (which the bytecode might (or might in the future) cache)
Hi there,
If you add bytecode-compiled functions to a class (or let R handle it by setting
ByteCompile: yes
in the DESCRIPTION), the byte code is lost during initialization.Example:
This should either be fixed or clearly documented.