Exemple #1
0
  Fixnum* Tuple::delete_inplace_prim(STATE, Fixnum *start, Fixnum *length, Object *obj) {
    native_int size = this->num_fields();
    native_int len  = length->to_native();
    native_int lend = start->to_native();
    native_int rend = lend + len;

    if(size == 0 || len == 0) return Fixnum::from(0);
    if(lend < 0 || lend >= size) {
      return force_as<Fixnum>(bounds_exceeded_error(state, "Tuple::delete_inplace", lend));
    }

    if(rend < 0 || rend > size) {
      return force_as<Fixnum>(bounds_exceeded_error(state, "Tuple::delete_inplace", rend));
    }

    return Fixnum::from(delete_inplace(lend, len, obj));
  }
Exemple #2
0
  /* The Tuple#at primitive. */
  Object* Tuple::at_prim(STATE, Fixnum* index_obj) {
    native_int index = index_obj->to_native();

    if(index < 0 || num_fields() <= index) {
      return bounds_exceeded_error(state, "Tuple::at_prim", index);
    }

    return field[index];
  }
Exemple #3
0
  Object* RTuple::at_prim(STATE, Fixnum* idx) {
    native_int index = idx->to_native();

    if(index < 0 || num_fields() <= index) {
      return bounds_exceeded_error(state, "RTuple::at_prim", index);
    }

    return MemoryHandle::object(reinterpret_cast<VALUE>(field[index]));
  }
Exemple #4
0
  Fixnum* Tuple::delete_inplace(STATE, Fixnum *start, Fixnum *length, Object *obj) {
    int size = this->num_fields();
    int len  = length->to_native();
    int lend = start->to_native();
    int rend = lend + len;

    if(size == 0 || len == 0) return Fixnum::from(0);
    if(lend < 0 || lend >= size) {
      return force_as<Fixnum>(bounds_exceeded_error(state, "Tuple::delete_inplace", lend));
    }

    if(rend < 0 || rend > size) {
      return force_as<Fixnum>(bounds_exceeded_error(state, "Tuple::delete_inplace", rend));
    }

    int i = lend;
    while(i < rend) {
      if(this->at(state,i) == obj) {
        int j = i;
        ++i;
        while(i < rend) {
          Object *val = this->field[i];
          if(val != obj) {
            // no need to set write_barrier since it's already
            // referenced to this object
            this->field[j] = val;
            ++j;
          }
          ++i;
        }
        // cleanup all the bins after
        i = j;
        while(i < rend) {
          this->field[i] = Qnil;
          ++i;
        }
        return Fixnum::from(rend-j);
      }
      ++i;
    }
    return Fixnum::from(0);
  }
Exemple #5
0
  /* The Tuple#put primitive. */
  Object* Tuple::put_prim(STATE, Fixnum* index, Object* val) {
    native_int idx = index->to_native();

    if(idx < 0 || num_fields() <= idx) {
      return bounds_exceeded_error(state, "Tuple::put_prim", idx);
    }

    field[idx] = val;
    write_barrier(state, val);
    return val;
  }
Exemple #6
0
  Object* RTuple::put_prim(STATE, Fixnum* idx, Object* val) {
    native_int index = idx->to_native();

    if(index < 0 || num_fields() <= index) {
      return bounds_exceeded_error(state, "RTuple::put_prim", index);
    }

    reinterpret_cast<VALUE*>(field)[index] = MemoryHandle::value(val);

    state->memory()->write_barrier(this, val);

    return val;
  }
Exemple #7
0
  Tuple* Tuple::copy_from(STATE, Tuple* other, Fixnum* start, Fixnum *length, Fixnum* dest) {
    native_int osize = other->num_fields();
    native_int size = this->num_fields();

    native_int src_start = start->to_native();
    native_int dst_start = dest->to_native();
    native_int len = length->to_native();

    // left end should be within range
    if(src_start < 0 || src_start > osize) {
      return other->bounds_exceeded_error(state, "Tuple::copy_from", src_start);
    }

    if(dst_start < 0 || dst_start > size) {
      return bounds_exceeded_error(state, "Tuple::copy_from", dst_start);
    }

    // length can not be negative and must fit in src/dest
    if(len < 0) {
      return other->bounds_exceeded_error(state, "Tuple::copy_from", len);
    }

    if((src_start + len) > osize) {
      return other->bounds_exceeded_error(state, "Tuple::copy_from", src_start + len);
    }

    if(len > (size - dst_start)) {
      return bounds_exceeded_error(state, "Tuple::copy_from", len);
    }

    // A memmove within the tuple
    if(other == this) {
      // No movement, no work!
      if(src_start == dst_start) return this;
      // right shift
      if(src_start < dst_start) {
        for(native_int dest_idx = dst_start + len - 1,
                       src_idx  = src_start + len - 1;
            src_idx >= src_start;
            src_idx--, dest_idx--) {
          this->field[dest_idx] = this->field[src_idx];
        }
      } else {
        // left shift
        for(native_int dest_idx = dst_start,
                       src_idx  = src_start;
            src_idx < src_start + len;
            src_idx++, dest_idx++) {
          this->field[dest_idx] = this->field[src_idx];
        }
      }

    } else {
      for(native_int src = src_start, dst = dst_start;
          src < (src_start + len);
          ++src, ++dst) {
        // Since we have carefully checked the bounds we don't need
        // to do it in at/put
        Object *obj = other->field[src];
        // but this is necessary to keep the GC happy
        field[dst] = obj;
        write_barrier(state, obj);
      }
    }

    return this;
  }