00001 #include "slate.hpp"
00002
00003
00004
00005
00006
00007 #ifdef SLATE_DAEMONIZE
00008 #include <pwd.h>
00009 #include <sys/stat.h>
00010 #include <signal.h>
00011 #endif
00012
00013 void prim_fixme(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00014 struct Object* x = args[0];
00015 printf("UNIMPLEMENTED PRIMITIVE\n");
00016 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_TYPE_ERROR_ON), x, NULL, resultStackPointer);
00017 }
00018
00019 #pragma mark Root
00020
00021 void prim_isIdenticalTo(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00022 oh->cached.interpreter->stack->elements[resultStackPointer] = (args[0]==args[1])? oh->cached.true_object : oh->cached.false_object;
00023 }
00024
00025 void prim_identity_hash(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00026
00027
00028
00029 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(object_hash(args[0]));
00030 }
00031
00032 void prim_identity_hash_univ(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00033
00034
00035
00036 if (object_is_smallint(args[0])) {
00037 oh->cached.interpreter->stack->elements[resultStackPointer] = args[0];
00038 } else {
00039 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(object_hash(args[0]));
00040 }
00041 }
00042
00043
00044 void prim_forward_to(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00045 struct Object* x = args[0];
00046 struct Object* y = args[1];
00047 oh->cached.interpreter->stack->elements[resultStackPointer] = y;
00048
00049
00050
00051 if (x == get_special(oh, SPECIAL_OOP_NIL)
00052 || x == get_special(oh, SPECIAL_OOP_TRUE)
00053 || x == get_special(oh, SPECIAL_OOP_FALSE)) {
00054 printf("Error... you cannot call forwardTo on this special object (did you add a slot to Nil/True/False?)\n");
00055 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_TYPE_ERROR_ON), x, NULL, resultStackPointer); \
00056 return;
00057 }
00058
00059 if (!object_is_smallint(x) && !object_is_smallint(y) && x != y) {
00060 heap_unpin_object(oh, x);
00061 heap_forward(oh, x, y);
00062
00063
00064 }
00065
00066 }
00067
00068
00069 void prim_at_slot_named(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00070 struct Object* obj;
00071 struct Object* name;
00072 struct SlotEntry * se;
00073
00074 obj = args[0];
00075 name = args[1];
00076
00077 if (object_is_smallint(obj)) {
00078 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, name, NULL, resultStackPointer);
00079 } else {
00080 se = slot_table_entry_for_name(oh, obj->map->slotTable, (struct Symbol*)name);
00081 if (se == NULL) {
00082 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, name, NULL, resultStackPointer);
00083 } else {
00084 word_t offset = object_to_smallint(se->offset);
00085 oh->cached.interpreter->stack->elements[resultStackPointer] = object_slot_value_at_offset(obj, offset);
00086 }
00087 }
00088 }
00089
00090
00091 void prim_at_slot_named_put(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00092 struct Object* obj=args[0], *val=args[2];
00093 struct Object* name = args[1];
00094 struct SlotEntry * se;
00095 struct Map* map;
00096
00097 if (object_is_smallint(obj)) {
00098 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, name, NULL, resultStackPointer);
00099 return;
00100 }
00101
00102 if (object_is_immutable(obj)) {
00103 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_IMMUTABLE), obj, NULL, resultStackPointer);
00104 return;
00105 }
00106
00107 map = obj->map;
00108 se = slot_table_entry_for_name(oh, map->slotTable, (struct Symbol*)name);
00109
00110 if (se == NULL) {
00111 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, name, NULL, resultStackPointer);
00112 } else {
00113 word_t offset = object_to_smallint(se->offset);
00114 oh->cached.interpreter->stack->elements[resultStackPointer] = object_slot_value_at_offset_put(oh, obj, offset, val);
00115 }
00116
00117
00118
00119 }
00120
00121 void prim_clone(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00122 if (object_is_smallint(args[0])) {
00123 oh->cached.interpreter->stack->elements[resultStackPointer] = args[0];
00124 } else {
00125 oh->cached.interpreter->stack->elements[resultStackPointer] = heap_clone(oh, args[0]);
00126 }
00127 }
00128
00129
00130 void prim_clone_setting_slots(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00131 Pinned<struct Object> obj(oh, args[0]), slotArray(oh, args[1]), valueArray(oh, args[2]), newObj(oh);
00132 word_t i;
00133
00134 if (object_is_smallint(obj)) {
00135 oh->cached.interpreter->stack->elements[resultStackPointer] = obj;
00136 return;
00137 }
00138 newObj = heap_clone(oh, obj);
00139
00140
00141
00142 for (i = 0; i < object_array_size(slotArray); i++) {
00143 struct Symbol* name = (struct Symbol*)object_array_get_element(slotArray, i);
00144 struct SlotEntry* se = slot_table_entry_for_name(oh, obj->map->slotTable, name);
00145 if (se == NULL) {
00146 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, (struct Object*)name, NULL, resultStackPointer);
00147 } else {
00148
00149 object_slot_value_at_offset_put(oh, newObj, object_to_smallint(se->offset), object_array_get_element(valueArray, i));
00150 }
00151 }
00152
00153 oh->cached.interpreter->stack->elements[resultStackPointer] = newObj;
00154 }
00155
00156 void prim_clone_with_slot_valued(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00157 Pinned<struct Object> obj(oh, args[0]), value(oh, args[2]);
00158 Pinned<struct Symbol> name(oh, (struct Symbol*)args[1]);
00159
00160 if (object_is_smallint(obj)) {
00161 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, (struct Object*)name, NULL, resultStackPointer);
00162 } else {
00163 oh->cached.interpreter->stack->elements[resultStackPointer] = object_add_slot_named(oh, obj, name, value);
00164 }
00165 }
00166
00167 void prim_clone_without_slot(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00168 Pinned<struct Object> obj(oh, args[0]);
00169 Pinned<struct Symbol> name(oh, (struct Symbol*)args[1]);
00170
00171 if (object_is_smallint(obj)) {
00172 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, (struct Object*)name, NULL, resultStackPointer);
00173 } else {
00174 oh->cached.interpreter->stack->elements[resultStackPointer] = object_remove_slot(oh, obj, name);
00175 }
00176 }
00177
00178 #pragma mark Map
00179
00180 void prim_map(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00181 struct Object* obj;
00182 obj = args[0];
00183
00184 if (object_is_smallint(obj)) {
00185 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00186 } else {
00187 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)obj->map;
00188 }
00189
00190
00191 }
00192
00193 void prim_set_map(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00194 Pinned<struct Object> obj(oh);
00195 Pinned<struct Map> map(oh);
00196 obj = args[0];
00197 map = (struct Map*)args[1];
00198
00199 if (object_is_smallint(obj) || object_is_immutable(obj)) {
00200 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00201 } else {
00202 object_change_map(oh, obj, map);
00203 heap_store_into(oh, args[0], args[1]);
00204 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)map;
00205 }
00206
00207 }
00208
00209 #pragma mark Method
00210
00211 void prim_applyto(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00212 Pinned<struct Closure> method(oh);
00213 Pinned<struct OopArray> argArray(oh);
00214 Pinned<struct OopArray> real_opts(oh);
00215
00216 method = (struct Closure*)args[0];
00217 argArray = (struct OopArray*) args[1];
00218
00219 if (opts != NULL && opts->elements[1] != oh->cached.nil) {
00220 real_opts = (struct OopArray*) opts->elements[1];
00221 }
00222 interpreter_apply_to_arity_with_optionals(oh, oh->cached.interpreter, method,
00223 argArray->elements, array_size(argArray), real_opts, resultStackPointer);
00224 }
00225
00226
00227 void prim_interrupt(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00228
00229 oh->interrupt_flag = 1;
00230
00231 }
00232
00233
00234 void prim_initializeThreadOn(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00235 Pinned<struct Closure> method(oh);
00236 Pinned<struct Interpreter> i(oh);
00237 Pinned<struct OopArray> newStack(oh);
00238 word_t newStackSize;
00239
00240 newStackSize = 16;
00241 newStack = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), newStackSize);
00242 i = (struct Interpreter*)args[0];
00243 method = (struct Closure*)args[1];
00244
00245 i->stack = newStack;
00246 i->stackSize = newStackSize;
00247 i->framePointer = 0;
00248 i->stackPointer = 0;
00249 i->ensureHandlers = smallint_to_object(0);
00250 i->codePointer = 0;
00251
00252 interpreter_apply_to_arity_with_optionals(oh, i, method, NULL, 0, NULL, 0);
00253 }
00254
00255 void prim_findon(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00256 struct MethodDefinition* def;
00257 Pinned<struct Symbol> selector(oh);
00258 Pinned<struct OopArray> arguments(oh);
00259
00260 selector = (struct Symbol*) args[0];
00261 arguments = (struct OopArray*) args[1];
00262
00263 def = method_dispatch_on(oh, selector, arguments->elements, array_size(arguments), NULL);
00264
00265 oh->cached.interpreter->stack->elements[resultStackPointer] = (def == NULL ? oh->cached.nil : (struct Object*) def->method);
00266 }
00267
00268 void prim_ensure(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00269
00270 Pinned<struct Closure> body(oh);
00271 Pinned<struct Object> ensureHandler(oh);
00272
00273 body = (struct Closure*) args[0];
00274 ensureHandler = args[1];
00275
00276 interpreter_apply_to_arity_with_optionals(oh, oh->cached.interpreter, body, NULL, 0, NULL, resultStackPointer);
00277
00278 interpreter_stack_push(oh, oh->cached.interpreter, oh->cached.interpreter->ensureHandlers);
00279 interpreter_stack_push(oh, oh->cached.interpreter, ensureHandler);
00280 oh->cached.interpreter->ensureHandlers = smallint_to_object(oh->cached.interpreter->stackPointer - 2);
00281 #ifdef PRINT_DEBUG_ENSURE
00282 printf("ensure handlers at %" PRIdPTR "\n", oh->cached.interpreter->stackPointer - 2);
00283 #endif
00284
00285 }
00286
00287 void prim_send_to(struct object_heap* oh, struct Object* args[], word_t n, struct OopArray* optionals, word_t resultStackPointer) {
00288 Pinned<struct Symbol> selector(oh,(struct Symbol*)args[0]);
00289 Pinned<struct OopArray> opts(oh), arguments(oh, (struct OopArray*)args[1]);
00290
00291 if (optionals == NULL) {
00292 opts = NULL;
00293 } else {
00294 opts = (struct OopArray*)optionals->elements[1];
00295 if (opts == (struct OopArray*)oh->cached.nil) opts = NULL;
00296 }
00297 send_to_through_arity_with_optionals(oh, selector, array_elements(arguments), array_elements(arguments), array_size(arguments), opts, resultStackPointer);
00298 }
00299
00300 void prim_send_to_through(struct object_heap* oh, struct Object* args[], word_t n, struct OopArray* optionals, word_t resultStackPointer) {
00301 Pinned<struct Symbol> selector(oh, (struct Symbol*)args[0]);
00302 Pinned<struct OopArray> opts(oh), arguments(oh, (struct OopArray*)args[1]), dispatchers(oh, (struct OopArray*)args[2]);
00303
00304 if (optionals == NULL) {
00305 opts = NULL;
00306 } else {
00307 opts = (struct OopArray*)optionals->elements[1];
00308 if (opts == (struct OopArray*)oh->cached.nil) opts = NULL;
00309 }
00310
00311 send_to_through_arity_with_optionals(oh, selector, array_elements(arguments), array_elements(dispatchers), array_size(arguments), opts, resultStackPointer);
00312 }
00313
00314
00315 void prim_as_method_on(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00316 Pinned<struct MethodDefinition> def(oh);
00317 Pinned<struct Object> method(oh);
00318 Pinned<struct Object> roles(oh);
00319 method = args[0];
00320 roles = args[2];
00321 Pinned<struct Symbol> selector(oh);
00322 selector = (struct Symbol*)args[1];
00323 Pinned<struct Object> traitsWindow(oh);
00324 traitsWindow = method->map->delegates->elements[0];
00325 Pinned<struct Object> closure(oh);
00326 std::vector<Pinned<struct Object> > pinnedRoles(object_array_size(roles), Pinned<struct Object>(oh));
00327 for (int i = 0; i < object_array_size(roles); i++) {
00328 pinnedRoles[i] = ((struct OopArray*)roles)->elements[i];
00329 }
00330
00331 if (traitsWindow == get_special(oh, SPECIAL_OOP_CLOSURE_WINDOW)) {
00332 closure = heap_clone(oh, method);
00333 ((struct Closure*)closure)->method = (struct CompiledMethod*)heap_clone(oh, (struct Object*)((struct Closure*)closure)->method);
00334 heap_store_into(oh, (struct Object*)closure, (struct Object*)((struct Closure*)closure)->method);
00335 ((struct Closure*)closure)->method->method = ((struct Closure*)closure)->method;
00336 ((struct Closure*)closure)->method->selector = selector;
00337 method = (struct Object*)closure;
00338 } else {
00339
00340 closure = heap_clone(oh, method);
00341 ((struct CompiledMethod*)closure)->method = closure;
00342 ((struct CompiledMethod*)closure)->selector = selector;
00343 method = (struct Object*) closure;
00344 }
00345 def = method_define(oh, method, (struct Symbol*)selector, ((struct OopArray*)roles)->elements, object_array_size(roles));
00346 def->slotAccessor = oh->cached.nil;
00347 method_flush_cache(oh, selector);
00348 #ifdef PRINT_DEBUG_DEFUN
00349 if (!oh->quiet) {
00350 printf("Defining function '"); print_symbol(selector);
00351 printf("' on: ");
00352 if (!print_printname(oh, ((struct OopArray*)roles)->elements[0])) printf("NoRole");
00353 {
00354 word_t i;
00355 for (i = 1; i < object_array_size(roles); i++) {
00356 printf(", ");
00357 if (!print_printname(oh, ((struct OopArray*)roles)->elements[i])) printf("NoRole");
00358 }
00359 }
00360 printf("\n");
00361 }
00362 #endif
00363
00364 oh->cached.interpreter->stack->elements[resultStackPointer] = method;
00365 }
00366
00367
00368 void prim_removefrom(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00369
00370 Pinned<struct Object> method(oh, args[0]), traitsWindow(oh);
00371 Pinned<struct OopArray> roles(oh, (struct OopArray*)args[1]);
00372 Pinned<struct Symbol> selector(oh);
00373 selector = (struct Symbol*)oh->cached.nil;
00374 Pinned<struct MethodDefinition> def(oh);
00375 word_t i;
00376
00377 traitsWindow = method->map->delegates->elements[0];
00378
00379 if (traitsWindow == oh->cached.closure_method_window || traitsWindow == oh->cached.compiled_method_window) {
00380 selector = ((struct Closure*)method)->method->selector;
00381 } else {
00382
00383 assert(0);
00384 };
00385
00386 def = method_is_on_arity(oh, method, selector, array_elements(roles), array_size(roles));
00387 if ((struct Object*)def == NULL) {
00388 oh->cached.interpreter->stack->elements[resultStackPointer] = method;
00389 return;
00390 };
00391
00392 for (i = 0; i < array_size(roles); i++) {
00393 struct Object* role = array_elements(roles)[i];
00394 if (!object_is_smallint(role)) {
00395 object_remove_role(oh, role, selector, def);
00396 }
00397 };
00398 method_flush_cache(oh, selector);
00399 oh->cached.interpreter->stack->elements[resultStackPointer] = method;
00400 }
00401
00402 void prim_as_accessor(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00403 Pinned<struct Object> method(oh);
00404 method = args[0];
00405 Pinned<struct Object> slot(oh);
00406 slot = args[2];
00407 Pinned<struct OopArray> roles(oh);
00408 roles = (struct OopArray*)args[3];
00409 Pinned<struct Symbol> selector(oh);
00410 selector = (struct Symbol*)args[1];
00411 Pinned<struct Object> traitsWindow(oh, method->map->delegates->elements[0]);
00412 struct MethodDefinition* def;
00413 Pinned<struct Object> closure(oh);
00414 std::vector<Pinned<struct Object> > pinnedRoles(object_array_size(roles), Pinned<struct Object>(oh));
00415 for (int i = 0; i < object_array_size(roles); i++) {
00416 pinnedRoles[i] = roles->elements[i];
00417 }
00418
00419 if (traitsWindow == oh->cached.closure_method_window) {
00420 closure = heap_clone(oh, method);
00421 ((struct Closure*)closure)->method = (struct CompiledMethod*)heap_clone(oh, (struct Object*)((struct Closure*)closure)->method);
00422 heap_store_into(oh, (struct Object*)closure, (struct Object*)((struct Closure*)closure)->method);
00423 ((struct Closure*)closure)->method->method = ((struct Closure*)closure)->method;
00424 ((struct Closure*)closure)->method->selector = selector;
00425 method = (struct Object*)closure;
00426 } else if (traitsWindow == oh->cached.compiled_method_window){
00427 closure = heap_clone(oh, method);
00428 ((struct CompiledMethod*)closure)->method = closure;
00429 ((struct CompiledMethod*)closure)->selector = selector;
00430 method = (struct Object*) closure;
00431 }
00432
00433 def = method_define(oh, method, selector, roles->elements, array_size(roles));
00434 def->slotAccessor = slot;
00435 method_flush_cache(oh, selector);
00436 oh->cached.interpreter->stack->elements[resultStackPointer] = method;
00437
00438 #ifdef PRINT_DEBUG_DEFUN
00439 if (!oh->quiet) {
00440 printf("Defining accessor '"); print_symbol(selector);
00441 printf("' on: ");
00442 if (!print_printname(oh, ((struct OopArray*)roles)->elements[0])) printf("NoRole");
00443 {
00444 word_t i;
00445 for (i = 1; i < array_size(roles); i++) {
00446 printf(", ");
00447 if (!print_printname(oh, ((struct OopArray*)roles)->elements[i])) printf("NoRole");
00448 }
00449 }
00450 printf("\n");
00451 }
00452 #endif
00453 }
00454
00455 #pragma mark Array
00456
00457 void prim_at(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00458 struct Object* array;
00459 word_t i;
00460
00461 array = args[0];
00462 i = object_to_smallint(args[1]);
00463 ASSURE_SMALLINT_ARG(1);
00464 if (i < object_array_size(array) && i >= 0) {
00465 oh->cached.interpreter->stack->elements[resultStackPointer] = ((struct OopArray*)array)->elements[i];
00466 } else {
00467 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), args[1], args[0], NULL, resultStackPointer);
00468 }
00469 }
00470
00471 void prim_at_put(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00472 struct Object *array = args[0], *i = args[1], *val = args[2];
00473 word_t index = object_to_smallint(i);
00474
00475 ASSURE_SMALLINT_ARG(1);
00476 if (object_is_immutable(array)) {
00477 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_IMMUTABLE), array, NULL, resultStackPointer);
00478 return;
00479 }
00480
00481 if (index < object_array_size(array)) {
00482 heap_store_into(oh, array, val);
00483 oh->cached.interpreter->stack->elements[resultStackPointer] = ((struct OopArray*)array)->elements[index] = val;
00484 } else {
00485 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), i, array, NULL, resultStackPointer);
00486 }
00487 }
00488
00489 void prim_ooparray_newsize(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00490
00491 struct Object* i = args[1];
00492 if (object_is_smallint(i)) {
00493 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)
00494 heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO),
00495 object_to_smallint(i));
00496 } else {
00497 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00498 }
00499 }
00500
00501 void prim_size(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00502 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(object_array_size(args[0]));
00503 }
00504
00505 #pragma mark ByteArray
00506
00507 void prim_bytearray_newsize(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00508 struct Object* obj, *i;
00509 obj = args[0];
00510 i = args[1];
00511
00512 if (!object_is_smallint(i)) {
00513 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00514 return;
00515 }
00516
00517 oh->cached.interpreter->stack->elements[resultStackPointer] =
00518 (struct Object*)heap_clone_byte_array_sized(oh, obj, (object_to_smallint(i) < 0) ? 0 : object_to_smallint(i));
00519 }
00520
00521 void prim_bytesize(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00522 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(payload_size(args[0]));
00523 }
00524
00525 void prim_byteat_put(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00526 struct Object* obj= args[0], *i=args[1], *val = args[2];
00527 word_t index;
00528
00529 index = object_to_smallint(i);
00530
00531 ASSURE_SMALLINT_ARG(1);
00532 ASSURE_SMALLINT_ARG(2);
00533
00534 if (object_is_immutable(obj)) {
00535 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_IMMUTABLE), obj, NULL, resultStackPointer);
00536 return;
00537 }
00538
00539 if (index < byte_array_size((struct ByteArray*)obj)) {
00540 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(byte_array_set_element((struct ByteArray*)obj, index, object_to_smallint(val)));
00541 } else {
00542 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), i, obj, NULL, resultStackPointer);
00543 }
00544
00545 }
00546
00547 void prim_byteat(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00548 struct Object* obj, *i;
00549 word_t index;
00550
00551 obj = args[0];
00552 i = args[1];
00553 index = object_to_smallint(i);
00554
00555 ASSURE_SMALLINT_ARG(1);
00556
00557 if (index < byte_array_size((struct ByteArray*)obj)) {
00558 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(byte_array_get_element(obj, index));
00559 } else {
00560 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), i, obj, NULL, resultStackPointer);
00561 }
00562
00563 }
00564
00565 #pragma mark File
00566
00567 void prim_atEndOf(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00568 word_t handle = object_to_smallint(args[1]);
00569 ASSURE_SMALLINT_ARG(1);
00570 if (file_isatend(oh, handle)) {
00571 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
00572 } else {
00573 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
00574 }
00575 }
00576
00577 void prim_sizeOf(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00578 word_t handle = object_to_smallint(args[1]);
00579 word_t retval = file_sizeof(oh, handle);
00580 ASSURE_SMALLINT_ARG(1);
00581 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
00582 }
00583
00584 void prim_flush_output(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00585
00586 fflush(stdout);
00587 fflush(stderr);
00588 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00589 }
00590
00591 void prim_handle_for(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00592 word_t handle;
00593 struct Object *fname=args[1];
00594
00595 handle = file_open(oh, (struct ByteArray*)fname, SF_READ|SF_WRITE);
00596 if (handle >= 0) {
00597 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(handle);
00598 } else {
00599 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00600 }
00601
00602 }
00603
00604 void prim_handleForNew(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00605 word_t handle;
00606 struct Object *fname=args[1];
00607
00608 handle = file_open(oh, (struct ByteArray*)fname, SF_READ|SF_WRITE|SF_CLEAR|SF_CREATE);
00609 if (handle >= 0) {
00610 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(handle);
00611 } else {
00612 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00613 }
00614
00615 }
00616
00617 void prim_handle_for_input(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00618 word_t handle;
00619 struct Object *fname=args[1];
00620
00621 handle = file_open(oh, (struct ByteArray*)fname, SF_READ);
00622 if (handle >= 0) {
00623 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(handle);
00624 } else {
00625 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00626 }
00627
00628 }
00629
00630 void prim_closePipe(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00631 word_t handle = object_to_smallint(args[0]);
00632 int retval;
00633
00634 ASSURE_SMALLINT_ARG(0);
00635 #ifdef WIN32
00636 retval = closesocket(handle);
00637 #else
00638 retval = close(handle);
00639 #endif
00640 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(retval);
00641
00642 }
00643
00644 void prim_readFromPipe(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00645 struct ByteArray* array = (struct ByteArray*) args[0];
00646 word_t handle = object_to_smallint(args[1]);
00647 word_t start = object_to_smallint(args[2]), end = object_to_smallint(args[3]);
00648 ssize_t retval;
00649
00650 ASSURE_TYPE_ARG(0, TYPE_BYTE_ARRAY);
00651 ASSURE_SMALLINT_ARG(1);
00652 ASSURE_SMALLINT_ARG(2);
00653 ASSURE_SMALLINT_ARG(3);
00654
00655 if (start < 0 || start >= byte_array_size(array)) {
00656 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), args[2], args[0], NULL, resultStackPointer);
00657 return;
00658 }
00659
00660 if (end < start || end > byte_array_size(array)) {
00661 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), args[3], args[0], NULL, resultStackPointer);
00662 return;
00663 }
00664
00665 retval = recv(handle, byte_array_elements(array)+start, end - start, 0);
00666
00667
00668 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(retval);
00669
00670
00671 }
00672
00673 void prim_writeToPipe(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00674 struct ByteArray* array = (struct ByteArray*) args[0];
00675 word_t handle = object_to_smallint(args[1]);
00676 word_t start = object_to_smallint(args[2]), end = object_to_smallint(args[3]);
00677 ssize_t retval;
00678
00679 ASSURE_TYPE_ARG(0, TYPE_BYTE_ARRAY);
00680 ASSURE_SMALLINT_ARG(1);
00681 ASSURE_SMALLINT_ARG(2);
00682 ASSURE_SMALLINT_ARG(3);
00683
00684 if (start < 0 || start >= byte_array_size(array)) {
00685 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), args[2], args[0], NULL, resultStackPointer);
00686 return;
00687 }
00688
00689 if (end < start || end > byte_array_size(array)) {
00690 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_KEY_NOT_FOUND_ON), args[3], args[0], NULL, resultStackPointer);
00691 return;
00692 }
00693
00694 retval = send(handle, byte_array_elements(array)+start, end - start, 0);
00695
00696 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(retval);
00697
00698 }
00699
00700
00701 void prim_selectOnWritePipesFor(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00702
00703 Pinned<struct OopArray> selectOn(oh);
00704 selectOn = (struct OopArray*) args[0];
00705 Pinned<struct OopArray> readyPipes(oh);
00706 word_t waitTime = object_to_smallint(args[1]);
00707 int retval, fdCount, maxFD;
00708 struct timeval tv;
00709 fd_set fdList;
00710 maxFD = 0;
00711
00712 ASSURE_SMALLINT_ARG(1);
00713
00714 if ((fdCount = socket_select_setup(selectOn, &fdList, &maxFD)) < 0) {
00715 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00716 return;
00717 }
00718
00719
00720 tv.tv_sec = waitTime / 1000000;
00721 tv.tv_usec = waitTime % 1000000;
00722 retval = select(maxFD+1, NULL, &fdList, NULL, &tv);
00723
00724 if (retval < 0) {
00725 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00726 return;
00727 }
00728
00729
00730 readyPipes = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), retval);
00731 socket_select_find_available(selectOn, &fdList, readyPipes, retval);
00732
00733 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)readyPipes;
00734
00735 }
00736
00737 #pragma mark Socket
00738
00739 void prim_socketCreate(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00740 word_t domain = object_to_smallint(args[0]);
00741 word_t type = object_to_smallint(args[1]);
00742 word_t protocol = object_to_smallint(args[2]);
00743 word_t ret = socket(socket_lookup_domain(domain), socket_lookup_type(type), socket_lookup_protocol(protocol));
00744 int ret2 = 0;
00745
00746 ASSURE_SMALLINT_ARG(0);
00747 ASSURE_SMALLINT_ARG(1);
00748 ASSURE_SMALLINT_ARG(2);
00749
00750 if (ret >= 0) {
00751 ret2 = socket_set_nonblocking(ret);
00752 } else {
00753 perror("socket create");
00754 };
00755
00756 if (ret2 < 0) {
00757 perror("set nonblocking");
00758 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(-1);
00759 } else {
00760 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00761 }
00762 }
00763
00764 void prim_socketListen(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00765 word_t fd = object_to_smallint(args[0]);
00766 word_t size = object_to_smallint(args[1]);
00767 word_t ret;
00768
00769 ASSURE_SMALLINT_ARG(0);
00770 ASSURE_SMALLINT_ARG(1);
00771
00772 ret = listen(fd, size);
00773
00774 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00775
00776 }
00777
00778 void prim_socketAccept(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00779 word_t fd = object_to_smallint(args[0]);
00780 word_t ret;
00781 struct sockaddr_storage addr;
00782 socklen_t len;
00783 Pinned<struct ByteArray> addrArray(oh);
00784 Pinned<struct OopArray> result(oh);
00785
00786 ASSURE_SMALLINT_ARG(0);
00787
00788 len = sizeof(addr);
00789 ret = accept(fd, (struct sockaddr*)&addr, &len);
00790
00791 if (ret >= 0) {
00792 addrArray = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), sizeof(struct sockaddr_in));
00793 } else {
00794 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00795 return;
00796 }
00797
00798 result = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 2);
00799
00800 object_array_set_element(oh, (struct Object*)result, 0, smallint_to_object(ret));
00801 object_array_set_element(oh, (struct Object*)result, 1, (struct Object*)addrArray);
00802
00803 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)result;
00804
00805 }
00806
00807 void prim_socketBind(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00808 word_t fd = object_to_smallint(args[0]);
00809 struct ByteArray* address = (struct ByteArray*) args[1];
00810 word_t ret;
00811
00812 ASSURE_SMALLINT_ARG(0);
00813
00814 ret = bind(fd, (const struct sockaddr*)byte_array_elements(address), (socklen_t)byte_array_size(address));
00815 if (ret < 0) perror("bind");
00816 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00817 }
00818
00819 void prim_socketConnect(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00820 word_t fd = object_to_smallint(args[0]);
00821 struct ByteArray* address = (struct ByteArray*) args[1];
00822 word_t ret;
00823
00824 ASSURE_SMALLINT_ARG(0);
00825
00826 ret = connect(fd, (const struct sockaddr*)byte_array_elements(address), (socklen_t)byte_array_size(address));
00827
00828 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00829
00830 }
00831
00832 void prim_socketGetError(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00833 word_t fd = object_to_smallint(args[0]);
00834 word_t ret;
00835 int optval;
00836 socklen_t optlen;
00837 optlen = 4;
00838 ASSURE_SMALLINT_ARG(0);
00839
00840 ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &optval, (socklen_t*)&optlen);
00841
00842 if (ret == 0) {
00843 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(optval);
00844 } else {
00845 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00846 }
00847
00848 }
00849
00850 void prim_getAddrInfo(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00851 struct ByteArray* hostname = (struct ByteArray*)args[1];
00852 struct ByteArray* service = (struct ByteArray*)args[2];
00853 word_t family = object_to_smallint(args[3]);
00854 word_t type = object_to_smallint(args[4]);
00855 word_t protocol = object_to_smallint(args[5]);
00856 word_t flags = object_to_smallint(args[6]);
00857 word_t ret, serviceSize, hostnameSize;
00858
00859 ASSURE_TYPE_ARG(1, TYPE_BYTE_ARRAY);
00860 ASSURE_SMALLINT_ARG(3);
00861 ASSURE_SMALLINT_ARG(4);
00862 ASSURE_SMALLINT_ARG(5);
00863 ASSURE_SMALLINT_ARG(6);
00864
00865 if ((struct Object*)hostname == oh->cached.nil) {
00866 hostnameSize = 0;
00867 } else {
00868 hostnameSize = byte_array_size(hostname)+1;
00869 }
00870
00871 if ((struct Object*)service == oh->cached.nil) {
00872 serviceSize = 0;
00873 } else {
00874 ASSURE_TYPE_ARG(2, TYPE_BYTE_ARRAY);
00875 serviceSize = byte_array_size(service)+1;
00876 }
00877
00878 ret = socket_getaddrinfo(oh, hostname, hostnameSize, service, serviceSize, family, type, protocol, flags);
00879
00880 oh->cached.interpreter->stack->elements[resultStackPointer] = SOCKET_RETURN(ret);
00881
00882 }
00883
00884 void prim_getAddrInfoResult(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00885 word_t ticket = object_to_smallint(args[0]);
00886 if (ticket >= oh->socketTicketCount || ticket < 0
00887 || oh->socketTickets[ticket].inUse == 0 || oh->socketTickets[ticket].finished == 0) {
00888 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
00889 return;
00890 }
00891 if (oh->socketTickets[ticket].result < 0) {
00892 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(socket_return(oh->socketTickets[ticket].result));
00893 } else {
00894 word_t count, i;
00895 struct addrinfo* ai = oh->socketTickets[ticket].addrResult;
00896 struct addrinfo* current = ai;
00897 Pinned<struct OopArray> retval(oh);
00898 Pinned<struct OopArray> aResult(oh);
00899 count = 0;
00900 while (current != NULL) {
00901 current = current->ai_next;
00902 count++;
00903 }
00904 current = ai;
00905 retval = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), count);
00906 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)retval;
00907 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)retval);
00908
00909 for (i = 0; i < count; i++) {
00910 aResult = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 6);
00911 struct ByteArray* aResultAddr;
00912 struct ByteArray* aResultCanonName;
00913 word_t canonNameLen = (current->ai_canonname == NULL)? 0 : strlen(current->ai_canonname);
00914 retval->elements[i] = (struct Object*)aResult;
00915 heap_store_into(oh, (struct Object*)retval, retval->elements[i]);
00916 aResult->elements[0] = smallint_to_object(current->ai_flags);
00917 aResult->elements[1] = smallint_to_object(socket_reverse_lookup_domain(current->ai_family));
00918 aResult->elements[2] = smallint_to_object(socket_reverse_lookup_type(current->ai_socktype));
00919 aResult->elements[3] = smallint_to_object(socket_reverse_lookup_protocol(current->ai_protocol));
00920
00921 aResultAddr = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), current->ai_addrlen);
00922 aResult->elements[4] = (struct Object*)aResultAddr;
00923 heap_store_into(oh, (struct Object*)aResult, aResult->elements[4]);
00924 copy_bytes_into((byte_t*)current->ai_addr, current->ai_addrlen, aResultAddr->elements);
00925 if (canonNameLen == 0) {
00926 aResult->elements[5] = oh->cached.nil;
00927 } else {
00928 aResultCanonName = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), canonNameLen);
00929 aResult->elements[5] = (struct Object*)aResultCanonName;
00930 heap_store_into(oh, (struct Object*)aResult, aResult->elements[5]);
00931 copy_bytes_into((byte_t*)current->ai_canonname, canonNameLen, aResultCanonName->elements);
00932 }
00933
00934 current = current->ai_next;
00935 }
00936
00937 }
00938 }
00939
00940 void prim_freeAddrInfoResult(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00941 word_t ticket = object_to_smallint(args[0]);
00942 if (ticket >= oh->socketTicketCount || ticket < 0
00943 || oh->socketTickets[ticket].inUse == 0 || oh->socketTickets[ticket].finished == 0) {
00944 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
00945 return;
00946 }
00947 free(oh->socketTickets[ticket].hostname);
00948 oh->socketTickets[ticket].hostname = 0;
00949 free(oh->socketTickets[ticket].service);
00950 oh->socketTickets[ticket].service = 0;
00951 freeaddrinfo(oh->socketTickets[ticket].addrResult);
00952 oh->socketTickets[ticket].addrResult = 0;
00953
00954 oh->socketTickets[ticket].inUse = 0;
00955 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
00956 }
00957
00958
00959 void prim_socketCreateIP(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
00960 word_t domain = object_to_smallint(args[0]);
00961 struct Object* address = args[1];
00962 word_t port = object_to_smallint(args[2]);
00963
00964 struct sockaddr_in* sin;
00965 struct sockaddr_in6* sin6;
00966 struct sockaddr_un* sun;
00967 Pinned<struct ByteArray> ret(oh);
00968
00969 ASSURE_SMALLINT_ARG(0);
00970
00971 switch (domain) {
00972
00973 case SLATE_DOMAIN_LOCAL:
00974 #ifdef WIN32
00975 #else
00976 if (byte_array_size((struct ByteArray*)address) > 100) {
00977 ret = (struct ByteArray*)oh->cached.nil;
00978 break;
00979 }
00980 ret = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), sizeof(struct sockaddr_un));
00981 sun = (struct sockaddr_un*)byte_array_elements(ret);
00982 sun->sun_family = socket_lookup_domain(domain);
00983 ASSURE_TYPE_ARG(1, TYPE_BYTE_ARRAY);
00984 strncpy(sun->sun_path, (char*)byte_array_elements((struct ByteArray*)address), 100);
00985 sun->sun_path[byte_array_size((struct ByteArray*)address)] = '\0';
00986 #endif
00987 break;
00988
00989 case SLATE_DOMAIN_IPV4:
00990 ASSURE_SMALLINT_ARG(2);
00991 if (object_array_size(address) < 4) {
00992 ret = (struct ByteArray*)oh->cached.nil;
00993 break;
00994 }
00995 ret = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), sizeof(struct sockaddr_in));
00996 sin = (struct sockaddr_in*)byte_array_elements(ret);
00997 sin->sin_family = socket_lookup_domain(domain);
00998 sin->sin_port = htons((uint16_t)port);
00999 ASSURE_TYPE_ARG(1, TYPE_OOP_ARRAY);
01000 sin->sin_addr.s_addr = htonl(((object_to_smallint(object_array_get_element(address, 0)) & 0xFF) << 24)
01001 | ((object_to_smallint(object_array_get_element(address, 1)) & 0xFF) << 16)
01002 | ((object_to_smallint(object_array_get_element(address, 2)) & 0xFF) << 8)
01003 | (object_to_smallint(object_array_get_element(address, 3)) & 0xFF));
01004 break;
01005
01006
01007 case SLATE_DOMAIN_IPV6:
01008 ASSURE_SMALLINT_ARG(2);
01009 if (object_array_size(address) < 16) {
01010 ret = (struct ByteArray*)oh->cached.nil;
01011 break;
01012 }
01013 ret = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), sizeof(struct sockaddr_in6));
01014 sin6 = (struct sockaddr_in6*)byte_array_elements(ret);
01015 sin6->sin6_family = socket_lookup_domain(domain);
01016 sin6->sin6_port = htons((uint16_t)port);
01017 ASSURE_TYPE_ARG(1, TYPE_OOP_ARRAY);
01018 {
01019 int i;
01020 for (i = 0; i < 16; i++)
01021 sin6->sin6_addr.s6_addr[i] = object_to_smallint(object_array_get_element(address, i)) & 0xFF;
01022 }
01023 break;
01024
01025 default:
01026 ret = (struct ByteArray*)oh->cached.nil;
01027 break;
01028 }
01029
01030 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)ret;
01031
01032 }
01033
01034 void prim_write_to_starting_at(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01035 struct Object *console=args[0], *n=args[1], *handle=args[2], *seq=args[3], *start=args[4];
01036 byte_t* bytes = &((struct ByteArray*)seq)->elements[0] + object_to_smallint(start);
01037 word_t size = object_to_smallint(n);
01038
01039
01040 ASSURE_SMALLINT_ARG(2);
01041 ASSURE_SMALLINT_ARG(4);
01042
01043 assert(arity == 5 && console != NULL);
01044
01045 oh->cached.interpreter->stack->elements[resultStackPointer] =
01046 smallint_to_object(fwrite(bytes, 1, size, (object_to_smallint(handle) == 0)? stdout : stderr));
01047
01048 }
01049
01050 void prim_close(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01051 word_t handle = object_to_smallint(args[1]);
01052 ASSURE_SMALLINT_ARG(1);
01053
01054 file_close(oh, handle);
01055 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01056
01057 }
01058
01059 void prim_file_delete(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01060 char filename[SLATE_FILE_NAME_LENGTH];
01061 word_t len;
01062 len = extractCString((struct ByteArray*)args[1], (byte_t*)filename, sizeof(filename));
01063 oh->cached.interpreter->stack->elements[resultStackPointer] = ((file_delete(oh, filename)) ? oh->cached.true_object : oh->cached.false_object);
01064 }
01065
01066 void prim_file_touch(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01067 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
01068 }
01069
01070 void prim_file_rename_to(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01071 char src[SLATE_FILE_NAME_LENGTH], dest[SLATE_FILE_NAME_LENGTH];
01072 word_t srcLen, destLen;
01073 srcLen = extractCString((struct ByteArray*)args[1], (byte_t*)src, sizeof(src));
01074 destLen = extractCString((struct ByteArray*)args[2], (byte_t*)dest, sizeof(dest));
01075 oh->cached.interpreter->stack->elements[resultStackPointer] = ((file_rename_to(oh, src, dest)) ? oh->cached.true_object : oh->cached.false_object);
01076 }
01077
01078 void prim_file_information(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01079 char filename[SLATE_FILE_NAME_LENGTH];
01080 word_t len;
01081 len = extractCString((struct ByteArray*)args[1], (byte_t*)filename, sizeof(filename));
01082 oh->cached.interpreter->stack->elements[resultStackPointer] = file_information(oh, filename);
01083 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, oh->cached.interpreter->stack->elements[resultStackPointer]);
01084 }
01085
01086 void prim_dir_make(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01087 char filename[SLATE_FILE_NAME_LENGTH];
01088 word_t len;
01089 len = extractCString((struct ByteArray*)args[1], (byte_t*)filename, sizeof(filename));
01090 oh->cached.interpreter->stack->elements[resultStackPointer] = ((dir_make(oh, filename)) ? oh->cached.true_object : oh->cached.false_object);
01091 }
01092
01093 void prim_dir_rename_to(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01094 char src[SLATE_FILE_NAME_LENGTH], dest[SLATE_FILE_NAME_LENGTH];
01095 word_t srcLen, destLen;
01096 srcLen = extractCString((struct ByteArray*)args[1], (byte_t*)src, sizeof(src));
01097 destLen = extractCString((struct ByteArray*)args[2], (byte_t*)dest, sizeof(dest));
01098 oh->cached.interpreter->stack->elements[resultStackPointer] = ((dir_rename_to(oh, src, dest)) ? oh->cached.true_object : oh->cached.false_object);
01099 }
01100
01101 void prim_dir_delete(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01102 char filename[SLATE_FILE_NAME_LENGTH];
01103 word_t len;
01104 len = extractCString((struct ByteArray*)args[1], (byte_t*)filename, sizeof(filename));
01105 oh->cached.interpreter->stack->elements[resultStackPointer] = ((dir_delete(oh, filename)) ? oh->cached.true_object : oh->cached.false_object);
01106 }
01107
01108
01109 void prim_readConsole_from_into_starting_at(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01110 word_t n = object_to_smallint(args[1]), start = object_to_smallint(args[4]);
01111 struct ByteArray* bytes = (struct ByteArray*)args[3];
01112 word_t retval;
01113
01114 ASSURE_SMALLINT_ARG(1);
01115 ASSURE_SMALLINT_ARG(4);
01116
01117 retval = fread((char*)(byte_array_elements(bytes) + start), 1, n, stdin);
01118 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
01119
01120 }
01121
01122 void prim_read_from_into_starting_at(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01123 word_t handle = object_to_smallint(args[2]), n = object_to_smallint(args[1]), start = object_to_smallint(args[4]);
01124 struct ByteArray* bytes = (struct ByteArray*)args[3];
01125 word_t retval;
01126 ASSURE_SMALLINT_ARG(1);
01127 ASSURE_SMALLINT_ARG(4);
01128 retval = file_read(oh, handle, n, (char*)(byte_array_elements(bytes) + start));
01129 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
01130 }
01131
01132 void prim_write_to_from_starting_at(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01133 word_t handle = object_to_smallint(args[2]), n = object_to_smallint(args[1]), start = object_to_smallint(args[4]);
01134 struct ByteArray* bytes = (struct ByteArray*)args[3];
01135 word_t retval;
01136 ASSURE_SMALLINT_ARG(1);
01137 ASSURE_SMALLINT_ARG(4);
01138 retval = file_write(oh, handle, n, (char*)(byte_array_elements(bytes) + start));
01139 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
01140 }
01141
01142 void prim_reposition_to(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01143 word_t handle = object_to_smallint(args[1]), n = object_to_smallint(args[2]);
01144 word_t retval = file_seek(oh, handle, n);
01145 ASSURE_SMALLINT_ARG(1);
01146 ASSURE_SMALLINT_ARG(2);
01147 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
01148 }
01149
01150 void prim_positionOf(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01151 word_t handle = object_to_smallint(args[1]);
01152 word_t retval = file_tell(oh, handle);
01153 ASSURE_SMALLINT_ARG(1);
01154 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
01155 }
01156
01157 #pragma mark Directory
01158
01159 void prim_dir_open(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01160 struct ByteArray* buf = (struct ByteArray*)args[1];
01161 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(dir_open(oh, buf));
01162 }
01163
01164 void prim_dir_close(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01165 word_t handle = object_to_smallint(args[1]);
01166 ASSURE_SMALLINT_ARG(1);
01167
01168 dir_close(oh, handle);
01169 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01170 }
01171
01172 void prim_dir_read(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01173 word_t handle = object_to_smallint(args[1]);
01174 struct ByteArray* buf = (struct ByteArray*)args[2];
01175 word_t retval;
01176
01177 ASSURE_SMALLINT_ARG(1);
01178
01179 retval = dir_read(oh, handle, buf);
01180
01181 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(retval);
01182 }
01183
01184 void prim_dir_getcwd(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01185 struct ByteArray* buf = (struct ByteArray*)args[1];
01186 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(dir_getcwd(buf));
01187 }
01188
01189 void prim_dir_setcwd(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01190 struct ByteArray* buf = (struct ByteArray*)args[1];
01191 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(dir_setcwd(buf));
01192 }
01193
01194 #pragma mark Platform
01195
01196 void prim_bytesPerWord(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01197 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(sizeof(word_t));
01198 }
01199
01200 int slate_refresh_systeminfo(struct object_heap* oh) {
01201 return !(uname(&oh->platform_info));
01202 }
01203
01204 void prim_system_name(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01205 struct ByteArray* result;
01206 int resultLength;
01207 if (slate_refresh_systeminfo(oh)) {
01208 resultLength = strlen(oh->platform_info.nodename);
01209 result = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), strlen(oh->platform_info.nodename));
01210 copy_bytes_into((byte_t*)oh->platform_info.nodename, resultLength, result->elements);
01211 } else {
01212 result = (struct ByteArray*)oh->cached.nil;
01213 };
01214 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)result;
01215 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)result);
01216 }
01217
01218 void prim_system_release(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01219 struct ByteArray *result;
01220 int resultLength;
01221 if (slate_refresh_systeminfo(oh)) {
01222 resultLength = strlen(oh->platform_info.release);
01223 result = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), strlen(oh->platform_info.release));
01224 copy_bytes_into((byte_t*)oh->platform_info.release, resultLength, result->elements);
01225 } else {
01226 result = (struct ByteArray*)oh->cached.nil;
01227 };
01228 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)result;
01229 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)result);
01230 }
01231
01232 void prim_system_version(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01233 struct ByteArray *result;
01234 int resultLength;
01235 if (slate_refresh_systeminfo(oh)) {
01236 resultLength = strlen(oh->platform_info.version);
01237 result = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), strlen(oh->platform_info.version));
01238 copy_bytes_into((byte_t*)oh->platform_info.version, resultLength, result->elements);
01239 } else {
01240 result = (struct ByteArray*)oh->cached.nil;
01241 };
01242 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)result;
01243 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)result);
01244 }
01245
01246 void prim_system_platform(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01247 struct ByteArray *result;
01248 int resultLength;
01249 if (slate_refresh_systeminfo(oh)) {
01250 resultLength = strlen(oh->platform_info.sysname);
01251 result = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), strlen(oh->platform_info.sysname));
01252 copy_bytes_into((byte_t*)oh->platform_info.sysname, resultLength, result->elements);
01253 } else {
01254 result = (struct ByteArray*)oh->cached.nil;
01255 };
01256 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)result;
01257 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)result);
01258 }
01259
01260 void prim_system_machine(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01261 struct ByteArray *result;
01262 int resultLength;
01263 if (slate_refresh_systeminfo(oh)) {
01264 resultLength = strlen(oh->platform_info.machine);
01265 result = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), strlen(oh->platform_info.machine));
01266 copy_bytes_into((byte_t*)oh->platform_info.machine, resultLength, result->elements);
01267 } else {
01268 result = (struct ByteArray*)oh->cached.nil;
01269 };
01270 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)result;
01271 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)result);
01272 }
01273
01274 void prim_environment_removekey(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01275 struct Object *keyString = args[1];
01276 size_t keyLength = payload_size(keyString);
01277 char key[SLATE_FILE_NAME_LENGTH];
01278 memcpy(key, (char*)byte_array_elements((struct ByteArray*)keyString), keyLength);
01279 key[keyLength] = '\0';
01280 #ifdef WIN32
01281 SetEnvironmentVariable(key, "");
01282 #else
01283 unsetenv(key);
01284 #endif
01285 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01286 }
01287
01288 void prim_environment_atput(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01289 struct Object *keyString = args[1];
01290 struct Object *valueString = args[2];
01291 size_t keyLength = payload_size(keyString);
01292 size_t valueLength = payload_size(valueString);
01293 char key[SLATE_FILE_NAME_LENGTH], value[SLATE_FILE_NAME_LENGTH];
01294 int success;
01295 memcpy(key, (char*)byte_array_elements((struct ByteArray*)keyString), keyLength);
01296 key[keyLength] = '\0';
01297 memcpy(value, (char*)byte_array_elements((struct ByteArray*)valueString), valueLength);
01298 value[valueLength] = '\0';
01299 #ifdef WIN32
01300 success = SetEnvironmentVariable(key, value);
01301 #else
01302 success = setenv(key, value, 1);
01303 #endif
01304 oh->cached.interpreter->stack->elements[resultStackPointer] = (success ? oh->cached.false_object : oh->cached.true_object);
01305 }
01306
01307 void prim_isLittleEndian(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01308 int x = 1;
01309 char little_endian = *(char*)&x;
01310 oh->cached.interpreter->stack->elements[resultStackPointer] = ((little_endian == 1) ? oh->cached.true_object : oh->cached.false_object);
01311 }
01312
01313 void prim_system_execute(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01314 struct Object *commandString = args[1];
01315 size_t commandLength = payload_size(commandString);
01316 char command[SLATE_FILE_NAME_LENGTH];
01317 memcpy(command, (char*)byte_array_elements((struct ByteArray*)commandString), commandLength);
01318 command[commandLength] = '\0';
01319 oh->cached.interpreter->stack->elements[resultStackPointer] = (system(command) ? oh->cached.false_object : oh->cached.true_object);
01320 }
01321
01322 #pragma mark Time
01323
01324 #ifdef WIN32 // gettimeofday() ported to WIN32 for prim_timeSinceEpoch()
01325
01326 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
01327 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
01328 #else
01329 #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
01330 #endif
01331
01332 struct timezone
01333 {
01334 int tz_minuteswest;
01335 int tz_dsttime;
01336 };
01337
01338 int gettimeofday(struct timeval *tv, struct timezone *tz)
01339 {
01340 FILETIME ft;
01341 unsigned __int64 tmpres = 0;
01342 static int tzflag = 0;
01343
01344 if (NULL != tv)
01345 {
01346 GetSystemTimeAsFileTime(&ft);
01347
01348 tmpres |= ft.dwHighDateTime;
01349 tmpres <<= 32;
01350 tmpres |= ft.dwLowDateTime;
01351
01352 tmpres /= 10;
01353
01354 tmpres -= DELTA_EPOCH_IN_MICROSECS;
01355 tv->tv_sec = (long)(tmpres / 1000000UL);
01356 tv->tv_usec = (long)(tmpres % 1000000UL);
01357 }
01358
01359 if (NULL != tz)
01360 {
01361 if (!tzflag)
01362 {
01363 _tzset();
01364 tzflag++;
01365 }
01366 tz->tz_minuteswest = _timezone / 60;
01367 tz->tz_dsttime = _daylight;
01368 }
01369
01370 return 0;
01371 }
01372
01373 #endif
01374
01375 void prim_timeSinceEpoch(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01376 int64_t time;
01377 int i;
01378 struct ByteArray* timeArray;
01379 const int arraySize = 8;
01380
01381 timeArray = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), arraySize);
01382
01383 time = getTickCount();
01384
01385 for (i = 0; i < arraySize; i++) {
01386 timeArray->elements[i] = ((time >> (i * 8)) & 0xFF);
01387 }
01388
01389 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)timeArray;
01390 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)timeArray);
01391 }
01392
01393 void prim_addressOf(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01394 struct Object *handle=args[1], *offset=args[2];
01395 struct ByteArray* addressBuffer=(struct ByteArray*) args[3];
01396 ASSURE_SMALLINT_ARG(1);
01397 ASSURE_SMALLINT_ARG(2);
01398 if (object_is_smallint(handle) && object_is_smallint(offset) && (unsigned)byte_array_size(addressBuffer) >= sizeof(word_t)) {
01399 oh->cached.interpreter->stack->elements[resultStackPointer] =
01400 smallint_to_object(memarea_addressof(oh,
01401 (int)object_to_smallint(handle),
01402 (int)object_to_smallint(offset),
01403 byte_array_elements(addressBuffer)));
01404 } else {
01405 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01406 }
01407
01408 }
01409
01410 #pragma mark ExternalLibrary
01411
01412 void prim_library_open(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01413 struct Object *libname=args[1], *handle = args[2];
01414
01415 if (openExternalLibrary(oh, (struct ByteArray*)libname, (struct ByteArray*)handle)) {
01416 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01417 } else {
01418 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
01419 }
01420
01421 }
01422
01423 void prim_library_close(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01424 struct Object *handle=args[1];
01425
01426 if (closeExternalLibrary(oh, (struct ByteArray*) handle)) {
01427 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01428 } else {
01429 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
01430 }
01431
01432 }
01433
01434 void prim_procAddressOf(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01435 struct Object *handle=args[2], *symname=args[1];
01436 struct ByteArray* addressBuffer=(struct ByteArray*) args[3];
01437
01438 if (lookupExternalLibraryPrimitive(oh, (struct ByteArray*) handle, (struct ByteArray *) symname, addressBuffer)) {
01439 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01440 } else {
01441 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
01442 }
01443
01444 }
01445
01446 void prim_extlibError(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01447 struct ByteArray* messageBuffer=(struct ByteArray*) args[1];
01448
01449 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(readExternalLibraryError(messageBuffer));
01450 }
01451
01452 void prim_applyExternal(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01453
01454 oh->cached.interpreter->stack->elements[resultStackPointer] =
01455 applyExternalLibraryPrimitive(oh, (struct ByteArray*)args[1],
01456 (struct OopArray*)args[2],
01457 args[3],
01458 args[4],
01459 (struct OopArray*)args[5]);
01460
01461 }
01462
01463 #pragma mark MemoryArea
01464
01465 void prim_memory_new(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01466 struct Object *size=args[1];
01467 word_t handle;
01468
01469 if (!object_is_smallint(size)) {
01470 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01471 return;
01472 }
01473
01474 handle = (word_t)memarea_open(oh, object_to_smallint(size));
01475 if (handle >= 0) {
01476 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(handle);
01477 } else {
01478 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01479 }
01480
01481 }
01482
01483 void prim_memory_close(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01484
01485 struct Object* handle = args[1];
01486 if (object_is_smallint(handle)) {
01487 memarea_close(oh, object_to_smallint(handle));
01488 }
01489 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01490
01491 }
01492
01493 void prim_memory_size(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01494
01495 struct Object* handle = args[1];
01496 if (object_is_smallint(handle)) {
01497 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(memarea_sizeof(oh, object_to_smallint(handle)));
01498 } else {
01499 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01500 }
01501
01502 }
01503
01504 void prim_memory_addRef(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01505
01506 struct Object* handle = args[1];
01507 if (object_is_smallint(handle)) {
01508 memarea_addref(oh, object_to_smallint(handle));
01509 }
01510
01511 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01512
01513 }
01514
01515 void prim_memory_read(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01516
01517 struct ByteArray* buf = (struct ByteArray*)args[0];
01518 word_t amount = object_to_smallint(args[1]), startingAt = object_to_smallint(args[3]),
01519 handle = object_to_smallint(args[2]);
01520
01521 ASSURE_SMALLINT_ARG(1);
01522 ASSURE_SMALLINT_ARG(2);
01523 ASSURE_SMALLINT_ARG(3);
01524
01525 if (!memarea_handle_isvalid(oh, handle)
01526 || byte_array_size(buf) < amount
01527 || startingAt + amount >= oh->memory_sizes [handle]) {
01528 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(-1);
01529 return;
01530 }
01531
01532 oh->cached.interpreter->stack->elements[resultStackPointer] =
01533 smallint_to_object(memarea_write(oh, handle, startingAt, amount, byte_array_elements(buf)));
01534
01535 }
01536
01537 void prim_memory_write(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01538
01539 struct ByteArray* buf = (struct ByteArray*)args[0];
01540 word_t amount = object_to_smallint(args[1]), startingAt = object_to_smallint(args[3]),
01541 handle = object_to_smallint(args[2]);
01542
01543 ASSURE_SMALLINT_ARG(1);
01544 ASSURE_SMALLINT_ARG(2);
01545 ASSURE_SMALLINT_ARG(3);
01546
01547 if (!memarea_handle_isvalid(oh, handle)
01548 || byte_array_size(buf) < amount
01549 || startingAt + amount >= oh->memory_sizes [handle]) {
01550 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(-1);
01551 return;
01552 }
01553
01554 oh->cached.interpreter->stack->elements[resultStackPointer] =
01555 smallint_to_object(memarea_read(oh, handle, startingAt, amount, byte_array_elements(buf)));
01556
01557 }
01558
01559 void prim_memory_resizeTo(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01560
01561 struct Object* handle = args[1], *size = args[2];
01562 if (object_is_smallint(handle) && object_is_smallint(size)) {
01563 oh->cached.interpreter->stack->elements[resultStackPointer] =
01564 smallint_to_object(memarea_resize(oh, object_to_smallint(handle), object_to_smallint(size)));
01565
01566 } else {
01567 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01568 }
01569
01570 }
01571
01572 void prim_smallint_at_slot_named(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01573 struct Object* obj;
01574 struct Object* name;
01575 struct SlotEntry * se;
01576 struct Object * proto;
01577
01578 obj = args[0];
01579 name = args[1];
01580 proto = get_special(oh, SPECIAL_OOP_SMALL_INT_PROTO);
01581 se = slot_table_entry_for_name(oh, proto->map->slotTable, (struct Symbol*)name);
01582 if (se == NULL) {
01583 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SLOT_NOT_FOUND_NAMED), obj, name, NULL, resultStackPointer);
01584 } else {
01585 word_t offset = object_to_smallint(se->offset);
01586 oh->cached.interpreter->stack->elements[resultStackPointer] = object_slot_value_at_offset(proto, offset);
01587 }
01588
01589
01590 }
01591
01592 void prim_frame_pointer_of(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01593
01594 struct Interpreter* i = (struct Interpreter*)args[0];
01595 struct Symbol* selector = (struct Symbol*) args[1];
01596 struct CompiledMethod* method;
01597 word_t frame = i->framePointer;
01598
01599
01600
01601 while (frame > FUNCTION_FRAME_SIZE) {
01602 method = (struct CompiledMethod*) i->stack->elements[frame - FRAME_OFFSET_METHOD];
01603 method = method->method;
01604 if (method->selector == selector) {
01605 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(frame);
01606 return;
01607 }
01608 frame = object_to_smallint(i->stack->elements[frame - FRAME_OFFSET_PREVIOUS_FRAME_POINTER]);
01609 }
01610
01611 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01612
01613 }
01614
01615 #pragma mark Clone/Daemonize System
01616
01617 void prim_cloneSystem(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01618 #ifdef WIN32
01619 #pragma message("TODO WIN32 port forking/cloning the system")
01620 return;
01621 #else
01622 pid_t retval;
01623 int pipes[2];
01624 struct OopArray* array;
01625
01626
01627
01628 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pipes) == -1) {
01629 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01630 return;
01631 }
01632
01633 retval = fork2();
01634
01635 if (retval == (pid_t)-1) {
01636 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01637 return;
01638 }
01639
01640 array = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 2);
01641 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)array;
01642
01643 if (!retval) {
01644 array->elements[0] = oh->cached.false_object;
01645 array->elements[1] = smallint_to_object(pipes[0]);
01646 } else {
01647 array->elements[0] = oh->cached.true_object;
01648 array->elements[1] = smallint_to_object(pipes[1]);
01649 }
01650
01651 #endif
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664 #ifdef SLATE_DAEMONIZE
01665
01666
01667 #define DAEMON_NAME "slatedaemon"
01668
01669
01670 #define RUN_AS_USER "root"
01671
01672 static void child_handler(int signum) {
01673 switch(signum) {
01674 case SIGALRM: exit(EXIT_FAILURE); break;
01675 case SIGUSR1: exit(EXIT_SUCCESS); break;
01676 case SIGCHLD: exit(EXIT_FAILURE); break;
01677 }
01678 }
01679
01680 void prim_daemonizeSystem(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01681 const char* lock_filename = (char*)byte_array_elements((struct ByteArray*) args[1]);
01682 #ifdef WIN32
01683 #pragma message("TODO WIN32 port daemonizing a system")
01684 #else
01685 pid_t pid, sid, parent;
01686 int lfp = -1;
01687
01688
01689 if (getppid() == 1) return;
01690
01691
01692 if (lock_filename && lock_filename[0]) {
01693 lfp = open(lock_filename,O_RDWR|O_CREAT,0640);
01694 if (lfp < 0) {
01695 printf("Unable to create lock file %s, code=%d (%s)",
01696 lock_filename, errno, strerror(errno));
01697 exit(EXIT_FAILURE);
01698 }
01699 }
01700
01701
01702 if (getuid() == 0 || geteuid() == 0) {
01703 struct passwd *pw = getpwnam(RUN_AS_USER);
01704 if (pw) {
01705 if (!oh->quiet)
01706 printf("Setting user to " RUN_AS_USER);
01707 setuid(pw->pw_uid);
01708 }
01709 }
01710
01711
01712 signal(SIGCHLD,child_handler);
01713 signal(SIGUSR1,child_handler);
01714 signal(SIGALRM,child_handler);
01715
01716
01717 pid = fork();
01718 if (pid < 0) {
01719 printf("Unable to fork daemon, code=%d (%s)",
01720 errno, strerror(errno));
01721 exit(EXIT_FAILURE);
01722 }
01723
01724 if (pid > 0) {
01725
01726
01727
01728 alarm(2);
01729 pause();
01730
01731 exit(EXIT_FAILURE);
01732 }
01733
01734
01735 parent = getppid();
01736
01737
01738 signal(SIGCHLD,SIG_DFL);
01739 signal(SIGTSTP,SIG_IGN);
01740 signal(SIGTTOU,SIG_IGN);
01741 signal(SIGTTIN,SIG_IGN);
01742 signal(SIGHUP, SIG_IGN);
01743 signal(SIGTERM,SIG_DFL);
01744
01745
01746 umask(0);
01747
01748
01749 sid = setsid();
01750 if (sid < 0) {
01751 printf("Unable to create a new session, code %d (%s)",
01752 errno, strerror(errno));
01753 exit(EXIT_FAILURE);
01754 }
01755
01756
01757
01758 if ((chdir("/")) < 0) {
01759 printf("Unable to change directory to %s, code %d (%s)",
01760 "/", errno, strerror(errno));
01761 exit(EXIT_FAILURE);
01762 }
01763
01764
01765 freopen("/dev/null", "r", stdin);
01766 freopen("/dev/null", "w", stdout);
01767 freopen("/dev/null", "w", stderr);
01768
01769
01770 kill(parent, SIGUSR1);
01771 #endif
01772 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01773 }
01774
01775 #endif //SLATE_DAEMONIZE
01776
01777 #pragma mark VM invocation arguments
01778
01779
01780 void prim_run_args_into(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01781 struct ByteArray* arguments = (struct ByteArray*)args[1];
01782 oh->cached.interpreter->stack->elements[resultStackPointer] =
01783 smallint_to_object(write_args_into(oh, (char*)byte_array_elements(arguments), byte_array_size(arguments)));
01784
01785
01786 }
01787
01788 void prim_vmArgCount(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01789 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(oh->argcSaved);
01790 }
01791
01792 void prim_vmArg(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01793 word_t i;
01794 int len;
01795 struct ByteArray* array;
01796 ASSURE_SMALLINT_ARG(1);
01797 i = object_to_smallint(args[1]);
01798
01799 if (i >= 0 && i < oh->argcSaved) {
01800 len = strlen(oh->argvSaved[i]);
01801 array = heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), len);
01802 copy_bytes_into((byte_t*)oh->argvSaved[i], len, array->elements);
01803 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)array;
01804 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)array);
01805 } else {
01806 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01807 }
01808 }
01809
01810 void prim_environmentVariables(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01811 int i, len;
01812 word_t lenstr;
01813 Pinned<struct OopArray> array(oh);
01814
01815 len = 0;
01816 while (oh->envp[len]) len++;
01817
01818 array = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), len);
01819
01820 for (i = 0; i < len; i++) {
01821 lenstr = strlen(oh->envp[i]);
01822 array->elements[i] = (struct Object*) heap_clone_byte_array_sized(oh, get_special(oh, SPECIAL_OOP_BYTE_ARRAY_PROTO), lenstr);
01823 copy_bytes_into((byte_t*)oh->envp[i], lenstr, ((struct ByteArray*)array->elements[i])->elements);
01824 heap_store_into(oh, (struct Object*) array, (struct Object*) array->elements[i]);
01825 }
01826
01827 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)array;
01828 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)array);
01829 }
01830
01831
01832 void prim_startProfiling(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01833 if (oh->currentlyProfiling) {
01834 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
01835 return;
01836 }
01837
01838 profiler_start(oh);
01839 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01840 }
01841
01842 void prim_stopProfiling(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01843 Pinned<struct OopArray> array(oh);
01844 std::vector<Pinned<struct OopArray> > pinnedArrays;
01845 std::vector<Pinned<struct Object> > pinnedMethods;
01846 word_t k;
01847 if (!oh->currentlyProfiling) {
01848 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
01849 return;
01850 }
01851
01852
01853
01854
01855 heap_full_gc(oh);
01856
01857
01858 array = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO),
01859 oh->profiledMethods.size()*5);
01860
01861
01862 #ifdef GC_BUG_CHECK
01863 for (std::set<struct Object*>::iterator i = oh->profiledMethods.begin();
01864 i != oh->profiledMethods.end();
01865 i++) {
01866 assert(object_hash(*i) < ID_HASH_RESERVED);
01867 }
01868 #endif
01869
01870
01871
01872
01873 for (std::set<struct Object*>::iterator i = oh->profiledMethods.begin();
01874 i != oh->profiledMethods.end();
01875 i++) {
01876 Pinned<struct Object> m(oh, *i);
01877 pinnedMethods.push_back(m);
01878 }
01879
01880
01881 profiler_stop(oh);
01882
01883
01884 k = 0;
01885 for (std::set<struct Object*>::iterator i = oh->profiledMethods.begin();
01886 i != oh->profiledMethods.end();
01887 i++) {
01888 struct Object* method = *i;
01889 int m = 0;
01890 Pinned<struct OopArray> childCounts(oh, heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO),
01891 oh->profilerChildCallCount[method].size()*2));
01892 Pinned<struct OopArray> childTimes(oh, heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO),
01893 oh->profilerChildCallTime[method].size()*2));
01894
01895 m = 0;
01896 for (std::map<struct Object*,word_t>::iterator cci = oh->profilerChildCallCount[method].begin();
01897 cci != oh->profilerChildCallCount[method].end();
01898 cci++) {
01899 #ifdef GC_BUG_CHECK
01900 assert_good_object(oh, (*cci).first);
01901 #endif
01902 childCounts->elements[m++] = (*cci).first;
01903 childCounts->elements[m++] = smallint_to_object((*cci).second);
01904 }
01905 m = 0;
01906 for (std::map<struct Object*,word_t>::iterator cti = oh->profilerChildCallTime[method].begin();
01907 cti != oh->profilerChildCallTime[method].end();
01908 cti++) {
01909 #ifdef GC_BUG_CHECK
01910 assert_good_object(oh, (*cti).first);
01911 #endif
01912 childTimes->elements[m++] = (*cti).first;
01913 childTimes->elements[m++] = smallint_to_object((*cti).second);
01914 }
01915
01916 pinnedArrays.push_back(childCounts);
01917 pinnedArrays.push_back(childTimes);
01918
01919 #ifdef GC_BUG_CHECK
01920 assert_good_object(oh, method);
01921 assert_good_object(oh, childCounts);
01922 assert_good_object(oh, childTimes);
01923 #endif
01924
01925 array->elements[k++] = method;
01926 array->elements[k++] = smallint_to_object(oh->profilerCallCounts[method]);
01927 array->elements[k++] = smallint_to_object(oh->profilerSelfTime[method]);
01928 array->elements[k++] = childCounts;
01929 array->elements[k++] = childTimes;
01930 }
01931
01932 oh->profiledMethods.clear();
01933 pinnedArrays.clear();
01934 pinnedMethods.clear();
01935
01936 oh->cached.interpreter->stack->elements[resultStackPointer] = array;
01937 heap_store_into(oh, (struct Object*)oh->cached.interpreter->stack, (struct Object*)array);
01938
01939 heap_full_gc(oh);
01940
01941 }
01942
01943 void prim_profilerStatistics(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01944 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01945 }
01946
01947
01948
01949 void prim_heap_gc(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01950 if (!oh->quiet) {
01951 printf("Collecting garbage...\n");
01952 };
01953 heap_full_gc(oh);
01954 }
01955
01956 void prim_save_image(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
01957 char nameString [SLATE_FILE_NAME_LENGTH];
01958 struct slate_image_header sih;
01959 struct Object* name = args[1];
01960 size_t nameLength = payload_size(name);
01961 FILE * imageFile;
01962
01963 word_t totalSize, forwardPointerEntryCount;
01964 byte_t* memoryStart;
01965 struct Object *writeObject;
01966 struct ForwardPointerEntry* forwardPointers;
01967
01968
01969
01970
01971
01972
01973
01974
01975 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
01976
01977 if (nameLength >= sizeof(nameString)) {
01978
01979
01980 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01981 return;
01982 }
01983 memcpy(nameString, (char*)byte_array_elements((struct ByteArray*)name), nameLength);
01984 nameString[nameLength] = '\0';
01985
01986 imageFile = fopen(nameString, "wb");
01987 if (!imageFile) {
01988
01989
01990 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.nil;
01991
01992 return;
01993 }
01994 printf("Saving image to %s\n", nameString);
01995 heap_full_gc(oh);
01996 totalSize = oh->memoryOldSize + oh->memoryYoungSize;
01997 forwardPointerEntryCount = ((totalSize / 4) + sizeof(struct ForwardPointerEntry) - 1) / sizeof(struct ForwardPointerEntry);
01998 memoryStart = (byte_t*)calloc(1, totalSize);
01999 writeObject = (struct Object*)memoryStart;
02000 forwardPointers = (struct ForwardPointerEntry*)calloc(1, forwardPointerEntryCount * sizeof(struct ForwardPointerEntry));
02001 assert(memoryStart != NULL);
02002 copy_used_objects(oh, &writeObject, oh->memoryOld, oh->memoryOldSize, forwardPointers, forwardPointerEntryCount);
02003 copy_used_objects(oh, &writeObject, oh->memoryYoung, oh->memoryYoungSize, forwardPointers, forwardPointerEntryCount);
02004 totalSize = (byte_t*)writeObject - memoryStart;
02005 adjust_object_fields_with_table(oh, memoryStart, totalSize, forwardPointers, forwardPointerEntryCount);
02006 adjust_oop_pointers_from(oh, 0-(word_t)memoryStart, memoryStart, totalSize);
02007 sih.magic = SLATE_IMAGE_MAGIC;
02008 sih.size = totalSize;
02009 sih.next_hash = heap_new_hash(oh);
02010 sih.special_objects_oop = (byte_t*) (forward_pointer_hash_get(forwardPointers, forwardPointerEntryCount, (struct Object*)oh->special_objects_oop)->toObj) - memoryStart;
02011 sih.current_dispatch_id = oh->current_dispatch_id;
02012
02013 if (fwrite(&sih, sizeof(struct slate_image_header), 1, imageFile) != 1
02014 || fwrite(memoryStart, 1, totalSize, imageFile) != (size_t)totalSize) {
02015 fprintf(stderr, "Error writing image!\n");
02016 }
02017 fclose(imageFile);
02018 free(forwardPointers);
02019 free(memoryStart);
02020
02021 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
02022
02023
02024
02025
02026 }
02027
02028 void prim_exit(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02029
02030
02031 ASSURE_SMALLINT_ARG(1);
02032 if (!oh->quiet) {
02033 printf("Slate process %d exiting...\n", getpid());
02034 }
02035 exit(object_to_smallint(args[1]));
02036 }
02037
02038 #pragma mark SmallInteger
02039
02040 void prim_equals(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02041 oh->cached.interpreter->stack->elements[resultStackPointer] = (args[0] == args[1])?oh->cached.true_object:oh->cached.false_object;
02042 }
02043
02044 void prim_less_than(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02045
02046 ASSURE_SMALLINT_ARG(0);
02047 ASSURE_SMALLINT_ARG(1);
02048 oh->cached.interpreter->stack->elements[resultStackPointer] =
02049 (object_to_smallint(args[0])<object_to_smallint(args[1]))?oh->cached.true_object:oh->cached.false_object;
02050 }
02051
02052 void prim_bitand(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02053 ASSURE_SMALLINT_ARG(0);
02054 ASSURE_SMALLINT_ARG(1);
02055 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)((word_t)args[0] & (word_t)args[1]);
02056 }
02057 void prim_bitor(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02058 ASSURE_SMALLINT_ARG(0);
02059 ASSURE_SMALLINT_ARG(1);
02060 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)((word_t)args[0] | (word_t)args[1]);
02061 }
02062 void prim_bitxor(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02063 ASSURE_SMALLINT_ARG(0);
02064 ASSURE_SMALLINT_ARG(1);
02065 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)(((word_t)args[0] ^ (word_t)args[1])|SMALLINT_MASK);
02066 }
02067 void prim_bitnot(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02068 ASSURE_SMALLINT_ARG(0);
02069 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)(~((word_t)args[0]) | SMALLINT_MASK);
02070 }
02071
02072 void prim_smallIntegerMinimum(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02073 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)(((word_t)1<< (sizeof(word_t)*8-1))|1);
02074 }
02075
02076 void prim_smallIntegerMaximum(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02077 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)LONG_MAX;
02078 }
02079
02080 void prim_plus(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02081 struct Object* x = args[0];
02082 struct Object* y = args[1];
02083 word_t z = object_to_smallint(x) + object_to_smallint(y);
02084
02085
02086 ASSURE_SMALLINT_ARG(0);
02087 ASSURE_SMALLINT_ARG(1);
02088
02089
02090 if (smallint_fits_object(z)) {
02091 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(z);
02092 } else {
02093 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_ADD_OVERFLOW), x, y, NULL, resultStackPointer);
02094 }
02095 }
02096
02097 void prim_exponent(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02098 struct ByteArray* x = (struct ByteArray*)args[0];
02099 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object((*(word_t*)float_part(x) >> FLOAT_EXPONENT_OFFSET) & 0xFF);
02100
02101 }
02102
02103 void prim_significand(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02104 struct ByteArray* x = (struct ByteArray*)args[0];
02105 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(*(word_t*)float_part(x) & FLOAT_SIGNIFICAND);
02106
02107 }
02108
02109 void prim_withSignificand_exponent(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02110
02111 word_t significand = object_to_smallint(args[1]), exponent = object_to_smallint(args[2]);
02112 struct ByteArray* f = heap_new_float(oh);
02113 *((word_t*)float_part(f)) = significand | exponent << FLOAT_EXPONENT_OFFSET;
02114
02115 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)f;
02116
02117 }
02118
02119
02120 void prim_bitshift(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02121 word_t bits = object_to_smallint(args[0]);
02122 word_t shift = object_to_smallint(args[1]);
02123 word_t z;
02124
02125 ASSURE_SMALLINT_ARG(0);
02126 ASSURE_SMALLINT_ARG(1);
02127
02128 if (shift >= 0) {
02129 if (shift >= __WORDSIZE && bits != 0) {
02130 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_BIT_SHIFT_OVERFLOW), args[0], args[1], NULL, resultStackPointer);
02131 return;
02132 }
02133
02134 z = bits << shift;
02135
02136 if (!smallint_fits_object(z) || z >> shift != bits) {
02137 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_BIT_SHIFT_OVERFLOW), args[0], args[1], NULL, resultStackPointer);
02138 return;
02139 }
02140
02141 } else if (shift <= -__WORDSIZE) {
02142 z = bits >> (__WORDSIZE-1);
02143 } else {
02144 z = bits >> -shift;
02145 }
02146
02147 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(z);
02148
02149 }
02150
02151
02152 void prim_minus(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02153 struct Object* x = args[0];
02154 struct Object* y = args[1];
02155 word_t z = object_to_smallint(x) - object_to_smallint(y);
02156
02157 ASSURE_SMALLINT_ARG(0);
02158 ASSURE_SMALLINT_ARG(1);
02159
02160 if (smallint_fits_object(z)) {
02161 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(z);
02162 } else {
02163 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_SUBTRACT_OVERFLOW), x, y, NULL, resultStackPointer);
02164 }
02165 }
02166
02167
02168 void prim_times(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02169 word_t x = object_to_smallint(args[0]);
02170 word_t y = object_to_smallint(args[1]);
02171 word_t z = x * y;
02172
02173
02174 ASSURE_SMALLINT_ARG(0);
02175 ASSURE_SMALLINT_ARG(1);
02176
02177
02178 if (y != 0 && (z / y != x || !smallint_fits_object(z))) {
02179 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_MULTIPLY_OVERFLOW), args[0], args[1], NULL, resultStackPointer);
02180 } else {
02181 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(z);
02182 }
02183 }
02184
02185
02186 void prim_quo(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02187 struct Object* x = args[0];
02188 struct Object* y = args[1];
02189
02190 ASSURE_SMALLINT_ARG(0);
02191 ASSURE_SMALLINT_ARG(1);
02192
02193 if (object_to_smallint(y) == 0) {
02194 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_DIVIDE_BY_ZERO), x, y, NULL, resultStackPointer);
02195 } else {
02196 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object(object_to_smallint(x) / object_to_smallint(y));
02197 }
02198 }
02199
02200 #pragma mark Float
02201
02202 void prim_float_equals(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02203 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02204 if (*float_part(x) == *float_part(y)) {
02205 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
02206 } else {
02207 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
02208 }
02209 }
02210
02211 void prim_float_less_than(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02212 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02213 if (*float_part(x) < *float_part(y)) {
02214 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.true_object;
02215 } else {
02216 oh->cached.interpreter->stack->elements[resultStackPointer] = oh->cached.false_object;
02217 }
02218 }
02219
02220 void prim_float_plus(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02221 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02222 struct ByteArray* z = heap_new_float(oh);
02223 *float_part(z) = *float_part(x) + *float_part(y);
02224 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02225 }
02226
02227 void prim_float_minus(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02228 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02229 struct ByteArray* z = heap_new_float(oh);
02230 *float_part(z) = *float_part(x) - *float_part(y);
02231 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02232 }
02233
02234
02235 void prim_float_times(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02236 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02237 struct ByteArray* z = heap_new_float(oh);
02238 *float_part(z) = *float_part(x) * *float_part(y);
02239 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02240 }
02241
02242 void prim_float_divide(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02243 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02244 struct ByteArray* z = heap_new_float(oh);
02245 *float_part(z) = *float_part(x) / *float_part(y);
02246 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02247 }
02248
02249 void prim_float_raisedTo(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02250 struct ByteArray *x = (struct ByteArray*)args[0], *y = (struct ByteArray*)args[1];
02251 struct ByteArray* z = heap_new_float(oh);
02252 *float_part(z) = pow(*float_part(x), *float_part(y));
02253 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02254 }
02255
02256 void prim_float_ln(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02257 struct ByteArray *x = (struct ByteArray*)args[0];
02258 struct ByteArray* z = heap_new_float(oh);
02259 *float_part(z) = log(*float_part(x));
02260 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02261 }
02262
02263 void prim_float_exp(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02264 struct ByteArray *x = (struct ByteArray*)args[0];
02265 struct ByteArray* z = heap_new_float(oh);
02266 *float_part(z) = exp(*float_part(x));
02267 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02268 }
02269
02270 void prim_float_sin(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02271 struct ByteArray *x = (struct ByteArray*)args[0];
02272 struct ByteArray* z = heap_new_float(oh);
02273 *float_part(z) = sin(*float_part(x));
02274 oh->cached.interpreter->stack->elements[resultStackPointer] = (struct Object*)z;
02275 }
02276
02277 void prim_objectPointerAddress(struct object_heap* oh, struct Object* args[], word_t arity, struct OopArray* opts, word_t resultStackPointer) {
02278 oh->cached.interpreter->stack->elements[resultStackPointer] = smallint_to_object((word_t)args[1]);
02279 }
02280
02281 void (*primitives[]) (struct object_heap* oh, struct Object* args[], word_t n, struct OopArray* opts, word_t resultStackPointer) = {
02282
02283 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,
02284 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,
02285 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,
02286 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,
02287 prim_bitxor, prim_bitnot, prim_bitshift, prim_plus, prim_minus, prim_times, prim_quo, prim_interrupt, prim_initializeThreadOn, prim_frame_pointer_of,
02288 prim_fixme, prim_fixme, prim_fixme, prim_heap_gc, prim_bytesPerWord, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme,
02289 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,
02290 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_dir_open,
02291 prim_dir_close, prim_dir_read, prim_dir_getcwd, prim_dir_setcwd, prim_significand, prim_exponent, prim_withSignificand_exponent, prim_float_equals, prim_float_less_than, prim_float_plus,
02292 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,
02293 prim_fixme, prim_fixme, prim_fixme, prim_memory_new, prim_memory_close, prim_memory_addRef, prim_memory_write, prim_memory_read, prim_memory_size, prim_memory_resizeTo,
02294 prim_addressOf, prim_library_open, prim_library_close, prim_procAddressOf, prim_extlibError, prim_applyExternal, prim_timeSinceEpoch, prim_cloneSystem, prim_readFromPipe, prim_writeToPipe,
02295 prim_selectOnReadPipesFor, prim_selectOnWritePipesFor, prim_closePipe, prim_socketCreate, prim_socketListen, prim_socketAccept, prim_socketBind, prim_socketConnect, prim_socketCreateIP, prim_smallIntegerMinimum,
02296 prim_smallIntegerMaximum, prim_socketGetError, prim_getAddrInfo, prim_getAddrInfoResult, prim_freeAddrInfoResult, prim_vmArgCount, prim_vmArg, prim_environmentVariables, prim_environment_atput, prim_environment_removekey,
02297 prim_isLittleEndian, prim_system_name, prim_system_release, prim_system_version, prim_system_platform, prim_system_machine, prim_system_execute, prim_startProfiling, prim_stopProfiling, prim_profilerStatistics,
02298 prim_file_delete, prim_file_touch, prim_file_rename_to, prim_file_information, prim_dir_make, prim_dir_rename_to, prim_dir_delete, prim_objectPointerAddress, prim_fixme, prim_fixme,
02299 prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme,
02300 prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme, prim_fixme,
02301
02302 };