示例#1
0
struct MethodDefinition* method_define(struct object_heap* oh, struct Object* method, struct Symbol* selector, struct Object* args[], word_t n) {

  word_t positions, i;
  struct Object* argBuffer[MAX_ARITY];
  Pinned<struct MethodDefinition> def(oh);
  Pinned<struct MethodDefinition> oldDef(oh);

  def = (struct MethodDefinition*)heap_clone_special(oh, SPECIAL_OOP_METHOD_DEF_PROTO);
  positions = 0;
  for (i = 0; i < n; i++) {
    if (!object_is_smallint(args[i]) && args[i] != get_special(oh, SPECIAL_OOP_NO_ROLE)) {
      positions |= (1 << i);
    }
  }

  /* any methods that call the same symbol must be decompiled because they might call an old version */
  method_remove_optimized_sending(oh, selector);
  selector->cacheMask = smallint_to_object(object_to_smallint(selector->cacheMask) | positions);
  assert(n <= MAX_ARITY);

  copy_words_into(args, n, argBuffer); /* method_dispatch_on modifies its arguments (first argument)*/
  oldDef = method_dispatch_on(oh, selector, argBuffer, n, NULL);
  if (oldDef == (struct Object*)NULL || oldDef->dispatchPositions != positions || oldDef != method_is_on_arity(oh, oldDef->method, selector, args, n)) {
    oldDef = NULL;
  }
  if (oldDef != (struct Object*)NULL) {
    Pinned<struct CompiledMethod> oldDefMethod(oh);
    oldDefMethod = (struct CompiledMethod*)oldDef->method;
    method_pic_flush_caller_pics(oh, (struct CompiledMethod*)oldDefMethod);
  }
  def->method = method;
  heap_store_into(oh, (struct Object*) def, (struct Object*) method);
  def->dispatchPositions = positions;


  for (i = 0; i < n; i++) {
    if (!object_is_smallint(args[i]) && (struct Object*)args[i] != get_special(oh, SPECIAL_OOP_NO_ROLE)) {
      if (oldDef != (struct Object*)NULL) {
        object_remove_role(oh, args[i], selector, oldDef);
      }
      object_add_role_at(oh, args[i], selector, 1<<i, def);
    }
  }
  return def;
    
}
示例#2
0
void method_pic_flush_caller_pics(struct object_heap* oh, struct CompiledMethod* callee) {

  int i;
  if (callee->base.map->delegates->elements[0] == oh->cached.closure_method_window) callee = callee->method;
  assert (callee->base.map->delegates->elements[0] == oh->cached.compiled_method_window);
  if (!object_is_smallint(callee->cachedInCallersCount)) return;
  for (i = 0; i < object_to_smallint(callee->cachedInCallersCount); i++) {
    /*this should reset the pic*/
    method_pic_setup(oh, (struct CompiledMethod*)callee->cachedInCallers->elements[i]);
  }


}
示例#3
0
void print_type(struct object_heap* oh, struct Object* o) {
  struct Object* traits;
  struct Object* traitsWindow;
  struct OopArray* x;
  if (object_is_smallint(o)) {
    fprintf(stderr, "%" PRIdPTR " (0x%" PRIuPTR ")\n", object_to_smallint(o), object_to_smallint(o));
    return;
  }

  if (object_type(o) == TYPE_BYTE_ARRAY) {
    fprintf(stderr, "(");
    print_byte_array(o);
    fprintf(stderr, ") ");
    /*return;*/
  }

  x = o->map->delegates;
  if (!x || array_size(x) < 1) goto fail;

  traitsWindow = x->elements[0];

  {
    if (traitsWindow == oh->cached.compiled_method_window) {
      fprintf(stderr, "(method #");
      print_byte_array((struct Object*)(((struct CompiledMethod*)o)->method->selector));
      fprintf(stderr, ")");
    }
  }

  x = traitsWindow->map->delegates;
  if (!x || array_size(x) < 1) goto fail;

  traits = x->elements[array_size(x)-1];

  if (o == oh->cached.nil) {
    fprintf(stderr, "nil\n");
  } else if (o == oh->cached.true_object) {
    fprintf(stderr, "true\n");
  } else if (o == oh->cached.false_object) {
    fprintf(stderr, "false\n");
  } else {
    print_printname(oh, o);
    fprintf(stderr, "(");
    print_printname(oh, traits);
    fprintf(stderr, ")\n");
  }

  return;
 fail:
  fprintf(stderr, "<unknown type>\n");
}
示例#4
0
bool_t print_printname(struct object_heap* oh, struct Object* o) {
  word_t i;
  struct Map* map = o->map;
  struct SlotTable* slotTable = map->slotTable;
  word_t limit = slot_table_capacity(slotTable);
  for (i=0; i < limit; i++) {
    if (slotTable->slots[i].name == (struct Symbol*)oh->cached.nil) continue;
    if (strncmp((char*)slotTable->slots[i].name->elements, "printName", 9) == 0) {
      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) {
        return FALSE;
      } else {
        print_byte_array(obj);
        return TRUE;
      }
    }
  }
  return FALSE;
}
示例#5
0
struct MethodDefinition* method_is_on_arity(struct object_heap* oh, struct Object* method, struct Symbol* selector, struct Object* args[], word_t n) {

  word_t positions, i;
  struct MethodDefinition* def;

  positions = 0;
  def = NULL;

  for (i = 0; i < n; i++) {
    if (!object_is_smallint(args[i])) {

      struct MethodDefinition* roleDef = object_has_role_named_at(args[i], selector, 1<<i, method);
      if (roleDef != NULL) {
        positions |= 1<<i;
        def = roleDef;
      }

    }
  }

  return ((def != NULL && positions == def->dispatchPositions)? def : NULL);

}
示例#6
0
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");
}
示例#7
0
/*
 * 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;
}