00001 #include "slate.hpp"
00002
00003
00004 void interpreter_grow_stack(struct object_heap* oh, struct Interpreter* i, word_t minimum) {
00005
00006 struct OopArray * newStack;
00007
00008
00009 do {
00010 i->stackSize *= 2;
00011 } while (i->stackSize < minimum);
00012 newStack = (struct OopArray *) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), i->stackSize);
00013 copy_words_into((word_t*) i->stack->elements, i->stackPointer, (word_t*) newStack->elements);
00014
00015 i -> stack = newStack;
00016
00017 }
00018
00019 void interpreter_stack_allocate(struct object_heap* oh, struct Interpreter* i, word_t n) {
00020
00021 if (i->stackPointer + n > i->stackSize) {
00022 interpreter_grow_stack(oh, i, i->stackPointer + n);
00023 assert(i->stackPointer + n <= i->stackSize);
00024 }
00025 i->stackPointer += n;
00026
00027 #ifdef PRINT_DEBUG_STACK_PUSH
00028 printf("stack allocate, new stack pointer: %" PRIdPTR "\n", i->stackPointer);
00029 #endif
00030
00031 }
00032
00033 void interpreter_stack_push(struct object_heap* oh, struct Interpreter* i, struct Object* value) {
00034
00035 #ifdef PRINT_DEBUG_STACK_PUSH
00036 printf("Stack push at %" PRIdPTR " (fp=%" PRIdPTR "): ", i->stackPointer, i->framePointer); print_type(oh, value);
00037 #endif
00038 if (!object_is_smallint(value)) {
00039 assert(object_hash(value) < ID_HASH_RESERVED);
00040 }
00041 if (i->stackPointer == i->stackSize) {
00042 interpreter_grow_stack(oh, i, 0);
00043 }
00044 heap_store_into(oh, (struct Object*)i->stack, value);
00045 i->stack->elements[i -> stackPointer] = value;
00046 i->stackPointer++;
00047 }
00048
00049 struct Object* interpreter_stack_pop(struct object_heap* oh, struct Interpreter* i) {
00050
00051 if (i -> stackPointer == 0) {
00052
00053 assert(0);
00054 }
00055
00056 i->stackPointer = i->stackPointer - 1;
00057
00058 {
00059 struct Object* o = i->stack->elements[i->stackPointer];
00060 #ifdef PRINT_DEBUG_STACK_POINTER
00061 printf("popping from stack, new stack pointer: %" PRIdPTR "\n", i->stackPointer);
00062
00063 #endif
00064 return o;
00065 }
00066
00067 }
00068
00069 void interpreter_stack_pop_amount(struct object_heap* oh, struct Interpreter* i, word_t amount) {
00070
00071 if (i -> stackPointer - amount < 0) {
00072
00073 assert(0);
00074 }
00075
00076 i->stackPointer = i->stackPointer - amount;
00077
00078 }
00079
00080
00081 void unhandled_signal(struct object_heap* oh, struct Symbol* selector, word_t n, struct Object* args[]) {
00082 word_t i;
00083 printf("Unhandled signal: "); print_symbol(selector); printf(" with %" PRIdPTR " arguments: \n", n);
00084 for (i = 0; i<n; i++) {
00085 printf("arg[%" PRIdPTR "] = ", i);
00086 print_detail(oh, args[i]);
00087 }
00088 printf("partial stack: \n");
00089
00090 print_backtrace(oh);
00091 assert(0);
00092 exit(1);
00093
00094 }
00095
00096
00097 void interpreter_signal(struct object_heap* oh, struct Interpreter* i, struct Object* signal, struct Object* args[], word_t n, struct OopArray* opts, word_t resultStackPointer) {
00098
00099 struct Closure* method;
00100 struct Symbol* selector = (struct Symbol*)signal;
00101 struct MethodDefinition* def = method_dispatch_on(oh, selector, args, n, NULL);
00102 if (def == NULL) {
00103 unhandled_signal(oh, selector, n, args);
00104 }
00105
00106
00107
00108 method = (struct Closure*)def->method;
00109 interpreter_apply_to_arity_with_optionals(oh, i, method, args, n, opts, resultStackPointer);
00110 }
00111
00112 void interpreter_signal_with(struct object_heap* oh, struct Interpreter* i, struct Object* signal, struct Object* arg, struct OopArray* opts, word_t resultStackPointer) {
00113
00114 struct Object* args[1];
00115 args[0] = arg;
00116 interpreter_signal(oh, i, signal, args, 1, opts, resultStackPointer);
00117 }
00118
00119
00120 void interpreter_signal_with_with(struct object_heap* oh, struct Interpreter* i, struct Object* signal, struct Object* arg, struct Object* arg2, struct OopArray* opts, word_t resultStackPointer) {
00121 struct Object* args[2];
00122 args[0] = arg;
00123 args[1] = arg2;
00124 interpreter_signal(oh, i, signal, args, 2, opts, resultStackPointer);
00125 }
00126
00127 void interpreter_signal_with_with_with(struct object_heap* oh, struct Interpreter* i, struct Object* signal, struct Object* arg, struct Object* arg2, struct Object* arg3, struct OopArray* opts, word_t resultStackPointer) {
00128 struct Object* args[3];
00129 args[0] = arg;
00130 args[1] = arg2;
00131 args[2] = arg3;
00132 interpreter_signal(oh, i, signal, args, 3, opts, resultStackPointer);
00133 }
00134
00135 bool_t interpreter_dispatch_optional_keyword(struct object_heap* oh, struct Interpreter * i, struct Object* key, struct Object* value) {
00136
00137 struct OopArray* optKeys = i->method->optionalKeywords;
00138
00139 word_t optKey, size = array_size(optKeys);
00140
00141 for (optKey = 0; optKey < size; optKey++) {
00142 if (optKeys->elements[optKey] == key) {
00143 if (i->method->heapAllocate == oh->cached.true_object) {
00144 heap_store_into(oh, (struct Object*)i->lexicalContext, value);
00145 i->lexicalContext->variables[object_to_smallint(i->method->inputVariables) + optKey] = value;
00146 } else {
00147 heap_store_into(oh, (struct Object*)i->stack, value);
00148 i->stack->elements[i->framePointer + object_to_smallint(i->method->inputVariables) + optKey] = value;
00149 }
00150 return TRUE;
00151 }
00152 }
00153
00154
00155 return FALSE;
00156 }
00157
00158 void interpreter_dispatch_optionals(struct object_heap* oh, struct Interpreter * i, struct OopArray* opts) {
00159
00160 word_t index, size = array_size(opts);
00161 for (index = 0; index < size; index += 2) {
00162 interpreter_dispatch_optional_keyword(oh, i, opts->elements[index], opts->elements[index+1]);
00163 }
00164
00165 }
00166
00167
00168 void interpreter_apply_to_arity_with_optionals(struct object_heap* oh, struct Interpreter * i, struct Closure * closure,
00169 struct Object* args[], word_t n, struct OopArray* opts,
00170 word_t resultStackPointer) {
00171
00172
00173 word_t inputs, framePointer, j, beforeCallStackPointer;
00174 struct Object** vars;
00175 Pinned<struct LexicalContext> lexicalContext(oh);
00176 Pinned<struct CompiledMethod> method(oh);
00177
00178
00179 #ifdef PRINT_DEBUG
00180 printf("apply to arity %" PRIdPTR "\n", n);
00181 #endif
00182
00183 struct Object* traitsWindow = closure->base.map->delegates->elements[0];
00184 if (traitsWindow != oh->cached.compiled_method_window && traitsWindow != oh->cached.closure_method_window) {
00185 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_TYPE_ERROR_ON), (struct Object*)closure, NULL, resultStackPointer);
00186 return;
00187 }
00188 method = closure->method;
00189 inputs = object_to_smallint(method->inputVariables);
00190
00191 method->callCount = smallint_to_object(object_to_smallint(method->callCount) + 1);
00192
00193
00194 assert(n <= 16);
00195
00196 #ifndef SLATE_DISABLE_METHOD_OPTIMIZATION
00197
00198 if (oh->automaticallyInline
00199 && method->callCount > (struct Object*)CALLEE_OPTIMIZE_AFTER
00200 && method->isInlined == oh->cached.false_object) {
00201 method_optimize(oh, method);
00202 }
00203 if (method->nextInlineAtCallCount != oh->cached.nil &&
00204 (word_t)method->nextInlineAtCallCount < (word_t)method->callCount) {
00205 method_optimize(oh, method);
00206 method->nextInlineAtCallCount = smallint_to_object(object_to_smallint(method->callCount) * 2);
00207
00208 }
00209 #endif
00210
00211 if (n < inputs || (n > inputs && method->restVariable != oh->cached.true_object)) {
00212 Pinned<struct OopArray> argsArray(oh);
00213 argsArray = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), n);
00214 copy_words_into(args, n, argsArray->elements);
00215 interpreter_signal_with_with(oh, i, get_special(oh, SPECIAL_OOP_WRONG_INPUTS_TO), (struct Object*) argsArray, (struct Object*)method, NULL, resultStackPointer);
00216 return;
00217 }
00218
00219
00220 framePointer = i->stackPointer + FUNCTION_FRAME_SIZE;
00221
00222 beforeCallStackPointer = i->stackPointer;
00223
00224 if (method->heapAllocate == oh->cached.true_object) {
00225 lexicalContext = (struct LexicalContext*) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_LEXICAL_CONTEXT_PROTO), object_to_smallint(method->localVariables));
00226 lexicalContext->framePointer = smallint_to_object(framePointer);
00227 interpreter_stack_allocate(oh, i, FUNCTION_FRAME_SIZE + object_to_smallint(method->registerCount));
00228 vars = &lexicalContext->variables[0];
00229 for (j = 0; j < inputs; j++) {
00230 heap_store_into(oh, (struct Object*)lexicalContext, args[j]);
00231 }
00232
00233 } else {
00234 lexicalContext = (struct LexicalContext*) oh->cached.nil;
00235 interpreter_stack_allocate(oh, i, FUNCTION_FRAME_SIZE + object_to_smallint(method->localVariables) + object_to_smallint(method->registerCount));
00236 vars = &i->stack->elements[framePointer];
00237 for (j = 0; j < inputs; j++) {
00238 heap_store_into(oh, (struct Object*)i->stack, args[j]);
00239 }
00240 }
00241
00242
00243
00244
00245 copy_words_into(args, inputs, vars);
00246 i->stack->elements[framePointer - FRAME_OFFSET_BEFORE_CALL_STACK_POINTER] = smallint_to_object(beforeCallStackPointer);
00247 i->stack->elements[framePointer - FRAME_OFFSET_RESULT_STACK_POINTER] = smallint_to_object(resultStackPointer);
00248 i->stack->elements[framePointer - FRAME_OFFSET_CODE_POINTER] = smallint_to_object(i->codePointer);
00249 i->stack->elements[framePointer - FRAME_OFFSET_METHOD] = (struct Object*) closure;
00250 i->stack->elements[framePointer - FRAME_OFFSET_LEXICAL_CONTEXT] = (struct Object*) lexicalContext;
00251 i->stack->elements[framePointer - FRAME_OFFSET_PREVIOUS_FRAME_POINTER] = smallint_to_object(i->framePointer);
00252
00253 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)closure);
00254 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)lexicalContext);
00255
00256 if (oh->currentlyProfiling) {
00257 profiler_enter_method(oh, (struct Object*)i->closure, (struct Object*)closure, 1);
00258 }
00259
00260 i->framePointer = framePointer;
00261 i->method = method;
00262 i->closure = closure;
00263 i->lexicalContext = lexicalContext;
00264
00265 heap_store_into(oh, (struct Object*)i, (struct Object*)lexicalContext);
00266 heap_store_into(oh, (struct Object*)i, (struct Object*)method);
00267 heap_store_into(oh, (struct Object*)i, (struct Object*)closure);
00268
00269 i->codeSize = array_size(method->code);
00270 i->codePointer = 0;
00271 fill_words_with(((word_t*)vars)+inputs, object_to_smallint(method->localVariables) - inputs, (word_t)oh->cached.nil);
00272
00273 if (n > inputs) {
00274 Pinned<struct OopArray> restArgs(oh);
00275 restArgs = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), n - inputs);
00276 copy_words_into(args+inputs, n - inputs, restArgs->elements);
00277 vars[inputs+array_size(method->optionalKeywords)] = (struct Object*) restArgs;
00278 heap_store_into(oh, (struct Object*)lexicalContext, (struct Object*)restArgs);
00279 } else {
00280 if (method->restVariable == oh->cached.true_object) {
00281 vars[inputs+array_size(method->optionalKeywords)] = get_special(oh, SPECIAL_OOP_ARRAY_PROTO);
00282 }
00283 }
00284 if (opts != NULL) {
00285 interpreter_dispatch_optionals(oh, i, opts);
00286 }
00287 }
00288
00289
00290 void send_to_through_arity_with_optionals(struct object_heap* oh,
00291 struct Symbol* selector, struct Object* args[],
00292 struct Object* dispatchers[], word_t arity, struct OopArray* opts,
00293 word_t resultStackPointer) {
00294 Pinned<struct OopArray> argsArray(oh);
00295 Pinned<struct Closure> method(oh);
00296 Pinned<struct Object> traitsWindow(oh);
00297 Pinned<struct MethodDefinition> def(oh);
00298 Pinned<struct CompiledMethod> callerMethod(oh);
00299 callerMethod = oh->cached.interpreter->method;
00300
00301
00302 assert(arity <= 16);
00303
00304 def = NULL;
00305
00306 #ifndef SLATE_DISABLE_PIC_LOOKUP
00307 word_t addToPic = FALSE;
00308
00309 if (object_is_old(oh, (struct Object*)callerMethod)
00310 && (callerMethod->callCount > (struct Object*)CALLER_PIC_SETUP_AFTER
00311 || object_is_smallint(callerMethod->nextInlineAtCallCount))) {
00312 if ((struct Object*)callerMethod->calleeCount == oh->cached.nil) {
00313 method_pic_setup(oh, callerMethod);
00314 addToPic = TRUE;
00315 } else {
00316 def = method_pic_find_callee(oh, callerMethod, selector, arity, dispatchers);
00317
00318 if ((struct Object*)def==NULL) {
00319 addToPic = TRUE;
00320 #ifdef PRINT_DEBUG_PIC_HITS
00321 printf("PIC miss\n");
00322 #endif
00323
00324 }
00325 else {
00326 #ifdef PRINT_DEBUG_PIC_HITS
00327 printf("PIC hit\n");
00328 #endif
00329 }
00330 }
00331
00332 }
00333 #endif
00334
00335 if ((struct Object*)def == NULL) {
00336 def = method_dispatch_on(oh, selector, dispatchers, arity, NULL);
00337 } else {
00338 #ifdef PRINT_DEBUG_PIC_HITS
00339 printf("Using PIC over dispatch\n");
00340 #endif
00341 }
00342 Pinned<struct OopArray> optsArray(oh);
00343 if ((struct Object*)def == NULL) {
00344
00345 argsArray = (struct OopArray*) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), arity);
00346 copy_words_into((word_t*)dispatchers, arity, (word_t*)&argsArray->elements[0]);
00347
00348 if (opts != NULL) {
00349 optsArray = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 2);
00350 optsArray->elements[0] = get_special(oh, SPECIAL_OOP_OPTIONALS);
00351 optsArray->elements[1] = (struct Object*)opts;
00352 heap_store_into(oh, (struct Object*)optsArray, (struct Object*)opts);
00353 }
00354
00355 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_NOT_FOUND_ON), (struct Object*)selector, (struct Object*)argsArray, optsArray, resultStackPointer);
00356
00357 return;
00358 }
00359
00360
00361 #ifndef SLATE_DISABLE_PIC_LOOKUP
00362 if (addToPic) method_pic_add_callee(oh, callerMethod, def, arity, dispatchers);
00363 #endif
00364
00365 method = (struct Closure*)def->method;
00366 traitsWindow = method->base.map->delegates->elements[0];
00367 if (traitsWindow == oh->cached.primitive_method_window) {
00368 #ifdef PRINT_DEBUG
00369 printf("calling primitive: %" PRIdPTR "\n", object_to_smallint(((struct PrimitiveMethod*)method)->index));
00370 #endif
00371
00372
00373 Pinned<struct OopArray> pinnedStack(oh);
00374 pinnedStack = oh->cached.interpreter->stack;
00375 primitives[object_to_smallint(((struct PrimitiveMethod*)method)->index)](oh, args, arity, opts, resultStackPointer);
00376 } else if (traitsWindow == oh->cached.compiled_method_window || traitsWindow == oh->cached.closure_method_window) {
00377 interpreter_apply_to_arity_with_optionals(oh, oh->cached.interpreter, method, args, arity, opts, resultStackPointer);
00378 } else {
00379 Pinned<struct OopArray> optsArray(oh);
00380 argsArray = (struct OopArray*) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), arity);
00381 copy_words_into((word_t*)dispatchers, arity, (word_t*)&argsArray->elements[0]);
00382
00383 if (opts != NULL) {
00384 optsArray = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 2);
00385 optsArray->elements[0] = get_special(oh, SPECIAL_OOP_OPTIONALS);
00386 optsArray->elements[1] = (struct Object*)opts;
00387 heap_store_into(oh, (struct Object*)optsArray, (struct Object*)opts);
00388 }
00389 interpreter_signal_with_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_APPLY_TO), def->method, (struct Object*)argsArray, optsArray, resultStackPointer);
00390 }
00391
00392 }
00393
00394
00395 bool_t interpreter_return_result(struct object_heap* oh, struct Interpreter* i, word_t context_depth, struct Object* result, word_t prevCodePointer) {
00396
00397
00398
00399
00400
00401
00402 word_t framePointer;
00403 word_t ensureHandlers;
00404 word_t resultStackPointer;
00405
00406 #ifdef PRINT_DEBUG_FUNCALL
00407 printf("interpreter_return_result BEFORE\n");
00408 printf("stack pointer: %" PRIdPTR "\n", i->stackPointer);
00409 printf("frame pointer: %" PRIdPTR "\n", i->framePointer);
00410 print_stack_types(oh, 16);
00411 #endif
00412
00413
00414 if (context_depth == 0) {
00415 framePointer = i->framePointer;
00416 } else {
00417 struct LexicalContext* targetContext = i->closure->lexicalWindow[context_depth-1];
00418 framePointer = object_to_smallint(targetContext->framePointer);
00419 if (framePointer > i->stackPointer || (struct Object*)targetContext != i->stack->elements[framePointer - FRAME_OFFSET_LEXICAL_CONTEXT]) {
00420 resultStackPointer = (word_t)i->stack->elements[framePointer - FRAME_OFFSET_RESULT_STACK_POINTER]>>1;
00421 interpreter_signal_with_with(oh, i, get_special(oh, SPECIAL_OOP_MAY_NOT_RETURN_TO),
00422 (struct Object*)i->closure, (struct Object*) targetContext, NULL, resultStackPointer);
00423 return 1;
00424 }
00425 }
00426
00427 resultStackPointer = (word_t)i->stack->elements[framePointer - FRAME_OFFSET_RESULT_STACK_POINTER]>>1;
00428
00429
00430
00431 if (result != NULL) {
00432 #ifdef PRINT_DEBUG_STACK
00433 printf("setting stack[%" PRIdPTR "] = ", resultStackPointer); print_object(result);
00434 #endif
00435
00436 i->stack->elements[resultStackPointer] = result;
00437 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)result);
00438 }
00439
00440 ensureHandlers = object_to_smallint(i->ensureHandlers);
00441 if (framePointer <= ensureHandlers) {
00442 Pinned<struct Object> ensureHandler(oh);
00443 ensureHandler = i->stack->elements[ensureHandlers+1];
00444 #ifdef PRINT_DEBUG_ENSURE
00445 printf("current ensure handlers at %" PRIdPTR "\n", object_to_smallint(i->ensureHandlers));
00446 #endif
00447 assert(object_to_smallint(i->stack->elements[ensureHandlers]) < 0x1000000);
00448 i->ensureHandlers = i->stack->elements[ensureHandlers];
00449 #ifdef PRINT_DEBUG_ENSURE
00450 printf("reset ensure handlers at %" PRIdPTR "\n", object_to_smallint(i->ensureHandlers));
00451 #endif
00452
00453 interpreter_stack_push(oh, i, smallint_to_object(i->stackPointer));
00454 interpreter_stack_push(oh, i, smallint_to_object(resultStackPointer));
00455 interpreter_stack_push(oh, i, smallint_to_object(prevCodePointer));
00456 interpreter_stack_push(oh, i, get_special(oh, SPECIAL_OOP_ENSURE_MARKER));
00457 interpreter_stack_push(oh, i, oh->cached.nil);
00458 interpreter_stack_push(oh, i, smallint_to_object(i->framePointer));
00459 i->codePointer = 0;
00460 i->framePointer = i->stackPointer;
00461
00462
00463
00464
00465
00466 if (oh->currentlyProfiling) {
00467 profiler_enter_method(oh, (struct Object*)i->closure, (struct Object*)i->stack->elements[i->framePointer - FRAME_OFFSET_METHOD], 1);
00468 }
00469
00470
00471
00472 {
00473 interpreter_apply_to_arity_with_optionals(oh, i, (struct Closure*) ensureHandler, NULL, 0, NULL, resultStackPointer);
00474 }
00475 return 1;
00476 }
00477 i->stackPointer = object_to_smallint(i->stack->elements[framePointer - FRAME_OFFSET_BEFORE_CALL_STACK_POINTER]);
00478 i->framePointer = object_to_smallint(i->stack->elements[framePointer - FRAME_OFFSET_PREVIOUS_FRAME_POINTER]);
00479 if (i->framePointer < FUNCTION_FRAME_SIZE) {
00480
00481 exit(0);
00482 return 0;
00483 }
00484
00485 if (oh->currentlyProfiling) {
00486 profiler_enter_method(oh, (struct Object*)i->closure, (struct Object*)i->stack->elements[i->framePointer - FRAME_OFFSET_METHOD], 0);
00487 }
00488
00489
00490 i->codePointer = object_to_smallint(i->stack->elements[framePointer - FRAME_OFFSET_CODE_POINTER]);
00491 i->lexicalContext = (struct LexicalContext*) i->stack->elements[i->framePointer - FRAME_OFFSET_LEXICAL_CONTEXT];
00492 i->closure = (struct Closure*) i->stack->elements[i->framePointer - FRAME_OFFSET_METHOD];
00493 heap_store_into(oh, (struct Object*)i, (struct Object*)i->lexicalContext);
00494 heap_store_into(oh, (struct Object*)i, (struct Object*)i->closure);
00495 i->method = i->closure->method;
00496 heap_store_into(oh, (struct Object*)i, (struct Object*)i->closure->method);
00497
00498 i->codeSize = array_size(i->method->code);
00499
00500 #ifdef PRINT_DEBUG_FUNCALL
00501 printf("interpreter_return_result AFTER\n");
00502 printf("stack pointer: %" PRIdPTR "\n", i->stackPointer);
00503 printf("frame pointer: %" PRIdPTR "\n", i->framePointer);
00504 print_stack_types(oh, 16);
00505 #endif
00506
00507
00508 return 1;
00509
00510 }
00511
00512
00513
00514
00515
00516 void interpreter_resend_message(struct object_heap* oh, struct Interpreter* i, word_t n, word_t resultStackPointer) {
00517
00518 word_t framePointer;
00519 Pinned<struct LexicalContext> lexicalContext(oh);
00520 Pinned<struct Object> barrier(oh), traitsWindow(oh);
00521 struct Object** args;
00522 Pinned<struct Symbol> selector(oh);
00523 Pinned<struct OopArray> argsArray(oh);
00524 Pinned<struct Closure> method(oh);
00525 Pinned<struct CompiledMethod> resender(oh);
00526 Pinned<struct MethodDefinition> def(oh);
00527
00528 if (n == 0) {
00529 framePointer = i->framePointer;
00530 lexicalContext = i->lexicalContext;
00531 } else {
00532 lexicalContext = i->closure->lexicalWindow[n-1];
00533 framePointer = object_to_smallint(lexicalContext->framePointer);
00534
00535 assert((struct Object*)lexicalContext == i->stack->elements[framePointer - FRAME_OFFSET_LEXICAL_CONTEXT]);
00536 }
00537
00538 barrier = i->stack->elements[framePointer - FRAME_OFFSET_METHOD];
00539 resender = ((struct Closure*) barrier)->method;
00540 args = (resender->heapAllocate == oh->cached.true_object)? lexicalContext->variables : &i->stack->elements[framePointer];
00541
00542
00543 selector = resender->selector;
00544 n = object_to_smallint(resender->inputVariables);
00545 assert(n <= 16);
00546 std::vector<Pinned<struct Object> > pinnedArgs(n, Pinned<struct Object>(oh));
00547 for (int k = 0; k < n; k++) pinnedArgs[k] = args[k];
00548
00549 def = method_dispatch_on(oh, selector, args, n, barrier);
00550 pinnedArgs[0] = args[0];
00551 if ((struct Object*)def == NULL) {
00552 argsArray = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), n);
00553 copy_words_into((word_t*)args, n, (word_t*)argsArray->elements);
00554 interpreter_signal_with_with_with(oh, i, get_special(oh, SPECIAL_OOP_NOT_FOUND_ON),
00555 (struct Object*)selector, (struct Object*)argsArray, (struct Object*) resender, NULL, resultStackPointer);
00556 return;
00557
00558 }
00559
00560 method = (struct Closure*)def->method;
00561 traitsWindow = method->base.map->delegates->elements[0];
00562 if (traitsWindow == oh->cached.primitive_method_window) {
00563 #ifdef PRINT_DEBUG
00564 printf("calling primitive: %" PRIdPTR "\n", object_to_smallint(((struct PrimitiveMethod*)method)->index));
00565 #endif
00566 primitives[object_to_smallint(((struct PrimitiveMethod*)method)->index)](oh, args, n, NULL, resultStackPointer);
00567 return;
00568 }
00569
00570 if (traitsWindow == oh->cached.compiled_method_window || traitsWindow == oh->cached.closure_method_window) {
00571 Pinned<struct OopArray> optKeys(oh);
00572 optKeys = resender->optionalKeywords;
00573 interpreter_apply_to_arity_with_optionals(oh, i, method, args, n, NULL, resultStackPointer);
00574 if (i->closure == method) {
00575 word_t optKey;
00576 for (optKey = 0; optKey < array_size(optKeys); optKey++) {
00577 struct Object* optVal = args[n+optKey];
00578 if (optVal != oh->cached.nil) {
00579 interpreter_dispatch_optional_keyword(oh, i, optKeys->elements[optKey], optVal);
00580 }
00581 }
00582 }
00583
00584 } else {
00585 Pinned<struct OopArray> optsArray(oh);
00586 Pinned<struct OopArray> optKeys(oh);
00587 Pinned<struct OopArray> signalOpts(oh);
00588 word_t optKey;
00589
00590 optKeys = resender->optionalKeywords;
00591 optsArray = (struct OopArray*) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO),
00592 array_size(optKeys) * 2);
00593
00594 for (optKey = 0; optKey < array_size(optKeys); optKey++) {
00595 struct Object* optVal = args[n+optKey];
00596 optsArray->elements[optKey*2] = optKeys->elements[optKey];
00597 optsArray->elements[optKey*2+1] = optVal;
00598 }
00599
00600 signalOpts = (struct OopArray*) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), 2);
00601 signalOpts->elements[0] = get_special(oh, SPECIAL_OOP_OPTIONALS);
00602 signalOpts->elements[1] = (struct Object*) optsArray;
00603 heap_store_into(oh, (struct Object*)signalOpts, (struct Object*)optsArray);
00604
00605 argsArray = (struct OopArray*) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), n);
00606 copy_words_into((word_t*) args, n, (word_t*) argsArray->elements);
00607
00608 interpreter_signal_with_with(oh, i, get_special(oh, SPECIAL_OOP_APPLY_TO),
00609 def->method, (struct Object*) argsArray, signalOpts, resultStackPointer);
00610
00611 }
00612
00613
00614 }
00615
00616
00617
00618 void interpreter_branch_keyed(struct object_heap* oh, struct Interpreter * i, struct OopArray* table, struct Object* oop) {
00619
00620 word_t tableSize;
00621 word_t hash;
00622 word_t index;
00623
00624 if (oop_is_object((word_t)oop))
00625 hash = object_hash(oop);
00626 else
00627 hash = object_to_smallint(oop);
00628 tableSize = array_size(table);
00629 hash = hash & (tableSize - 2);
00630 index = hash;
00631
00632
00633 while (index < tableSize)
00634 {
00635 struct Object* offset;
00636 struct Object* key;
00637
00638 key = table->elements[index];
00639 offset = table->elements[index + 1];
00640 if (offset == oh->cached.nil)
00641 {
00642 return;
00643 }
00644 if (oop == key)
00645 {
00646 i->codePointer = i->codePointer + object_to_smallint(offset);
00647
00648 return;
00649 }
00650 index = index + 2;
00651 }
00652 index = 0;
00653 while (index < hash)
00654 {
00655 struct Object* offset;
00656 struct Object* key;
00657
00658 key = table->elements[index];
00659 offset = table->elements[index + 1];
00660 if (offset == oh->cached.nil)
00661 {
00662 return;
00663 }
00664 if (oop == key)
00665 {
00666 i->codePointer = i->codePointer + object_to_smallint(offset);
00667
00668 return;
00669 }
00670 index = index + 2;
00671 }
00672
00673
00674 }
00675
00676
00677 void interpret(struct object_heap* oh) {
00678
00679
00680 unsigned long int instruction_counter = 0;
00681 #if SLATE_CUSTOM_BREAKPOINT
00682 word_t myBreakpoint = 0;
00683 #endif
00684
00685 #ifdef PRINT_DEBUG
00686 printf("Interpret: img:%p size:%" PRIdPTR " spec:%p next:%" PRIdPTR "\n",
00687 (void*)oh->memoryOld, oh->memoryOldSize, (void*)oh->special_objects_oop, oh->lastHash);
00688 printf("Special oop: "); print_object((struct Object*)oh->special_objects_oop);
00689 #endif
00690
00691 cache_specials(oh);
00692 std::vector<Pinned<struct Object> > pinnedObjects(6, Pinned<struct Object>(oh));
00693 pinnedObjects[0] = (struct Object*) oh->cached.interpreter;
00694 pinnedObjects[1] = (struct Object*) oh->cached.true_object;
00695 pinnedObjects[2] = (struct Object*) oh->cached.false_object;
00696 pinnedObjects[3] = (struct Object*) oh->cached.primitive_method_window;
00697 pinnedObjects[4] = (struct Object*) oh->cached.compiled_method_window;
00698 pinnedObjects[5] = (struct Object*) oh->cached.closure_method_window;
00699
00700 #ifdef PRINT_DEBUG
00701 printf("Interpreter stack: "); print_object((struct Object*)oh->cached.interpreter);
00702 printf("Interpreter stack size: %" PRIdPTR "\n", oh->cached.interpreter->stackSize);
00703 printf("Interpreter stack pointer: %" PRIdPTR "\n", oh->cached.interpreter->stackPointer);
00704 printf("Interpreter frame pointer: %" PRIdPTR "\n", oh->cached.interpreter->framePointer);
00705 #endif
00706
00707
00708 if (oh->cached.interpreter->framePointer == FUNCTION_FRAME_SIZE
00709 && oh->cached.interpreter->stackPointer == FUNCTION_FRAME_SIZE
00710 && oh->cached.interpreter->stackSize == 16) {
00711 interpreter_stack_allocate(oh, oh->cached.interpreter, object_to_smallint(oh->cached.interpreter->method->registerCount));
00712 }
00713
00714 for (;;) {
00715 word_t op, prevPointer;
00716 struct Interpreter* i;
00717 cache_specials(oh);
00718 i = oh->cached.interpreter;
00719 pinnedObjects[0] = (struct Object*) oh->cached.interpreter;
00720
00721
00722
00723 for(;;) {
00724
00725 if (oh->interrupt_flag) {
00726 oh->interrupt_flag = 0;
00727 break;
00728 }
00729
00730 if (globalInterrupt) {
00731 printf("\nInterrupting...\n");
00732 interpreter_signal_with(oh, oh->cached.interpreter, get_special(oh, SPECIAL_OOP_TYPE_ERROR_ON), oh->cached.nil, NULL, object_to_smallint(i->stack->elements[i->framePointer - FRAME_OFFSET_RESULT_STACK_POINTER]));
00733 globalInterrupt = 0;
00734 }
00735
00736 #ifdef SLATE_CUSTOM_BREAKPOINT
00737 if (instruction_counter > 11475843) {
00738 myBreakpoint++;
00739 }
00740 #endif
00741
00742 instruction_counter++;
00743 prevPointer = i->codePointer;
00744 op = (word_t)i->method->code->elements[i->codePointer];
00745 #ifdef PRINT_DEBUG_CODE_POINTER
00746 printf("(%" PRIdPTR "/%" PRIdPTR ") %" PRIdPTR " ", i->codePointer, i->codeSize, op>>1);
00747 #endif
00748 i->codePointer++;
00749
00750 switch (op) {
00751
00752 case OP_SEND:
00753 {
00754 word_t result, arity;
00755 int k;
00756 Pinned<struct Object> selector(oh);
00757 struct Object* argsArray[16], *pinnedArgs[16];
00758 result = SSA_NEXT_PARAM_SMALLINT;
00759 selector = SSA_NEXT_PARAM_OBJECT;
00760 arity = SSA_NEXT_PARAM_SMALLINT;
00761
00762
00763 #ifdef PRINT_DEBUG_OPCODES
00764 printf("send message fp: %" PRIdPTR ", result: %" PRIdPTR ", arity: %" PRIdPTR ", message: ", i->framePointer, result, arity);
00765 print_type(oh, selector);
00766 #endif
00767 assert(arity <= 16);
00768
00769 HEAP_READ_AND_PIN_ARGS(k, arity, argsArray, pinnedArgs);
00770
00771 send_to_through_arity_with_optionals(oh, (struct Symbol*)selector, argsArray, argsArray, arity, NULL, i->framePointer + result);
00772
00773 HEAP_UNPIN_ARGS(k, pinnedArgs);
00774
00775 break;
00776 }
00777 case OP_SEND_MESSAGE_WITH_OPTS:
00778 {
00779 word_t result, arity, optsArrayReg;
00780 int k;
00781 Pinned<struct Object> selector(oh);
00782 struct Object* argsArray[16], *pinnedArgs[16];
00783 Pinned<struct OopArray> optsArray(oh);
00784 result = SSA_NEXT_PARAM_SMALLINT;
00785 selector = SSA_NEXT_PARAM_OBJECT;
00786 arity = SSA_NEXT_PARAM_SMALLINT;
00787 optsArrayReg = SSA_NEXT_PARAM_SMALLINT;
00788 optsArray = (struct OopArray*)SSA_REGISTER(optsArrayReg);
00789
00790 #ifdef PRINT_DEBUG_OPCODES
00791 printf("send message with opts fp: %" PRIdPTR ", result: %" PRIdPTR " arity: %" PRIdPTR ", opts: %" PRIdPTR ", message: ", i->framePointer, result, arity, optsArrayReg);
00792 print_type(oh, selector);
00793 #endif
00794 assert(arity <= 16);
00795
00796 HEAP_READ_AND_PIN_ARGS(k, arity, argsArray, pinnedArgs);
00797
00798 send_to_through_arity_with_optionals(oh, (struct Symbol*)selector, argsArray, argsArray,
00799 arity, optsArray,
00800 i->framePointer + result);
00801
00802 HEAP_UNPIN_ARGS(k, pinnedArgs);
00803
00804 break;
00805 }
00806 case OP_NEW_ARRAY_WITH:
00807 {
00808 word_t result, size, k;
00809 Pinned<struct OopArray> array(oh);
00810 result = SSA_NEXT_PARAM_SMALLINT;
00811 size = SSA_NEXT_PARAM_SMALLINT;
00812
00813 #ifdef PRINT_DEBUG_OPCODES
00814 printf("new array, result: %" PRIdPTR ", size: %" PRIdPTR "\n", result, size);
00815 #endif
00816 array = heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_ARRAY_PROTO), size);
00817 for (k = 0; k < size; k++) {
00818 array->elements[k] = SSA_REGISTER(SSA_NEXT_PARAM_SMALLINT);
00819 }
00820 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)array);
00821 #ifdef PRINT_DEBUG_STACK
00822 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(result)); print_object((struct Object*)array);
00823 #endif
00824 ASSERT_VALID_REGISTER(result);
00825 SSA_REGISTER(result) = (struct Object*) array;
00826 break;
00827 }
00828 case OP_NEW_CLOSURE:
00829 {
00830 word_t result;
00831 Pinned<struct CompiledMethod> block(oh);
00832 Pinned<struct Closure> newClosure(oh);
00833 result = SSA_NEXT_PARAM_SMALLINT;
00834 block = (struct CompiledMethod*)SSA_NEXT_PARAM_OBJECT;
00835 #ifdef PRINT_DEBUG_OPCODES
00836 printf("new closure, result: %" PRIdPTR ", block", result);
00837 print_type(oh, (struct Object*)block);
00838 #endif
00839 if ((struct CompiledMethod *) i->closure == i->method) {
00840 newClosure = (struct Closure *) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_CLOSURE_PROTO), 1);
00841 } else {
00842 word_t inheritedSize;
00843
00844 inheritedSize = object_array_size((struct Object *) i->closure);
00845 newClosure = (struct Closure *) heap_clone_oop_array_sized(oh, get_special(oh, SPECIAL_OOP_CLOSURE_PROTO), inheritedSize+1);
00846 copy_words_into((word_t *) i->closure->lexicalWindow, inheritedSize, (word_t*) newClosure->lexicalWindow + 1);
00847 }
00848 newClosure->lexicalWindow[0] = i->lexicalContext;
00849 newClosure->method = block;
00850 heap_store_into(oh, (struct Object*)newClosure, (struct Object*)i->lexicalContext);
00851 #if 1
00852 if (object_is_free((struct Object*)block)) {
00853
00854 }
00855 #endif
00856 heap_store_into(oh, (struct Object*)newClosure, (struct Object*)block);
00857 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)newClosure);
00858 #ifdef PRINT_DEBUG_STACK
00859 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(result)); print_object((struct Object*)newClosure);
00860 #endif
00861 ASSERT_VALID_REGISTER(result);
00862 SSA_REGISTER(result) = (struct Object*) newClosure;
00863 break;
00864 }
00865 case OP_LOAD_LITERAL:
00866 {
00867 word_t destReg;
00868 Pinned<struct Object> literal(oh);
00869 destReg = SSA_NEXT_PARAM_SMALLINT;
00870 literal = SSA_NEXT_PARAM_OBJECT;
00871 #ifdef PRINT_DEBUG_OPCODES
00872 printf("load literal into reg %" PRIdPTR ", value: ", destReg);
00873 print_type(oh, literal);
00874 #endif
00875 heap_store_into(oh, (struct Object*)i->stack, literal);
00876 #ifdef PRINT_DEBUG_STACK
00877 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(destReg)); print_object((struct Object*)literal);
00878 #endif
00879 ASSERT_VALID_REGISTER(destReg);
00880 SSA_REGISTER(destReg) = literal;
00881 break;
00882 }
00883 case OP_RESEND_MESSAGE:
00884 {
00885 word_t resultRegister, lexicalOffset;
00886 resultRegister = SSA_NEXT_PARAM_SMALLINT;
00887 lexicalOffset = SSA_NEXT_PARAM_SMALLINT;
00888 #ifdef PRINT_DEBUG_OPCODES
00889 printf("resend message reg %" PRIdPTR ", offset: %" PRIdPTR "\n", resultRegister, lexicalOffset);
00890 #endif
00891 interpreter_resend_message(oh, i, lexicalOffset, i->framePointer + resultRegister);
00892 break;
00893 }
00894 case OP_LOAD_VARIABLE:
00895 {
00896 word_t var;
00897 var = SSA_NEXT_PARAM_SMALLINT;
00898 #ifdef PRINT_DEBUG_OPCODES
00899 printf("load var %" PRIdPTR "\n", var);
00900 #endif
00901 if (i->method->heapAllocate == oh->cached.true_object) {
00902 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)i->lexicalContext);
00903 #ifdef PRINT_DEBUG_STACK
00904 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(var)); print_object(i->lexicalContext->variables[var]);
00905 #endif
00906 ASSERT_VALID_REGISTER(var);
00907 SSA_REGISTER(var) = i->lexicalContext->variables[var];
00908 }
00909 #ifdef PRINT_DEBUG_OPCODES
00910 printf("var val =");
00911 print_type(oh, SSA_REGISTER(var));
00912 #endif
00913
00914 break;
00915 }
00916 case OP_STORE_VARIABLE:
00917 {
00918 word_t var;
00919 var = SSA_NEXT_PARAM_SMALLINT;
00920 #ifdef PRINT_DEBUG_OPCODES
00921 printf("store var %" PRIdPTR "\n", var);
00922 #endif
00923 if (i->method->heapAllocate == oh->cached.true_object) {
00924 heap_store_into(oh, (struct Object*)i->lexicalContext, (struct Object*)i->stack);
00925 i->lexicalContext->variables[var] = SSA_REGISTER(var);
00926 }
00927
00928 #ifdef PRINT_DEBUG_OPCODES
00929 printf("var val =");
00930 print_type(oh, SSA_REGISTER(var));
00931 #endif
00932 break;
00933 }
00934 case OP_LOAD_FREE_VARIABLE:
00935 {
00936 word_t destReg, lexOffset, varIndex;
00937 destReg = SSA_NEXT_PARAM_SMALLINT;
00938 lexOffset = SSA_NEXT_PARAM_SMALLINT;
00939 varIndex = SSA_NEXT_PARAM_SMALLINT;
00940 #ifdef PRINT_DEBUG_OPCODES
00941 printf("load free var to: %" PRIdPTR ", lexoffset: %" PRIdPTR ", index: %" PRIdPTR "\n", destReg, lexOffset, varIndex);
00942 #endif
00943 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)i->closure->lexicalWindow[lexOffset-1]);
00944 #ifdef PRINT_DEBUG_STACK
00945 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(destReg)); print_object(i->closure->lexicalWindow[lexOffset-1]->variables[varIndex]);
00946 #endif
00947 ASSERT_VALID_REGISTER(destReg);
00948 SSA_REGISTER(destReg) = i->closure->lexicalWindow[lexOffset-1]->variables[varIndex];
00949
00950 #ifdef PRINT_DEBUG_OPCODES
00951 printf("var val =");
00952 print_type(oh, SSA_REGISTER(destReg));
00953 #endif
00954 break;
00955 }
00956 case OP_STORE_FREE_VARIABLE:
00957 {
00958 word_t srcReg, lexOffset, varIndex;
00959 lexOffset = SSA_NEXT_PARAM_SMALLINT;
00960 varIndex = SSA_NEXT_PARAM_SMALLINT;
00961 srcReg = SSA_NEXT_PARAM_SMALLINT;
00962 #ifdef PRINT_DEBUG_OPCODES
00963 printf("store free var from: %" PRIdPTR ", lexoffset: %" PRIdPTR ", index: %" PRIdPTR "\n", srcReg, lexOffset, varIndex);
00964 #endif
00965 heap_store_into(oh, (struct Object*)i->closure->lexicalWindow[lexOffset-1], (struct Object*)i->stack);
00966 i->closure->lexicalWindow[lexOffset-1]->variables[varIndex] = SSA_REGISTER(srcReg);
00967
00968 #ifdef PRINT_DEBUG_OPCODES
00969 printf("var val =");
00970 print_type(oh, SSA_REGISTER(srcReg));
00971 #endif
00972 break;
00973 }
00974 case OP_MOVE_REGISTER:
00975 {
00976 word_t destReg, srcReg;
00977 destReg = SSA_NEXT_PARAM_SMALLINT;
00978 srcReg = SSA_NEXT_PARAM_SMALLINT;
00979
00980 #ifdef PRINT_DEBUG_OPCODES
00981 printf("move reg %" PRIdPTR ", %" PRIdPTR "\n", destReg, srcReg);
00982 #endif
00983 heap_store_into(oh, (struct Object*)i->stack, SSA_REGISTER(srcReg));
00984 #ifdef PRINT_DEBUG_STACK
00985 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(destReg)); print_object(SSA_REGISTER(srcReg));
00986 #endif
00987 ASSERT_VALID_REGISTER(destReg);
00988 SSA_REGISTER(destReg) = SSA_REGISTER(srcReg);
00989 break;
00990 }
00991 case OP_IS_NIL:
00992 {
00993 word_t srcReg, resultReg;
00994 resultReg = SSA_NEXT_PARAM_SMALLINT;
00995 srcReg = SSA_NEXT_PARAM_SMALLINT;
00996 ASSERT_VALID_REGISTER(resultReg);
00997 SSA_REGISTER(resultReg) = (SSA_REGISTER(srcReg) == oh->cached.nil) ? oh->cached.true_object : oh->cached.false_object;
00998 break;
00999 }
01000 case OP_IS_IDENTICAL_TO:
01001 {
01002 word_t destReg, srcReg, resultReg;
01003 resultReg = SSA_NEXT_PARAM_SMALLINT;
01004 destReg = SSA_NEXT_PARAM_SMALLINT;
01005 srcReg = SSA_NEXT_PARAM_SMALLINT;
01006
01007 #ifdef PRINT_DEBUG_OPCODES
01008 printf("is identical %" PRIdPTR ", %" PRIdPTR "\n", destReg, srcReg);
01009 #endif
01010 ASSERT_VALID_REGISTER(resultReg);
01011
01012 SSA_REGISTER(resultReg) = (SSA_REGISTER(destReg) == SSA_REGISTER(srcReg)) ? oh->cached.true_object : oh->cached.false_object;
01013 #ifdef PRINT_DEBUG_STACK
01014 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(resultReg)); print_object(SSA_REGISTER(resultReg));
01015 #endif
01016 break;
01017 }
01018 case OP_BRANCH_KEYED:
01019 {
01020 word_t tableReg, keyReg;
01021 keyReg = SSA_NEXT_PARAM_SMALLINT;
01022 tableReg = SSA_NEXT_PARAM_SMALLINT;
01023
01024 Pinned<struct OopArray> table(oh), key(oh);
01025
01026
01027 #ifdef PRINT_DEBUG_OPCODES
01028 printf("branch keyed: %" PRIdPTR "/%" PRIdPTR "\n", tableReg, keyReg);
01029 #endif
01030 table = (struct OopArray*)SSA_REGISTER(tableReg);
01031 key = (struct OopArray*)SSA_REGISTER(keyReg);
01032
01033 interpreter_branch_keyed(oh, i, table, key);
01034 break;
01035 }
01036 case OP_BRANCH_IF_TRUE:
01037 {
01038 word_t condReg, offset;
01039 Pinned<struct Object> val(oh);
01040 condReg = SSA_NEXT_PARAM_SMALLINT;
01041 offset = SSA_NEXT_PARAM_SMALLINT - 1;
01042
01043 val = SSA_REGISTER(condReg);
01044
01045 #ifdef PRINT_DEBUG_OPCODES
01046 printf("branch if true: %" PRIdPTR ", offset: %" PRIdPTR ", val: ", condReg, offset);
01047 print_type(oh, val);
01048 #endif
01049 if (val == oh->cached.true_object) {
01050 i->codePointer = i->codePointer + offset;
01051 } else {
01052 if (val != oh->cached.false_object) {
01053 i->codePointer = i->codePointer - 3;
01054 interpreter_signal_with(oh, i, get_special(oh, SPECIAL_OOP_NOT_A_BOOLEAN), val, NULL, condReg );
01055 }
01056 }
01057 break;
01058 }
01059 case OP_BRANCH_IF_FALSE:
01060 {
01061 word_t condReg, offset;
01062 Pinned<struct Object> val(oh);
01063 condReg = SSA_NEXT_PARAM_SMALLINT;
01064 offset = SSA_NEXT_PARAM_SMALLINT - 1;
01065
01066 val = SSA_REGISTER(condReg);
01067
01068 #ifdef PRINT_DEBUG_OPCODES
01069 printf("branch if false: %" PRIdPTR ", offset: %" PRIdPTR ", val: ", condReg, offset);
01070 print_type(oh, val);
01071 #endif
01072 if (val == oh->cached.false_object) {
01073 i->codePointer = i->codePointer + offset;
01074 } else {
01075 if (val != oh->cached.true_object) {
01076 i->codePointer = i->codePointer - 3;
01077 interpreter_signal_with(oh, i, get_special(oh, SPECIAL_OOP_NOT_A_BOOLEAN), val, NULL, condReg );
01078 }
01079 }
01080 break;
01081 }
01082 case OP_JUMP_TO:
01083 {
01084 word_t offset;
01085 offset = SSA_NEXT_PARAM_SMALLINT - 1;
01086 assert(offset < 20000 && offset > -20000);
01087 #ifdef PRINT_DEBUG_OPCODES
01088 printf("jump to offset: %" PRIdPTR "\n", offset);
01089 #endif
01090 i->codePointer = i->codePointer + offset;
01091
01092 break;
01093 }
01094 case OP_LOAD_ENVIRONMENT:
01095 {
01096 word_t next_param;
01097 next_param = SSA_NEXT_PARAM_SMALLINT;
01098 #ifdef PRINT_DEBUG_OPCODES
01099 printf("load environment into reg %" PRIdPTR ", value: ", next_param);
01100 print_type(oh, i->method->environment);
01101 #endif
01102 heap_store_into(oh, (struct Object*)i->stack, (struct Object*)i->method->environment);
01103 ASSERT_VALID_REGISTER(next_param);
01104 SSA_REGISTER(next_param) = i->method->environment;
01105 #ifdef PRINT_DEBUG_STACK
01106 printf("%" PRIuPTR "u: setting stack[%" PRIdPTR "] = ", instruction_counter, REG_STACK_POINTER(next_param)); print_object(SSA_REGISTER(next_param));
01107 #endif
01108 break;
01109 }
01110 case OP_RETURN_REGISTER:
01111 {
01112 word_t reg;
01113 reg = SSA_NEXT_PARAM_SMALLINT;
01114 #ifdef PRINT_DEBUG_OPCODES
01115 printf("return reg %" PRIdPTR ", value: ", reg);
01116 print_type(oh, SSA_REGISTER(reg));
01117 #endif
01118 #ifdef PRINT_DEBUG_STACK
01119 printf("%" PRIuPTR "u: ", instruction_counter);
01120 #endif
01121 ASSERT_VALID_REGISTER(reg);
01122 Pinned<struct Object> result(oh);
01123 result = SSA_REGISTER(reg);
01124 interpreter_return_result(oh, i, 0, result, prevPointer);
01125 #ifdef PRINT_DEBUG_OPCODES
01126 printf("in function: \n");
01127 print_type(oh, (struct Object*)i->method);
01128 #endif
01129 break;
01130 }
01131 case OP_RESUME:
01132 {
01133 PRINTOP("op: resume\n");
01134
01135
01136
01137 interpreter_return_result(oh, i, 0, NULL, prevPointer);
01138 #ifdef PRINT_DEBUG_OPCODES
01139 printf("in function: \n");
01140 print_type(oh, (struct Object*)i->method);
01141 #endif
01142 break;
01143 }
01144 case OP_RETURN_FROM:
01145 {
01146 word_t reg, offset;
01147 PRINTOP("op: return from\n");
01148 reg = SSA_NEXT_PARAM_SMALLINT;
01149 offset = SSA_NEXT_PARAM_SMALLINT;
01150 #ifdef PRINT_DEBUG_OPCODES
01151 printf("return result reg: %" PRIdPTR ", offset: %" PRIdPTR ", value: ", reg, offset);
01152 print_type(oh, SSA_REGISTER(reg));
01153 #endif
01154 #ifdef PRINT_DEBUG_STACK
01155 printf("%" PRIuPTR "u: ", instruction_counter);
01156 #endif
01157 ASSERT_VALID_REGISTER(reg);
01158 Pinned<struct Object> result(oh);
01159 result = SSA_REGISTER(reg);
01160 interpreter_return_result(oh, i, offset, result, prevPointer);
01161 #ifdef PRINT_DEBUG_OPCODES
01162 printf("in function: \n");
01163 print_type(oh, (struct Object*)i->method);
01164 #endif
01165 break;
01166 }
01167 case OP_RETURN_VALUE:
01168 {
01169 Pinned<struct Object> obj(oh);
01170 PRINTOP("op: return obj\n");
01171 obj = SSA_NEXT_PARAM_OBJECT;
01172 #ifdef PRINT_DEBUG_STACK
01173 printf("%" PRIuPTR "u: ", instruction_counter);
01174 #endif
01175 interpreter_return_result(oh, i, 0, obj, prevPointer);
01176 #ifdef PRINT_DEBUG_OPCODES
01177 printf("in function: \n");
01178 print_type(oh, (struct Object*)i->method);
01179 #endif
01180 break;
01181 }
01182 case OP_PRIMITIVE_DO:
01183 {
01184 word_t primNum, resultReg, arity, k;
01185 struct Object* argsArray[16], *pinnedArgs[16];
01186 primNum = object_to_smallint(SSA_REGISTER(SSA_NEXT_PARAM_SMALLINT));
01187 arity = SSA_NEXT_PARAM_SMALLINT;
01188 resultReg = SSA_NEXT_PARAM_SMALLINT;
01189
01190 assert(arity <= 16);
01191 HEAP_READ_AND_PIN_ARGS(k, arity, argsArray, pinnedArgs);
01192
01193 primitives[primNum](oh, argsArray, arity, NULL, i->framePointer + resultReg);
01194
01195 HEAP_UNPIN_ARGS(k, pinnedArgs);
01196
01197 break;
01198 }
01199
01200 case OP_INLINE_PRIMITIVE_CHECK:
01201 {
01202 word_t primNum, resultReg, arity, k, jumpOffset;
01203 struct Object* mapArray;
01204 struct Object* argsArray[16], *pinnedArgs[16];
01205 resultReg = SSA_NEXT_PARAM_SMALLINT;
01206 mapArray = SSA_NEXT_PARAM_OBJECT;
01207 primNum = SSA_NEXT_PARAM_SMALLINT;
01208 arity = SSA_NEXT_PARAM_SMALLINT;
01209 jumpOffset = SSA_NEXT_PARAM_SMALLINT;
01210
01211 assert(arity <= 16);
01212
01213 HEAP_READ_AND_PIN_ARGS(k, arity, argsArray, pinnedArgs);
01214
01215
01216 word_t success = 0;
01217 if (arity == object_array_size(mapArray)) {
01218 success = 1;
01219 for (word_t k = 0; k < arity; k++) {
01220 if ((struct Map*) ((struct OopArray*)mapArray)->elements[k] != object_get_map(oh, argsArray[k])) {
01221 success = 0;
01222 break;
01223 }
01224 }
01225 }
01226
01227 if (success) {
01228
01229 i->codePointer = i->codePointer + jumpOffset;
01230 primitives[primNum](oh, argsArray, arity, NULL, i->framePointer + resultReg);
01231 }
01232
01233 HEAP_UNPIN_ARGS(k, pinnedArgs);
01234
01235
01236 break;
01237 }
01238
01239 case OP_INLINE_METHOD_CHECK:
01240 {
01241 word_t arity, k, jumpOffset;
01242 struct Object* mapArray;
01243 struct Object* argsArray[16], *pinnedArgs[16];
01244 mapArray = SSA_NEXT_PARAM_OBJECT;
01245 arity = SSA_NEXT_PARAM_SMALLINT;
01246 jumpOffset = SSA_NEXT_PARAM_SMALLINT;
01247
01248 assert(arity <= 16);
01249
01250 HEAP_READ_AND_PIN_ARGS(k, arity, argsArray, pinnedArgs);
01251
01252
01253 word_t success = 0;
01254 if (arity == object_array_size(mapArray)) {
01255 success = 1;
01256 for (word_t k = 0; k < arity; k++) {
01257 if ((struct Map*) ((struct OopArray*)mapArray)->elements[k] != object_get_map(oh, argsArray[k])) {
01258 success = 0;
01259 break;
01260 }
01261 }
01262 }
01263
01264 if (!success) {
01265 i->codePointer = i->codePointer + jumpOffset;
01266 }
01267
01268 HEAP_UNPIN_ARGS(k, pinnedArgs);
01269
01270
01271 break;
01272 }
01273
01274 case OP_APPLY_TO:
01275 {
01276 word_t resultReg, arity, k;
01277 Pinned<struct Object> method(oh);
01278 struct Object* argsArray[16], *pinnedArgs[16];
01279 method = SSA_REGISTER(SSA_NEXT_PARAM_SMALLINT);
01280 arity = SSA_NEXT_PARAM_SMALLINT;
01281 resultReg = SSA_NEXT_PARAM_SMALLINT;
01282
01283 assert(arity <= 16);
01284
01285 HEAP_READ_AND_PIN_ARGS(k, arity, argsArray, pinnedArgs);
01286
01287 interpreter_apply_to_arity_with_optionals(oh, oh->cached.interpreter, method,
01288 argsArray, arity, NULL, i->framePointer + resultReg);
01289
01290 HEAP_UNPIN_ARGS(k, pinnedArgs);
01291
01292 break;
01293 }
01294
01295 default:
01296 printf("error bad opcode... %" PRIdPTR "\n", op>>1);
01297 assert(0);
01298 break;
01299 }
01300
01301
01302 }
01303 }
01304
01305
01306
01307 }