void print_byte_array(struct Object* o) { word_t i; char* elements = (char*)inc_ptr(o, object_array_offset(o)); fprintf(stderr, "'"); for (i=0; i < payload_size(o); i++) { if (elements[i] >= 32 && elements[i] <= 126) { fprintf(stderr, "%c", elements[i]); } else { fprintf(stderr, "\\x%02" PRIxPTR "", (word_t)elements[i]); } if (i > 10 && payload_size(o) - i > 100) { i = payload_size(o) - 20; fprintf(stderr, "{..snip..}"); } } fprintf(stderr, "'"); }
void print_object_with_depth(struct object_heap* oh, struct Object* o, word_t depth, word_t max_depth) { struct Map* map; word_t i; if (depth >= max_depth || object_is_smallint(o)) { fprintf(stderr, "(depth limit reached) "); print_object(o); return; } if (o == oh->cached.nil) { fprintf(stderr, "<object NilObject>\n"); return; } map = o->map; print_object(o); if (object_hash(o) >= ID_HASH_RESERVED) { indent(depth); fprintf(stderr, "<object is free/reserved>\n"); return; } indent(depth); fprintf(stderr, "{\n"); if (object_type(o) == TYPE_BYTE_ARRAY) { indent(depth); fprintf(stderr, "bytes: "); print_byte_array(o); fprintf(stderr, "\n"); } if (object_type(o) == TYPE_OOP_ARRAY) { struct OopArray* array = (struct OopArray*)o; indent(depth); fprintf(stderr, "size(array) = %" PRIdPTR "\n", object_array_size(o)); for (i=0; i < object_array_size(o); i++) { indent(depth); fprintf(stderr, "array[%" PRIdPTR "]: ", i); print_object_with_depth(oh, array->elements[i], depth+1, max_depth); if (object_array_size(o) - i > 10) { indent(depth); fprintf(stderr, "...\n"); i = object_array_size(o) - 2; } } } indent(depth); fprintf(stderr, "map flags: %" PRIdPTR " (%s)\n", object_to_smallint(map->flags), ((((word_t)map->flags & MAP_FLAG_RESTRICT_DELEGATION)==0)? "delegation not restricted":"delegation restricted")); { /*print if delegate*/ struct OopArray* delegates = map->delegates; word_t offset = object_array_offset((struct Object*)delegates); word_t limit = object_total_size((struct Object*)delegates); for (i = 0; offset != limit; offset += sizeof(word_t), i++) { struct Object* delegate = object_slot_value_at_offset((struct Object*)delegates, offset); indent(depth); fprintf(stderr, "delegate[%" PRIdPTR "] = ", i); print_object_with_depth(oh, delegate, (((word_t)map->flags & MAP_FLAG_RESTRICT_DELEGATION) == 0)? depth+1 : max(max_depth-1, depth+1), max_depth); } } {/*if?*/ struct SlotTable* slotTable = map->slotTable; word_t limit = slot_table_capacity(map->slotTable); indent(depth); fprintf(stderr, "slot count: %" PRIdPTR "\n", object_to_smallint(map->slotCount)); for (i=0; i < limit; i++) { if (slotTable->slots[i].name == (struct Symbol*)oh->cached.nil) continue; indent(depth); fprintf(stderr, "slot[%" PRIdPTR "]['", i); print_symbol(slotTable->slots[i].name); fprintf(stderr, "'] = "); { struct Object* obj = object_slot_value_at_offset(o, object_to_smallint(slotTable->slots[i].offset)); if (object_is_smallint(obj) || object_type(obj) != TYPE_BYTE_ARRAY) { print_object(obj); } else { print_byte_array(obj); fprintf(stderr, "\n"); } } } } /*indent(depth); fprintf(stderr, "map = "); print_object_with_depth(oh, (struct Object*)map, depth+1, max_depth);*/ /*roles */ { struct RoleTable* roleTable = map->roleTable; word_t limit = role_table_capacity(roleTable); indent(depth); fprintf(stderr, "role table capacity: %" PRIdPTR "\n", limit); for (i = 0; i < limit; i++) { if (roleTable->roles[i].name == (struct Symbol*)oh->cached.nil) {continue;} else { indent(depth); fprintf(stderr, "role[%" PRIdPTR "]['", i); print_symbol(roleTable->roles[i].name); fprintf(stderr, "'] @ 0x%04" PRIxPTR "\n", object_to_smallint(roleTable->roles[i].rolePositions)); #if 0 print_object_with_depth(oh, (struct Object*)roleTable->roles[i].methodDefinition, max_depth, max_depth); #endif if (limit - i > 50 && depth >= 2) { indent(depth); fprintf(stderr, "...\n"); i = limit - 3; } } } } indent(depth); fprintf(stderr, "}\n"); }
/* * This is the main dispatch function * */ struct MethodDefinition* method_dispatch_on(struct object_heap* oh, struct Symbol* name, struct Object* arguments[], word_t arity, struct Object* resendMethod) { struct MethodDefinition *dispatch, *bestDef; struct Object* slotLocation; word_t bestRank, depth, delegationCount, resendRank, restricted, i; #ifdef PRINT_DEBUG_DISPATCH fprintf(stderr, "dispatch to: '"); print_symbol(name); fprintf(stderr, "' (arity: %" PRIdPTR ")\n", arity); for (i = 0; i < arity; i++) { fprintf(stderr, "arguments[%" PRIdPTR "] (%p) = ", i, (void*)arguments[i]); print_type(oh, arguments[i]); } /* fprintf(stderr, "resend: "); print_object(resendMethod);*/ #endif dispatch = NULL; slotLocation = NULL; #ifndef SLATE_DISABLE_METHOD_CACHE if (resendMethod == NULL && arity <= METHOD_CACHE_ARITY) { dispatch = method_check_cache(oh, name, arguments, arity); if (dispatch != NULL) return dispatch; } #endif oh->current_dispatch_id++; bestRank = 0; bestDef = NULL; resendRank = ((resendMethod == NULL) ? WORDT_MAX : 0); for (i = 0; i < arity; i++) { struct Object *obj; struct Map* map; struct Object* arg = arguments[i]; delegationCount = 0; depth = 0; restricted = WORDT_MAX; /*pointer in delegate_stack (with sp of delegateCount) to where we don't trace further*/ do { /* Set up obj to be a pointer to the object, or SmallInteger if it's a direct SmallInt. */ if (object_is_smallint(arg)) { obj = get_special(oh, SPECIAL_OOP_SMALL_INT_PROTO); } else { obj = arg; } /* Identify the map, and update its dispatchID and reset the visited mask if it hasn't been visited during this call already. */ map = obj->map; if (map->dispatchID != oh->current_dispatch_id) { map->dispatchID = oh->current_dispatch_id; map->visitedPositions = 0; } /* we haven't been here before */ if ((map->visitedPositions & (1 << i)) == 0) { struct RoleEntry* role; /* If the map marks an obj-meta transition and the top of the stack is not the original argument, then mark the restriction point at the top of the delegation stack. */ if (((word_t)map->flags & MAP_FLAG_RESTRICT_DELEGATION) && (arg != arguments[i])) { restricted = delegationCount; } map->visitedPositions |= (1 << i); role = role_table_entry_for_name(oh, map->roleTable, name); while (role != NULL) { if ((object_to_smallint(role->rolePositions) & (1 << i)) != 0) { struct MethodDefinition* def = role->methodDefinition; /* If the method hasn't been visited this time, mark it so and clear the other dispatch marks.*/ if (def->dispatchID != oh->current_dispatch_id) { def->dispatchID = oh->current_dispatch_id; def->foundPositions = 0; def->dispatchRank = 0; } /*If the method hasn't been found at this position...*/ if ((def->foundPositions & (1 << i)) == 0) { /*fix*/ def->dispatchRank |= ((31 - depth) << ((5 - i) * 5)); def->foundPositions |= (1 << i); #ifdef PRINT_DEBUG_FOUND_ROLE fprintf(stderr, "found role index %" PRIdPTR " <%p> for '%s' foundPos: %" PRIuPTR "x dispatchPos: %" PRIuPTR "x\n", i, (void*) role, ((struct Symbol*)(role->name))->elements, def->foundPositions, def->dispatchPositions); #endif if (def->method == resendMethod) { struct RoleEntry* rescan = role_table_entry_for_name(oh, map->roleTable, name); resendRank = def->dispatchRank; while (rescan != role) { struct MethodDefinition* redef = rescan->methodDefinition; if (redef->foundPositions == redef->dispatchPositions && (dispatch == NULL || redef->dispatchRank <= resendRank)) { dispatch = redef; slotLocation = obj; if (redef->dispatchRank > bestRank) { bestRank = redef->dispatchRank; bestDef = redef; } } if (rescan->nextRole == oh->cached.nil) { rescan = NULL; } else { rescan = &map->roleTable->roles[object_to_smallint(rescan->nextRole)]; } } } else /*not a resend*/ { if (def->foundPositions == def->dispatchPositions && (dispatch == NULL || def->dispatchRank > dispatch->dispatchRank) && def->dispatchRank <= resendRank) { dispatch = def; slotLocation = obj; if (def->dispatchRank > bestRank) { bestRank = def->dispatchRank; bestDef = def; } } } if (def->dispatchRank >= bestRank && def != bestDef) { bestRank = def->dispatchRank; bestDef = NULL; } } } role = ((role->nextRole == oh->cached.nil) ? NULL : &map->roleTable->roles[object_to_smallint(role->nextRole)]); } /*while role != NULL*/ if (depth > 31) { /*fix wordsize*/ assert(0); } if (dispatch != NULL && bestDef == dispatch) { if (dispatch->slotAccessor != oh->cached.nil) { arguments[0] = slotLocation; /*do we need to try to do a heap_store_into?*/ #ifdef PRINT_DEBUG_DISPATCH_SLOT_CHANGES fprintf(stderr, "arguments[0] changed to slot location: \n"); print_detail(oh, arguments[0]); #endif } if (resendMethod == 0 && arity <= METHOD_CACHE_ARITY) method_save_cache(oh, dispatch, name, arguments, arity); return dispatch; } depth++; /* We add the delegates to the list when we didn't just finish checking a restricted object*/ if (delegationCount <= restricted && array_size(map->delegates) > 0) { struct OopArray* delegates = map->delegates; word_t offset = object_array_offset((struct Object*)delegates); word_t limit = object_total_size((struct Object*)delegates); for (; offset != limit; offset += sizeof(word_t)) { struct Object* delegate = object_slot_value_at_offset((struct Object*)delegates, offset); if (delegate != oh->cached.nil) { oh->delegation_stack[delegationCount++] = delegate; } } } } /*end haven't been here before*/ delegationCount--; if (delegationCount < restricted) restricted = WORDT_MAX; /*everything is unrestricted now*/ if (delegationCount < 0 || delegationCount >= DELEGATION_STACK_SIZE) break; arg = oh->delegation_stack[delegationCount]; } while (1); } if (dispatch != NULL && dispatch->slotAccessor != oh->cached.nil) { /*check heap store into?*/ arguments[0] = slotLocation; #ifdef PRINT_DEBUG_DISPATCH_SLOT_CHANGES fprintf(stderr, "arguments[0] changed to slot location: \n"); print_detail(oh, arguments[0]); #endif } #ifndef SLATE_DISABLE_METHOD_CACHE if (dispatch != NULL && resendMethod == 0 && arity < METHOD_CACHE_ARITY) { method_save_cache(oh, dispatch, name, arguments, arity); } #endif return dispatch; }