Author Topic: Bit Shift  (Read 5863 times)

0 Members and 1 Guest are viewing this topic.

JRS

  • Guest
Bit Shift
« on: September 11, 2016, 02:56:45 PM »
Charles,

Do you remember when you helped me create a bit shift / rotate set of routines when I was working on the SDL_gfx library?
Well, I need to use these routines again with my JavaScript extension module to set property attribute flags and I'm getting a seg fault / core dump trying to call them.

Bit Shift and Rotate
Code: C
  1. besFUNCTION(SB_shifts)
  2.   DIM AS int bp, co, v, x, y, d, p, ar;
  3.   besARGUMENTS("ii[i]")
  4.     AT v, AT p, AT ar
  5.   besARGEND
  6.   IF (ar EQ NULL) THEN_DO ar = 0;
  7.   x = 0xffffffff & v;
  8.   IF (p >= 0) THEN
  9.     y = x << p; // bit shift left
  10.   ELSE
  11.     y = x >> (-p); // bit shift right
  12.   END_IF
  13. //
  14. // SUPPORT FOR ARITHMETIC RIGHT SHIFTS
  15. //
  16.   IF ((ar) AND (p < 0) AND (x & 0x80000000)) THEN
  17.     d = 31 + p;
  18.     IF (d < 0) THEN_DO d = 0; // LIMIT
  19.     bp = 0x80000000;
  20.     DEF_FOR (co = 31 TO co >= d STEP DECR co)
  21.     BEGIN_FOR
  22.       y = y | bp;
  23.       bp = bp >> 1;
  24.     NEXT
  25.   END_IF
  26.   besRETURN_LONG(y);
  27. besEND
  28.  
  29. besFUNCTION(SB_rotates)
  30.   DIM AS int co, v, x, y, d, p, ar;
  31.   besARGUMENTS("ii[i]")
  32.     AT v, AT p, AT ar
  33.   besARGEND
  34.   IF (ar EQ NULL) THEN_DO ar = 0;
  35.   x = 0xffffffff & v;
  36.   d = p;
  37.   IF (d < 0) THEN_DO d=-d;
  38.   DEF_FOR (co = 1 TO co <= d STEP INCR co)
  39.   BEGIN_FOR
  40.     IF (p >= 0) THEN
  41.       y = x << 1; // bit shift left
  42.       IF (x & 0x80000000) THEN_DO y |= 1;
  43.     ELSE
  44.       y = x >> 1; // bit shift right
  45.       IF (x & 1) THEN_DO y |= 0x80000000;
  46.     END_IF
  47.     x = y;
  48.   NEXT
  49.   besRETURN_LONG(y);
  50. besEND
  51.  

Test Program
Code: Script BASIC
  1. IMPORT js.bas
  2.  
  3. PRINT "V7_PROPERTY_NON_WRITABLE: ",JS::SHIFT(1, 0),"\n"
  4. PRINT "V7_PROPERTY_NON_ENUMERABLE: ",JS::SHIFT(1, 1),"\n"
  5. PRINT "V7_PROPERTY_NON_CONFIGURABLE: ",JS::SHIFT(1, 2),"\n"
  6. PRINT "V7_PROPERTY_GETTER: ",JS::SHIFT(1, 3),"\n"
  7. PRINT "V7_PROPERTY_SETTER: ",JS::SHIFT(1, 4),"\n"
  8. PRINT "_V7_PROPERTY_HIDDEN: ",JS::SHIFT(1, 5),"\n"
  9. PRINT "_V7_PROPERTY_OFF_HEAP: ",JS::SHIFT(1, 6),"\n"
  10. PRINT "_V7_PROPERTY_USER_DATA_AND_DESTRUCTOR: ",JS::SHIFT(1, 7),"\n"
  11.  


jrs@laptop:~/sb/sb22/js$ scriba shift.sb
Segmentation fault (core dumped)
jrs@laptop:~/sb/sb22/js$


Here is the C code I'm trying to emulate.

Code: C
  1. /*
  2.  * Property attributes bitmask
  3.  */
  4. typedef unsigned short v7_prop_attr_t;
  5. #define V7_PROPERTY_NON_WRITABLE (1 << 0)
  6. #define V7_PROPERTY_NON_ENUMERABLE (1 << 1)
  7. #define V7_PROPERTY_NON_CONFIGURABLE (1 << 2)
  8. #define V7_PROPERTY_GETTER (1 << 3)
  9. #define V7_PROPERTY_SETTER (1 << 4)
  10. #define _V7_PROPERTY_HIDDEN (1 << 5)
  11. /* property not managed by V7 HEAP */
  12. #define _V7_PROPERTY_OFF_HEAP (1 << 6)
  13. /* special property holding user data and destructor cb */
  14. #define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR (1 << 7)
  15. /*
  16.  * not a property attribute, but a flag for `v7_def()`. It's here in order to
  17.  * keep all offsets in one place
  18.  */
  19. #define _V7_DESC_PRESERVE_VALUE (1 << 8)
  20.  
  21. /*
  22.  * Internal helpers for `V7_DESC_...` macros
  23.  */
  24. #define _V7_DESC_SHIFT 16
  25. #define _V7_DESC_MASK ((1 << _V7_DESC_SHIFT) - 1)
  26. #define _V7_MK_DESC(v, n) \
  27.   (((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0))
  28. #define _V7_MK_DESC_INV(v, n) _V7_MK_DESC(!(v), (n))
  29.  
  30. /*
  31.  * Property attribute descriptors that may be given to `v7_def()`: for each
  32.  * attribute (`v7_prop_attr_t`), there is a corresponding macro, which takes
  33.  * param: either 1 (set attribute) or 0 (clear attribute). If some particular
  34.  * attribute isn't mentioned at all, it's left unchanged (or default, if the
  35.  * property is being created)
  36.  *
  37.  * There is additional flag: `V7_DESC_PRESERVE_VALUE`. If it is set, the
  38.  * property value isn't changed (or set to `undefined` if the property is being
  39.  * created)
  40.  */
  41. typedef unsigned long v7_prop_attr_desc_t;
  42. #define V7_DESC_WRITABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE)
  43. #define V7_DESC_ENUMERABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE)
  44. #define V7_DESC_CONFIGURABLE(v) _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE)
  45. #define V7_DESC_GETTER(v) _V7_MK_DESC(v, V7_PROPERTY_GETTER)
  46. #define V7_DESC_SETTER(v) _V7_MK_DESC(v, V7_PROPERTY_SETTER)
  47. #define V7_DESC_PRESERVE_VALUE _V7_DESC_PRESERVE_VALUE
  48.  
  49. #define _V7_DESC_HIDDEN(v) _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN)
  50. #define _V7_DESC_OFF_HEAP(v) _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP)
  51.  

This is an example v7_def() call.

Code: C
  1. v7_def(v7, v, "foo", -1, V7_DESC_CONFIGURABLE(0), v7_mk_number(v7, 1.0))
  2.  

« Last Edit: September 11, 2016, 05:53:28 PM by John »

Charles Pegge

  • Guest
Re: Bit Shift
« Reply #1 on: September 12, 2016, 02:55:19 AM »

Hi John,

You can replace most of the shifts:

Code: [Select]
#define V7_PROPERTY_NON_WRITABLE     1
#define V7_PROPERTY_NON_ENUMERABLE   2
#define V7_PROPERTY_NON_CONFIGURABLE 4
#define V7_PROPERTY_GETTER           8
#define V7_PROPERTY_SETTER           16
#define _V7_PROPERTY_HIDDEN          32
#define _V7_PROPERTY_OFF_HEAP        64
#define _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR 128
#define _V7_DESC_PRESERVE_VALUE               256
#define _V7_DESC_MASK                         0xffff

but this wierdy one is hard to crack:

#define _V7_MK_DESC(v, n) \
(((v7_prop_attr_desc_t)(n)) << _V7_DESC_SHIFT | ((v) ? (n) : 0))

My interpretation:

if v then return n or (n<<16) else return n<<16)
---->
if v then return n*0x10000 + n else return n*0x10000

Mike Lobanovsky

  • Guest
Re: Bit Shift
« Reply #2 on: September 17, 2016, 02:10:08 PM »
Well, here we go and may success attend us! ;)

Code: Script BASIC
  1. CONST V7_PROPERTY_NON_WRITABLE              = 1
  2. CONST V7_PROPERTY_NON_ENUMERABLE            = 2
  3. CONST V7_PROPERTY_NON_CONFIGURABLE          = 4
  4. CONST V7_PROPERTY_GETTER                    = 8
  5. CONST V7_PROPERTY_SETTER                    = 16
  6. CONST _V7_PROPERTY_HIDDEN                   = 32
  7. CONST _V7_PROPERTY_OFF_HEAP                 = 64
  8. CONST _V7_PROPERTY_USER_DATA_AND_DESTRUCTOR = 128
  9. CONST _V7_DESC_PRESERVE_VALUE               = 256
  10. CONST _V7_DESC_MASK                         = &HFFFF
  11.  
  12. CONST SET_ATTR   = 1
  13. CONST CLEAR_ATTR = 0
  14.  
  15. FUNCTION _V7_MK_DESC(v, n)
  16.     IF v THEN
  17.         _V7_MK_DESC = (n OR (n * 0x10000))
  18.     ELSE
  19.         _V7_MK_DESC = INT(n * 0x10000)
  20.     END IF
  21. END FUNCTION
  22. FUNCTION _V7_MK_DESC_INV(v, n)
  23.     _V7_MK_DESC_INV = _V7_MK_DESC(NOT v, n)
  24. END FUNCTION
  25.  
  26. FUNCTION V7_DESC_WRITABLE(v)
  27.     V7_DESC_WRITABLE = V7_MK_DESC_INV(v, V7_PROPERTY_NON_WRITABLE)
  28. END FUNCTION
  29. FUNCTION V7_DESC_ENUMERABLE(v)
  30.     V7_DESC_ENUMERABLE = _V7_MK_DESC_INV(v, V7_PROPERTY_NON_ENUMERABLE)
  31. END FUNCTION
  32. FUNCTION V7_DESC_CONFIGURABLE(v)
  33.     V7_DESC_CONFIGURABLE = _V7_MK_DESC_INV(v, V7_PROPERTY_NON_CONFIGURABLE)
  34. END FUNCTION
  35. FUNCTION V7_DESC_GETTER(v)
  36.     V7_DESC_GETTER = _V7_MK_DESC(v, V7_PROPERTY_GETTER)
  37. END FUNCTION
  38. FUNCTION V7_DESC_SETTER(v)
  39.     V7_DESC_SETTER _V7_MK_DESC(v, V7_PROPERTY_SETTER)
  40. END FUNCTION
  41. FUNCTION V7_DESC_PRESERVE_VALUE()
  42.     V7_DESC_PRESERVE_VALUE = _V7_DESC_PRESERVE_VALUE
  43. END FUNCTION
  44.  
  45. FUNCTION _V7_DESC_HIDDEN(v)
  46.     _V7_DESC_HIDDEN = _V7_MK_DESC(v, _V7_PROPERTY_HIDDEN)
  47. END FUNCTION
  48. FUNCTION _V7_DESC_OFF_HEAP(v)
  49.     _V7_DESC_OFF_HEAP = _V7_MK_DESC(v, _V7_PROPERTY_OFF_HEAP)
  50. END FUNCTION




' ============================== HOW TO USE? ==============================
' Assumptions:
' ============
' I assume you've already got pointer to v7 and objptr (whatever it is)
' as integers in SB when you created the v7 object. Then you can send them back
' to JS::DEF() safely as SB integers that your C(BASIC) code in JS:: would accept
' (and cast?) to v7* and v7_val_t (whatever it is again because the header is
' still incomplete!), respectively. And finally I assume that val in the v7_def()
' description refers to v in its declaration, so that it is in fact as follows:
'
' int v7_def(struct v7 *v7, v7_val_t obj, const char *name, size_t name_len,
'           v7_prop_attr_desc_t attrs_desc, v7_val_t val);
'
' Use Cases:
' ==========
' Suppose we want to set a WRITABLE attribute to a property. Then we'd call:
'
' ret = JS::DEF(v7, objptr, "prop_name", LEN("prop_name"), V7_DESC_WRITABLE(SET_ATTR), prop_value)
' IF ret THEN
'    PRINT "SUCCESS!!! :-)", "\n"
' ELSE
'    PRINT "failure... :-(", "\n"
' END IF
'
' Now suppose we want to clear off the ENUMERABLE attribute of a property. Then we'd call:
'
' ret = JS::DEF(v7, objptr, "prop_name", LEN("prop_name"), V7_DESC_ENUMERABLE(CLEAR_ATTR), prop_value)
' IF ret THEN
'    PRINT "SUCCESS!!! :-)", "\n"
' ELSE
'    PRINT "failure... :-(", "\n"
' END IF
' =========================================================================




[EDIT] John, you've just split this topic right in the middle of my posting!  :o
« Last Edit: September 17, 2016, 02:20:22 PM by Mike Lobanovsky »

JRS

  • Guest
Re: Bit Shift
« Reply #3 on: September 17, 2016, 02:20:25 PM »
You're amazing!

Thanks.

Quote
John, you've just split this topic right in the middle of my posting!

Thankfully we didn't lose it. That would have be a disaster.

Curious. Is the unreferenced attributes preserved if a change in the definition is made? I would like to be able to do that optionally if possible.
« Last Edit: September 17, 2016, 09:04:59 PM by John »

JRS

  • Guest
Re: Bit Shift
« Reply #4 on: September 17, 2016, 02:51:32 PM »
Mike,

The C version allows me to set multiple attributes with one call by ORing them and tagging on the Preserve option to save the state (not resetting them to default) of those attributes not referenced in the call.

« Last Edit: September 17, 2016, 09:05:09 PM by John »

Mike Lobanovsky

  • Guest
Re: Bit Shift
« Reply #5 on: September 17, 2016, 02:59:20 PM »
Curious. Is the unreferenced attributes preserved if a change in the definition is made? I would like to be able to do that optionally if possible.

1. Property values, you mean? Yes, they can be preserved and then the val member will be ignored.

See below:

Quote
CONST _V7_DESC_PRESERVE_VALUE               = 256

....

FUNCTION V7_DESC_PRESERVE_VALUE()
    V7_DESC_PRESERVE_VALUE = _V7_DESC_PRESERVE_VALUE
END FUNCTION

....


Use Case:
=========

ret = JS::DEF(v7, objptr, "prop_name", LEN("prop_name"), _
      V7_DESC_WRITABLE(SET_ATTR) OR V7_DESC_SETTER(CLEAR_ATTR) OR V7_DESC_PRESERVE_VALUE(), _
      prop_value)
IF ret THEN
   PRINT "SUCCESS!!! :-)", "\n"
ELSE
   PRINT "failure... :-(", "\n"
END IF


Note that V7_DESC_PRESERVE_VALUE() is unconditional: you don't set or clear it, but just add it (I mean, OR it, hehe), is all.

2. The other attributes of the same property will be preserved at all times. The beauty of bitwise flags that are P.O.T.'s is that they can be freely OR'ed and XOR'ed together not interfering with one another. :)   (OR's always set a new bitwise flag while successive XOR's toggle it off and on again)

3. If you mean the attributes and values of the other properties, then of course they are preserved as well. Each property is addressed by an individual call by "prop_name" and "propname_length". Computers don't faulter. :)


OK, I guess now it's your move. Trial and error, trial and error... Well, our bread does smell of sweat.
« Last Edit: September 17, 2016, 03:21:53 PM by Mike Lobanovsky »

JRS

  • Guest
Re: Bit Shift
« Reply #6 on: September 17, 2016, 03:23:32 PM »
Thanks Mike!

I'm looking forward to giving this a try and then move on to finishing the interface. Next will come converting the V7 test suite from C to SB.

« Last Edit: September 17, 2016, 09:05:22 PM by John »

Mike Lobanovsky

  • Guest
Re: Bit Shift
« Reply #7 on: September 17, 2016, 03:34:15 PM »
Fine!

But please mind that I was short of info and so I can be not exact in my assumptions. But the interface doesn't seem too illogical to make out what's what by trial and error. At least the SB coding part should be solid and the rest will come with practice.

Good luck!

JRS

  • Guest
Re: Bit Shift
« Reply #8 on: September 17, 2016, 03:46:45 PM »
Having a tiny / fast JavaScript engine to call on is sweet. I think this beats the Tiny Scheme, Perl and MyBASIC embedded extension languages if not by popularity alone.


« Last Edit: September 17, 2016, 09:05:32 PM by John »

Mike Lobanovsky

  • Guest
Re: SBJS
« Reply #9 on: September 17, 2016, 04:37:42 PM »
... a tiny / fast JavaScript engine ...

Benchmarks will show who's fast and who's tiny.

JRS

  • Guest
Re: Bit Shift
« Reply #10 on: September 17, 2016, 05:18:37 PM »
V7 doesn't do well with recursive functions. It degrades the greater the recursion. Python seems to have the same problem. I posted a message on the Github incident site and someone is looking at it.

Quote
Benchmarks will show who's fast and who's tiny.

From what I've seen so far, it keeps up with SB without adding a load. The multi-threading aspect was a plus.
« Last Edit: September 17, 2016, 09:05:49 PM by John »

Mike Lobanovsky

  • Guest
Re: Bit Shift
« Reply #11 on: September 17, 2016, 07:42:34 PM »
V7 doesn't do well with recursive functions. It degrades the greater the recursion. Python seems to have the same problem. I posted a message on the Github incident site and someone is looking at it.

This can be said about any interpreter, bytecode or otherwise. Memory fragmentation and garbage collection do take their toll. I think you'll be surprised to find out it's true about SB as well (nothing personal, just business). Interpretative loop iteration is faster than recursion.

Quote
The multi-threading aspect was a plus.

I did examine the repo.

1) It isn't efficient to spawn a new v7 object in each function call. This is a test script only tactics. Once created, the v7 instance(s) should be reused to reduce overhead and memory fragmentation.

2) v7 is not thread safe. When used in multiple threads, v7 instances should serialize their respective memory accesses e.g. with mutexes and the like.

JRS

  • Guest
Re: Bit Shift
« Reply #12 on: September 17, 2016, 08:59:02 PM »
Quote
I think you'll be surprised to find out it's true about SB as well ...

That isn't what I'm seeing.

js_fibonacci.sb
Code: Script BASIC
  1. IMPORT js.bas
  2.  
  3. jscode = """
  4. function fibonacci(n) {
  5.  if (n <= 2) {
  6.    return 1;
  7.  } else {
  8.    return fibonacci(n - 1) + fibonacci(n - 2);
  9.  }
  10. }  
  11.  
  12. print(fibonacci(24));
  13. """
  14.  
  15. jsobj = JS::CREATE()
  16. results = JS::EXEC(jsobj, jscode, rtncode)
  17. JS::DESTROY(jsobj)
  18.  


jrs@laptop:~/sb/sb22/js$ time scriba js_fibonacci.sb
46368

real   0m1.754s
user   0m1.676s
sys   0m0.000s
jrs@laptop:~/sb/sb22/js$


fibonacci.sb
Code: Script BASIC
  1. FUNCTION Fibonacci(n)
  2.   IF n <= 2 THEN
  3.     Fibonacci = 1
  4.   ELSE
  5.     Fibonacci = Fibonacci(n - 1) + Fibonacci(n - 2)
  6.   END IF
  7. END FUNCTION
  8.  
  9. PRINT Fibonacci(24),"\n"
  10.  


jrs@laptop:~/sb/sb22/test$ time scriba fibonacci.sb
46368

real   0m0.091s
user   0m0.086s
sys   0m0.000s
jrs@laptop:~/sb/sb22/test$


Quote
v7 is not thread safe. When used in multiple threads, v7 instances should serialize their respective memory accesses e.g. with mutexes and the like.

V7 is static linked to the SB ext. module shared object which is thread safe. SB scripting acts as the glue between V7 instances. (threaded or not) At this point, I haven't seen any issues running V7 in a SB threaded environment.