poke-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] pvm: add new pvm value: opaque values


From: Jose E. Marchesi
Subject: Re: [PATCH v2] pvm: add new pvm value: opaque values
Date: Sun, 23 Apr 2023 11:36:20 +0200
User-agent: Gnus/5.13 (Gnus v5.13)

> This commit introduces a new PVM type to wrap opaque values,
> things like handles to resources which PVM cannot deal with
> them directly.

I think we do not need eqo and neo instructions, because:

1) They can always conmpare to false (in _pkl_eq_any).
2) These values are not directly visible in Poke unless you use
   asm.  Similar to null.




> 2023-04-20  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
>
>       * libpoke/pkl-insn.def (opqgetn): New instruction.
>       (mktyopq): Likewise.
>       (tyisopq): Likewise.
>       (eqo): Likewise.
>       (neo): Likewise.
>       * libpoke/pvm.jitter (opqgetn): New instruction.
>       (mktyopq): Likewise.
>       (tyisopq): Likewise.
>       (eqo): Likewise.
>       (neo): Likewise.
>       (wrapped-functions): Add `pvm_make_opaque' and `pvm_make_opaque_type'.
>       * libpoke/pkl-rt.pk (_pkl_print_format_any): Handle "opaque" values.
>       (_pkl_eq_any): Likewise.
>       * libpoke/pvm.h (pvm_make_opaque): Likewise.
>       (pvm_make_opaque_type): Likewise.
>       * libpoke/pvm-val.h (PVM_VAL_TAG_OPQ): New macro.
>       (PVM_VAL_BOX_OPQ): Likewise.
>       (struct pvm_val_box): New entry for "opaque" values.
>       (enum pvm_type_code): Likewise.
>       (PVM_VAL_OPQ): New macro.
>       (PVM_VAL_OPQ_NAME): Likewise.
>       (PVM_VAL_OPQ_PAYLOAD): Likewise.
>       (struct pvm_opq): New struct.
>       (pvm_opq): New typedef.
>       (PVM_IS_OPQ): New macro.
>       * libpoke/pvm-val.c (opaque_type): New variable.
>       (pvm_make_opaque_type): New function.
>       (pvm_make_opaque): Likewise.
>       (pvm_val_equal_p): Handle "opaque" values.
>       (pvm_typeof): Likewise.
>       (pvm_val_initialize): Handle `opaque_type'.
>       (pvm_val_finalize): Likewise.
> ---
>
> Hi Jose.
>
> Changes w.r.t v1:
>
>   - Removed `_pkl_eq_opaque'
>   - Removed `opqsetn`, `opqgetp' insns
>   - Added `eqo' and `neo` insns
>       For now they compare the payload's pointer, but in future,
>       we can add a new `cmp' function pointer in the `struct pvm_opq'
>       to be able do the right thing for each opaque value.
>
>
> Regards,
> Mohammad-Reza
>
>
>  ChangeLog            | 35 ++++++++++++++++++++
>  libpoke/pkl-insn.def | 10 ++++++
>  libpoke/pkl-rt.pk    | 16 +++++++++
>  libpoke/pvm-val.c    | 35 ++++++++++++++++++++
>  libpoke/pvm-val.h    | 22 ++++++++++++
>  libpoke/pvm.h        | 12 +++++++
>  libpoke/pvm.jitter   | 79 +++++++++++++++++++++++++++++++++++++++++++-
>  7 files changed, 208 insertions(+), 1 deletion(-)
>
> diff --git a/ChangeLog b/ChangeLog
> index 1f790dc8..d1be1eb1 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,38 @@
> +2023-04-20  Mohammad-Reza Nabipoor  <mnabipoor@gnu.org>
> +
> +     * libpoke/pkl-insn.def (opqgetn): New instruction.
> +     (mktyopq): Likewise.
> +     (tyisopq): Likewise.
> +     (eqo): Likewise.
> +     (neo): Likewise.
> +     * libpoke/pvm.jitter (opqgetn): New instruction.
> +     (mktyopq): Likewise.
> +     (tyisopq): Likewise.
> +     (eqo): Likewise.
> +     (neo): Likewise.
> +     (wrapped-functions): Add `pvm_make_opaque' and `pvm_make_opaque_type'.
> +     * libpoke/pkl-rt.pk (_pkl_print_format_any): Handle "opaque" values.
> +     (_pkl_eq_any): Likewise.
> +     * libpoke/pvm.h (pvm_make_opaque): Likewise.
> +     (pvm_make_opaque_type): Likewise.
> +     * libpoke/pvm-val.h (PVM_VAL_TAG_OPQ): New macro.
> +     (PVM_VAL_BOX_OPQ): Likewise.
> +     (struct pvm_val_box): New entry for "opaque" values.
> +     (enum pvm_type_code): Likewise.
> +     (PVM_VAL_OPQ): New macro.
> +     (PVM_VAL_OPQ_NAME): Likewise.
> +     (PVM_VAL_OPQ_PAYLOAD): Likewise.
> +     (struct pvm_opq): New struct.
> +     (pvm_opq): New typedef.
> +     (PVM_IS_OPQ): New macro.
> +     * libpoke/pvm-val.c (opaque_type): New variable.
> +     (pvm_make_opaque_type): New function.
> +     (pvm_make_opaque): Likewise.
> +     (pvm_val_equal_p): Handle "opaque" values.
> +     (pvm_typeof): Likewise.
> +     (pvm_val_initialize): Handle `opaque_type'.
> +     (pvm_val_finalize): Likewise.
> +
>  2023-04-17  Jose E. Marchesi  <jemarch@gnu.org>
>  
>       * NEWS: Add entries for 3.1.
> diff --git a/libpoke/pkl-insn.def b/libpoke/pkl-insn.def
> index 94a0a06b..2e22f0df 100644
> --- a/libpoke/pkl-insn.def
> +++ b/libpoke/pkl-insn.def
> @@ -255,6 +255,9 @@ PKL_DEF_INSN(PKL_INSN_LES,"","les")
>  PKL_DEF_INSN(PKL_INSN_EQC,"","eqc")
>  PKL_DEF_INSN(PKL_INSN_NEC,"","nec")
>  
> +PKL_DEF_INSN(PKL_INSN_EQO,"","eqo")
> +PKL_DEF_INSN(PKL_INSN_NEO,"","neo")
> +
>  /* String instructions.  */
>  
>  PKL_DEF_INSN(PKL_INSN_SCONC,"","sconc")
> @@ -284,6 +287,10 @@ PKL_DEF_INSN(PKL_INSN_OSETM,"","osetm")
>  PKL_DEF_INSN(PKL_INSN_OGETU,"","ogetu")
>  PKL_DEF_INSN(PKL_INSN_OGETBT,"","ogetbt")
>  
> +/* Opaque values instructions.  */
> +
> +PKL_DEF_INSN(PKL_INSN_OPQGETN,"","opqgetn")
> +
>  /* Containers instructions.  */
>  
>  PKL_DEF_INSN(PKL_INSN_SEL,"","sel")
> @@ -369,6 +376,9 @@ PKL_DEF_INSN(PKL_INSN_TYOGETM,"","tyogetm")
>  PKL_DEF_INSN(PKL_INSN_TYOGETU,"","tyogetu")
>  PKL_DEF_INSN(PKL_INSN_TYISO,"","tyiso")
>  
> +PKL_DEF_INSN(PKL_INSN_MKTYOPQ,"","mktyopq")
> +PKL_DEF_INSN(PKL_INSN_TYISOPQ,"","tyisopq")
> +
>  PKL_DEF_INSN(PKL_INSN_MKTYC,"","mktyc")
>  PKL_DEF_INSN(PKL_INSN_TYISC,"","tyisc")
>  /* PKL_DEF_INSN(PKL_INSN_TYCNA,"","tycna") */
> diff --git a/libpoke/pkl-rt.pk b/libpoke/pkl-rt.pk
> index be60948c..decb3b24 100644
> --- a/libpoke/pkl-rt.pk
> +++ b/libpoke/pkl-rt.pk
> @@ -1268,6 +1268,10 @@ immutable fun _pkl_eq_any = (any v1, any v2) int<32>:
>             && asm int<32>: ("typof; nip; tyiso; nip" : v2))
>      /* Offsets.  */
>      return _pkl_eq_offset (v1, v2);
> +  else if (asm int<32>: ("typof; nip; tyisopq; nip" : v1)
> +           && asm int<32>: ("typof; nip; tyisopq; nip" : v2))
> +    /* Opaques.  */
> +    return asm int<32>: ("eqo; nip2" : v1, v2);
>    else if (asm int<32>: ("typof; nip; tyiss; nip" : v1)
>             && asm int<32>: ("typof; nip; tyiss; nip" : v2))
>      /* Strings.  */
> @@ -1358,6 +1362,8 @@ immutable fun _pkl_print_format_any = (any val,
>        ctx.emit ("string");
>      else if (asm int<32>: ("tyisv; nip" : val))
>        ctx.emit ("void");
> +    else if (asm int<32>: ("tyisopq; nip" : val))
> +      ctx.emit ("opaque");
>      else if (asm int<32>: ("tyisa; nip" : val))
>        {
>          var bound = asm any: ("tyagetb; nip; call" : val);
> @@ -1665,6 +1671,16 @@ immutable fun _pkl_print_format_any = (any val,
>      handle_integral :long_p 0 :signed_p 1;
>    else if (asm int<32>: ("typof; nip; tyiso; nip" : val))
>      handle_offset;
> +  else if (asm int<32>: ("typof; nip; tyisopq; nip" : val))
> +    {
> +      var name = asm string: ("opqgetn; nip" : val);
> +
> +      ctx.begin_class ("special");
> +      ctx.emit ("#<opaque:");
> +      ctx.emit (name);
> +      ctx.emit (">");
> +      ctx.end_class ("special");
> +    }
>    else if (asm int<32>: ("typof; nip; tyisl; nip" : val))
>      handle_integral :long_p 1 :signed_p 1;
>    else if (asm int<32>: ("typof; nip; tyisiu; nip" : val))
> diff --git a/libpoke/pvm-val.c b/libpoke/pvm-val.c
> index 21c114e9..5cfcce91 100644
> --- a/libpoke/pvm-val.c
> +++ b/libpoke/pvm-val.c
> @@ -38,6 +38,7 @@
>  
>  static pvm_val string_type;
>  static pvm_val void_type;
> +static pvm_val opaque_type;
>  
>  /* We are currently only supporting a relatively small number of
>     integral types, i.e. signed and unsigned types of sizes 1 to 64
> @@ -516,6 +517,12 @@ pvm_make_void_type (void)
>    return void_type;
>  }
>  
> +pvm_val
> +pvm_make_opaque_type (void)
> +{
> +  return opaque_type;
> +}
> +
>  pvm_val
>  pvm_make_offset_type (pvm_val base_type, pvm_val unit)
>  {
> @@ -593,6 +600,18 @@ pvm_make_offset (pvm_val magnitude, pvm_val type)
>    return PVM_BOX (box);
>  }
>  
> +pvm_val
> +pvm_make_opaque (pvm_val name, uintptr_t payload)
> +{
> +  pvm_val_box box = pvm_make_box (PVM_VAL_TAG_OPQ);
> +  pvm_opq opq = pvm_alloc (sizeof (struct pvm_opq));
> +
> +  opq->name = name;
> +  opq->payload = payload;
> +  PVM_VAL_BOX_OPQ (box) = opq;
> +  return PVM_BOX (box);
> +}
> +
>  int
>  pvm_val_equal_p (pvm_val val1, pvm_val val2)
>  {
> @@ -625,6 +644,8 @@ pvm_val_equal_p (pvm_val val1, pvm_val val2)
>  
>        return pvm_off_mag_equal && pvm_off_unit_equal;
>      }
> +  else if (PVM_IS_OPQ (val1) && PVM_IS_OPQ (val2))
> +    return PVM_VAL_OPQ_PAYLOAD (val1) == PVM_VAL_OPQ_PAYLOAD (val2);
>    else if (PVM_IS_SCT (val1) && PVM_IS_SCT (val2))
>      {
>        size_t pvm_sct1_nfields = PVM_VAL_ULONG (PVM_VAL_SCT_NFIELDS (val1));
> @@ -981,6 +1002,9 @@ pvm_sizeof (pvm_val val)
>      }
>    else if (PVM_IS_OFF (val))
>      return pvm_sizeof (PVM_VAL_OFF_MAGNITUDE (val));
> +  else if (PVM_IS_OPQ (val))
> +    /* By convention, opque values have size zero.  */
> +    return 0;
>    else if (PVM_IS_TYP (val))
>      /* By convention, type values have size zero.  */
>      return 0;
> @@ -1578,6 +1602,12 @@ pvm_print_val_1 (pvm vm, int depth, int mode, int 
> base, int indent,
>        print_unit_name (PVM_VAL_ULONG (PVM_VAL_TYP_O_UNIT (val_type)));
>        pk_term_end_class ("offset");
>      }
> +  else if (PVM_IS_OPQ (val))
> +    {
> +      pk_term_class ("special");
> +      pk_printf ("#<opaque:%s>", PVM_VAL_OPQ_NAME (val));
> +      pk_term_end_class ("special");
> +    }
>    else if (PVM_IS_CLS (val))
>      {
>        pk_term_class ("special");
> @@ -1652,6 +1682,8 @@ pvm_typeof (pvm_val val)
>      type = val;
>    else if (PVM_IS_CLS (val))
>      type = PVM_NULL;
> +  else if (PVM_IS_OPQ (val))
> +    type = pvm_make_opaque_type ();
>    else
>      PK_UNREACHABLE ();
>  
> @@ -1819,10 +1851,12 @@ pvm_val_initialize (void)
>  
>    pvm_alloc_add_gc_roots (&string_type, 1);
>    pvm_alloc_add_gc_roots (&void_type, 1);
> +  pvm_alloc_add_gc_roots (&opaque_type, 1);
>    pvm_alloc_add_gc_roots (&common_int_types, 65 * 2);
>  
>    string_type = pvm_make_type (PVM_TYPE_STRING);
>    void_type = pvm_make_type (PVM_TYPE_VOID);
> +  opaque_type = pvm_make_type (PVM_TYPE_OPAQUE);
>  
>    for (i = 0; i < 65; ++i)
>      for (j = 0; j < 2; ++j)
> @@ -1834,5 +1868,6 @@ pvm_val_finalize (void)
>  {
>    pvm_alloc_remove_gc_roots (&string_type, 1);
>    pvm_alloc_remove_gc_roots (&void_type, 1);
> +  pvm_alloc_remove_gc_roots (&opaque_type, 1);
>    pvm_alloc_remove_gc_roots (&common_int_types, 65 * 2);
>  }
> diff --git a/libpoke/pvm-val.h b/libpoke/pvm-val.h
> index 192a5741..c3c8a479 100644
> --- a/libpoke/pvm-val.h
> +++ b/libpoke/pvm-val.h
> @@ -45,6 +45,7 @@
>  #define PVM_VAL_TAG_SCT 0xb
>  #define PVM_VAL_TAG_TYP 0xc
>  #define PVM_VAL_TAG_CLS 0xd
> +#define PVM_VAL_TAG_OPQ 0xe
>  
>  #define PVM_VAL_BOXED_P(V) (PVM_VAL_TAG((V)) > 1)
>  
> @@ -148,6 +149,7 @@
>  #define PVM_VAL_BOX_TYP(B) ((B)->v.type)
>  #define PVM_VAL_BOX_CLS(B) ((B)->v.cls)
>  #define PVM_VAL_BOX_OFF(B) ((B)->v.offset)
> +#define PVM_VAL_BOX_OPQ(B) ((B)->v.opaque)
>  
>  struct pvm_val_box
>  {
> @@ -160,6 +162,7 @@ struct pvm_val_box
>      struct pvm_type *type;
>      struct pvm_off *offset;
>      struct pvm_cls *cls;
> +    struct pvm_opq *opaque;
>    } v;
>  };
>  
> @@ -446,6 +449,7 @@ enum pvm_type_code
>    PVM_TYPE_STRUCT,
>    PVM_TYPE_OFFSET,
>    PVM_TYPE_CLOSURE,
> +  PVM_TYPE_OPAQUE,
>    PVM_TYPE_VOID
>  };
>  
> @@ -546,6 +550,21 @@ struct pvm_off
>  
>  typedef struct pvm_off *pvm_off;
>  
> +/* Opaques are boxed values.  */
> +
> +#define PVM_VAL_OPQ(V) (PVM_VAL_BOX_OPQ (PVM_VAL_BOX ((V))))
> +
> +#define PVM_VAL_OPQ_NAME(V) (PVM_VAL_OPQ((V))->name)
> +#define PVM_VAL_OPQ_PAYLOAD(V) (PVM_VAL_OPQ((V))->payload)
> +
> +struct pvm_opq
> +{
> +  pvm_val name;
> +  uintptr_t payload;
> +};
> +
> +typedef struct pvm_opq *pvm_opq;
> +
>  #define PVM_IS_INT(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_INT)
>  #define PVM_IS_UINT(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_UINT)
>  #define PVM_IS_LONG(V) (PVM_VAL_TAG(V) == PVM_VAL_TAG_LONG)
> @@ -568,6 +587,9 @@ typedef struct pvm_off *pvm_off;
>  #define PVM_IS_OFF(V)                                                   \
>    (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
>     && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_OFF)
> +#define PVM_IS_OPQ(V)                                                   \
> +  (PVM_VAL_TAG(V) == PVM_VAL_TAG_BOX                                    \
> +   && PVM_VAL_BOX_TAG (PVM_VAL_BOX ((V))) == PVM_VAL_TAG_OPQ)
>  
>  
>  #define PVM_IS_INTEGRAL(V)                                      \
> diff --git a/libpoke/pvm.h b/libpoke/pvm.h
> index 44a0d11c..100ba685 100644
> --- a/libpoke/pvm.h
> +++ b/libpoke/pvm.h
> @@ -236,6 +236,15 @@ pvm_val pvm_make_string_nodup (char *value);
>  
>  pvm_val pvm_make_offset (pvm_val magnitude, pvm_val type);
>  
> +/* Make an opaque PVM value.
> +
> +   NAME is a PVM string value.
> +
> +   PAYLOAD is the opaque thing that we want to wrap; it's capable of
> +   wrapping pointer values safely.  */
> +
> +pvm_val pvm_make_opaque (pvm_val name, uintptr_t payload);
> +
>  /* Make an array PVM value.
>  
>     NELEM is an ulong<64> PVM value specifying the number of elements
> @@ -303,7 +312,10 @@ pvm_val pvm_make_array_type (pvm_val type, pvm_val 
> bound);
>  pvm_val pvm_make_struct_type (pvm_val nfields, pvm_val name,
>                                pvm_val *fnames, pvm_val *ftypes);
>  
> +pvm_val pvm_make_opaque_type (void);
> +
>  pvm_val pvm_make_offset_type (pvm_val base_type, pvm_val unit);
> +
>  pvm_val pvm_make_closure_type (pvm_val rtype, pvm_val nargs,
>                                 pvm_val *atypes);
>  
> diff --git a/libpoke/pvm.jitter b/libpoke/pvm.jitter
> index d42b69bd..cb515462 100644
> --- a/libpoke/pvm.jitter
> +++ b/libpoke/pvm.jitter
> @@ -84,11 +84,13 @@ wrapped-functions
>    pvm_make_uint
>    pvm_make_long
>    pvm_make_ulong
> +  pvm_make_opaque
>    pvm_make_exception
>    pvm_make_integral_type
>    pvm_make_string_type
>    pvm_make_offset_type
>    pvm_make_array_type
> +  pvm_make_opaque_type
>    pk_upow
>    pk_print_binary
>    pk_format_binary
> @@ -3908,6 +3910,38 @@ instruction nec ()
>    end
>  end
>  
> +# Instruction: eqo
> +#
> +# Push 1 on the stack if the two opaque values at the top of the stack
> +# are equal.  Otherwise push 0.
> +#
> +# Stack: ( OPQ OPQ -- OPQ OPQ INT )
> +
> +instruction eqo ()
> +  code
> +    pvm_val a = PVM_VAL_OPQ_PAYLOAD (JITTER_TOP_STACK ());
> +    pvm_val b = PVM_VAL_OPQ_PAYLOAD (JITTER_UNDER_TOP_STACK ());
> +
> +    JITTER_PUSH_STACK (PVM_MAKE_INT (a == b, 32));
> +  end
> +end
> +
> +# Instruction: neo
> +#
> +# Push 1 on the stack if the two opaque values at the top of the stack
> +# are not equal.  Otherwise push 0.
> +#
> +# Stack: ( OPQ OPQ -- OPQ OPQ INT )
> +
> +instruction neo ()
> +  code
> +    pvm_val a = PVM_VAL_OPQ_PAYLOAD (JITTER_TOP_STACK ());
> +    pvm_val b = PVM_VAL_OPQ_PAYLOAD (JITTER_UNDER_TOP_STACK ());
> +
> +    JITTER_PUSH_STACK (PVM_MAKE_INT (a != b, 32));
> +  end
> +end
> +
>  
>  ## Concatenation instructions
>  
> @@ -5584,6 +5618,21 @@ instruction ogetbt ()
>    end
>  end
>  
> +
> +## Opaque Values Instructions
> +
> +# Instruction: opqgetn
> +#
> +# Given an opaque OPQ, push its name on the stack.
> +#
> +# Stack: ( OPQ -- OPQ NAME )
> +
> +instruction opqgetn ()
> +  code
> +    JITTER_PUSH_STACK (PVM_VAL_OPQ_NAME (JITTER_TOP_STACK ()));
> +  end
> +end
> +
>  
>  ## Instructions to handle mapped values
>  
> @@ -6102,7 +6151,7 @@ end
>  # Given a type, push 1 on the stack if it is a void.  Push 0
>  # otherwise.
>  #
> -# Stack: ( TYPE -- TYPE INT)
> +# Stack: ( TYPE -- TYPE INT )
>  
>  instruction tyisv ()
>    code
> @@ -6113,6 +6162,22 @@ instruction tyisv ()
>    end
>  end
>  
> +# Instruction: tyisopq
> +#
> +# Given a type, push 1 on the stack if it is a opaque.  Push 0
> +# otherwise.
> +#
> +# Stack: ( TYPE -- TYPE INT )
> +
> +instruction tyisopq ()
> +  code
> +    pvm_val typ = JITTER_TOP_STACK ();
> +    int isopq_p = PVM_VAL_TYP_CODE (typ) == PVM_TYPE_OPAQUE;
> +
> +    JITTER_PUSH_STACK (PVM_MAKE_INT (isopq_p, 32));
> +  end
> +end
> +
>  # Instruction: mktyv
>  #
>  # Build a "void" type and push it on the stack.
> @@ -6125,6 +6190,18 @@ instruction mktyv ()
>    end
>  end
>  
> +# Instruction: mktyopq
> +#
> +# Build an "opaque" type and push it on the stack.
> +#
> +# Stack: ( -- TYPE )
> +
> +instruction mktyopq ()
> +  code
> +    JITTER_PUSH_STACK (pvm_make_opaque_type ());
> +  end
> +end
> +
>  # Instruction: mktyi
>  #
>  # Given an unsigned long denoting a bit width, and an unsigned int



reply via email to

[Prev in Thread] Current Thread [Next in Thread]