Commit 94fdc1d0 authored by Radford Neal's avatar Radford Neal

First version released on github

parent 9ea54f65
......@@ -135,7 +135,10 @@
\item **24
\item **25
\item **26
\item **27
\item Lookup of some builtin/special function symbols (eg, '+' and 'if')
has been sped up by allowing fast bypass of non-global environments
that do not contain (and have never contained) one of these
symbols.
\item **28
\item **29
\item **30
......
......@@ -270,6 +270,12 @@ other objects when tracing duplications (see @code{tracemem}).
The bit called @code{misc} in @pqR{} was called @code{spare} in R-2.15.0,
and was said to be unused, but this was not true.
For closures, the @code{misc} bit is used as the @code{RSTEP} flag.
The @code{misc} bit is used as the @code{SPEC_SYM} flag for the printnames of
symbols, indicating that it is one a of set of special symbols (eg, @code{+}
and @code{if}). It is also used as the @code{NO_SPEC_SYM} flag for
environments, to indicate that the environment has no symbols with the
@code{SPEC_SYM} flag set (and has never had such a symbol),
so that it can be bypassed in searches for such symbols.
@findex named bit
@findex NAMED
......
Lookup of some builtin/special function symbols (eg, '+' and 'if') has
been sped up by allowing fast bypass of non-global environments that
do not contain (and have never contained) one of these symbols. The
symbols that are special for this purpose are specified in InitNames
in names.c.
......@@ -343,12 +343,18 @@ typedef union { VECTOR_SEXPREC s; double align; } SEXPREC_ALIGN;
#define UNSET_DDVAL_BIT(x) (((x)->sxpinfo.gp) &= ~DDVAL_MASK)
#define SET_DDVAL(x,v) ((v) ? SET_DDVAL_BIT(x) : UNSET_DDVAL_BIT(x)) /* for ..1, ..2 etc */
/* Flag indicating whether a symbol starts with a special character. */
#define SPEC_SYM(x) (PRINTNAME(x)->sxpinfo.misc)
#define SET_SPEC_SYM(x,v) (PRINTNAME(x)->sxpinfo.misc = (v))
/* Environment Access Macros */
#define FRAME(x) ((x)->u.envsxp.frame)
#define ENCLOS(x) ((x)->u.envsxp.enclos)
#define HASHTAB(x) ((x)->u.envsxp.hashtab)
#define ENVFLAGS(x) ((x)->sxpinfo.gp) /* for environments */
#define SET_ENVFLAGS(x,v) (((x)->sxpinfo.gp)=(v))
#define NO_SPEC_SYM(x) ((x)->sxpinfo.misc) /* 1 = env has symbol w spec char*/
#define SET_NO_SPEC_SYM(x,v) ((x)->sxpinfo.misc = (v))
#else /* not USE_RINTERNALS */
......@@ -662,6 +668,7 @@ Rboolean Rf_psmatch(const char *, const char *, Rboolean);
void Rf_PrintValue(SEXP);
SEXP Rf_protect(SEXP);
SEXP Rf_setAttrib(SEXP, SEXP, SEXP);
void Rf_setNoSpecSymFlag(SEXP);
void Rf_setSVector(SEXP*, int, SEXP);
void Rf_set_elements_to_NA_or_NULL(SEXP, int, int);
void Rf_setVar(SEXP, SEXP, SEXP);
......@@ -1026,6 +1033,7 @@ Rboolean R_compute_identical(SEXP, SEXP, int);
#define ScalarString Rf_ScalarString
#define ScalarRaw Rf_ScalarRaw
#define setAttrib Rf_setAttrib
#define setNoSpecSymFlag Rf_setNoSpecSymFlag
#define setSVector Rf_setSVector
#define set_elements_to_NA_or_NULL Rf_set_elements_to_NA_or_NULL
#define setVar Rf_setVar
......
......@@ -48,6 +48,9 @@
* "value" slot is inspected for a value. This "top-level"
* environment is where system functions and variables reside.
*
* Environments with the NO_SPEC_SYM flag are known to not contain any
* special symbols, as indicated by the SPEC_SYM macro. Lookup for
* such a symbol can then bypass this environment without searching it.
*/
/* R 1.8.0: namespaces are no longer experimental, so the following
......@@ -156,6 +159,26 @@ static SEXP getActiveValue(SEXP fun)
/* Macro version of isNull for only the test against R_NilValue */
#define ISNULL(x) ((x) == R_NilValue)
/* Function to correctly set NO_SPEC_SYM flag for an (unhashed) environment. */
void setNoSpecSymFlag (SEXP env)
{
SEXP frame;
if (HASHTAB(env)!=R_NilValue) {
SET_NO_SPEC_SYM (env, 0);
return;
}
for (frame = FRAME(env); frame != R_NilValue; frame = CDR(frame))
if (SPEC_SYM(TAG(frame))) {
SET_NO_SPEC_SYM (env, 0);
return;
}
SET_NO_SPEC_SYM (env, 1);
}
/*----------------------------------------------------------------------
Hash Tables
......@@ -1303,6 +1326,14 @@ SEXP dynamicfindVar(SEXP symbol, RCNTXT *cptr)
SEXP findFun(SEXP symbol, SEXP rho)
{
SEXP vl;
/* If it's a symbol starting with a special character, skip to the first
environment that might contain such a symbol. */
if (SPEC_SYM(symbol)) {
while (rho != R_EmptyEnv && NO_SPEC_SYM(rho))
rho = ENCLOS(rho);
}
while (rho != R_EmptyEnv) {
/* This is not really right. Any variable can mask a function */
#ifdef USE_GLOBAL_CACHE
......@@ -1371,6 +1402,10 @@ void defineVar(SEXP symbol, SEXP value, SEXP rho)
#ifdef USE_GLOBAL_CACHE
if (IS_GLOBAL_FRAME(rho)) R_FlushGlobalCache(symbol);
#endif
if (SPEC_SYM(symbol))
SET_NO_SPEC_SYM(rho,0);
if (HASHTAB(rho) == R_NilValue) {
/* First check for an existing binding */
frame = FRAME(rho);
......@@ -2131,6 +2166,7 @@ SEXP attribute_hidden do_attach(SEXP call, SEXP op, SEXP args, SEXP env)
error(_("all elements of a list must be named"));
PROTECT(s = allocSExp(ENVSXP));
SET_FRAME(s, duplicate(CAR(args)));
setNoSpecSymFlag(s);
} else if (isEnvironment(CAR(args))) {
SEXP p, loadenv = CAR(args);
......
......@@ -769,6 +769,8 @@ static SEXP applyClosure_v (SEXP call, SEXP op, SEXP arglist, SEXP rho,
a = CDR(a);
}
setNoSpecSymFlag (newrho);
/* Fix up any extras that were supplied by usemethod. */
if (suppliedenv != R_NilValue) {
......
......@@ -1044,6 +1044,29 @@ attribute_hidden FUNTAB R_FunTab[] =
};
/* Table of special names. There are marked as special with SET_SPEC_SYM.
Environments that have never contained such a symbol are marked as such,
so they can be quickly skipped when searching for a function named by such
a special symbol.
Any symbols can be put here, but ones that contain special characters, or are
reserved words, are the ones unlikely to be defined in any environment other
than base, and hence the ones where this is most likely to help. */
static char *Spec_name[] = {
"if", "while", "repeat", "for", "break", "next", "return", "function",
"(", "{",
"+", "-", "*", "/", "^", "%%", "%/%", "%*%", ":",
"==", "!=", "<", ">", "<=", ">=",
"&", "|", "&&", "||", "!",
"<-", "<<-", "=",
"$", "[", "[[",
"$<-", "[<-", "[[<-",
0
};
/* also used in eval.c */
SEXP attribute_hidden R_Primitive(const char *primname)
{
......@@ -1177,13 +1200,19 @@ void InitNames()
R_print.na_string = NA_STRING;
/* R_BlankString */
R_BlankString = mkChar("");
/* Initialize the symbol Table */
for (int i = 0; i < HSIZE; i++) R_SymbolTable[i] = R_NilValue;
/* Set up a set of globals so that a symbol table search can be
avoided when matching something like dim or dimnames. */
SymbolShortcuts();
/* Builtin Functions */
for (int i = 0; R_FunTab[i].name; i++) installFunTab(i);
for (int i = 0; Spec_name[i]; i++)
SET_SPEC_SYM (install(Spec_name[i]), 1);
framenames = R_NilValue;
R_initialize_bcode();
......@@ -1212,6 +1241,7 @@ SEXP install(const char *name)
sym = mkSYMSXP(mkChar(name), R_UnboundValue);
SET_HASHVALUE(PRINTNAME(sym), hashcode);
SET_HASHASH(PRINTNAME(sym), 1);
R_SymbolTable[i] = CONS(sym, R_SymbolTable[i]);
return (sym);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment