Merge remote-tracking branch 'origin/master' into feature/android

This commit is contained in:
Po Lu 2023-03-11 07:53:45 +08:00
commit 769a4e7ff5
4 changed files with 115 additions and 69 deletions

View file

@ -211,7 +211,9 @@ Used to gray out relevant toolbar icons.")
;; We then merge them here into `gud-minor-mode-map'.
:parent gud-menu-mode-map
"<menu-bar>" `(menu-item nil ,gud-text-menu-bar-map
:filter ,(lambda (map) (unless window-system map))))
;; Be careful to return an empty keymap rather than nil
;; so as not to hide the parent's menus.
:filter ,(lambda (map) (if window-system '(keymap) map))))
(easy-menu-define gud-menu-map gud-menu-mode-map
"Menu for `gud-mode'."

View file

@ -645,7 +645,7 @@ back from point."
;; Email addresses
(defvar thing-at-point-email-regexp
"<?[-+_.~a-zA-Z][-+_.~:a-zA-Z0-9]*@[-.a-zA-Z0-9]+>?"
"<?[-+_~a-zA-Z0-9][-+_.~:a-zA-Z0-9]*@[-a-zA-Z0-9]+[-.a-zA-Z0-9]*>?"
"A regular expression probably matching an email address.
This does not match the real name portion, only the address, optionally
with angle brackets.")

View file

@ -49,7 +49,13 @@ static const struct hash_table_test hashtest_profiler =
hashfn_profiler,
};
static Lisp_Object
struct profiler_log {
Lisp_Object log;
EMACS_INT gc_count; /* Samples taken during GC. */
EMACS_INT discarded; /* Samples evicted during table overflow. */
};
static struct profiler_log
make_log (void)
{
/* We use a standard Elisp hash-table object, but we use it in
@ -60,11 +66,13 @@ make_log (void)
= clip_to_bounds (0, profiler_log_size, MOST_POSITIVE_FIXNUM);
ptrdiff_t max_stack_depth
= clip_to_bounds (0, profiler_max_stack_depth, PTRDIFF_MAX);;
Lisp_Object log = make_hash_table (hashtest_profiler, heap_size,
DEFAULT_REHASH_SIZE,
DEFAULT_REHASH_THRESHOLD,
Qnil, false);
struct Lisp_Hash_Table *h = XHASH_TABLE (log);
struct profiler_log log
= { make_hash_table (hashtest_profiler, heap_size,
DEFAULT_REHASH_SIZE,
DEFAULT_REHASH_THRESHOLD,
Qnil, false),
0, 0 };
struct Lisp_Hash_Table *h = XHASH_TABLE (log.log);
/* What is special about our hash-tables is that the values are pre-filled
with the vectors we'll use as keys. */
@ -116,8 +124,9 @@ static EMACS_INT approximate_median (log_t *log,
}
}
static void evict_lower_half (log_t *log)
static void evict_lower_half (struct profiler_log *plog)
{
log_t *log = XHASH_TABLE (plog->log);
ptrdiff_t size = ASIZE (log->key_and_value) / 2;
EMACS_INT median = approximate_median (log, 0, size);
@ -127,6 +136,8 @@ static void evict_lower_half (log_t *log)
if (XFIXNUM (HASH_VALUE (log, i)) <= median)
{
Lisp_Object key = HASH_KEY (log, i);
EMACS_INT count = XFIXNUM (HASH_VALUE (log, i));
plog->discarded = saturated_add (plog->discarded, count);
{ /* FIXME: we could make this more efficient. */
Lisp_Object tmp;
XSET_HASH_TABLE (tmp, log); /* FIXME: Use make_lisp_ptr. */
@ -148,12 +159,12 @@ static void evict_lower_half (log_t *log)
size for memory. */
static void
record_backtrace (log_t *log, EMACS_INT count)
record_backtrace (struct profiler_log *plog, EMACS_INT count)
{
eassert (HASH_TABLE_P (plog->log));
log_t *log = XHASH_TABLE (plog->log);
if (log->next_free < 0)
/* FIXME: transfer the evicted counts to a special entry rather
than dropping them on the floor. */
evict_lower_half (log);
evict_lower_half (plog);
ptrdiff_t index = log->next_free;
/* Get a "working memory" vector. */
@ -222,10 +233,10 @@ static enum profiler_cpu_running
profiler_cpu_running;
/* Hash-table log of CPU profiler. */
static Lisp_Object cpu_log;
static struct profiler_log cpu;
/* Separate counter for the time spent in the GC. */
static EMACS_INT cpu_gc_count;
/* Hash-table log of Memory profiler. */
static struct profiler_log memory;
/* The current sampling interval in nanoseconds. */
static EMACS_INT current_sampling_interval;
@ -233,30 +244,34 @@ static EMACS_INT current_sampling_interval;
/* Signal handler for sampling profiler. */
static void
handle_profiler_signal (int signal)
add_sample (struct profiler_log *plog, EMACS_INT count)
{
if (EQ (backtrace_top_function (), QAutomatic_GC))
if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */
/* Special case the time-count inside GC because the hash-table
code is not prepared to be used while the GC is running.
More specifically it uses ASIZE at many places where it does
not expect the ARRAY_MARK_FLAG to be set. We could try and
harden the hash-table code, but it doesn't seem worth the
effort. */
cpu_gc_count = saturated_add (cpu_gc_count, 1);
plog->gc_count = saturated_add (plog->gc_count, count);
else
{
EMACS_INT count = 1;
record_backtrace (plog, count);
}
static void
handle_profiler_signal (int signal)
{
EMACS_INT count = 1;
#if defined HAVE_ITIMERSPEC && defined HAVE_TIMER_GETOVERRUN
if (profiler_timer_ok)
{
int overruns = timer_getoverrun (profiler_timer);
eassert (overruns >= 0);
count += overruns;
}
#endif
eassert (HASH_TABLE_P (cpu_log));
record_backtrace (XHASH_TABLE (cpu_log), count);
if (profiler_timer_ok)
{
int overruns = timer_getoverrun (profiler_timer);
eassert (overruns >= 0);
count += overruns;
}
#endif
add_sample (&cpu, count);
}
static void
@ -343,11 +358,8 @@ See also `profiler-log-size' and `profiler-max-stack-depth'. */)
if (profiler_cpu_running)
error ("CPU profiler is already running");
if (NILP (cpu_log))
{
cpu_gc_count = 0;
cpu_log = make_log ();
}
if (NILP (cpu.log))
cpu = make_log ();
int status = setup_cpu_timer (sampling_interval);
if (status < 0)
@ -409,6 +421,26 @@ DEFUN ("profiler-cpu-running-p",
return profiler_cpu_running ? Qt : Qnil;
}
static Lisp_Object
export_log (struct profiler_log *log)
{
Lisp_Object result = log->log;
if (log->gc_count)
Fputhash (CALLN (Fvector, QAutomatic_GC, Qnil),
make_fixnum (log->gc_count),
result);
if (log->discarded)
Fputhash (CALLN (Fvector, QDiscarded_Samples, Qnil),
make_fixnum (log->discarded),
result);
/* Here we're making the log visible to Elisp, so it's not safe any
more for our use afterwards since we can't rely on its special
pre-allocated keys anymore. So we have to allocate a new one. */
if (profiler_cpu_running)
*log = make_log ();
return result;
}
DEFUN ("profiler-cpu-log", Fprofiler_cpu_log, Sprofiler_cpu_log,
0, 0, 0,
doc: /* Return the current cpu profiler log.
@ -418,16 +450,7 @@ of functions, where the last few elements may be nil.
Before returning, a new log is allocated for future samples. */)
(void)
{
Lisp_Object result = cpu_log;
/* Here we're making the log visible to Elisp, so it's not safe any
more for our use afterwards since we can't rely on its special
pre-allocated keys anymore. So we have to allocate a new one. */
cpu_log = profiler_cpu_running ? make_log () : Qnil;
Fputhash (make_vector (1, QAutomatic_GC),
make_fixnum (cpu_gc_count),
result);
cpu_gc_count = 0;
return result;
return (export_log (&cpu));
}
#endif /* PROFILER_CPU_SUPPORT */
@ -436,8 +459,6 @@ Before returning, a new log is allocated for future samples. */)
/* True if memory profiler is running. */
bool profiler_memory_running;
static Lisp_Object memory_log;
DEFUN ("profiler-memory-start", Fprofiler_memory_start, Sprofiler_memory_start,
0, 0, 0,
doc: /* Start/restart the memory profiler.
@ -450,8 +471,8 @@ See also `profiler-log-size' and `profiler-max-stack-depth'. */)
if (profiler_memory_running)
error ("Memory profiler is already running");
if (NILP (memory_log))
memory_log = make_log ();
if (NILP (memory.log))
memory = make_log ();
profiler_memory_running = true;
@ -490,12 +511,7 @@ of functions, where the last few elements may be nil.
Before returning, a new log is allocated for future samples. */)
(void)
{
Lisp_Object result = memory_log;
/* Here we're making the log visible to Elisp , so it's not safe any
more for our use afterwards since we can't rely on its special
pre-allocated keys anymore. So we have to allocate a new one. */
memory_log = profiler_memory_running ? make_log () : Qnil;
return result;
return (export_log (&memory));
}
@ -505,11 +521,7 @@ Before returning, a new log is allocated for future samples. */)
void
malloc_probe (size_t size)
{
if (EQ (backtrace_top_function (), QAutomatic_GC)) /* bug#60237 */
/* FIXME: We should do something like what we did with `cpu_gc_count`. */
return;
eassert (HASH_TABLE_P (memory_log));
record_backtrace (XHASH_TABLE (memory_log), min (size, MOST_POSITIVE_FIXNUM));
add_sample (&memory, min (size, MOST_POSITIVE_FIXNUM));
}
DEFUN ("function-equal", Ffunction_equal, Sfunction_equal, 2, 2, 0,
@ -589,21 +601,22 @@ to make room for new entries. */);
profiler_log_size = 10000;
DEFSYM (Qprofiler_backtrace_equal, "profiler-backtrace-equal");
DEFSYM (QDiscarded_Samples, "Discarded Samples");
defsubr (&Sfunction_equal);
#ifdef PROFILER_CPU_SUPPORT
profiler_cpu_running = NOT_RUNNING;
cpu_log = Qnil;
staticpro (&cpu_log);
cpu.log = Qnil;
staticpro (&cpu.log);
defsubr (&Sprofiler_cpu_start);
defsubr (&Sprofiler_cpu_stop);
defsubr (&Sprofiler_cpu_running_p);
defsubr (&Sprofiler_cpu_log);
#endif
profiler_memory_running = false;
memory_log = Qnil;
staticpro (&memory_log);
memory.log = Qnil;
staticpro (&memory.log);
defsubr (&Sprofiler_memory_start);
defsubr (&Sprofiler_memory_stop);
defsubr (&Sprofiler_memory_running_p);
@ -618,16 +631,16 @@ syms_of_profiler_for_pdumper (void)
if (dumped_with_pdumper_p ())
{
#ifdef PROFILER_CPU_SUPPORT
cpu_log = Qnil;
cpu.log = Qnil;
#endif
memory_log = Qnil;
memory.log = Qnil;
}
else
{
#ifdef PROFILER_CPU_SUPPORT
eassert (NILP (cpu_log));
eassert (NILP (cpu.log));
#endif
eassert (NILP (memory_log));
eassert (NILP (memory.log));
}
}

View file

@ -72,7 +72,38 @@
("<url:ftp.example.net/abc/>" 1 url "ftp://ftp.example.net/abc/")
;; UUID, only hex is allowed
("01234567-89ab-cdef-ABCD-EF0123456789" 1 uuid "01234567-89ab-cdef-ABCD-EF0123456789")
("01234567-89ab-cdef-ABCD-EF012345678G" 1 uuid nil))
("01234567-89ab-cdef-ABCD-EF012345678G" 1 uuid nil)
;; email addresses
("foo@example.com" 1 email "foo@example.com")
("f@example.com" 1 email "f@example.com")
("foo@example.com" 4 email "foo@example.com")
("foo@example.com" 5 email "foo@example.com")
("foo@example.com" 15 email "foo@example.com")
("foo@example.com" 16 email "foo@example.com")
("<foo@example.com>" 1 email "<foo@example.com>")
("<foo@example.com>" 4 email "<foo@example.com>")
("<foo@example.com>" 5 email "<foo@example.com>")
("<foo@example.com>" 16 email "<foo@example.com>")
("<foo@example.com>" 17 email "<foo@example.com>")
;; email adresses containing numbers
("foo1@example.com" 1 email "foo1@example.com")
("1foo@example.com" 1 email "1foo@example.com")
("11@example.com" 1 email "11@example.com")
("1@example.com" 1 email "1@example.com")
;; email adresses user portion containing dots
("foo.bar@example.com" 1 email "foo.bar@example.com")
(".foobar@example.com" 1 email nil)
(".foobar@example.com" 2 email "foobar@example.com")
;; email adresses domain portion containing dots and dashes
("foobar@.example.com" 1 email nil)
("foobar@-example.com" 1 email "foobar@-example.com")
;; These are illegal, but thingatpt doesn't yet handle them
;; ("foo..bar@example.com" 1 email nil)
;; ("foobar@.example.com" 1 email nil)
;; ("foobar@example..com" 1 email nil)
;; ("foobar.@example.com" 1 email nil)
)
"List of `thing-at-point' tests.
Each list element should have the form