]> git.mxchange.org Git - simgear.git/commitdiff
Sync with Nasal upstream. Mostly fixes to naContinue(), which
authorandy <andy>
Wed, 30 May 2007 22:49:41 +0000 (22:49 +0000)
committerandy <andy>
Wed, 30 May 2007 22:49:41 +0000 (22:49 +0000)
FlightGear doesn't use.  Also includes a performance fix for the
call() builtin that should help Melchior, who was measuring lower
performance for the props.Node() interface than the getprop/setprop
API.

simgear/nasal/code.c
simgear/nasal/code.h
simgear/nasal/data.h
simgear/nasal/lib.c
simgear/nasal/misc.c
simgear/nasal/nasal.h

index 5f57a77147c32bb3fb1e5ccc874e886d2ac940f8..031be628b2205910a2494ed677c6f48b3204853e 100644 (file)
@@ -807,12 +807,30 @@ naRef naContinue(naContext ctx)
 {
     naRef result;
     if(!ctx->callParent) naModLock();
+
+    ctx->dieArg = naNil();
+    ctx->error[0] = 0;
+
     if(setjmp(ctx->jumpHandle)) {
         if(!ctx->callParent) naModUnlock(ctx);
+        else naRethrowError(ctx);
         return naNil();
     }
+
+    // Wipe off the old function arguments, and push the expected
+    // result (either the result of our subcontext, or a synthesized
+    // nil if the thrown error was from an extension function or
+    // in-script die() call) before re-running the code from the
+    // instruction following the error.
     ctx->opTop = ctx->opFrame;
-    PUSH(naNil());
+    PUSH(ctx->callChild ? naContinue(ctx->callChild) : naNil());
+
+    // Getting here means the child completed successfully.  But
+    // because its original C stack was longjmp'd out of existence,
+    // there is no one left to free the context, so we have to do it.
+    // This is fragile, but unfortunately required.
+    if(ctx->callChild) naFreeContext(ctx->callChild);
+
     result = run(ctx);
     if(!ctx->callParent) naModUnlock();
     return result;
index a71f13095f1fb529cdb9370420d78263b18c0619..af90e2d2c4bd18dde9372ea9c94701d7d4b0b0cb 100644 (file)
 #define MAX_MARK_DEPTH 128
 
 // Number of objects (per pool per thread) asked for using naGC_get().
-// Testing with fib.nas shows that this gives the best performance,
-// without too much per-thread overhead.
-#define OBJ_CACHE_SZ 128
+// The idea is that contexts can "cache" allocations to prevent thread
+// contention on the global pools.  But in practice this interacts
+// very badly with small subcontext calls, which grab huge numbers of
+// cached objects and don't use them, causing far more collections
+// than necessary.  Just leave it at 1 pending a rework of the
+// collector synchronization.
+#define OBJ_CACHE_SZ 1
 
 enum {    
     OP_NOT, OP_MUL, OP_PLUS, OP_MINUS, OP_DIV, OP_NEG,
index 3c5a23b0c15e4cec2638c7c90d760a6be969ee94..7c851be590c28b884552f25f26a4130e6ab41a39 100644 (file)
@@ -9,7 +9,7 @@
 // bitmask that sets the top 16 bits.  As a double, this is a
 // signalling NaN that cannot itself be produced by normal numerics
 // code.  The pointer value can be reconstructed if (and only if) we
-// are guaranteed that all memory that can be poitned to by a naRef
+// are guaranteed that all memory that can be pointed to by a naRef
 // (i.e. all memory returned by naAlloc) lives in the bottom 48 bits
 // of memory.  Linux on x86_64, Win64, Solaris and Irix all have such
 // policies with address spaces:
@@ -82,7 +82,7 @@ enum { T_STR, T_VEC, T_HASH, T_CODE, T_FUNC, T_CCODE, T_GHOST,
 #define MUTABLE(r) (IS_STR(r) && PTR(r).str->hashcode == 0)
 
 // This is a macro instead of a separate struct to allow compilers to
-// avoid padding.  GCC on x86, at least, will always padd the size of
+// avoid padding.  GCC on x86, at least, will always pad the size of
 // an embedded struct up to 32 bits.  Doing it this way allows the
 // implementing objects to pack in 16 bits worth of data "for free".
 #define GC_HEADER \
index ff35104c90a36ee1d689b5b3527d7aff0097ddf2..a724d5cb0bb20a11954dcb4a3223a6f21119637d 100644 (file)
@@ -227,29 +227,32 @@ static naRef f_call(naContext c, naRef me, int argc, naRef* args)
     if(!IS_FUNC(args[0]) || (!IS_NIL(callargs) && !IS_VEC(callargs)))
         ARGERR();
 
-    // Note that we don't free the subcontext, in case the user
-    // re-throws the same error.  That happens at the next OP_RETURN
-    // or naSubContext().
     subc = naSubContext(c);
     vr = IS_NIL(callargs) ? 0 : PTR(callargs).vec->rec;
     result = naCall(subc, args[0], vr ? vr->size : 0, vr ? vr->array : 0,
                     callme, callns);
-    if(naGetError(subc)) {
-        if(argc <= 2 || !IS_VEC(args[argc-1])) {
-            naRethrowError(subc);
-        } else {
-            int i, sd;
-            naRef errv = args[argc-1];
-            if(!IS_NIL(subc->dieArg)) naVec_append(errv, subc->dieArg);
-            else naVec_append(errv, NEWCSTR(subc, naGetError(subc)));
-            sd = naStackDepth(subc);
-            for(i=0; i<sd; i++) {
-                naVec_append(errv, naGetSourceFile(subc, i));
-                naVec_append(errv, naNum(naGetLine(subc, i)));
-            }
+    if(!naGetError(subc)) {
+        naFreeContext(subc);
+        return result;
+    }
+
+    // Error handling. Note that we don't free the subcontext after an
+    // error, in case the user re-throws the same error or calls
+    // naContinue()
+    if(argc <= 2 || !IS_VEC(args[argc-1])) {
+        naRethrowError(subc);
+    } else {
+        int i, sd;
+        naRef errv = args[argc-1];
+        if(!IS_NIL(subc->dieArg)) naVec_append(errv, subc->dieArg);
+        else naVec_append(errv, NEWCSTR(subc, naGetError(subc)));
+        sd = naStackDepth(subc);
+        for(i=0; i<sd; i++) {
+            naVec_append(errv, naGetSourceFile(subc, i));
+            naVec_append(errv, naNum(naGetLine(subc, i)));
         }
     }
-    return result;
+    return naNil();
 }
 
 static naRef f_die(naContext c, naRef me, int argc, naRef* args)
index 6e0e92398d7e4fcb2e3561667df700dc8418f4f5..85a9f126440462915e16a60bcf3d1fa7238ddc24 100644 (file)
@@ -5,17 +5,9 @@
 #include "nasal.h"
 #include "code.h"
 
-static void* chkptr(void* p)
-{
-    naRef foo;
-    SETPTR(foo, p);
-    if(PTR(foo).obj != p) *(int*)0=0;
-    return p;
-}
-
 void naFree(void* m) { free(m); }
-void* naAlloc(int n) { return chkptr(malloc(n)); }
-void* naRealloc(void* b, int n) { return chkptr(realloc(b, n)); }
+void* naAlloc(int n) { return malloc(n); }
+void* naRealloc(void* b, int n) { return realloc(b, n); }
 void naBZero(void* m, int n) { memset(m, 0, n); }
 
 void naTempSave(naContext c, naRef r)
index 29f2baabaa8d6550031e6160c3a08a8189fc69ae..1b8184bcbeb7f50d4e95d2227f19e838c6fa9908 100644 (file)
@@ -6,6 +6,15 @@ extern "C" {
 
 #include "naref.h"
 
+#if __GNUC__ > 2
+/* This marks the function as having no side effects and depending on
+ * nothing but its arguments, which allows the optimizer to avoid
+ * duplicate calls to naNil(). */
+#define GCC_PURE __attribute__((__pure__))
+#else
+#define GCC_PURE
+#endif
+
 typedef struct Context* naContext;
     
 // The function signature for an extension function:
@@ -27,7 +36,7 @@ naContext naSubContext(naContext super);
 // provision for sharing it, nor for validating the source or type of
 // the pointer returned.
 void naSetUserData(naContext c, void* p);
-void* naGetUserData(naContext c);
+void* naGetUserData(naContext c) GCC_PURE;
 
 // "Save" this object in the context, preventing it (and objects
 // referenced by it) from being garbage collected.
@@ -117,19 +126,19 @@ naRef naGetSourceFile(naContext ctx, int frame);
 char* naGetError(naContext ctx);
 
 // Type predicates
-int naIsNil(naRef r);
-int naIsNum(naRef r);
-int naIsString(naRef r);
-int naIsScalar(naRef r);
-int naIsVector(naRef r);
-int naIsHash(naRef r);
-int naIsCode(naRef r);
-int naIsFunc(naRef r);
-int naIsCCode(naRef r);
+int naIsNil(naRef r) GCC_PURE;
+int naIsNum(naRef r) GCC_PURE;
+int naIsString(naRef r) GCC_PURE;
+int naIsScalar(naRef r) GCC_PURE;
+int naIsVector(naRef r) GCC_PURE;
+int naIsHash(naRef r) GCC_PURE;
+int naIsCode(naRef r) GCC_PURE;
+int naIsFunc(naRef r) GCC_PURE;
+int naIsCCode(naRef r) GCC_PURE;
 
 // Allocators/generators:
-naRef naNil();
-naRef naNum(double num);
+naRef naNil() GCC_PURE;
+naRef naNum(double num) GCC_PURE;
 naRef naNewString(naContext c);
 naRef naNewVector(naContext c);
 naRef naNewHash(naContext c);
@@ -137,10 +146,10 @@ naRef naNewFunc(naContext c, naRef code);
 naRef naNewCCode(naContext c, naCFunction fptr);
 
 // Some useful conversion/comparison routines
-int naEqual(naRef a, naRef b);
-int naStrEqual(naRef a, naRef b);
-int naTrue(naRef b);
-naRef naNumValue(naRef n);
+int naEqual(naRef a, naRef b) GCC_PURE;
+int naStrEqual(naRef a, naRef b) GCC_PURE;
+int naTrue(naRef b) GCC_PURE;
+naRef naNumValue(naRef n) GCC_PURE;
 naRef naStringValue(naContext c, naRef n);
 
 // String utilities: