| /* |
| * R : A Computer Language for Statistical Data Analysis |
| * Copyright (C) 2000-2014 The R Core Team |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, a copy is available at |
| * https://www.R-project.org/Licenses/ |
| */ |
| |
| |
| /* We need to know the sizes of certain internal structures */ |
| #define USE_RINTERNALS |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <Defn.h> |
| |
| /* A count of the memory used by an object. The following assumptions |
| are made. |
| |
| 1) this is called from user-level, so only some types of objects are |
| important. |
| 2) an object gets charged for all the space allocated on the heap |
| and all the nodes specifically due to it, but not for the |
| space for its name nor for .Internals it references. |
| */ |
| SEXP Rf_csduplicated(SEXP x); /* from unique.c */ |
| |
| static R_size_t objectsize(SEXP s) |
| { |
| R_size_t cnt = 0, vcnt = 0; |
| SEXP tmp, dup; |
| Rboolean isVec = FALSE; |
| |
| switch (TYPEOF(s)) { |
| case NILSXP: |
| return(0); |
| break; |
| case SYMSXP: |
| break; |
| case LISTSXP: |
| case LANGSXP: |
| case BCODESXP: |
| case DOTSXP: |
| R_CheckStack(); |
| for (Rboolean done = FALSE; ! done; ) { |
| cnt += objectsize(TAG(s)); |
| cnt += objectsize(CAR(s)); |
| cnt += sizeof(SEXPREC); |
| cnt += objectsize(ATTRIB(s)); |
| s = CDR(s); |
| switch (TYPEOF(s)) { |
| case LISTSXP: |
| case LANGSXP: |
| case BCODESXP: |
| case DOTSXP: break; |
| case NILSXP: return cnt; |
| default: done = TRUE; |
| } |
| } |
| cnt += objectsize(s); |
| break; |
| case CLOSXP: |
| R_CheckStack(); |
| cnt += objectsize(FORMALS(s)); |
| cnt += objectsize(BODY(s)); |
| /* no charge for the environment */ |
| break; |
| case ENVSXP: |
| R_CheckStack(); /* in case attributes might lead to a cycle */ |
| case PROMSXP: |
| case SPECIALSXP: |
| case BUILTINSXP: |
| break; |
| case CHARSXP: |
| vcnt = BYTE2VEC(length(s)+1); |
| isVec = TRUE; |
| break; |
| case LGLSXP: |
| case INTSXP: |
| vcnt = INT2VEC(xlength(s)); |
| isVec = TRUE; |
| break; |
| case REALSXP: |
| vcnt = FLOAT2VEC(xlength(s)); |
| isVec = TRUE; |
| break; |
| case CPLXSXP: |
| vcnt = COMPLEX2VEC(xlength(s)); |
| isVec = TRUE; |
| break; |
| case STRSXP: |
| R_CheckStack(); |
| vcnt = PTR2VEC(xlength(s)); |
| PROTECT(dup = Rf_csduplicated(s)); |
| for (R_xlen_t i = 0; i < xlength(s); i++) { |
| tmp = STRING_ELT(s, i); |
| if(tmp != NA_STRING && !LOGICAL(dup)[i]) |
| cnt += objectsize(tmp); |
| } |
| isVec = TRUE; |
| UNPROTECT(1); |
| break; |
| case ANYSXP: |
| /* we don't know about these */ |
| break; |
| case VECSXP: |
| case EXPRSXP: |
| case WEAKREFSXP: |
| /* Generic Vector Objects */ |
| R_CheckStack(); |
| vcnt = PTR2VEC(xlength(s)); |
| for (R_xlen_t i = 0; i < xlength(s); i++) |
| cnt += objectsize(VECTOR_ELT(s, i)); |
| isVec = TRUE; |
| break; |
| case EXTPTRSXP: |
| R_CheckStack(); |
| cnt += sizeof(void *); /* the actual pointer */ |
| cnt += objectsize(EXTPTR_PROT(s)); |
| cnt += objectsize(EXTPTR_TAG(s)); |
| break; |
| case RAWSXP: |
| vcnt = BYTE2VEC(xlength(s)); |
| isVec = TRUE; |
| break; |
| case S4SXP: |
| /* Has TAG and ATRIB but no CAR nor CDR */ |
| R_CheckStack(); |
| cnt += objectsize(TAG(s)); |
| break; |
| default: |
| UNIMPLEMENTED_TYPE("object.size", s); |
| } |
| /* add in node space: |
| we need to take into account the rounding up that goes on |
| in the node classes. */ |
| if(isVec) { |
| cnt += sizeof(SEXPREC_ALIGN); |
| if (vcnt > 16) cnt += 8*vcnt; |
| else if (vcnt > 8) cnt += 128; |
| else if (vcnt > 6) cnt += 64; |
| else if (vcnt > 4) cnt += 48; |
| else if (vcnt > 2) cnt += 32; |
| else if (vcnt > 1) cnt += 16; |
| else if (vcnt > 0) cnt += 8; |
| } else cnt += sizeof(SEXPREC); |
| /* add in attributes: these are fake for CHARSXPs */ |
| if(TYPEOF(s) != CHARSXP) cnt += objectsize(ATTRIB(s)); |
| return(cnt); |
| } |
| |
| |
| SEXP objectSize(SEXP x) |
| { |
| return ScalarReal( (double) objectsize(x) ); |
| } |