: define-constructor ( len -- )
[ <alien> ] cons
- <% "<" % "struct-name" get % ">" % %> "in" get create swap
+ <% "<" % "struct-name" get % ">" % %>
+ "in" get create swap
+ define-compound ;
+
+: define-local-constructor ( len -- )
+ [ <local-alien> ] cons
+ <% "<local-" % "struct-name" get % ">" % %>
+ "in" get create swap
define-compound ;
: define-struct-type ( len -- )
"struct-name" set
0 swap [ define-field ] each
dup define-constructor
+ dup define-local-constructor
define-struct-type
] with-scope ;
DEFER: dlsym-self
DEFER: dlclose
DEFER: <alien>
+DEFER: <local-alien>
DEFER: alien-cell
DEFER: set-alien-cell
DEFER: alien-4
dlsym-self
dlclose
<alien>
+ <local-alien>
alien-cell
set-alien-cell
alien-4
! This is the naive implementation, for benchmarking purposes.
1 swap [ succ * ] times* ;
-: 2^ ( x -- 2^x )
- 1 swap [ 2 * ] times ;
-
-: harmonic ( n -- 1 + 1/2 + 1/3 + ... + 1/n )
- 0 swap [ succ recip + ] times* ;
-
: mag2 ( x y -- mag )
#! Returns the magnitude of the vector (x,y).
swap sq swap sq + fsqrt ;
[
"/library/platform/native/kernel.factor"
"/library/platform/native/stack.factor"
+ "/library/platform/native/types.factor"
"/library/cons.factor"
"/library/combinators.factor"
"/library/logic.factor"
"/library/platform/native/kernel.factor"
"/library/platform/native/stack.factor"
"/library/platform/native/types.factor"
+ "/library/math/math.factor"
"/library/platform/native/math.factor"
"/library/cons.factor"
"/library/combinators.factor"
USE: vectors
USE: words
-: expired-port-error ( obj -- )
- "Expired port: " write . ;
+: expired-error ( obj -- )
+ "Object did not survive image save/load: " write . ;
: io-task-twice-error ( obj -- )
"Attempting to perform two simultaneous I/O operations on "
: signal-error ( obj -- )
"Operating system signal " write . ;
-: profiling-disabled-error ( obj -- )
- drop "Recompile with #define FACTOR_PROFILER." print ;
-
: negative-array-size-error ( obj -- )
"Cannot allocate array with negative size " write . ;
: kernel-error. ( obj n -- str )
{
- expired-port-error
+ expired-error
io-task-twice-error
no-io-tasks-error
incompatible-port-error
array-range-error
float-format-error
signal-error
- profiling-disabled-error
negative-array-size-error
bad-primitive-error
c-string-error
USE: vectors
USE: words
-: abs ( z -- abs )
- #! This definition is replaced when the remainder of the
- #! math library is read in at stage2.
- dup 0 < [ neg ] when ;
-
: (gcd) ( x y -- z ) dup 0 = [ drop ] [ tuck mod (gcd) ] ifte ;
: gcd ( x y -- z ) abs swap abs 2dup < [ swap ] when (gcd) ;
: POSTPONE: ( -- ) scan-word parsed ; parsing
! Colon defs
-: CREATE
+: CREATE ( -- word )
scan "in" get create dup set-word
f "documentation" pick set-word-property ;
[ dlsym-self | " name -- ptr " ]
[ dlclose | " dll -- " ]
[ <alien> | " ptr len -- alien " ]
+ [ <local-alien> | " len -- alien " ]
[ alien-cell | " alien off -- n " ]
[ set-alien-cell | " n alien off -- " ]
[ alien-4 | " alien off -- n " ]
[ t ] [ #{ 12 13 } #{ 13 14 } / #{ 13 14 } * #{ 12 13 } ] [ = ] test-word
[ #{ -3 4 } ] [ #{ 3 -4 } ] [ neg ] test-word
+
+[ 5 ] [ #{ 3 4 } abs ] unit-test
+[ 5 ] [ -5.0 abs ] unit-test
-#define ERROR_PORT_EXPIRED (0<<3)
+#define ERROR_EXPIRED (0<<3)
#define ERROR_IO_TASK_TWICE (1<<3)
#define ERROR_IO_TASK_NONE (2<<3)
#define ERROR_INCOMPATIBLE_PORT (3<<3)
#define ERROR_RANGE (7<<3)
#define ERROR_FLOAT_FORMAT (8<<3)
#define ERROR_SIGNAL (9<<3)
-#define ERROR_PROFILING_DISABLED (10<<3)
-#define ERROR_NEGATIVE_ARRAY_SIZE (11<<3)
-#define ERROR_BAD_PRIMITIVE (12<<3)
-#define ERROR_C_STRING (13<<3)
-#define ERROR_FFI_DISABLED (14<<3)
-#define ERROR_FFI (15<<3)
+#define ERROR_NEGATIVE_ARRAY_SIZE (10<<3)
+#define ERROR_BAD_PRIMITIVE (11<<3)
+#define ERROR_C_STRING (12<<3)
+#define ERROR_FFI_DISABLED (13<<3)
+#define ERROR_FFI (14<<3)
void fatal_error(char* msg, CELL tagged);
void critical_error(char* msg, CELL tagged);
#include "factor.h"
+DLL* untag_dll(CELL tagged)
+{
+ DLL* dll = (DLL*)UNTAG(tagged);
+ type_check(DLL_TYPE,tagged);
+ if(dll->dll == NULL)
+ general_error(ERROR_EXPIRED,tagged);
+ return (DLL*)UNTAG(tagged);
+}
+
void primitive_dlopen(void)
{
#ifdef FFI
ALIEN* alien = allot_object(ALIEN_TYPE,sizeof(ALIEN));
alien->ptr = ptr;
alien->length = length;
+ alien->local = false;
dpush(tag_object(alien));
#else
general_error(ERROR_FFI_DISABLED,F);
#endif
}
-ALIEN* unbox_alien(void)
+void primitive_local_alien(void)
+{
+#ifdef FFI
+ CELL length = unbox_integer();
+ ALIEN* alien = allot_object(ALIEN_TYPE,sizeof(ALIEN));
+ STRING* local = string(length / CHARS,'\0');
+ alien->ptr = (CELL)local + sizeof(STRING);
+ alien->length = length;
+ alien->local = true;
+ dpush(tag_object(alien));
+#else
+ general_error(ERROR_FFI_DISABLED,F);
+#endif
+}
+
+#ifdef FFI
+CELL unbox_alien(void)
{
return untag_alien(dpop())->ptr;
}
{
FIXNUM offset = unbox_integer();
ALIEN* alien = untag_alien(dpop());
+ CELL ptr = alien->ptr;
+
+ if(ptr == NULL)
+ general_error(ERROR_EXPIRED,tag_object(alien));
+
if(offset < 0 || offset >= alien->length)
{
range_error(tag_object(alien),offset,alien->length);
return 0; /* can't happen */
}
else
- return alien->ptr + offset;
+ return ptr + offset;
}
+#endif
void primitive_alien_cell(void)
{
general_error(ERROR_FFI_DISABLED,F);
#endif
}
+
+void fixup_dll(DLL* dll)
+{
+ dll->dll = NULL;
+}
+
+void fixup_alien(ALIEN* alien)
+{
+ alien->ptr = NULL;
+}
+
+void collect_alien(ALIEN* alien)
+{
+ if(alien->local && alien->ptr != NULL)
+ {
+ STRING* ptr = alien->ptr - sizeof(STRING);
+ ptr = copy_untagged_object(ptr,SSIZE(ptr));
+ alien->ptr = (CELL)ptr + sizeof(STRING);
+ }
+}
void* dll;
} DLL;
-INLINE DLL* untag_dll(CELL tagged)
-{
- type_check(DLL_TYPE,tagged);
- return (DLL*)UNTAG(tagged);
-}
+DLL* untag_dll(CELL tagged);
typedef struct {
CELL header;
CELL ptr;
CELL length;
+ /* local aliens are heap-allocated as strings and must be collected. */
+ bool local;
} ALIEN;
INLINE ALIEN* untag_alien(CELL tagged)
void primitive_dlsym_self(void);
void primitive_dlclose(void);
void primitive_alien(void);
-ALIEN* unbox_alien(void);
+void primitive_local_alien(void);
+CELL unbox_alien(void);
void primitive_alien_cell(void);
void primitive_set_alien_cell(void);
void primitive_alien_4(void);
void primitive_set_alien_2(void);
void primitive_alien_1(void);
void primitive_set_alien_1(void);
+void fixup_dll(DLL* dll);
+void fixup_alien(ALIEN* alien);
+void collect_alien(ALIEN* alien);
gc_in_progress = false;
}
-#ifdef FACTOR_PROFILER
void allot_profile_step(CELL a)
{
CELL depth = (cs - cs_bot) / CELLS;
executing->allot_count += a;
}
-#endif
void check_memory(void)
{
void primitive_allot_profiling(void)
{
-#ifndef FACTOR_PROFILER
- general_error(ERROR_PROFILING_DISABLED,F);
-#else
CELL d = dpop();
if(d == F)
allot_profiling = false;
allot_profiling = true;
profile_depth = to_fixnum(d);
}
-#endif
}
void primitive_address(void)
{
CELL h = active.here;
active.here += align8(a);
-#ifdef FACTOR_PROFILER
if(allot_profiling)
allot_profile_step(align8(a));
-#endif
check_memory();
return (void*)h;
}
p = (PORT*)UNTAG(tagged);
/* after image load & save, ports are no longer valid */
if(p->fd == -1)
- general_error(ERROR_PORT_EXPIRED,tagged);
+ general_error(ERROR_EXPIRED,tagged);
return p;
}
primitive_dlsym_self,
primitive_dlclose,
primitive_alien,
+ primitive_local_alien,
primitive_alien_cell,
primitive_set_alien_cell,
primitive_alien_4,
extern XT primitives[];
-#define PRIMITIVE_COUNT 191
+#define PRIMITIVE_COUNT 192
CELL primitive_to_xt(CELL primitive);
case PORT_TYPE:
fixup_port((PORT*)relocating);
break;
+ case DLL_TYPE:
+ fixup_dll((DLL*)relocating);
+ break;
+ case ALIEN_TYPE:
+ fixup_alien((ALIEN*)relocating);
+ break;
}
}
if(callframe == F)
{
callframe = cpop();
-#ifdef FACTOR_PROFILER
cpop();
-#endif
continue;
}
void primitive_call_profiling(void)
{
-#ifndef FACTOR_PROFILER
- general_error(ERROR_PROFILING_DISABLED,F);
-#else
CELL d = dpop();
if(d == F)
{
if(setitimer(ITIMER_PROF,&prof_timer,NULL) < 0)
io_error(__FUNCTION__);
-#endif
}
/* tail call optimization */
if(callframe != F)
{
-#ifdef FACTOR_PROFILER
cpush(tag_word(executing));
-#endif
cpush(callframe);
}
callframe = quot;