3 //Template for defining Slate primitive signatures. Not a macro because IDEs don't process it:
4 //#define SLATE_PRIM(prim_name) void prim_name(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer)
12 void prim_fixme(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
14 printf("unimplemented primitive... dying\n");
20 void prim_closePipe(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
21 word_t handle
= object_to_smallint(args
[0]);
24 ASSURE_SMALLINT_ARG(0);
26 retval
= closesocket(handle
);
28 retval
= close(handle
);
30 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(retval
);
34 void prim_readFromPipe(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
35 struct ByteArray
* array
= (struct ByteArray
*) args
[0];
36 word_t handle
= object_to_smallint(args
[1]);
37 word_t start
= object_to_smallint(args
[2]), end
= object_to_smallint(args
[3]);
40 ASSURE_TYPE_ARG(0, TYPE_BYTE_ARRAY
);
41 ASSURE_SMALLINT_ARG(1);
42 ASSURE_SMALLINT_ARG(2);
43 ASSURE_SMALLINT_ARG(3);
45 if (start
< 0 || start
>= byte_array_size(array
)) {
46 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[2], args
[0], NULL
, resultStackPointer
);
50 if (end
< start
|| end
> byte_array_size(array
)) {
51 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[3], args
[0], NULL
, resultStackPointer
);
55 retval
= recv(handle
, byte_array_elements(array
)+start
, end
- start
, 0);
58 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(retval
);
63 void prim_writeToPipe(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
64 struct ByteArray
* array
= (struct ByteArray
*) args
[0];
65 word_t handle
= object_to_smallint(args
[1]);
66 word_t start
= object_to_smallint(args
[2]), end
= object_to_smallint(args
[3]);
69 ASSURE_TYPE_ARG(0, TYPE_BYTE_ARRAY
);
70 ASSURE_SMALLINT_ARG(1);
71 ASSURE_SMALLINT_ARG(2);
72 ASSURE_SMALLINT_ARG(3);
74 if (start
< 0 || start
>= byte_array_size(array
)) {
75 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[2], args
[0], NULL
, resultStackPointer
);
79 if (end
< start
|| end
> byte_array_size(array
)) {
80 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[3], args
[0], NULL
, resultStackPointer
);
84 retval
= send(handle
, byte_array_elements(array
)+start
, end
- start
, 0);
86 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(retval
);
90 /*FIXME this is a copy of the last function with only the select call changed*/
91 void prim_selectOnWritePipesFor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
93 GC_VOLATILE
struct OopArray
* selectOn
= (struct OopArray
*) args
[0];
94 GC_VOLATILE
struct OopArray
* readyPipes
;
95 word_t waitTime
= object_to_smallint(args
[1]);
96 int retval
, fdCount
, maxFD
;
101 ASSURE_SMALLINT_ARG(1);
103 if ((fdCount
= socket_select_setup(selectOn
, &fdList
, &maxFD
)) < 0) {
104 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
109 tv
.tv_sec
= waitTime
/ 1000000;
110 tv
.tv_usec
= waitTime
% 1000000;
111 retval
= select(maxFD
+1, NULL
, &fdList
, NULL
, &tv
);
114 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
119 readyPipes
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), retval
);
120 socket_select_find_available(selectOn
, &fdList
, readyPipes
, retval
);
122 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)readyPipes
;
126 void prim_cloneSystem(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
128 #pragma message("TODO WIN32 port forking/cloning the system")
133 GC_VOLATILE
struct OopArray
* array
;
135 /* make two pipes that we can use exclusively in each process to talk to the other */
136 /*FIXME remap fds for safety*/
137 if (socketpair(AF_UNIX
, SOCK_STREAM
, 0, pipes
) == -1) {
138 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
144 if (retval
== (pid_t
)-1) {
145 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
149 array
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), 2);
150 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)array
;
152 if (!retval
) { /* child */
153 array
->elements
[0] = oh
->cached
.false_object
;
154 array
->elements
[1] = smallint_to_object(pipes
[0]);
155 } else { /* parent */
156 array
->elements
[0] = oh
->cached
.true_object
;
157 array
->elements
[1] = smallint_to_object(pipes
[1]);
164 void prim_cloneSystemInProcess(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
166 #pragma message("TODO WIN32 port cloning/threading a system")
173 #ifdef SLATE_DAEMONIZE
175 /* Change this to whatever your daemon is called */
176 #define DAEMON_NAME "slatedaemon"
178 /* Change this to the user under which to run */
179 #define RUN_AS_USER "root"
181 static void child_handler(int signum
) {
183 case SIGALRM
: exit(EXIT_FAILURE
); break;
184 case SIGUSR1
: exit(EXIT_SUCCESS
); break;
185 case SIGCHLD
: exit(EXIT_FAILURE
); break;
189 void prim_daemonizeSystem(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
190 const char* lock_filename
= (char*)byte_array_elements((struct ByteArray
*) args
[1]);
192 #pragma message("TODO WIN32 port daemonizing a system")
194 pid_t pid
, sid
, parent
;
197 /* already a daemon */
198 if (getppid() == 1) return;
200 /* Create the lock file as the current user */
201 if (lock_filename
&& lock_filename
[0]) {
202 lfp
= open(lock_filename
,O_RDWR
|O_CREAT
,0640);
204 printf("Unable to create lock file %s, code=%d (%s)",
205 lock_filename
, errno
, strerror(errno
));
210 /* Drop user if there is one, and we were run as root */
211 if (getuid() == 0 || geteuid() == 0) {
212 struct passwd
*pw
= getpwnam(RUN_AS_USER
);
215 printf("Setting user to " RUN_AS_USER
);
220 /* Trap signals that we expect to receive */
221 signal(SIGCHLD
,child_handler
);
222 signal(SIGUSR1
,child_handler
);
223 signal(SIGALRM
,child_handler
);
225 /* Fork off the parent process */
228 printf("Unable to fork daemon, code=%d (%s)",
229 errno
, strerror(errno
));
232 /* If we got a good PID, then we can exit the parent process. */
235 /* Wait for confirmation from the child via SIGTERM or SIGCHLD, or
236 for two seconds to elapse (SIGALRM). pause() should not return. */
243 /* At this point we are executing as the child process */
246 /* Cancel certain signals */
247 signal(SIGCHLD
,SIG_DFL
); /* A child process dies */
248 signal(SIGTSTP
,SIG_IGN
); /* Various TTY signals */
249 signal(SIGTTOU
,SIG_IGN
);
250 signal(SIGTTIN
,SIG_IGN
);
251 signal(SIGHUP
, SIG_IGN
); /* Ignore hangup signal */
252 signal(SIGTERM
,SIG_DFL
); /* Die on SIGTERM */
254 /* Change the file mode mask */
257 /* Create a new SID for the child process */
260 printf("Unable to create a new session, code %d (%s)",
261 errno
, strerror(errno
));
265 /* Change the current working directory. This prevents the current
266 directory from being locked; hence not being able to remove it. */
267 if ((chdir("/")) < 0) {
268 printf("Unable to change directory to %s, code %d (%s)",
269 "/", errno
, strerror(errno
));
273 /* Redirect standard files to /dev/null */
274 freopen("/dev/null", "r", stdin
);
275 freopen("/dev/null", "w", stdout
);
276 freopen("/dev/null", "w", stderr
);
278 /* Tell the parent process that we are A-okay */
279 kill(parent
, SIGUSR1
);
281 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
284 #endif //SLATE_DAEMONIZE
286 void prim_socketCreate(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
287 word_t domain
= object_to_smallint(args
[0]);
288 word_t type
= object_to_smallint(args
[1]);
289 word_t protocol
= object_to_smallint(args
[2]);
290 word_t ret
= socket(socket_lookup_domain(domain
), socket_lookup_type(type
), socket_lookup_protocol(protocol
));
293 ASSURE_SMALLINT_ARG(0);
294 ASSURE_SMALLINT_ARG(1);
295 ASSURE_SMALLINT_ARG(2);
298 ret2
= socket_set_nonblocking(ret
);
300 perror("socket create");
304 perror("set nonblocking");
305 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(-1);
307 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
311 void prim_socketListen(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
312 word_t fd
= object_to_smallint(args
[0]);
313 word_t size
= object_to_smallint(args
[1]);
316 ASSURE_SMALLINT_ARG(0);
317 ASSURE_SMALLINT_ARG(1);
319 ret
= listen(fd
, size
);
321 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
325 void prim_socketAccept(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
326 word_t fd
= object_to_smallint(args
[0]);
328 struct sockaddr_storage addr
;
330 GC_VOLATILE
struct ByteArray
* addrArray
;
331 GC_VOLATILE
struct OopArray
* result
;
333 ASSURE_SMALLINT_ARG(0);
336 ret
= accept(fd
, (struct sockaddr
*)&addr
, &len
);
339 addrArray
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_in
));
341 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
345 heap_fixed_add(oh
, (struct Object
*)addrArray
);
346 result
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), 2);
347 heap_fixed_remove(oh
, (struct Object
*)addrArray
);
349 object_array_set_element(oh
, (struct Object
*)result
, 0, smallint_to_object(ret
));
350 object_array_set_element(oh
, (struct Object
*)result
, 1, (struct Object
*)addrArray
);
352 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)result
;
356 void prim_socketBind(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
357 word_t fd
= object_to_smallint(args
[0]);
358 struct ByteArray
* address
= (struct ByteArray
*) args
[1];
361 ASSURE_SMALLINT_ARG(0);
363 ret
= bind(fd
, (const struct sockaddr
*)byte_array_elements(address
), (socklen_t
)byte_array_size(address
));
364 if (ret
< 0) perror("bind");
365 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
368 void prim_socketConnect(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
369 word_t fd
= object_to_smallint(args
[0]);
370 struct ByteArray
* address
= (struct ByteArray
*) args
[1];
373 ASSURE_SMALLINT_ARG(0);
375 ret
= connect(fd
, (const struct sockaddr
*)byte_array_elements(address
), (socklen_t
)byte_array_size(address
));
377 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
381 void prim_socketGetError(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
382 word_t fd
= object_to_smallint(args
[0]);
387 ASSURE_SMALLINT_ARG(0);
389 ret
= getsockopt(fd
, SOL_SOCKET
, SO_ERROR
, &optval
, (socklen_t
*)&optlen
);
392 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(optval
);
394 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
399 void prim_getAddrInfo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
400 struct ByteArray
* hostname
= (struct ByteArray
*)args
[1];
401 struct ByteArray
* service
= (struct ByteArray
*)args
[2];
402 word_t family
= object_to_smallint(args
[3]);
403 word_t type
= object_to_smallint(args
[4]);
404 word_t protocol
= object_to_smallint(args
[5]);
405 word_t flags
= object_to_smallint(args
[6]);
406 word_t ret
, serviceSize
, hostnameSize
;
408 ASSURE_TYPE_ARG(1, TYPE_BYTE_ARRAY
);
409 ASSURE_SMALLINT_ARG(3);
410 ASSURE_SMALLINT_ARG(4);
411 ASSURE_SMALLINT_ARG(5);
412 ASSURE_SMALLINT_ARG(6);
414 if ((struct Object
*)hostname
== oh
->cached
.nil
) {
417 hostnameSize
= byte_array_size(hostname
)+1;
420 if ((struct Object
*)service
== oh
->cached
.nil
) {
423 ASSURE_TYPE_ARG(2, TYPE_BYTE_ARRAY
);
424 serviceSize
= byte_array_size(service
)+1;
427 ret
= socket_getaddrinfo(oh
, hostname
, hostnameSize
, service
, serviceSize
, family
, type
, protocol
, flags
);
429 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = SOCKET_RETURN(ret
);
434 void prim_getAddrInfoResult(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
435 word_t ticket
= object_to_smallint(args
[0]);
436 if (ticket
>= oh
->socketTicketCount
|| ticket
< 0
437 || oh
->socketTickets
[ticket
].inUse
== 0 || oh
->socketTickets
[ticket
].finished
== 0) {
438 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
441 if (oh
->socketTickets
[ticket
].result
< 0) {
442 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(socket_return(oh
->socketTickets
[ticket
].result
));
445 struct addrinfo
* ai
= oh
->socketTickets
[ticket
].addrResult
;
446 struct addrinfo
* current
= ai
;
447 GC_VOLATILE
struct OopArray
* retval
;
449 while (current
!= NULL
) {
450 current
= current
->ai_next
;
454 retval
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), count
);
455 heap_fixed_add(oh
, (struct Object
*)retval
);
456 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)retval
;
457 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)retval
);
459 for (i
= 0; i
< count
; i
++) {
460 GC_VOLATILE
struct OopArray
* aResult
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), 6);
461 struct ByteArray
* aResultAddr
;
462 struct ByteArray
* aResultCanonName
;
463 word_t canonNameLen
= (current
->ai_canonname
== NULL
)? 0 : strlen(current
->ai_canonname
);
464 retval
->elements
[i
] = (struct Object
*)aResult
;
465 heap_store_into(oh
, (struct Object
*)retval
, retval
->elements
[i
]);
466 aResult
->elements
[0] = smallint_to_object(current
->ai_flags
);
467 aResult
->elements
[1] = smallint_to_object(socket_reverse_lookup_domain(current
->ai_family
));
468 aResult
->elements
[2] = smallint_to_object(socket_reverse_lookup_type(current
->ai_socktype
));
469 aResult
->elements
[3] = smallint_to_object(socket_reverse_lookup_protocol(current
->ai_protocol
));
471 aResultAddr
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), current
->ai_addrlen
);
472 aResult
->elements
[4] = (struct Object
*)aResultAddr
;
473 heap_store_into(oh
, (struct Object
*)aResult
, aResult
->elements
[4]);
474 copy_bytes_into((byte_t
*)current
->ai_addr
, current
->ai_addrlen
, aResultAddr
->elements
);
475 if (canonNameLen
== 0) {
476 aResult
->elements
[5] = oh
->cached
.nil
;
478 aResultCanonName
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), canonNameLen
);
479 aResult
->elements
[5] = (struct Object
*)aResultCanonName
;
480 heap_store_into(oh
, (struct Object
*)aResult
, aResult
->elements
[5]);
481 copy_bytes_into((byte_t
*)current
->ai_canonname
, canonNameLen
, aResultCanonName
->elements
);
484 current
= current
->ai_next
;
487 heap_fixed_remove(oh
, (struct Object
*)retval
);
493 void prim_freeAddrInfoResult(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
494 word_t ticket
= object_to_smallint(args
[0]);
495 if (ticket
>= oh
->socketTicketCount
|| ticket
< 0
496 || oh
->socketTickets
[ticket
].inUse
== 0 || oh
->socketTickets
[ticket
].finished
== 0) {
497 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
500 free(oh
->socketTickets
[ticket
].hostname
);
501 oh
->socketTickets
[ticket
].hostname
= 0;
502 free(oh
->socketTickets
[ticket
].service
);
503 oh
->socketTickets
[ticket
].service
= 0;
504 freeaddrinfo(oh
->socketTickets
[ticket
].addrResult
);
505 oh
->socketTickets
[ticket
].addrResult
= 0;
507 oh
->socketTickets
[ticket
].inUse
= 0;
508 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
512 void prim_socketCreateIP(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
513 word_t domain
= object_to_smallint(args
[0]);
514 struct Object
* address
= args
[1];
515 word_t port
= object_to_smallint(args
[2]);
516 /* struct OopArray* options = (struct OopArray*) args[3];*/
517 struct sockaddr_in
* sin
;
518 struct sockaddr_in6
* sin6
;
519 struct sockaddr_un
* sun
;
520 GC_VOLATILE
struct ByteArray
* ret
;
522 ASSURE_SMALLINT_ARG(0);
526 case SLATE_DOMAIN_LOCAL
:
529 if (byte_array_size((struct ByteArray
*)address
) > 100) {
530 ret
= (struct ByteArray
*)oh
->cached
.nil
;
533 ret
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_un
));
534 sun
= (struct sockaddr_un
*)byte_array_elements(ret
);
535 sun
->sun_family
= socket_lookup_domain(domain
);
536 ASSURE_TYPE_ARG(1, TYPE_BYTE_ARRAY
);
537 strncpy(sun
->sun_path
, (char*)byte_array_elements((struct ByteArray
*)address
), 100);
538 sun
->sun_path
[byte_array_size((struct ByteArray
*)address
)] = '\0';
542 case SLATE_DOMAIN_IPV4
:
543 ASSURE_SMALLINT_ARG(2);
544 if (object_array_size(address
) < 4) {
545 ret
= (struct ByteArray
*)oh
->cached
.nil
;
548 ret
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_in
));
549 sin
= (struct sockaddr_in
*)byte_array_elements(ret
);
550 sin
->sin_family
= socket_lookup_domain(domain
);
551 sin
->sin_port
= htons((uint16_t)port
);
552 ASSURE_TYPE_ARG(1, TYPE_OOP_ARRAY
);
553 sin
->sin_addr
.s_addr
= htonl(((object_to_smallint(object_array_get_element(address
, 0)) & 0xFF) << 24)
554 | ((object_to_smallint(object_array_get_element(address
, 1)) & 0xFF) << 16)
555 | ((object_to_smallint(object_array_get_element(address
, 2)) & 0xFF) << 8)
556 | (object_to_smallint(object_array_get_element(address
, 3)) & 0xFF));
560 case SLATE_DOMAIN_IPV6
:
561 ASSURE_SMALLINT_ARG(2);
562 if (object_array_size(address
) < 16) {
563 ret
= (struct ByteArray
*)oh
->cached
.nil
;
566 ret
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), sizeof(struct sockaddr_in6
));
567 sin6
= (struct sockaddr_in6
*)byte_array_elements(ret
);
568 sin6
->sin6_family
= socket_lookup_domain(domain
);
569 sin6
->sin6_port
= htons((uint16_t)port
);
570 ASSURE_TYPE_ARG(1, TYPE_OOP_ARRAY
);
573 for (i
= 0; i
< 16; i
++)
574 sin6
->sin6_addr
.s6_addr
[i
] = object_to_smallint(object_array_get_element(address
, i
)) & 0xFF;
579 ret
= (struct ByteArray
*)oh
->cached
.nil
;
583 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)ret
;
587 void prim_write_to_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
588 struct Object
*console
=args
[0], *n
=args
[1], *handle
=args
[2], *seq
=args
[3], *start
=args
[4];
589 byte_t
* bytes
= &((struct ByteArray
*)seq
)->elements
[0] + object_to_smallint(start
);
590 word_t size
= object_to_smallint(n
);
593 ASSURE_SMALLINT_ARG(2);
594 ASSURE_SMALLINT_ARG(4);
596 assert(arity
== 5 && console
!= NULL
);
598 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
599 smallint_to_object(fwrite(bytes
, 1, size
, (object_to_smallint(handle
) == 0)? stdout
: stderr
));
603 void prim_close(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
604 word_t handle
= object_to_smallint(args
[1]);
605 ASSURE_SMALLINT_ARG(1);
607 closeFile(oh
, handle
);
608 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
612 void prim_readConsole_from_into_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
613 word_t
/*handle = object_to_smallint(args[2]),*/ n
= object_to_smallint(args
[1]), start
= object_to_smallint(args
[4]);
614 struct ByteArray
* bytes
= (struct ByteArray
*)args
[3];
617 ASSURE_SMALLINT_ARG(1);
618 ASSURE_SMALLINT_ARG(4);
620 retval
= fread((char*)(byte_array_elements(bytes
) + start
), 1, n
, stdin
);
621 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
625 void prim_read_from_into_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
626 word_t handle
= object_to_smallint(args
[2]), n
= object_to_smallint(args
[1]), start
= object_to_smallint(args
[4]);
627 struct ByteArray
* bytes
= (struct ByteArray
*)args
[3];
629 ASSURE_SMALLINT_ARG(1);
630 ASSURE_SMALLINT_ARG(4);
631 retval
= readFile(oh
, handle
, n
, (char*)(byte_array_elements(bytes
) + start
));
632 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
635 void prim_write_to_from_starting_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
636 word_t handle
= object_to_smallint(args
[2]), n
= object_to_smallint(args
[1]), start
= object_to_smallint(args
[4]);
637 struct ByteArray
* bytes
= (struct ByteArray
*)args
[3];
639 ASSURE_SMALLINT_ARG(1);
640 ASSURE_SMALLINT_ARG(4);
641 retval
= writeFile(oh
, handle
, n
, (char*)(byte_array_elements(bytes
) + start
));
642 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
646 void prim_reposition_to(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
647 word_t handle
= object_to_smallint(args
[1]), n
= object_to_smallint(args
[2]);
648 word_t retval
= seekFile(oh
, handle
, n
);
649 ASSURE_SMALLINT_ARG(1);
650 ASSURE_SMALLINT_ARG(2);
651 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
654 void prim_positionOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
655 word_t handle
= object_to_smallint(args
[1]);
656 word_t retval
= tellFile(oh
, handle
);
657 ASSURE_SMALLINT_ARG(1);
658 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
661 void prim_bytesPerWord(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
662 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(sizeof(word_t
));
665 void prim_timeSinceEpoch(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
669 #pragma message("TODO WIN32 time-since-epoch")
672 gettimeofday(&tv
, NULL
);
673 time
= (word_t
)tv
.tv_sec
* 1000000 + (word_t
)tv
.tv_usec
;
675 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(time
);
678 void prim_atEndOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
679 word_t handle
= object_to_smallint(args
[1]);
680 ASSURE_SMALLINT_ARG(1);
681 if (endOfFile(oh
, handle
)) {
682 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
684 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
688 void prim_sizeOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
689 word_t handle
= object_to_smallint(args
[1]);
690 word_t retval
= sizeOfFile(oh
, handle
);
691 ASSURE_SMALLINT_ARG(1);
692 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(retval
);
697 void prim_flush_output(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
698 /*struct Object *console=args[0];*/
701 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
704 void prim_handle_for(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
706 struct Object
/**file=args[0],*/ *fname
=args
[1];
708 handle
= openFile(oh
, (struct ByteArray
*)fname
, SF_READ
|SF_WRITE
);
710 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
712 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
717 void prim_handleForNew(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
719 struct Object
/**file=args[0],*/ *fname
=args
[1];
721 handle
= openFile(oh
, (struct ByteArray
*)fname
, SF_READ
|SF_WRITE
|SF_CLEAR
|SF_CREATE
);
723 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
725 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
731 void prim_handle_for_input(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
733 struct Object
/**file=args[0],*/ *fname
=args
[1];
735 handle
= openFile(oh
, (struct ByteArray
*)fname
, SF_READ
);
737 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
739 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
745 void prim_addressOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
746 struct Object
*handle
=args
[1], *offset
=args
[2];
747 struct ByteArray
* addressBuffer
=(struct ByteArray
*) args
[3];
748 ASSURE_SMALLINT_ARG(1);
749 ASSURE_SMALLINT_ARG(2);
750 if (object_is_smallint(handle
) && object_is_smallint(offset
) && byte_array_size(addressBuffer
) >= sizeof(word_t
)) {
751 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
752 smallint_to_object(addressOfMemory(oh
,
753 (int)object_to_smallint(handle
),
754 (int)object_to_smallint(offset
),
755 byte_array_elements(addressBuffer
)));
757 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
762 void prim_loadLibrary(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
763 struct Object
*libname
=args
[1], *handle
= args
[2];
765 if (openExternalLibrary(oh
, (struct ByteArray
*)libname
, (struct ByteArray
*)handle
)) {
766 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
768 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
773 void prim_closeLibrary(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
774 struct Object
*handle
=args
[1];
776 if (closeExternalLibrary(oh
, (struct ByteArray
*) handle
)) {
777 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
779 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
785 void prim_procAddressOf(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
786 struct Object
*handle
=args
[2], *symname
=args
[1];
787 struct ByteArray
* addressBuffer
=(struct ByteArray
*) args
[3];
789 if (lookupExternalLibraryPrimitive(oh
, (struct ByteArray
*) handle
, (struct ByteArray
*) symname
, addressBuffer
)) {
790 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
792 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
797 void prim_extlibError(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
798 struct ByteArray
* messageBuffer
=(struct ByteArray
*) args
[1];
800 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(readExternalLibraryError(messageBuffer
));
804 void prim_applyExternal(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
806 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
807 applyExternalLibraryPrimitive(oh
, (struct ByteArray
*)args
[1],
808 (struct OopArray
*)args
[2],
811 (struct OopArray
*)args
[5]);
815 void prim_newFixedArea(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
816 struct Object
*size
=args
[1];
819 if (!object_is_smallint(size
)) {
820 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
824 handle
= (word_t
)openMemory(oh
, object_to_smallint(size
));
826 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(handle
);
828 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
833 void prim_closeFixedArea(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
835 struct Object
* handle
= args
[1];
836 if (object_is_smallint(handle
)) {
837 closeMemory(oh
, object_to_smallint(handle
));
839 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
843 void prim_fixedAreaSize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
845 struct Object
* handle
= args
[1];
846 if (object_is_smallint(handle
)) {
847 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(sizeOfMemory(oh
, object_to_smallint(handle
)));
849 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
854 void prim_fixedAreaAddRef(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
856 struct Object
* handle
= args
[1];
857 if (object_is_smallint(handle
)) {
858 addRefMemory(oh
, object_to_smallint(handle
));
861 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
865 void prim_fixedReadFromStarting(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
867 struct ByteArray
* buf
= (struct ByteArray
*)args
[0];
868 word_t amount
= object_to_smallint(args
[1]), startingAt
= object_to_smallint(args
[3]),
869 handle
= object_to_smallint(args
[2]);
871 ASSURE_SMALLINT_ARG(1);
872 ASSURE_SMALLINT_ARG(2);
873 ASSURE_SMALLINT_ARG(3);
875 if (!validMemoryHandle(oh
, handle
)
876 || byte_array_size(buf
) < amount
877 || startingAt
+ amount
>= oh
->memory_sizes
[handle
]) {
878 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(-1);
882 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
883 smallint_to_object(writeMemory(oh
, handle
, startingAt
, amount
, byte_array_elements(buf
)));
887 void prim_fixedWriteFromStarting(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
889 struct ByteArray
* buf
= (struct ByteArray
*)args
[0];
890 word_t amount
= object_to_smallint(args
[1]), startingAt
= object_to_smallint(args
[3]),
891 handle
= object_to_smallint(args
[2]);
893 ASSURE_SMALLINT_ARG(1);
894 ASSURE_SMALLINT_ARG(2);
895 ASSURE_SMALLINT_ARG(3);
897 if (!validMemoryHandle(oh
, handle
)
898 || byte_array_size(buf
) < amount
899 || startingAt
+ amount
>= oh
->memory_sizes
[handle
]) {
900 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(-1);
904 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
905 smallint_to_object(readMemory(oh
, handle
, startingAt
, amount
, byte_array_elements(buf
)));
910 void prim_fixedAreaResize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
912 struct Object
* handle
= args
[1], *size
= args
[2];
913 if (object_is_smallint(handle
) && object_is_smallint(size
)) {
914 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
915 smallint_to_object(resizeMemory(oh
, object_to_smallint(handle
), object_to_smallint(size
)));
918 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
923 void prim_smallint_at_slot_named(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
926 struct SlotEntry
* se
;
927 struct Object
* proto
;
931 proto
= get_special(oh
, SPECIAL_OOP_SMALL_INT_PROTO
);
932 se
= slot_table_entry_for_name(oh
, proto
->map
->slotTable
, (struct Symbol
*)name
);
934 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
936 word_t offset
= object_to_smallint(se
->offset
);
937 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_slot_value_at_offset(proto
, offset
);
945 void prim_bytesize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
946 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(payload_size(args
[0]));
949 void prim_findon(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
950 struct MethodDefinition
* def
;
951 struct Symbol
* selector
= (struct Symbol
*) args
[0];
952 struct OopArray
* arguments
= (struct OopArray
*) args
[1];
955 def
= method_dispatch_on(oh
, selector
, arguments
->elements
, array_size(arguments
), NULL
);
957 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (def
== NULL
? oh
->cached
.nil
: (struct Object
*) def
->method
);
962 void prim_ensure(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
964 struct Closure
* body
= (struct Closure
*) args
[0];
965 struct Object
* ensureHandler
= args
[1];
966 interpreter_apply_to_arity_with_optionals(oh
, oh
->cached
.interpreter
, body
, NULL
, 0, NULL
, resultStackPointer
);
967 /*the registers are already allocated on the stack so we don't worry about overwriting them*/
968 interpreter_stack_push(oh
, oh
->cached
.interpreter
, oh
->cached
.interpreter
->ensureHandlers
);
969 interpreter_stack_push(oh
, oh
->cached
.interpreter
, ensureHandler
);
970 oh
->cached
.interpreter
->ensureHandlers
= smallint_to_object(oh
->cached
.interpreter
->stackPointer
- 2);
971 #ifdef PRINT_DEBUG_ENSURE
972 printf("ensure handlers at %" PRIdPTR
"\n", oh
->cached
.interpreter
->stackPointer
- 2);
978 void prim_frame_pointer_of(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
980 struct Interpreter
* i
= (struct Interpreter
*)args
[0];
981 struct Symbol
* selector
= (struct Symbol
*) args
[1];
982 struct CompiledMethod
* method
;
983 word_t frame
= i
->framePointer
;
987 while (frame
> FUNCTION_FRAME_SIZE
) {
988 method
= (struct CompiledMethod
*) i
->stack
->elements
[frame
-3];
989 method
= method
->method
; /*incase it's a closure and not a compiledmethod*/
990 if (method
->selector
== selector
) {
991 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(frame
);
994 frame
= object_to_smallint(i
->stack
->elements
[frame
-1]);
997 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1002 void prim_bytearray_newsize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1003 struct Object
* obj
, *i
;
1007 if (!object_is_smallint(i
)) {
1008 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1012 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1013 (struct Object
*)heap_clone_byte_array_sized(oh
, obj
, (object_to_smallint(i
) < 0) ? 0 : object_to_smallint(i
));
1017 void prim_byteat_put(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1018 struct Object
* obj
= args
[0], *i
=args
[1], *val
= args
[2];
1021 index
= object_to_smallint(i
);
1023 ASSURE_SMALLINT_ARG(1);
1024 ASSURE_SMALLINT_ARG(2);
1026 if (object_is_immutable(obj
)) {
1027 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_IMMUTABLE
), obj
, NULL
, resultStackPointer
);
1031 if (index
< byte_array_size((struct ByteArray
*)obj
)) {
1032 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(byte_array_set_element((struct ByteArray
*)obj
, index
, object_to_smallint(val
)));
1034 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), i
, obj
, NULL
, resultStackPointer
);
1040 void prim_byteat(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1041 struct Object
* obj
, *i
;
1046 index
= object_to_smallint(i
);
1048 ASSURE_SMALLINT_ARG(1);
1050 if (index
< byte_array_size((struct ByteArray
*)obj
)) {
1051 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(byte_array_get_element(obj
, index
));
1053 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), i
, obj
, NULL
, resultStackPointer
);
1059 void prim_map(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1063 if (object_is_smallint(obj
)) {
1064 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1066 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)obj
->map
;
1072 void prim_set_map(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1073 GC_VOLATILE
struct Object
* obj
;
1074 GC_VOLATILE
struct Map
* map
;
1076 map
= (struct Map
*)args
[1];
1078 if (object_is_smallint(obj
) || object_is_immutable(obj
)) {
1079 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1081 object_change_map(oh
, obj
, map
);
1082 heap_store_into(oh
, args
[0], args
[1]);
1083 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)map
;
1089 void prim_run_args_into(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1090 struct ByteArray
* arguments
= (struct ByteArray
*)args
[1];
1091 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1092 smallint_to_object(write_args_into(oh
, (char*)byte_array_elements(arguments
), byte_array_size(arguments
)));
1097 void prim_vmArgCount(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1098 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(oh
->argcSaved
);
1101 void prim_vmArg(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1104 GC_VOLATILE
struct ByteArray
* array
;
1105 ASSURE_SMALLINT_ARG(1);
1106 i
= object_to_smallint(args
[1]);
1107 len
= strlen(oh
->argvSaved
[i
]);
1109 array
= heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), len
);
1110 copy_bytes_into((byte_t
*)oh
->argvSaved
[i
], len
, array
->elements
);
1111 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)array
;
1112 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)array
);
1116 void prim_environmentVariables(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1119 GC_VOLATILE
struct OopArray
* array
;
1122 while (oh
->envp
[len
]) len
++;
1124 array
= heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
), len
);
1125 heap_fixed_add(oh
, (struct Object
*)array
);
1127 for (i
= 0; i
< len
; i
++) {
1128 lenstr
= strlen(oh
->envp
[i
]);
1129 array
->elements
[i
] = (struct Object
*) heap_clone_byte_array_sized(oh
, get_special(oh
, SPECIAL_OOP_BYTE_ARRAY_PROTO
), lenstr
);
1130 copy_bytes_into((byte_t
*)oh
->envp
[i
], lenstr
, ((struct ByteArray
*)array
->elements
[i
])->elements
);
1134 heap_fixed_remove(oh
, (struct Object
*)array
);
1136 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)array
;
1137 heap_store_into(oh
, (struct Object
*)oh
->cached
.interpreter
->stack
, (struct Object
*)array
);
1141 void prim_exit(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1142 /* print_stack_types(oh, 128);*/
1143 /* print_backtrace(oh);*/
1145 printf("Slate process %d exiting...\n", getpid());
1150 void prim_isIdenticalTo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1151 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (args
[0]==args
[1])? oh
->cached
.true_object
: oh
->cached
.false_object
;
1154 void prim_identity_hash(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1156 /* print_detail(oh, args[0]);
1157 print_backtrace(oh);*/
1158 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_hash(args
[0]));
1161 void prim_identity_hash_univ(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1163 /* print_detail(oh, args[0]);
1164 print_backtrace(oh);*/
1165 if (object_is_smallint(args
[0])) {
1166 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = args
[0];
1168 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_hash(args
[0]));
1173 void prim_clone(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1174 if (object_is_smallint(args
[0])) {
1175 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = args
[0];
1177 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = heap_clone(oh
, args
[0]);
1181 void prim_applyto(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1182 struct Closure
*method
= (struct Closure
*)args
[0];
1183 struct OopArray
* argArray
= (struct OopArray
*) args
[1];
1184 struct OopArray
* real_opts
= NULL
;
1186 if (opts
!= NULL
&& opts
->elements
[1] != oh
->cached
.nil
) {
1187 real_opts
= (struct OopArray
*) opts
->elements
[1];
1189 interpreter_apply_to_arity_with_optionals(oh
, oh
->cached
.interpreter
, method
,
1190 argArray
->elements
, array_size(argArray
), real_opts
, resultStackPointer
);
1196 void prim_at(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1197 struct Object
* array
;
1201 i
= object_to_smallint(args
[1]);
1202 ASSURE_SMALLINT_ARG(1);
1203 if (i
< object_array_size(array
) && i
>= 0) {
1204 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = ((struct OopArray
*)array
)->elements
[i
];
1206 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), args
[1], args
[0], NULL
, resultStackPointer
);
1214 void prim_at_put(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1215 struct Object
*array
= args
[0], *i
= args
[1], *val
= args
[2];
1216 word_t index
= object_to_smallint(i
);
1218 ASSURE_SMALLINT_ARG(1);
1219 if (object_is_immutable(array
)) {
1220 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_IMMUTABLE
), array
, NULL
, resultStackPointer
);
1224 if (index
< object_array_size(array
)) {
1225 heap_store_into(oh
, array
, val
);
1226 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = ((struct OopArray
*)array
)->elements
[index
] = val
;
1228 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_KEY_NOT_FOUND_ON
), i
, array
, NULL
, resultStackPointer
);
1233 void prim_ooparray_newsize(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1234 /*struct Object* array = args[0];*/
1235 struct Object
* i
= args
[1];
1236 if (object_is_smallint(i
)) {
1237 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)
1238 heap_clone_oop_array_sized(oh
, get_special(oh
, SPECIAL_OOP_ARRAY_PROTO
),
1239 object_to_smallint(i
));
1241 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1246 void prim_equals(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1247 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (args
[0] == args
[1])?oh
->cached
.true_object
:oh
->cached
.false_object
;
1250 void prim_less_than(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1252 ASSURE_SMALLINT_ARG(0);
1253 ASSURE_SMALLINT_ARG(1);
1254 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] =
1255 (object_to_smallint(args
[0])<object_to_smallint(args
[1]))?oh
->cached
.true_object
:oh
->cached
.false_object
;
1259 void prim_size(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1260 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_array_size(args
[0]));
1263 void prim_bitand(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1264 ASSURE_SMALLINT_ARG(0);
1265 ASSURE_SMALLINT_ARG(1);
1266 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)((word_t
)args
[0] & (word_t
)args
[1]);
1268 void prim_bitor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1269 ASSURE_SMALLINT_ARG(0);
1270 ASSURE_SMALLINT_ARG(1);
1271 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)((word_t
)args
[0] | (word_t
)args
[1]);
1273 void prim_bitxor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1274 ASSURE_SMALLINT_ARG(0);
1275 ASSURE_SMALLINT_ARG(1);
1276 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)(((word_t
)args
[0] ^ (word_t
)args
[1])|SMALLINT_MASK
);
1278 void prim_bitnot(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1279 ASSURE_SMALLINT_ARG(0);
1280 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)(~((word_t
)args
[0]) | SMALLINT_MASK
);
1283 void prim_smallIntegerMinimum(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1284 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)(((word_t
)1<< (sizeof(word_t
)*8-1))|1); /*top and smallint bit set*/
1287 void prim_smallIntegerMaximum(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1288 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)LONG_MAX
; /*has all bits except the top set*/
1291 void prim_plus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1292 struct Object
* x
= args
[0];
1293 struct Object
* y
= args
[1];
1294 word_t z
= object_to_smallint(x
) + object_to_smallint(y
);
1297 ASSURE_SMALLINT_ARG(0);
1298 ASSURE_SMALLINT_ARG(1);
1301 if (smallint_fits_object(z
)) {
1302 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1304 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_ADD_OVERFLOW
), x
, y
, NULL
, resultStackPointer
);
1308 void prim_removefrom(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1310 struct Object
*method
= args
[0], *traitsWindow
;
1311 struct OopArray
* roles
= (struct OopArray
*)args
[1];
1312 struct Symbol
* selector
= (struct Symbol
*)oh
->cached
.nil
;
1313 struct MethodDefinition
* def
;
1316 traitsWindow
= method
->map
->delegates
->elements
[0];
1318 if (traitsWindow
== oh
->cached
.closure_method_window
|| traitsWindow
== oh
->cached
.compiled_method_window
) {
1319 selector
= ((struct Closure
*)method
)->method
->selector
;
1321 /*May only remove a CompiledMethod or Closure.*/
1325 def
= method_is_on_arity(oh
, method
, selector
, array_elements(roles
), array_size(roles
));
1327 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
1331 for (i
= 0; i
< array_size(roles
); i
++) {
1332 struct Object
* role
= array_elements(roles
)[i
];
1333 if (!object_is_smallint(role
)) {
1334 object_remove_role(oh
, role
, selector
, def
);
1338 method_flush_cache(oh
, selector
);
1339 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
1344 void prim_exponent(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1345 struct ByteArray
* x
= (struct ByteArray
*)args
[0];
1346 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object((*(word_t
*)float_part(x
) >> FLOAT_EXPONENT_OFFSET
) & 0xFF);
1350 void prim_significand(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1351 struct ByteArray
* x
= (struct ByteArray
*)args
[0];
1352 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(*(word_t
*)float_part(x
) & FLOAT_SIGNIFICAND
);
1356 void prim_getcwd(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1357 struct ByteArray
* buf
= (struct ByteArray
*)args
[1];
1358 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(getCurrentDirectory(buf
));
1360 void prim_setcwd(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1361 struct ByteArray
* buf
= (struct ByteArray
*)args
[1];
1362 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(setCurrentDirectory(buf
));
1366 void prim_float_equals(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1367 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1368 if (*float_part(x
) == *float_part(y
)) {
1369 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1371 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1375 void prim_float_less_than(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1376 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1377 if (*float_part(x
) < *float_part(y
)) {
1378 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1380 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1384 void prim_float_plus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1385 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1386 struct ByteArray
* z
= heap_new_float(oh
);
1387 *float_part(z
) = *float_part(x
) + *float_part(y
);
1388 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1391 void prim_float_minus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1392 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1393 struct ByteArray
* z
= heap_new_float(oh
);
1394 *float_part(z
) = *float_part(x
) - *float_part(y
);
1395 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1399 void prim_float_times(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1400 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1401 struct ByteArray
* z
= heap_new_float(oh
);
1402 *float_part(z
) = *float_part(x
) * *float_part(y
);
1403 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1406 void prim_float_divide(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1407 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1408 struct ByteArray
* z
= heap_new_float(oh
);
1409 *float_part(z
) = *float_part(x
) / *float_part(y
);
1410 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1413 void prim_float_raisedTo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1414 struct ByteArray
*x
= (struct ByteArray
*)args
[0], *y
= (struct ByteArray
*)args
[1];
1415 struct ByteArray
* z
= heap_new_float(oh
);
1416 *float_part(z
) = pow(*float_part(x
), *float_part(y
));
1417 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1420 void prim_float_ln(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1421 struct ByteArray
*x
= (struct ByteArray
*)args
[0];
1422 struct ByteArray
* z
= heap_new_float(oh
);
1423 *float_part(z
) = log(*float_part(x
));
1424 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1427 void prim_float_exp(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1428 struct ByteArray
*x
= (struct ByteArray
*)args
[0];
1429 struct ByteArray
* z
= heap_new_float(oh
);
1430 *float_part(z
) = exp(*float_part(x
));
1431 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1434 void prim_float_sin(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1435 struct ByteArray
*x
= (struct ByteArray
*)args
[0];
1436 struct ByteArray
* z
= heap_new_float(oh
);
1437 *float_part(z
) = sin(*float_part(x
));
1438 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)z
;
1441 void prim_withSignificand_exponent(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1442 /*this is really a bytearray*/
1443 word_t significand
= object_to_smallint(args
[1]), exponent
= object_to_smallint(args
[2]);
1444 struct ByteArray
* f
= heap_new_float(oh
);
1445 *((word_t
*)float_part(f
)) = significand
| exponent
<< FLOAT_EXPONENT_OFFSET
;
1447 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = (struct Object
*)f
;
1451 void prim_bitshift(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1452 word_t bits
= object_to_smallint(args
[0]);
1453 word_t shift
= object_to_smallint(args
[1]);
1456 ASSURE_SMALLINT_ARG(0);
1457 ASSURE_SMALLINT_ARG(1);
1460 if (shift
>= __WORDSIZE
&& bits
!= 0) {
1461 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_BIT_SHIFT_OVERFLOW
), args
[0], args
[1], NULL
, resultStackPointer
);
1467 if (!smallint_fits_object(z
) || z
>> shift
!= bits
) {
1468 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_BIT_SHIFT_OVERFLOW
), args
[0], args
[1], NULL
, resultStackPointer
);
1472 } else if (shift
<= -__WORDSIZE
) {
1473 z
= bits
>> (__WORDSIZE
-1);
1478 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1483 void prim_minus(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1484 struct Object
* x
= args
[0];
1485 struct Object
* y
= args
[1];
1486 word_t z
= object_to_smallint(x
) - object_to_smallint(y
);
1488 ASSURE_SMALLINT_ARG(0);
1489 ASSURE_SMALLINT_ARG(1);
1491 if (smallint_fits_object(z
)) {
1492 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1494 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SUBTRACT_OVERFLOW
), x
, y
, NULL
, resultStackPointer
);
1499 void prim_times(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1500 word_t x
= object_to_smallint(args
[0]);
1501 word_t y
= object_to_smallint(args
[1]);
1505 ASSURE_SMALLINT_ARG(0);
1506 ASSURE_SMALLINT_ARG(1);
1509 if (y
!= 0 && (z
/ y
!= x
|| !smallint_fits_object(z
))) { /*thanks slava*/
1510 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_MULTIPLY_OVERFLOW
), args
[0], args
[1], NULL
, resultStackPointer
);
1512 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(z
);
1516 void prim_quo(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1517 struct Object
* x
= args
[0];
1518 struct Object
* y
= args
[1];
1520 ASSURE_SMALLINT_ARG(0);
1521 ASSURE_SMALLINT_ARG(1);
1523 if (object_to_smallint(y
) == 0) {
1524 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_DIVIDE_BY_ZERO
), x
, y
, NULL
, resultStackPointer
);
1526 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = smallint_to_object(object_to_smallint(x
) / object_to_smallint(y
));
1531 void prim_forward_to(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1532 struct Object
* x
= args
[0];
1533 struct Object
* y
= args
[1];
1534 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = y
;
1535 /* since some objects like roleTables store pointers to things like Nil in byte arrays rather than oop arrays,
1536 * we must make sure that these special objects do not move.
1538 if (x
== get_special(oh
, SPECIAL_OOP_NIL
)
1539 || x
== get_special(oh
, SPECIAL_OOP_TRUE
)
1540 || x
== get_special(oh
, SPECIAL_OOP_FALSE
)) {
1541 printf("Error... you cannot call forwardTo on this special object (did you add a slot to Nil/True/False?)\n");
1542 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_TYPE_ERROR_ON
), x
, NULL
, resultStackPointer
); \
1546 if (!object_is_smallint(x
) && !object_is_smallint(y
) && x
!= y
) {
1547 heap_forward(oh
, x
, y
);
1555 void prim_clone_setting_slots(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1556 struct Object
*obj
= args
[0], *slotArray
= args
[1], *valueArray
= args
[2], *newObj
;
1559 if (object_is_smallint(obj
)) {
1560 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = obj
;
1563 newObj
= heap_clone(oh
, obj
);
1565 /*fix, check that arrays are same size, and signal errors*/
1567 for (i
= 0; i
< object_array_size(slotArray
); i
++) {
1568 struct Symbol
* name
= (struct Symbol
*)object_array_get_element(slotArray
, i
);
1569 struct SlotEntry
* se
= slot_table_entry_for_name(oh
, obj
->map
->slotTable
, name
);
1571 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, (struct Object
*)name
, NULL
, resultStackPointer
);
1573 /*since the object was just cloned, we aren't expecting a tenured obj to point to a new one*/
1574 object_slot_value_at_offset_put(oh
, newObj
, object_to_smallint(se
->offset
), object_array_get_element(valueArray
, i
));
1578 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = newObj
;
1583 void prim_as_method_on(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1584 struct MethodDefinition
* def
;
1585 GC_VOLATILE
struct Object
*method
= args
[0], *roles
=args
[2];
1586 struct Symbol
*selector
= (struct Symbol
*)args
[1];
1587 struct Object
* traitsWindow
= method
->map
->delegates
->elements
[0];
1590 if (traitsWindow
== get_special(oh
, SPECIAL_OOP_CLOSURE_WINDOW
)) {
1591 GC_VOLATILE
struct Closure
* closure
= (struct Closure
*)heap_clone(oh
, method
);
1592 heap_fixed_add(oh
, (struct Object
*)closure
);
1593 closure
->method
= (struct CompiledMethod
*)heap_clone(oh
, (struct Object
*)closure
->method
);
1594 heap_fixed_remove(oh
, (struct Object
*)closure
);
1595 heap_store_into(oh
, (struct Object
*)closure
, (struct Object
*)closure
->method
);
1596 closure
->method
->method
= closure
->method
;
1597 closure
->method
->selector
= selector
;
1598 method
= (struct Object
*)closure
;
1600 GC_VOLATILE
struct CompiledMethod
* closure
= (struct CompiledMethod
*)heap_clone(oh
, method
);
1601 closure
->method
= closure
;
1602 closure
->selector
= selector
;
1603 method
= (struct Object
*) closure
;
1605 def
= method_define(oh
, method
, (struct Symbol
*)selector
, ((struct OopArray
*)roles
)->elements
, object_array_size(roles
));
1606 def
->slotAccessor
= oh
->cached
.nil
;
1607 method_flush_cache(oh
, selector
);
1608 #ifdef PRINT_DEBUG_DEFUN
1610 printf("Defining function '"); print_symbol(selector
);
1612 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[0])) printf("NoRole");
1615 for (i
= 1; i
< object_array_size(roles
); i
++) {
1617 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[i
])) printf("NoRole");
1624 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
1628 void prim_at_slot_named(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1630 struct Object
* name
;
1631 struct SlotEntry
* se
;
1636 if (object_is_smallint(obj
)) {
1637 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
1639 se
= slot_table_entry_for_name(oh
, obj
->map
->slotTable
, (struct Symbol
*)name
);
1641 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
1643 word_t offset
= object_to_smallint(se
->offset
);
1644 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_slot_value_at_offset(obj
, offset
);
1652 void prim_at_slot_named_put(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1653 struct Object
* obj
=args
[0], *val
=args
[2];
1654 struct Object
* name
= args
[1];
1655 struct SlotEntry
* se
;
1658 if (object_is_smallint(obj
)) {
1659 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
1663 if (object_is_immutable(obj
)) {
1664 interpreter_signal_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_IMMUTABLE
), obj
, NULL
, resultStackPointer
);
1669 se
= slot_table_entry_for_name(oh
, map
->slotTable
, (struct Symbol
*)name
);
1672 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, name
, NULL
, resultStackPointer
);
1674 word_t offset
= object_to_smallint(se
->offset
);
1675 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_slot_value_at_offset_put(oh
, obj
, offset
, val
);
1678 /*note: not supporting delegate slots*/
1685 void prim_clone_with_slot_valued(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1686 struct Object
* obj
= args
[0], *value
= args
[2];
1687 struct Symbol
* name
= (struct Symbol
*)args
[1];
1689 if (object_is_smallint(obj
)) {
1690 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, (struct Object
*)name
, NULL
, resultStackPointer
);
1692 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_add_slot_named(oh
, obj
, name
, value
);
1696 void prim_clone_without_slot(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1697 struct Object
* obj
= args
[0];
1698 struct Symbol
* name
= (struct Symbol
*)args
[1];
1700 if (object_is_smallint(obj
)) {
1701 interpreter_signal_with_with(oh
, oh
->cached
.interpreter
, get_special(oh
, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED
), obj
, (struct Object
*)name
, NULL
, resultStackPointer
);
1703 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = object_remove_slot(oh
, obj
, name
);
1709 void prim_send_to(struct object_heap
* oh
, struct Object
* args
[], word_t n
, struct OopArray
* optionals
, word_t resultStackPointer
) {
1710 struct Symbol
* selector
= (struct Symbol
*)args
[0];
1711 struct OopArray
* opts
, *arguments
= (struct OopArray
*)args
[1];
1713 if (optionals
== NULL
) {
1716 opts
= (struct OopArray
*)optionals
->elements
[1];
1717 if (opts
== (struct OopArray
*)oh
->cached
.nil
) opts
= NULL
;
1719 send_to_through_arity_with_optionals(oh
, selector
, array_elements(arguments
), array_elements(arguments
), array_size(arguments
), opts
, resultStackPointer
);
1722 void prim_send_to_through(struct object_heap
* oh
, struct Object
* args
[], word_t n
, struct OopArray
* optionals
, word_t resultStackPointer
) {
1723 struct Symbol
* selector
= (struct Symbol
*)args
[0];
1724 struct OopArray
* opts
, * arguments
= (struct OopArray
*)args
[1], *dispatchers
= (struct OopArray
*)args
[2];
1726 if (optionals
== NULL
) {
1729 opts
= (struct OopArray
*)optionals
->elements
[1];
1730 if (opts
== (struct OopArray
*)oh
->cached
.nil
) opts
= NULL
;
1732 /*fix check array sizes are the same*/
1733 send_to_through_arity_with_optionals(oh
, selector
, array_elements(arguments
), array_elements(dispatchers
), array_size(arguments
), opts
, resultStackPointer
);
1739 void prim_as_accessor(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1740 GC_VOLATILE
struct Object
*method
= args
[0], *slot
= args
[2];
1741 struct OopArray
*roles
= (struct OopArray
*)args
[3];
1742 struct Symbol
* selector
= (struct Symbol
*)args
[1];
1743 struct Object
* traitsWindow
= method
->map
->delegates
->elements
[0];
1744 struct MethodDefinition
* def
;
1746 if (traitsWindow
== oh
->cached
.closure_method_window
) {
1747 GC_VOLATILE
struct Closure
* closure
= (struct Closure
*)heap_clone(oh
, method
);
1748 heap_fixed_add(oh
, (struct Object
*)closure
);
1749 closure
->method
= (struct CompiledMethod
*)heap_clone(oh
, (struct Object
*)closure
->method
);
1750 heap_fixed_remove(oh
, (struct Object
*)closure
);
1751 heap_store_into(oh
, (struct Object
*)closure
, (struct Object
*)closure
->method
);
1752 closure
->method
->method
= closure
->method
;
1753 closure
->method
->selector
= selector
;
1754 method
= (struct Object
*)closure
;
1755 } else if (traitsWindow
== oh
->cached
.compiled_method_window
){
1756 GC_VOLATILE
struct CompiledMethod
* closure
= (struct CompiledMethod
*)heap_clone(oh
, method
);
1757 closure
->method
= closure
;
1758 closure
->selector
= selector
;
1759 method
= (struct Object
*) closure
;
1762 def
= method_define(oh
, method
, selector
, roles
->elements
, array_size(roles
));
1763 def
->slotAccessor
= slot
;
1764 method_flush_cache(oh
, selector
);
1765 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = method
;
1767 #ifdef PRINT_DEBUG_DEFUN
1769 printf("Defining accessor '"); print_symbol(selector
);
1771 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[0])) printf("NoRole");
1774 for (i
= 1; i
< array_size(roles
); i
++) {
1776 if (!print_printname(oh
, ((struct OopArray
*)roles
)->elements
[i
])) printf("NoRole");
1787 void prim_save_image(struct object_heap
* oh
, struct Object
* args
[], word_t arity
, struct OopArray
* opts
, word_t resultStackPointer
) {
1788 char nameString
[SLATE_FILE_NAME_LENGTH
];
1789 struct slate_image_header sih
;
1790 struct Object
* name
= args
[1];
1791 size_t nameLength
= payload_size(name
);
1794 word_t totalSize
, forwardPointerEntryCount
;
1795 byte_t
* memoryStart
;
1796 struct Object
*writeObject
;
1797 struct ForwardPointerEntry
* forwardPointers
;
1798 /* do a full gc, allocate a new chunk of memory the size of the young and old combined,
1799 * copy all the non-free objects to the new memory while keeping an array of the position changes,
1800 * go through the memory and fix up the pointers, adjust points to start from 0 instead of memoryStart,
1801 * and write the header and the memory out to disk
1804 /*push true so if it resumes from the save image, it will do init code*/
1806 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.true_object
;
1808 if (nameLength
>= sizeof(nameString
)) {
1809 /*interpreter_stack_pop(oh, oh->cached.interpreter);*/
1811 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1814 memcpy(nameString
, (char*)byte_array_elements((struct ByteArray
*)name
), nameLength
);
1815 nameString
[nameLength
] = '\0';
1817 imageFile
= fopen(nameString
, "wb");
1819 /*interpreter_stack_pop(oh, oh->cached.interpreter);*/
1821 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.nil
;
1825 printf("Saving image to %s\n", nameString
);
1827 totalSize
= oh
->memoryOldSize
+ oh
->memoryYoungSize
;
1828 forwardPointerEntryCount
= ((totalSize
/ 4) + sizeof(struct ForwardPointerEntry
) - 1) / sizeof(struct ForwardPointerEntry
);
1829 memoryStart
= calloc(1, totalSize
);
1830 writeObject
= (struct Object
*)memoryStart
;
1831 forwardPointers
= calloc(1, forwardPointerEntryCount
* sizeof(struct ForwardPointerEntry
));
1832 assert(memoryStart
!= NULL
);
1833 copy_used_objects(oh
, &writeObject
, oh
->memoryOld
, oh
->memoryOldSize
, forwardPointers
, forwardPointerEntryCount
);
1834 copy_used_objects(oh
, &writeObject
, oh
->memoryYoung
, oh
->memoryYoungSize
, forwardPointers
, forwardPointerEntryCount
);
1835 totalSize
= (byte_t
*)writeObject
- memoryStart
;
1836 adjust_object_fields_with_table(oh
, memoryStart
, totalSize
, forwardPointers
, forwardPointerEntryCount
);
1837 adjust_oop_pointers_from(oh
, 0-(word_t
)memoryStart
, memoryStart
, totalSize
);
1838 sih
.magic
= SLATE_IMAGE_MAGIC
;
1839 sih
.size
= totalSize
;
1840 sih
.next_hash
= heap_new_hash(oh
);
1841 sih
.special_objects_oop
= (byte_t
*) (forward_pointer_hash_get(forwardPointers
, forwardPointerEntryCount
, (struct Object
*)oh
->special_objects_oop
)->toObj
) - memoryStart
;
1842 sih
.current_dispatch_id
= oh
->current_dispatch_id
;
1844 if (fwrite(&sih
, sizeof(struct slate_image_header
), 1, imageFile
) != 1
1845 || fwrite(memoryStart
, 1, totalSize
, imageFile
) != totalSize
) {
1846 fprintf(stderr
, "Error writing image!\n");
1849 free(forwardPointers
);
1852 oh
->cached
.interpreter
->stack
->elements
[resultStackPointer
] = oh
->cached
.false_object
;
1854 interpreter_stack_pop(oh, oh->cached.interpreter);
1855 interpreter_push_false(oh, oh->cached.interpreter);
1863 void (*primitives
[]) (struct object_heap
* oh
, struct Object
* args
[], word_t n
, struct OopArray
* opts
, word_t resultStackPointer
) = {
1865 /*0-9*/ prim_as_method_on
, prim_as_accessor
, prim_map
, prim_set_map
, prim_fixme
, prim_removefrom
, prim_clone
, prim_clone_setting_slots
, prim_clone_with_slot_valued
, prim_fixme
,
1866 /*10-9*/ prim_fixme
, prim_fixme
, prim_clone_without_slot
, prim_at_slot_named
, prim_smallint_at_slot_named
, prim_at_slot_named_put
, prim_forward_to
, prim_bytearray_newsize
, prim_bytesize
, prim_byteat
,
1867 /*20-9*/ prim_byteat_put
, prim_ooparray_newsize
, prim_size
, prim_at
, prim_at_put
, prim_ensure
, prim_applyto
, prim_send_to
, prim_send_to_through
, prim_findon
,
1868 /*30-9*/ prim_fixme
, prim_run_args_into
, prim_exit
, prim_isIdenticalTo
, prim_identity_hash
, prim_identity_hash_univ
, prim_equals
, prim_less_than
, prim_bitor
, prim_bitand
,
1869 /*40-9*/ prim_bitxor
, prim_bitnot
, prim_bitshift
, prim_plus
, prim_minus
, prim_times
, prim_quo
, prim_fixme
, prim_fixme
, prim_frame_pointer_of
,
1870 /*50-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_bytesPerWord
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
,
1871 /*60-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_readConsole_from_into_starting_at
, prim_write_to_starting_at
, prim_flush_output
, prim_handle_for
, prim_handle_for_input
, prim_fixme
,
1872 /*70-9*/ prim_handleForNew
, prim_close
, prim_read_from_into_starting_at
, prim_write_to_from_starting_at
, prim_reposition_to
, prim_positionOf
, prim_atEndOf
, prim_sizeOf
, prim_save_image
, prim_fixme
,
1873 /*80-9*/ prim_fixme
, prim_fixme
, prim_getcwd
, prim_setcwd
, prim_significand
, prim_exponent
, prim_withSignificand_exponent
, prim_float_equals
, prim_float_less_than
, prim_float_plus
,
1874 /*90-9*/ prim_float_minus
, prim_float_times
, prim_float_divide
, prim_float_raisedTo
, prim_float_ln
, prim_float_exp
, prim_float_sin
, prim_fixme
, prim_fixme
, prim_fixme
,
1875 /*00-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_newFixedArea
, prim_closeFixedArea
, prim_fixedAreaAddRef
, prim_fixedWriteFromStarting
, prim_fixedReadFromStarting
, prim_fixedAreaSize
, prim_fixedAreaResize
,
1876 /*10-9*/ prim_addressOf
, prim_loadLibrary
, prim_closeLibrary
, prim_procAddressOf
, prim_extlibError
, prim_applyExternal
, prim_timeSinceEpoch
, prim_cloneSystem
, prim_readFromPipe
, prim_writeToPipe
,
1877 /*20-9*/ prim_selectOnReadPipesFor
, prim_selectOnWritePipesFor
, prim_closePipe
, prim_socketCreate
, prim_socketListen
, prim_socketAccept
, prim_socketBind
, prim_socketConnect
, prim_socketCreateIP
, prim_smallIntegerMinimum
,
1878 /*30-9*/ prim_smallIntegerMaximum
, prim_socketGetError
, prim_getAddrInfo
, prim_getAddrInfoResult
, prim_freeAddrInfoResult
, prim_vmArgCount
, prim_vmArg
, prim_environmentVariables
, prim_fixme
, prim_fixme
,
1879 /*40-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
,
1880 /*50-9*/ prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
, prim_fixme
,