[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH][WIP] ios ranges and dirty marking
From: |
David Faust |
Subject: |
[PATCH][WIP] ios ranges and dirty marking |
Date: |
Thu, 19 Sep 2024 22:56:21 +0200 |
Hello,
I have been hacking on this for a couple of days with much help from
Jose.
We have got a basic working implementation of the ios ranges as we
discussed at the Cauldron BoF, to mark ranges which have been written
to as dirty and remap values only if they overlap with a range which
has been marked dirty.
This patch is not ready for commit; needs to be debugged (11 tests are
failing currently) and needs cleanup and new tests at the very least.
Currently we use a very simple (doubly) linked list for the range
table. It's not fast, and should be replaced with an actual data
structure like an interval tree. That will be fixed too.
We thought it will be fun to share :)
---
(WIP) Very simple dirty range marking with stupid list table
---
libpoke/ios.c | 139 +++++++++++++++++++++++++++++++++++++++++++
libpoke/ios.h | 9 +++
libpoke/pkl-asm.pks | 4 ++
libpoke/pkl-gen.pks | 18 ++++++
libpoke/pkl-insn.def | 5 ++
libpoke/pkl-rt.pk | 7 +++
libpoke/pvm-alloc.c | 42 +++++++++++++
libpoke/pvm-alloc.h | 6 ++
libpoke/pvm-val.c | 14 ++++-
libpoke/pvm-val.h | 33 ++++++++++
libpoke/pvm.jitter | 77 ++++++++++++++++++++++++
11 files changed, 352 insertions(+), 2 deletions(-)
diff --git a/libpoke/ios.c b/libpoke/ios.c
index c53ff13d..368f5755 100644
--- a/libpoke/ios.c
+++ b/libpoke/ios.c
@@ -53,6 +53,21 @@
return IOD_ERROR_TO_IOS_ERROR (ret); \
}
+
+struct range_entry {
+ uint64_t val; /* this is a pvm_val */
+ unsigned long begin;
+ unsigned long end;
+ struct range_entry *prev;
+ struct range_entry *next;
+};
+
+struct range_table {
+ unsigned long num_entries;
+ struct range_entry *head;
+ struct range_entry *tail;
+};
+
/* The following struct implements an instance of an IO space.
`ID' is an unique integer identifying the IO space.
@@ -81,6 +96,7 @@ struct ios
void *dev;
const struct ios_dev_if *dev_if;
ios_off bias;
+ struct range_table *ranges;
struct ios *next;
};
@@ -201,12 +217,22 @@ ios_open (ios_context ios_ctx, const char *handler,
uint64_t flags,
if (!io)
return IOS_ENOMEM;
+ /* Allocate and initialze the range table for the new IO space. */
+ struct range_table *tbl = malloc (sizeof (struct range_table));
+ if (!tbl)
+ return IOS_ENOMEM;
+ tbl->head = NULL;
+ tbl->tail = NULL;
+ tbl->num_entries = 0;
+
io->zombie_p = 0;
io->num_sub_devs = 0;
io->handler = NULL;
io->next = NULL;
io->bias = 0;
+ io->ranges = tbl;
+
/* Look for a device interface suitable to operate on the given
handler. */
dev_if = ios_ctx->foreign_dev_if;
@@ -1560,6 +1586,8 @@ ios_write_int (ios io, ios_off offset, int flags,
/* Apply the IOS bias. */
offset += ios_get_bias (io);
+ ios_mark_dirty_range (io, offset, offset + bits);
+
/* Fast track for byte-aligned 8x bits */
if (offset % 8 == 0 && bits % 8 == 0)
return ios_write_int_fast (io, offset, flags, bits, endian, value);
@@ -1585,6 +1613,8 @@ ios_write_uint (ios io, ios_off offset, int flags,
/* Apply the IOS bias. */
offset += ios_get_bias (io);
+ ios_mark_dirty_range (io, offset, offset + bits);
+
/* Fast track for byte-aligned 8x bits */
if (offset % 8 == 0 && bits % 8 == 0)
return ios_write_int_fast (io, offset, flags, bits, endian, value);
@@ -1649,3 +1679,112 @@ ios_dec_sub_dev (ios io)
if (io->zombie_p && io->num_sub_devs == 0)
free (io);
}
+
+void
+range_table_insert (struct range_table *tbl,
+ uint64_t val,
+ unsigned long offset,
+ unsigned long size)
+{
+ struct range_entry *newent
+ = (struct range_entry *) malloc (sizeof (struct range_entry));
+
+ newent->val = val;
+ newent->begin = offset;
+ newent->end = offset + size;
+ newent->prev = tbl->tail;
+ newent->next = NULL;
+
+ if (!tbl->head)
+ tbl->head = newent;
+
+ if (tbl->tail)
+ tbl->tail->next = newent;
+
+ tbl->tail = newent;
+ tbl->num_entries++;
+}
+
+
+void
+range_table_delete_val (struct range_table *tbl, uint64_t val)
+{
+ if (!tbl || !val)
+ return;
+
+ struct range_entry *e = tbl->head;
+ while (e)
+ {
+ if (e->val == val)
+ {
+ if (tbl->tail == e)
+ tbl->tail = e->prev;
+ if (tbl->head == e)
+ tbl->head = e->next;
+
+ e->prev->next = e->next;
+ e->next->prev = e->prev;
+
+ free (e);
+ tbl->num_entries--;
+ break;
+ }
+ e = e->next;
+ }
+}
+
+int
+range_table_entry_overlap (struct range_entry *e, uint64_t begin, uint64_t end)
+{
+ return (e->begin <= end && e->end >= begin);
+}
+
+void pvm_val_set_dirty (uint64_t);
+
+void
+range_table_mark_dirty (struct range_table *tbl, uint64_t begin, uint64_t end)
+{
+ if (!tbl)
+ return;
+
+ struct range_entry *e = tbl->head;
+ while (e)
+ {
+ if (range_table_entry_overlap (e, begin, end))
+ {
+ /* printf ("setting dirty flag in val %lu\n", e->val); */
+ pvm_val_set_dirty (e->val);
+ /* PVM_VAL_DIRTY_P (e->val) = 1; */
+ }
+
+ e = e->next;
+ }
+}
+
+void
+ios_register_range (uint64_t val, ios io, ios_off offset, unsigned long size)
+{
+ /* printf ("ios_register_range (%lu, %x, %lu, %lu)\n", val, io, offset,
size); */
+
+ range_table_insert (io->ranges, val, (unsigned long) offset, size);
+}
+
+void
+ios_deregister_range (uint64_t val, ios io)
+{
+ /* get ios from val mapinfo */
+ /* if (!io || !val) */
+ /* return; */
+
+ assert (io);
+
+ /* printf ("ios_deregister_range (%lu, %lu)\n", val, io); */
+
+ range_table_delete_val (io->ranges, val);
+}
+
+void
+ios_mark_dirty_range (ios io, unsigned long begin, unsigned long end)
+{
+ range_table_mark_dirty (io->ranges, begin, end);
+}
diff --git a/libpoke/ios.h b/libpoke/ios.h
index 7a992fb1..62471f8b 100644
--- a/libpoke/ios.h
+++ b/libpoke/ios.h
@@ -397,4 +397,13 @@ void ios_inc_sub_dev (ios io);
/* Decrease the number of sub-devices for IOS. */
void ios_dec_sub_dev (ios io);
+/* **************** Range Mapping ************** */
+
+/* Register VAL to be mapped in IO having given OFFSET and SIZE. */
+void ios_register_range (uint64_t val, ios io, ios_off offset, unsigned long
size);
+
+void ios_deregister_range (uint64_t val, ios io);
+
+void ios_mark_dirty_range (ios io, unsigned long begin, unsigned long end);
+
#endif /* ! IOS_H */
diff --git a/libpoke/pkl-asm.pks b/libpoke/pkl-asm.pks
index 7819753d..25ee5d03 100644
--- a/libpoke/pkl-asm.pks
+++ b/libpoke/pkl-asm.pks
@@ -60,6 +60,10 @@
mm ; VAL MAPPED_P
bzi .done ; VAL MAPPED_P
drop ; VAL
+ ;; if the dirty flag is not set, no need to remap
+ mgetd ; VAL DIRTY_P
+ bzi .done
+ drop
;; If the IO space where the value is mapped is non-volatile
;; and read-only, there is no need to remap.
mgetios ; VAL IOS
diff --git a/libpoke/pkl-gen.pks b/libpoke/pkl-gen.pks
index 66cdaa80..4e3d1a93 100644
--- a/libpoke/pkl-gen.pks
+++ b/libpoke/pkl-gen.pks
@@ -221,6 +221,15 @@
pushvar $strict ; ARRAY STRICT
msets ; ARRAY
map ; ARRAY
+ ;; Register the newly mapped array in the IOS
+ dup ; ARRAY ARRAY
+ mgetios ; ARRAY ARRAY IOS
+ swap ; ARRAY IOS ARRAY
+ mgeto ; ARRAY IOS ARRAY OFF
+ over ; ARRAY IOS ARRAY OFF ARRAY
+ siz ; ARRAY IOS ARRAY OFF ARRAY SIZ
+ nip ; ARRAY IOS ARRAY OFF SIZ
+ ioregval ; ARRAY
popf 1
return
.bounds_fail:
@@ -1457,6 +1466,15 @@
pushvar $strict ; SCT STRICT
msets ; SCT
map ; SCT
+ ;; Register the newly mapped struct in the IOS
+ dup ; SCT SCT
+ mgetios ; SCT SCT IOS
+ swap ; SCT IOS SCT
+ mgeto ; SCT IOS SCT OFF
+ over ; SCT IOS SCT OFF SCT
+ siz ; SCT IOS SCT OFF SCT SIZ
+ nip ; SCT IOS SCT OFF SIZ
+ ioregval ; SCT
popf 1
return
.end
diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
index 4f842f3d..8d09f24c 100644
--- a/libpoke/pkl-insn.def
+++ b/libpoke/pkl-insn.def
@@ -335,6 +335,10 @@ PKL_DEF_INSN(PKL_INSN_MSETO,"","mseto")
PKL_DEF_INSN(PKL_INSN_MGETS,"","mgets")
PKL_DEF_INSN(PKL_INSN_MSETS,"","msets")
+PKL_DEF_INSN(PKL_INSN_MGETD,"","mgetd")
+PKL_DEF_INSN(PKL_INSN_MSETD,"","msetd")
+PKL_DEF_INSN(PKL_INSN_MCLEARD,"","mcleard")
+
PKL_DEF_INSN(PKL_INSN_MGETIOS,"","mgetios")
PKL_DEF_INSN(PKL_INSN_MSETIOS,"","msetios")
@@ -508,6 +512,7 @@ PKL_DEF_INSN(PKL_INSN_IOHANDLER,"","iohandler")
PKL_DEF_INSN(PKL_INSN_IOFLAGS,"","ioflags")
PKL_DEF_INSN(PKL_INSN_IOGETB,"","iogetb")
PKL_DEF_INSN(PKL_INSN_IOSETB,"","iosetb")
+PKL_DEF_INSN(PKL_INSN_IOREGVAL,"","ioregval")
PKL_DEF_INSN(PKL_INSN_IONUM,"","ionum")
PKL_DEF_INSN(PKL_INSN_IOREF,"","ioref")
PKL_DEF_INSN(PKL_INSN_IOGETV,"","iogetv")
diff --git a/libpoke/pkl-rt.pk b/libpoke/pkl-rt.pk
index 8566c25f..1d8919de 100644
--- a/libpoke/pkl-rt.pk
+++ b/libpoke/pkl-rt.pk
@@ -982,6 +982,13 @@ immutable fun iovolatile = (int<32>ios = get_ios) int<32>:
return asm int<32>: ("iogetv; nip" : ios);
}
+immutable fun ioregval = (any val, int<32> ios = val'ios,
+ offset<uint<64>,1> begin = val'offset,
+ offset<uint<64>,1> size = val'size) void:
+{
+ asm ("ioregval" :: ios, val, begin, size);
+}
+
immutable fun iosetbias = (offset<uint<64>,1> bias = 0#1, int<32> ios =
get_ios) void:
{
asm ("iosetb; drop" :: bias, ios);
diff --git a/libpoke/pvm-alloc.c b/libpoke/pvm-alloc.c
index 4c8ee84d..7b6a75d9 100644
--- a/libpoke/pvm-alloc.c
+++ b/libpoke/pvm-alloc.c
@@ -64,6 +64,30 @@ pvm_alloc_finalize_closure (void *object, void *client_data)
/* pvm_destroy_program (PVM_VAL_CLS_PROGRAM (cls)); */
}
+static void
+pvm_alloc_finalize_struct (void *object, void *client_data)
+{
+ /* printf("pvm_alloc_finalize_struct\n"); */
+ /* Remove from range map table. */
+ pvm_struct sct = (pvm_struct) object;
+ pvm_val val = (uint64_t) sct | 0xb;
+
+ if (sct->mapinfo.mapped_p)
+ ios_deregister_range (val, sct->mapinfo.io);
+}
+
+static void
+pvm_alloc_finalize_array (void *object, void *client_data)
+{
+ /* printf("pvm_alloc_finalize_array\n"); */
+ /* Remove from range map table. */
+ pvm_array arr = (pvm_array) object;
+ pvm_val val = (uint64_t) arr | 0xa;
+
+ if (arr->mapinfo.mapped_p)
+ ios_deregister_range (val, arr->mapinfo.io);
+}
+
void *
pvm_alloc_cls (void)
{
@@ -74,6 +98,24 @@ pvm_alloc_cls (void)
return cls;
}
+void *
+pvm_alloc_arr (void)
+{
+ pvm_array arr = pvm_alloc (sizeof (struct pvm_array));
+ GC_register_finalizer_no_order (arr, pvm_alloc_finalize_array, NULL,
+ NULL, NULL);
+ return arr;
+}
+
+void *
+pvm_alloc_sct (void)
+{
+ pvm_struct sct = pvm_alloc (sizeof (struct pvm_struct));
+ GC_register_finalizer_no_order (sct, pvm_alloc_finalize_struct, NULL,
+ NULL, NULL);
+ return sct;
+}
+
void
pvm_alloc_initialize ()
{
diff --git a/libpoke/pvm-alloc.h b/libpoke/pvm-alloc.h
index a7be52ca..331e749b 100644
--- a/libpoke/pvm-alloc.h
+++ b/libpoke/pvm-alloc.h
@@ -74,6 +74,12 @@ void *pvm_realloc (void *ptr, size_t size)
void *pvm_alloc_cls (void)
__attribute__ ((malloc));
+void *pvm_alloc_arr (void)
+ __attribute__ ((malloc));
+
+void *pvm_alloc_sct (void)
+ __attribute__ ((malloc));
+
/* Allocate and return a copy of the given STRING. This call has the
same semantics than strdup(3). */
diff --git a/libpoke/pvm-val.c b/libpoke/pvm-val.c
index dcd3b0e5..6ed3eb86 100644
--- a/libpoke/pvm-val.c
+++ b/libpoke/pvm-val.c
@@ -139,7 +139,7 @@ pvm_val
pvm_make_array (pvm_val nelem, pvm_val type)
{
pvm_val_box box = pvm_make_box (PVM_VAL_TAG_ARR);
- pvm_array arr = pvm_alloc (sizeof (struct pvm_array));
+ pvm_array arr = pvm_alloc_arr ();
size_t num_elems = PVM_VAL_ULONG (nelem);
size_t num_allocated = num_elems > 0 ? num_elems : 16;
size_t nbytes = (sizeof (struct pvm_array_elem) * num_allocated);
@@ -287,7 +287,7 @@ pvm_val
pvm_make_struct (pvm_val nfields, pvm_val nmethods, pvm_val type)
{
pvm_val_box box = pvm_make_box (PVM_VAL_TAG_SCT);
- pvm_struct sct = pvm_alloc (sizeof (struct pvm_struct));
+ pvm_struct sct = pvm_alloc_sct ();
size_t i;
size_t nfieldbytes
= sizeof (struct pvm_struct_field) * PVM_VAL_ULONG (nfields);
@@ -1857,3 +1857,13 @@ pvm_val_finalize (void)
pvm_alloc_remove_gc_roots (&void_type, 1);
pvm_alloc_remove_gc_roots (&common_int_types, 65 * 2);
}
+
+void
+pvm_val_set_dirty (pvm_val val)
+{
+ if (PVM_IS_ARR (val))
+ PVM_VAL_ARR_DIRTY_P (val)= 1;
+ else if (PVM_IS_SCT (val))
+ PVM_VAL_SCT_DIRTY_P (val) = 1;
+
+}
diff --git a/libpoke/pvm-val.h b/libpoke/pvm-val.h
index e466bef5..b569cc09 100644
--- a/libpoke/pvm-val.h
+++ b/libpoke/pvm-val.h
@@ -193,14 +193,18 @@ typedef struct pvm_val_box *pvm_val_box;
#define PVM_MAPINFO_MAPPED_P(MINFO) ((MINFO).mapped_p)
#define PVM_MAPINFO_STRICT_P(MINFO) ((MINFO).strict_p)
+#define PVM_MAPINFO_DIRTY_P(MINFO) ((MINFO).dirty_p)
#define PVM_MAPINFO_IOS(MINFO) ((MINFO).ios)
+#define PVM_MAPINFO_IOS_PTR(MINFO) ((MINFO).io)
#define PVM_MAPINFO_OFFSET(MINFO) ((MINFO).offset)
struct pvm_mapinfo
{
int mapped_p;
int strict_p;
+ int dirty_p;
pvm_val ios;
+ ios io;
pvm_val offset;
};
@@ -247,7 +251,9 @@ struct pvm_mapinfo
#define PVM_VAL_ARR_MAPINFO_BACK(V) (PVM_VAL_ARR(V)->mapinfo_back)
#define PVM_VAL_ARR_MAPPED_P(V) (PVM_MAPINFO_MAPPED_P (PVM_VAL_ARR_MAPINFO
((V))))
#define PVM_VAL_ARR_STRICT_P(V) (PVM_MAPINFO_STRICT_P (PVM_VAL_ARR_MAPINFO
((V))))
+#define PVM_VAL_ARR_DIRTY_P(V) (PVM_MAPINFO_DIRTY_P (PVM_VAL_ARR_MAPINFO
((V))))
#define PVM_VAL_ARR_IOS(V) (PVM_MAPINFO_IOS (PVM_VAL_ARR_MAPINFO ((V))))
+#define PVM_VAL_ARR_IOS_PTR(V) (PVM_MAPINFO_IOS_PTR (PVM_VAL_ARR_MAPINFO
((V))))
#define PVM_VAL_ARR_OFFSET(V) (PVM_MAPINFO_OFFSET (PVM_VAL_ARR_MAPINFO ((V))))
#define PVM_VAL_ARR_ELEMS_BOUND(V) (PVM_VAL_ARR(V)->elems_bound)
#define PVM_VAL_ARR_SIZE_BOUND(V) (PVM_VAL_ARR(V)->size_bound)
@@ -327,7 +333,9 @@ struct pvm_array_elem
#define PVM_VAL_SCT_MAPINFO_BACK(V) (PVM_VAL_SCT((V))->mapinfo_back)
#define PVM_VAL_SCT_MAPPED_P(V) (PVM_MAPINFO_MAPPED_P (PVM_VAL_SCT_MAPINFO
((V))))
#define PVM_VAL_SCT_STRICT_P(V) (PVM_MAPINFO_STRICT_P (PVM_VAL_SCT_MAPINFO
((V))))
+#define PVM_VAL_SCT_DIRTY_P(V) (PVM_MAPINFO_DIRTY_P (PVM_VAL_SCT_MAPINFO
((V))))
#define PVM_VAL_SCT_IOS(V) (PVM_MAPINFO_IOS (PVM_VAL_SCT_MAPINFO ((V))))
+#define PVM_VAL_SCT_IOS_PTR(V) (PVM_MAPINFO_IOS_PTR (PVM_VAL_SCT_MAPINFO
((V))))
#define PVM_VAL_SCT_OFFSET(V) (PVM_MAPINFO_OFFSET (PVM_VAL_SCT_MAPINFO ((V))))
#define PVM_VAL_SCT_MAPPER(V) (PVM_VAL_SCT((V))->mapper)
#define PVM_VAL_SCT_WRITER(V) (PVM_VAL_SCT((V))->writer)
@@ -621,6 +629,16 @@ typedef struct pvm_off *pvm_off;
PVM_VAL_SCT_IOS ((V)) = (I); \
} while (0)
+#define PVM_VAL_SET_IOS_PTR(V,P) \
+ do \
+ { \
+ if (PVM_IS_ARR ((V))) \
+ PVM_VAL_ARR_IOS_PTR ((V)) = (P); \
+ else if (PVM_IS_SCT (V)) \
+ PVM_VAL_SCT_IOS_PTR ((V)) = (P); \
+ } while (0)
+
+
#define PVM_VAL_MAPPED_P(V) \
(PVM_IS_ARR ((V)) ? PVM_VAL_ARR_MAPPED_P ((V)) \
: PVM_IS_SCT ((V)) ? PVM_VAL_SCT_MAPPED_P ((V)) \
@@ -651,6 +669,21 @@ typedef struct pvm_off *pvm_off;
} \
while (0)
+#define PVM_VAL_DIRTY_P(V) \
+ (PVM_IS_ARR ((V)) ? PVM_VAL_ARR_DIRTY_P ((V)) \
+ : PVM_IS_SCT ((V)) ? PVM_VAL_SCT_DIRTY_P ((V)) \
+ : 0)
+
+#define PVM_VAL_SET_DIRTY_P(V,I) \
+ do \
+ { \
+ if (PVM_IS_ARR ((V))) \
+ PVM_VAL_ARR_DIRTY_P ((V)) = (I); \
+ else if (PVM_IS_SCT ((V))) \
+ PVM_VAL_SCT_DIRTY_P ((V)) = (I); \
+ } \
+ while (0)
+
#define PVM_VAL_MAPPER(V) \
(PVM_IS_ARR ((V)) ? PVM_VAL_ARR_MAPPER ((V)) \
: PVM_IS_SCT ((V)) ? PVM_VAL_SCT_MAPPER ((V)) \
diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
index f10c30bd..a0e8ceb5 100644
--- a/libpoke/pvm.jitter
+++ b/libpoke/pvm.jitter
@@ -1859,6 +1859,36 @@ instruction iosetb ()
end
end
+# Instruction: ioregval
+#
+# Register the given range in the given IO space as to correspond
+# to the mapped area of the given value.
+#
+# Stack: ( IOS VAL BEGIN SIZE -- )
+
+instruction ioregval ()
+ branching
+ code
+ pvm_val val;
+ uint64_t size, begin;
+ ios io;
+ ios_context ios_ctx = PVM_STATE_BACKING_FIELD (ios_ctx);
+
+ size = PVM_VAL_ULONG (JITTER_TOP_STACK ());
+ begin = PVM_VAL_ULONG (JITTER_UNDER_TOP_STACK ());
+ JITTER_DROP_STACK ();
+ JITTER_DROP_STACK ();
+ val = JITTER_TOP_STACK ();
+ io = ios_search_by_id (ios_ctx, PVM_VAL_INT (JITTER_UNDER_TOP_STACK ()));
+ if (io == NULL)
+ PVM_RAISE_DFL (PVM_E_NO_IOS);
+ JITTER_DROP_STACK ();
+ JITTER_DROP_STACK ();
+
+ ios_register_range (val, io, begin, size);
+ end
+end
+
## Function management instructions
@@ -5900,11 +5930,18 @@ end
# IO space is ignored.
#
# Stack: ( VAL INT -- VAL )
+# Exceptions: PVM_E_NO_IOS
instruction msetios ()
+ branching
code
+ ios_context ios_ctx = PVM_STATE_BACKING_FIELD (ios_ctx);
+ ios io = ios_search_by_id (ios_ctx, PVM_VAL_INT (JITTER_TOP_STACK ()));
+ if (io < 0)
+ PVM_RAISE_DFL (PVM_E_NO_IOS);
PVM_VAL_SET_IOS (JITTER_UNDER_TOP_STACK (),
JITTER_TOP_STACK ());
+ PVM_VAL_SET_IOS_PTR (JITTER_UNDER_TOP_STACK (), io);
JITTER_DROP_STACK ();
end
end
@@ -5963,6 +6000,46 @@ instruction msetw ()
end
end
+# Instruction: mgetd
+#
+# Given a value, push a boolean indicating whether the value is dirty.
+# If the given value is not map-able then push false, i.e. 0.
+#
+# Stack: ( VAL -- VAL INT )
+
+instruction mgetd ()
+ code
+ int dirty_p = PVM_VAL_DIRTY_P (JITTER_TOP_STACK ());
+ JITTER_PUSH_STACK (PVM_MAKE_INT (dirty_p, 32));
+ end
+end
+
+# Instruction: msetd
+#
+# Given a value, mark it dirty. If the value is not map-able,
+# this is a no-op.
+#
+# Stack: ( VAL -- VAL )
+
+instruction msetd ()
+ code
+ PVM_VAL_SET_DIRTY_P (JITTER_TOP_STACK (), 1);
+ end
+end
+
+# Instruction: mcleard
+#
+# Given a value, clear its dirty bit. If the value is not map-able,
+# this is a no-op.
+#
+# Stack: ( VAL -- VAL )
+
+instruction mcleard ()
+ code
+ PVM_VAL_SET_DIRTY_P (JITTER_TOP_STACK (), 0);
+ end
+end
+
# Instruction: mgetsel
#
# Given a map-able value in the TOS, push the number of elements to
--
2.43.5
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH][WIP] ios ranges and dirty marking,
David Faust <=