Implement TARGET_OBJECT_STACK_MEMORY.
authorDoug Evans <dje@google.com>
Mon, 31 Aug 2009 20:18:46 +0000 (20:18 +0000)
committerDoug Evans <dje@google.com>
Mon, 31 Aug 2009 20:18:46 +0000 (20:18 +0000)
* NEWS: Add note on new "set stack-cache" option.
* corefile.c (read_stack): New function.
* dcache.c (dcache_struct): New member ptid.
(dcache_enable_p): Mark as obsolete.
(show_dcache_enabled_p): Flag option as deprecated.
(dcache_invalidate): Update ptid.
(dcache_invalidate_line): New function.
(dcache_read_line): No longer check cacheable attribute, stack
accesses get cached despite attribute.
(dcache_init): Set ptid.
(dcache_xfer_memory): Flush cache if from different ptid than before.
Update cache after write.
(dcache_update): New function.
(dcache_info): Report ptid.
(_initialize_dcache): Update text for `remotecache' to indicate it
is obsolete.
* dcache.h (dcache_update): Declare.
* dwarf2loc.c (dwarf2_evaluate_loc_desc): Mark values on stack with
set_value_stack.
* frame-unwind.c (frame_unwind_got_memory): Ditto.
* gdbcore.h (read_stack): Declare.
* memattr.c (mem_enable_command): Call target_dcache_invalidate
instead of dcache_invalidate.
(mem_disable_command, mem_delete_command): Ditto.
* target.c (stack_cache_enabled_p_1): New static global.
(stack_cache_enabled_p): New static global.
(set_stack_cache_enabled_p): New function.
(show_stack_cache_enabled_p): New function.
(target_dcache): Make static.
(target_dcache_invalidate): New function.
(target_load, target_resume): Call target_dcache_invalidate
instead of dcache_invalidate.
(memory_xfer_partial): New arg object, all callers updated.
Check for existing inferior before calling dcache routines.
When writing non-TARGET_OBJECT_STACK_MEMORY, notify dcache.
(target_xfer_partial): Call memory_xfer_partial for
TARGET_OBJECT_STACK_MEMORY.
(target_read_stack): New function.
(initialize_targets): Install new option `stack-cache'.
* target.h: Remove #include of dcache.h.
(enum target_object): New value TARGET_OBJECT_STACK_MEMORY.
(target_dcache): Delete.
(target_dcache_invalidate): Declare.
(target_read_stack): Declare.
* top.c (prepare_execute_command): New function.
(execute_command): Call prepare_execute_command
instead of free_all_values.
* top.h (prepare_execute_command): Declare.
* valops.c (get_value_at): New function.
(value_at): Guts moved to get_value_at.
(value_at_lazy): Similarly.
(value_fetch_lazy): Call read_stack for stack values.
* value.c (struct value): New member `stack'.
(value_stack, set_value_stack): New functions.
* value.h (value_stack, set_value_stack): Declare.
* mi/mi-main.c (mi_cmd_execute): Call prepare_execute_command
instead of free_all_values.

doc/
* gdb.texinfo (Caching Data of Remote Targets): Update text.
Mark `set/show remotecache' options as obsolete.
Document new `set/show stack-cache' option.
Update text for `info dcache'.

19 files changed:
gdb/ChangeLog
gdb/NEWS
gdb/corefile.c
gdb/dcache.c
gdb/dcache.h
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/dwarf2loc.c
gdb/frame-unwind.c
gdb/gdbcore.h
gdb/memattr.c
gdb/mi/mi-main.c
gdb/target.c
gdb/target.h
gdb/top.c
gdb/top.h
gdb/valops.c
gdb/value.c
gdb/value.h

index 32fcf5dcaedcf0750a9deeaa6e479458fda19a17..19c41517f2a7f7397ee4e56b3f4585bcd2ea6784 100644 (file)
@@ -1,3 +1,65 @@
+2009-08-31  Jacob Potter  <jdpotter@google.com>
+           Doug Evans  <dje@google.com>
+
+       Implement TARGET_OBJECT_STACK_MEMORY.
+       * NEWS: Add note on new "set stack-cache" option.
+       * corefile.c (read_stack): New function.
+       * dcache.c (dcache_struct): New member ptid.
+       (dcache_enable_p): Mark as obsolete.
+       (show_dcache_enabled_p): Flag option as deprecated.
+       (dcache_invalidate): Update ptid.
+       (dcache_invalidate_line): New function.
+       (dcache_read_line): No longer check cacheable attribute, stack
+       accesses get cached despite attribute.
+       (dcache_init): Set ptid.
+       (dcache_xfer_memory): Flush cache if from different ptid than before.
+       Update cache after write.
+       (dcache_update): New function.
+       (dcache_info): Report ptid.
+       (_initialize_dcache): Update text for `remotecache' to indicate it
+       is obsolete.
+       * dcache.h (dcache_update): Declare.
+       * dwarf2loc.c (dwarf2_evaluate_loc_desc): Mark values on stack with
+       set_value_stack.
+       * frame-unwind.c (frame_unwind_got_memory): Ditto.
+       * gdbcore.h (read_stack): Declare.
+       * memattr.c (mem_enable_command): Call target_dcache_invalidate
+       instead of dcache_invalidate.
+       (mem_disable_command, mem_delete_command): Ditto.
+       * target.c (stack_cache_enabled_p_1): New static global.
+       (stack_cache_enabled_p): New static global.
+       (set_stack_cache_enabled_p): New function.
+       (show_stack_cache_enabled_p): New function.
+       (target_dcache): Make static.
+       (target_dcache_invalidate): New function.
+       (target_load, target_resume): Call target_dcache_invalidate
+       instead of dcache_invalidate.
+       (memory_xfer_partial): New arg object, all callers updated.
+       Check for existing inferior before calling dcache routines.
+       When writing non-TARGET_OBJECT_STACK_MEMORY, notify dcache.
+       (target_xfer_partial): Call memory_xfer_partial for
+       TARGET_OBJECT_STACK_MEMORY.
+       (target_read_stack): New function.
+       (initialize_targets): Install new option `stack-cache'.
+       * target.h: Remove #include of dcache.h.
+       (enum target_object): New value TARGET_OBJECT_STACK_MEMORY.
+       (target_dcache): Delete.
+       (target_dcache_invalidate): Declare.
+       (target_read_stack): Declare.
+       * top.c (prepare_execute_command): New function.
+       (execute_command): Call prepare_execute_command
+       instead of free_all_values.
+       * top.h (prepare_execute_command): Declare.
+       * valops.c (get_value_at): New function.
+       (value_at): Guts moved to get_value_at.
+       (value_at_lazy): Similarly.
+       (value_fetch_lazy): Call read_stack for stack values.
+       * value.c (struct value): New member `stack'.
+       (value_stack, set_value_stack): New functions.
+       * value.h (value_stack, set_value_stack): Declare.
+       * mi/mi-main.c (mi_cmd_execute): Call prepare_execute_command
+       instead of free_all_values.
+
 2009-08-29  Hui Zhu  <teawater@gmail.com>
 
        * i386-tdep.c (i386_process_record): Fix the error of string
index 179c977773d97a52711e0ed0b539646c92dfc067..e3e67741c41f653762effd26cc6d8e0680417386 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -394,6 +394,12 @@ show schedule-multiple
   Allow GDB to resume all threads of all processes or only threads of
   the current process.
 
+set stack-cache
+show stack-cache
+  Use more aggressive caching for accesses to the stack.  This improves
+  performance of remote debugging (particularly backtraces) without
+  affecting correctness.
+
 * Removed commands
 
 info forks
index 6de0772584ca623463c7087ba18654b65b9eb6e1..e70688ee314ab74daf3db5cdfdb3a26cc912f78a 100644 (file)
@@ -228,6 +228,7 @@ memory_error (int status, CORE_ADDR memaddr)
 }
 
 /* Same as target_read_memory, but report an error if can't read.  */
+
 void
 read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
 {
@@ -237,6 +238,17 @@ read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
     memory_error (status, memaddr);
 }
 
+/* Same as target_read_stack, but report an error if can't read.  */
+
+void
+read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+  int status;
+  status = target_read_stack (memaddr, myaddr, len);
+  if (status != 0)
+    memory_error (status, memaddr);
+}
+
 /* Argument / return result struct for use with
    do_captured_read_memory_integer().  MEMADDR and LEN are filled in
    by gdb_read_memory_integer().  RESULT is the contents that were
index 17c948a4d200c96f7ae94cc6d8e4a1408160026b..52375f092a19d468cb2a352562aca809d2b2c616 100644 (file)
@@ -24,6 +24,7 @@
 #include "gdb_string.h"
 #include "gdbcore.h"
 #include "target.h"
+#include "inferior.h"
 #include "splay-tree.h"
 
 /* The data cache could lead to incorrect results because it doesn't
@@ -103,6 +104,9 @@ struct dcache_struct
 
   /* The number of in-use lines in the cache.  */
   int size;
+
+  /* The ptid of last inferior to use cache or null_ptid.  */
+  ptid_t ptid;
 };
 
 static struct dcache_block *dcache_hit (DCACHE *dcache, CORE_ADDR addr);
@@ -117,16 +121,15 @@ static void dcache_info (char *exp, int tty);
 
 void _initialize_dcache (void);
 
-static int dcache_enabled_p = 0;
+static int dcache_enabled_p = 0; /* OBSOLETE */
 
 static void
 show_dcache_enabled_p (struct ui_file *file, int from_tty,
                       struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Cache use for remote targets is %s.\n"), value);
+  fprintf_filtered (file, _("Deprecated remotecache flag is %s.\n"), value);
 }
 
-
 static DCACHE *last_cache; /* Used by info dcache */
 
 /* Free all the data cache blocks, thus discarding all cached data.  */
@@ -152,6 +155,23 @@ dcache_invalidate (DCACHE *dcache)
   dcache->oldest = NULL;
   dcache->newest = NULL;
   dcache->size = 0;
+  dcache->ptid = null_ptid;
+}
+
+/* Invalidate the line associated with ADDR.  */
+
+static void
+dcache_invalidate_line (DCACHE *dcache, CORE_ADDR addr)
+{
+  struct dcache_block *db = dcache_hit (dcache, addr);
+
+  if (db)
+    {
+      splay_tree_remove (dcache->tree, (splay_tree_key) db->addr);
+      db->newer = dcache->freelist;
+      dcache->freelist = db;
+      --dcache->size;
+    }
 }
 
 /* If addr is present in the dcache, return the address of the block
@@ -198,8 +218,9 @@ dcache_read_line (DCACHE *dcache, struct dcache_block *db)
       else
        reg_len = region->hi - memaddr;
 
-      /* Skip non-cacheable/non-readable regions.  */
-      if (!region->attrib.cache || region->attrib.mode == MEM_WO)
+      /* Skip non-readable regions.  The cache attribute can be ignored,
+         since we may be loading this for a stack access.  */
+      if (region->attrib.mode == MEM_WO)
        {
          memaddr += reg_len;
          myaddr  += reg_len;
@@ -296,7 +317,7 @@ dcache_peek_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
    an area of memory which wasn't present in the cache doesn't cause
    it to be loaded in.
 
-   Always return 1 to simplify dcache_xfer_memory.  */
+   Always return 1 (meaning success) to simplify dcache_xfer_memory.  */
 
 static int
 dcache_poke_byte (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr)
@@ -338,6 +359,7 @@ dcache_init (void)
   dcache->newest = NULL;
   dcache->freelist = NULL;
   dcache->size = 0;
+  dcache->ptid = null_ptid;
   last_cache = dcache;
 
   return dcache;
@@ -366,7 +388,7 @@ dcache_free (DCACHE *dcache)
    to or from debugger address MYADDR.  Write to inferior if SHOULD_WRITE is
    nonzero. 
 
-   Returns length of data written or read; 0 for error.  */
+   The meaning of the result is the same as for target_write.  */
 
 int
 dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
@@ -378,6 +400,15 @@ dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
   int (*xfunc) (DCACHE *dcache, CORE_ADDR addr, gdb_byte *ptr);
   xfunc = should_write ? dcache_poke_byte : dcache_peek_byte;
 
+  /* If this is a different inferior from what we've recorded,
+     flush the cache.  */
+
+  if (! ptid_equal (inferior_ptid, dcache->ptid))
+    {
+      dcache_invalidate (dcache);
+      dcache->ptid = inferior_ptid;
+    }
+
   /* Do write-through first, so that if it fails, we don't write to
      the cache at all.  */
 
@@ -385,14 +416,25 @@ dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
     {
       res = target_write (ops, TARGET_OBJECT_RAW_MEMORY,
                          NULL, myaddr, memaddr, len);
-      if (res < len)
-       return 0;
+      if (res <= 0)
+       return res;
+      /* Update LEN to what was actually written.  */
+      len = res;
     }
       
   for (i = 0; i < len; i++)
     {
       if (!xfunc (dcache, memaddr + i, myaddr + i))
-       return 0;
+       {
+         /* That failed.  Discard its cache line so we don't have a
+            partially read line.  */
+         dcache_invalidate_line (dcache, memaddr + i);
+         /* If we're writing, we still wrote LEN bytes.  */
+         if (should_write)
+           return len;
+         else
+           return i;
+       }
     }
     
   return len;
@@ -407,6 +449,18 @@ dcache_xfer_memory (struct target_ops *ops, DCACHE *dcache,
    "logically" connected but not actually a single call to one of the
    memory transfer functions.  */
 
+/* Just update any cache lines which are already present.  This is called
+   by memory_xfer_partial in cases where the access would otherwise not go
+   through the cache.  */
+
+void
+dcache_update (DCACHE *dcache, CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+  int i;
+  for (i = 0; i < len; i++)
+    dcache_poke_byte (dcache, memaddr + i, myaddr + i);
+}
+
 static void
 dcache_print_line (int index)
 {
@@ -474,12 +528,15 @@ dcache_info (char *exp, int tty)
   printf_filtered (_("Dcache line width %d, maximum size %d\n"),
                   LINE_SIZE, DCACHE_SIZE);
 
-  if (!last_cache)
+  if (!last_cache || ptid_equal (last_cache->ptid, null_ptid))
     {
       printf_filtered (_("No data cache available.\n"));
       return;
     }
 
+  printf_filtered (_("Contains data for %s\n"),
+                  target_pid_to_str (last_cache->ptid));
+
   refcount = 0;
 
   n = splay_tree_min (last_cache->tree);
@@ -507,11 +564,10 @@ _initialize_dcache (void)
                           &dcache_enabled_p, _("\
 Set cache use for remote targets."), _("\
 Show cache use for remote targets."), _("\
-When on, use data caching for remote targets.  For many remote targets\n\
-this option can offer better throughput for reading target memory.\n\
-Unfortunately, gdb does not currently know anything about volatile\n\
-registers and thus data caching will produce incorrect results with\n\
-volatile registers are in use.  By default, this option is off."),
+This used to enable the data cache for remote targets.  The cache\n\
+functionality is now controlled by the memory region system and the\n\
+\"stack-cache\" flag; \"remotecache\" now does nothing and\n\
+exists only for compatibility reasons."),
                           NULL,
                           show_dcache_enabled_p,
                           &setlist, &showlist);
index 3f7400cbdbba75c26dc992be2a65ad02b210a1be..a141b85a57be266da35e31c6ecdcc4d8debbdb48 100644 (file)
@@ -38,4 +38,7 @@ void dcache_free (DCACHE *);
 int dcache_xfer_memory (struct target_ops *ops, DCACHE *cache, CORE_ADDR mem,
                        gdb_byte *my, int len, int should_write);
 
+void dcache_update (DCACHE *dcache, CORE_ADDR memaddr, gdb_byte *myaddr,
+                   int len);
+
 #endif /* DCACHE_H */
index 3423ee21639930d02f9f304f0d82a9d72a83bd4a..8831e0aa76e06a4f55a12a2da73efb094147fea7 100644 (file)
@@ -1,3 +1,11 @@
+2009-08-31  Jacob Potter  <jdpotter@google.com>
+           Doug Evans  <dje@google.com>
+
+       * gdb.texinfo (Caching Data of Remote Targets): Update text.
+       Mark `set/show remotecache' options as obsolete.
+       Document new `set/show stack-cache' option.
+       Update text for `info dcache'.
+
 2009-08-27  Doug Evans  <dje@google.com>
 
        * gdb.texinfo (Symbols): Delete `set print symbol-loading'.
index cc66d1284799042082f387b0d6e3012fd55de421..0e9fd449bded4aa2685e8cb2cac969df2993c93f 100644 (file)
@@ -8421,32 +8421,47 @@ character.
 @section Caching Data of Remote Targets
 @cindex caching data of remote targets
 
-@value{GDBN} can cache data exchanged between the debugger and a
+@value{GDBN} caches data exchanged between the debugger and a
 remote target (@pxref{Remote Debugging}).  Such caching generally improves
 performance, because it reduces the overhead of the remote protocol by
-bundling memory reads and writes into large chunks.  Unfortunately,
-@value{GDBN} does not currently know anything about volatile
-registers, and thus data caching will produce incorrect results when
-volatile registers are in use.
+bundling memory reads and writes into large chunks.  Unfortunately, simply
+caching everything would lead to incorrect results, since @value{GDBN} 
+does not necessarily know anything about volatile values, memory-mapped I/O
+addresses, etc.  Therefore, by default, @value{GDBN} only caches data
+known to be on the stack.  Other regions of memory can be explicitly marked
+cacheable; see @pxref{Memory Region Attributes}.
 
 @table @code
 @kindex set remotecache
 @item set remotecache on
 @itemx set remotecache off
-Set caching state for remote targets.  When @code{ON}, use data
-caching.  By default, this option is @code{OFF}.
+This option no longer does anything; it exists for compatibility
+with old scripts.
 
 @kindex show remotecache
 @item show remotecache
-Show the current state of data caching for remote targets.
+Show the current state of the obsolete remotecache flag.
+
+@kindex set stack-cache
+@item set stack-cache on
+@itemx set stack-cache off
+Enable or disable caching of stack accesses.  When @code{ON}, use
+caching.  By default, this option is @code{ON}.
+
+@kindex show stack-cache
+@item show stack-cache
+Show the current state of data caching for memory accesses.
 
 @kindex info dcache
-@item info dcache
+@item info dcache @r{[}line@r{]}
 Print the information about the data cache performance.  The
-information displayed includes: the dcache width and depth; and for
-each cache line, how many times it was referenced, and its data and
-state (invalid, dirty, valid).  This command is useful for debugging
-the data cache operation.
+information displayed includes the dcache width and depth, and for
+each cache line, its number, address, and how many times it was
+referenced.  This command is useful for debugging the data cache
+operation.
+
+If a line number is specified, the contents of that line will be
+printed in hex.
 @end table
 
 @node Searching Memory
index 1df6a9f05c4ce6646115b2816bf6803f1b1138ef..b6c9b1104fb3791a26fd6e218b334ac861bedbc0 100644 (file)
@@ -280,6 +280,7 @@ dwarf2_evaluate_loc_desc (struct symbol *var, struct frame_info *frame,
       retval = allocate_value (SYMBOL_TYPE (var));
       VALUE_LVAL (retval) = lval_memory;
       set_value_lazy (retval, 1);
+      set_value_stack (retval, 1);
       set_value_address (retval, address);
     }
 
index 238c6a1b5615eae0252aff869b7ebb3e38be6134..f0c2a64c787271e2bfc68017d0c73d3851720119 100644 (file)
@@ -153,8 +153,10 @@ struct value *
 frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr)
 {
   struct gdbarch *gdbarch = frame_unwind_arch (frame);
+  struct value *v = value_at_lazy (register_type (gdbarch, regnum), addr);
 
-  return value_at_lazy (register_type (gdbarch, regnum), addr);
+  set_value_stack (v, 1);
+  return v;
 }
 
 /* Return a value which indicates that FRAME's saved version of
index e339c0baa5c7b00c626269ea770dbc13cb42048c..7a7dcb2b3acf4a278474111cdecad6f3342b93d3 100644 (file)
@@ -47,6 +47,10 @@ extern void memory_error (int status, CORE_ADDR memaddr);
 
 extern void read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
 
+/* Like target_read_stack, but report an error if can't read.  */
+
+extern void read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
+
 /* Read an integer from debugged memory, given address and number of
    bytes.  */
 
index 356b4d6194a470b8243a6ecbe759db0d568ef020..0d2fea2c3c1a1ccd3229d1982f18c526e154d575 100644 (file)
@@ -571,7 +571,7 @@ mem_enable_command (char *args, int from_tty)
 
   require_user_regions (from_tty);
 
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
 
   if (p == 0)
     {
@@ -625,7 +625,7 @@ mem_disable_command (char *args, int from_tty)
 
   require_user_regions (from_tty);
 
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
 
   if (p == 0)
     {
@@ -686,7 +686,7 @@ mem_delete_command (char *args, int from_tty)
 
   require_user_regions (from_tty);
 
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
 
   if (p == 0)
     {
index 6aa1d08db994366bb97158674215f1b2cb40e144..857a5d5125d060b24e89f58db007054d53dddd8b 100644 (file)
@@ -1353,7 +1353,8 @@ mi_cmd_execute (struct mi_parse *parse)
   struct cleanup *cleanup;
   int i;
 
-  free_all_values ();
+  prepare_execute_command ();
+
   cleanup = make_cleanup (null_cleanup, NULL);
 
   if (parse->frame != -1 && parse->thread == -1)
index 040087b0aa1b97685f967b1a5f1c1185904425de..d828332883f90ee686641f7d606d384f55c900f1 100644 (file)
@@ -210,7 +210,45 @@ show_targetdebug (struct ui_file *file, int from_tty,
 
 static void setup_target_debug (void);
 
-DCACHE *target_dcache;
+/* The option sets this.  */
+static int stack_cache_enabled_p_1 = 1;
+/* And set_stack_cache_enabled_p updates this.
+   The reason for the separation is so that we don't flush the cache for
+   on->on transitions.  */
+static int stack_cache_enabled_p = 1;
+
+/* This is called *after* the stack-cache has been set.
+   Flush the cache for off->on and on->off transitions.
+   There's no real need to flush the cache for on->off transitions,
+   except cleanliness.  */
+
+static void
+set_stack_cache_enabled_p (char *args, int from_tty,
+                          struct cmd_list_element *c)
+{
+  if (stack_cache_enabled_p != stack_cache_enabled_p_1)
+    target_dcache_invalidate ();
+
+  stack_cache_enabled_p = stack_cache_enabled_p_1;
+}
+
+static void
+show_stack_cache_enabled_p (struct ui_file *file, int from_tty,
+                           struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Cache use for stack accesses is %s.\n"), value);
+}
+
+/* Cache of memory operations, to speed up remote access.  */
+static DCACHE *target_dcache;
+
+/* Invalidate the target dcache.  */
+
+void
+target_dcache_invalidate (void)
+{
+  dcache_invalidate (target_dcache);
+}
 
 /* The user just typed 'target' without the name of a target.  */
 
@@ -413,7 +451,7 @@ target_kill (void)
 void
 target_load (char *arg, int from_tty)
 {
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
   (*current_target.to_load) (arg, from_tty);
 }
 
@@ -1143,12 +1181,14 @@ target_section_by_addr (struct target_ops *target, CORE_ADDR addr)
    value are just as for target_xfer_partial.  */
 
 static LONGEST
-memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf,
-                    ULONGEST memaddr, LONGEST len)
+memory_xfer_partial (struct target_ops *ops, enum target_object object,
+                    void *readbuf, const void *writebuf, ULONGEST memaddr,
+                    LONGEST len)
 {
   LONGEST res;
   int reg_len;
   struct mem_region *region;
+  struct inferior *inf;
 
   /* Zero length requests are ok and require no work.  */
   if (len == 0)
@@ -1223,7 +1263,11 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
       return -1;
     }
 
-  if (region->attrib.cache)
+  inf = find_inferior_pid (ptid_get_pid (inferior_ptid));
+
+  if (inf != NULL
+      && (region->attrib.cache
+         || (stack_cache_enabled_p && object == TARGET_OBJECT_STACK_MEMORY)))
     {
       if (readbuf != NULL)
        res = dcache_xfer_memory (ops, target_dcache, memaddr, readbuf,
@@ -1245,6 +1289,19 @@ memory_xfer_partial (struct target_ops *ops, void *readbuf, const void *writebuf
        }
     }
 
+  /* Make sure the cache gets updated no matter what - if we are writing
+     to the stack, even if this write is not tagged as such, we still need
+     to update the cache. */
+
+  if (inf != NULL
+      && readbuf == NULL
+      && !region->attrib.cache
+      && stack_cache_enabled_p
+      && object != TARGET_OBJECT_STACK_MEMORY)
+    {
+      dcache_update (target_dcache, memaddr, (void *) writebuf, reg_len);
+    }
+
   /* If none of those methods found the memory we wanted, fall back
      to a target partial transfer.  Normally a single call to
      to_xfer_partial is enough; if it doesn't recognize an object
@@ -1308,8 +1365,9 @@ target_xfer_partial (struct target_ops *ops,
   /* If this is a memory transfer, let the memory-specific code
      have a look at it instead.  Memory transfers are more
      complicated.  */
-  if (object == TARGET_OBJECT_MEMORY)
-    retval = memory_xfer_partial (ops, readbuf, writebuf, offset, len);
+  if (object == TARGET_OBJECT_MEMORY || object == TARGET_OBJECT_STACK_MEMORY)
+    retval = memory_xfer_partial (ops, object, readbuf,
+                                 writebuf, offset, len);
   else
     {
       enum target_object raw_object = object;
@@ -1391,6 +1449,23 @@ target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
     return EIO;
 }
 
+/* Like target_read_memory, but specify explicitly that this is a read from
+   the target's stack.  This may trigger different cache behavior.  */
+
+int
+target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len)
+{
+  /* Dispatch to the topmost target, not the flattened current_target.
+     Memory accesses check target->to_has_(all_)memory, and the
+     flattened target doesn't inherit those.  */
+
+  if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
+                  myaddr, memaddr, len) == len)
+    return 0;
+  else
+    return EIO;
+}
+
 int
 target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, int len)
 {
@@ -2055,7 +2130,7 @@ target_resume (ptid_t ptid, int step, enum target_signal signal)
 {
   struct target_ops *t;
 
-  dcache_invalidate (target_dcache);
+  target_dcache_invalidate ();
 
   for (t = current_target.beneath; t != NULL; t = t->beneath)
     {
@@ -3479,5 +3554,16 @@ Tells gdb whether to control the inferior in asynchronous mode."),
                           &setlist,
                           &showlist);
 
+  add_setshow_boolean_cmd ("stack-cache", class_support,
+                          &stack_cache_enabled_p, _("\
+Set cache use for stack access."), _("\
+Show cache use for stack access."), _("\
+When on, use the data cache for all stack access, regardless of any\n\
+configured memory regions.  This improves remote performance significantly.\n\
+By default, caching for stack access is on."),
+                          set_stack_cache_enabled_p,
+                          show_stack_cache_enabled_p,
+                          &setlist, &showlist);
+
   target_dcache = dcache_init ();
 }
index 2c743e93fcc9f0826097c09d422a1bd7432c39c4..c210fea3b1bc600951f5eb866cc245295c5b767f 100644 (file)
@@ -53,7 +53,6 @@ struct target_section_table;
 
 #include "bfd.h"
 #include "symtab.h"
-#include "dcache.h"
 #include "memattr.h"
 #include "vec.h"
 #include "gdb_signals.h"
@@ -203,6 +202,10 @@ enum target_object
      Target implementations of to_xfer_partial never need to handle
      this object, and most callers should not use it.  */
   TARGET_OBJECT_RAW_MEMORY,
+  /* Memory known to be part of the target's stack.  This is cached even
+     if it is not in a region marked as such, since it is known to be
+     "normal" RAM.  */
+  TARGET_OBJECT_STACK_MEMORY,
   /* Kernel Unwind Table.  See "ia64-tdep.c".  */
   TARGET_OBJECT_UNWIND_TABLE,
   /* Transfer auxilliary vector.  */
@@ -671,12 +674,15 @@ extern void target_store_registers (struct regcache *regcache, int regs);
 #define        target_supports_multi_process() \
      (*current_target.to_supports_multi_process) ()
 
-extern DCACHE *target_dcache;
+/* Invalidate all target dcaches.  */
+extern void target_dcache_invalidate (void);
 
 extern int target_read_string (CORE_ADDR, char **, int, int *);
 
 extern int target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
 
+extern int target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, int len);
+
 extern int target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr,
                                int len);
 
index d1fe69bbfc18e24da84898abfaf19542024fc7be..b98fa9a745bcfe7af56719a15ea29e3e49a99402 100644 (file)
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -345,6 +345,19 @@ do_chdir_cleanup (void *old_dir)
 }
 #endif
 
+void
+prepare_execute_command (void)
+{
+  free_all_values ();
+
+  /* With multiple threads running while the one we're examining is stopped,
+     the dcache can get stale without us being able to detect it.
+     For the duration of the command, though, use the dcache to help
+     things like backtrace.  */
+  if (non_stop)
+    target_dcache_invalidate ();
+}
+
 /* Execute the line P as a command, in the current user context.
    Pass FROM_TTY as second argument to the defining function.  */
 
@@ -374,8 +387,8 @@ execute_command (char *p, int from_tty)
 #endif
        }
     }
-  
-  free_all_values ();
+
+  prepare_execute_command ();
 
   /* Force cleanup of any alloca areas if using C alloca instead of
      a builtin alloca.  */
index 0a752355d28be83322549657fd561e44035bc6fb..070a62e7cd245383c2f2395a7ee521b2f555e0ae 100644 (file)
--- a/gdb/top.h
+++ b/gdb/top.h
@@ -49,6 +49,10 @@ extern void quit_command (char *, int);
 extern int quit_cover (void *);
 extern void execute_command (char *, int);
 
+/* Prepare for execution of a command.
+   Call this before every command, CLI or MI.  */
+extern void prepare_execute_command (void);
+
 /* This function returns a pointer to the string that is used
    by gdb for its command prompt. */
 extern char *get_prompt (void);
index 5e5c4edeb30bfdcca4194df09f719b29693e6191..b64cb21eacea0675e9bc268b93cb900774c4e68d 100644 (file)
@@ -565,6 +565,32 @@ value_one (struct type *type, enum lval_type lv)
   return val;
 }
 
+/* Helper function for value_at, value_at_lazy, and value_at_lazy_stack.  */
+
+static struct value *
+get_value_at (struct type *type, CORE_ADDR addr, int lazy)
+{
+  struct value *val;
+
+  if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
+    error (_("Attempt to dereference a generic pointer."));
+
+  if (lazy)
+    {
+      val = allocate_value_lazy (type);
+    }
+  else
+    {
+      val = allocate_value (type);
+      read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type));
+    }
+
+  VALUE_LVAL (val) = lval_memory;
+  set_value_address (val, addr);
+
+  return val;
+}
+
 /* Return a value with type TYPE located at ADDR.
 
    Call value_at only if the data needs to be fetched immediately;
@@ -580,19 +606,7 @@ value_one (struct type *type, enum lval_type lv)
 struct value *
 value_at (struct type *type, CORE_ADDR addr)
 {
-  struct value *val;
-
-  if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
-    error (_("Attempt to dereference a generic pointer."));
-
-  val = allocate_value (type);
-
-  read_memory (addr, value_contents_all_raw (val), TYPE_LENGTH (type));
-
-  VALUE_LVAL (val) = lval_memory;
-  set_value_address (val, addr);
-
-  return val;
+  return get_value_at (type, addr, 0);
 }
 
 /* Return a lazy value with type TYPE located at ADDR (cf. value_at).  */
@@ -600,17 +614,7 @@ value_at (struct type *type, CORE_ADDR addr)
 struct value *
 value_at_lazy (struct type *type, CORE_ADDR addr)
 {
-  struct value *val;
-
-  if (TYPE_CODE (check_typedef (type)) == TYPE_CODE_VOID)
-    error (_("Attempt to dereference a generic pointer."));
-
-  val = allocate_value_lazy (type);
-
-  VALUE_LVAL (val) = lval_memory;
-  set_value_address (val, addr);
-
-  return val;
+  return get_value_at (type, addr, 1);
 }
 
 /* Called only from the value_contents and value_contents_all()
@@ -656,7 +660,12 @@ value_fetch_lazy (struct value *val)
       int length = TYPE_LENGTH (check_typedef (value_enclosing_type (val)));
 
       if (length)
-       read_memory (addr, value_contents_all_raw (val), length);
+       {
+         if (value_stack (val))
+           read_stack (addr, value_contents_all_raw (val), length);
+         else
+           read_memory (addr, value_contents_all_raw (val), length);
+       }
     }
   else if (VALUE_LVAL (val) == lval_register)
     {
index f26e16c7d626012f17a8a58b3b70b503dd7616b9..589e03b14964df01e5387c090316b9c819067f0b 100644 (file)
@@ -196,6 +196,10 @@ struct value
   /* If value is a variable, is it initialized or not.  */
   int initialized;
 
+  /* If value is from the stack.  If this is set, read_stack will be
+     used instead of read_memory to enable extra caching.  */
+  int stack;
+
   /* Actual contents of the value.  Target byte-order.  NULL or not
      valid if lazy is nonzero.  */
   gdb_byte *contents;
@@ -424,6 +428,18 @@ set_value_lazy (struct value *value, int val)
   value->lazy = val;
 }
 
+int
+value_stack (struct value *value)
+{
+  return value->stack;
+}
+
+void
+set_value_stack (struct value *value, int val)
+{
+  value->stack = val;
+}
+
 const gdb_byte *
 value_contents (struct value *value)
 {
index 6f6b756085f1e7c7aab3aba6c29391cfe1d0e02c..51e6960ab81aee54b942efbfeab95188afff53da 100644 (file)
@@ -215,6 +215,9 @@ extern void *value_computed_closure (struct value *value);
 extern int value_lazy (struct value *);
 extern void set_value_lazy (struct value *value, int val);
 
+extern int value_stack (struct value *);
+extern void set_value_stack (struct value *value, int val);
+
 /* value_contents() and value_contents_raw() both return the address
    of the gdb buffer used to hold a copy of the contents of the lval.
    value_contents() is used when the contents of the buffer are needed