Esempio n. 1
0
// Store a constant value.  Also used with a patch table when importing a saved heap which has
// been exported using the C exporter.
void ScanAddress::SetConstantValue(byte *addressOfConstant, PolyWord p, ScanRelocationKind code)
{

    switch (code)
    {
    case PROCESS_RELOC_DIRECT: // 32 or 64 bit address of target
        {
            POLYUNSIGNED valu = p.AsUnsigned();
            for (unsigned i = 0; i < sizeof(PolyWord); i++)
            {
                addressOfConstant[i] = (byte)(valu & 255); 
                valu >>= 8;
            }
        }
        break;
    case PROCESS_RELOC_I386RELATIVE:         // 32 bit relative address
        {
            POLYSIGNED newDisp = p.AsCodePtr() - addressOfConstant - 4;
#if (SIZEOF_VOIDP != 4)
            ASSERT(newDisp < 0x80000000 && newDisp >= -(POLYSIGNED)0x80000000);
#endif
            for (unsigned i = 0; i < 4; i++) {
                addressOfConstant[i] = (byte)(newDisp & 0xff);
                newDisp >>= 8;
            }
        }
        break;
    }
}
Esempio n. 2
0
// Update the addresses in a group of words.
void LoadRelocate::RelocateAddressAt(PolyWord *pt)
{
    PolyWord val = *pt;

    if (val.IsTagged()) return;

    // Which segment is this address in?
    unsigned i;
    for (i = 0; i < nDescrs; i++)
    {
        SavedStateSegmentDescr *descr = &descrs[i];
        if (val.AsAddress() > descr->originalAddress &&
            val.AsAddress() <= (char*)descr->originalAddress + descr->segmentSize)
        {
            // It's in this segment: relocate it to the current position.
            MemSpace *space =
                descr->segmentIndex == 0 ? gMem.IoSpace() : gMem.SpaceForIndex(descr->segmentIndex);
            // Error if this doesn't match.
            byte *setAddress = (byte*)space->bottom + ((char*)val.AsAddress() - (char*)descr->originalAddress);
            *pt = PolyWord::FromCodePtr(setAddress);
            break;
        }
    }
    if (i == nDescrs)
    {
        // Error: Not found.
        errorMessage = "Unmatched address";
    }
}
Esempio n. 3
0
// Process the value at a given location and update it as necessary.
POLYUNSIGNED ScanAddress::ScanAddressAt(PolyWord *pt)
{
    PolyWord val = *pt;
    PolyWord newVal = val;
    if (IS_INT(val) || val == PolyWord::FromUnsigned(0))
    {
        // We can get zeros in the constant area if we garbage collect
        //  while compiling some code. */
    }
    else if (val.IsCodePtr())
    {
        // We can get code pointers either in the stack as return addresses or
        // handler pointers or in constants in code segments as the addresses of
        // exception handlers.

        // Find the start of the code segment
        PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject;
        // Mustn't use ScanAddressAt here.  That's only valid if the value points
        // into the area being updated.
        PolyObject *newObject = ScanObjectAddress(oldObject);
        newVal = PolyWord::FromCodePtr((byte*)newObject + offset);
    }
    else
    {
        ASSERT(OBJ_IS_DATAPTR(val));
        // Database pointer, local pointer or IO pointer.
        // We need to include IO area pointers when we produce an object module.
        newVal = ScanObjectAddress(val.AsObjPtr());
    }
    if (newVal != val) // Only update if we need to.
        *pt = newVal;
    return 0;
}
Esempio n. 4
0
// adds w to the set
// returns true iff the set was changed
bool MalcevSet::addWord( const PolyWord& pw ) {

  bool wasChanged = false;
  PolyWord remainder = collect(pw);

  while( ! remainder.isEmpty() ) {
    Generator key = leader(remainder);

    // if there is no word with the same leader, include the remainder to the set

    if( ! theSet.bound(key) ) {
      theSet.bind( key, remainder );
      isBasis = false;
      isNormal = dontknow;
      return true;
    }

    // reduce the remainder

    PolyWord currentWord = theSet.valueOf(key);

    if( reduceWords( currentWord, remainder) ) {
      theSet.bind( key, currentWord );
      isBasis = false;
      isNormal = dontknow;
      wasChanged = true;
    }
  }
  return wasChanged;
}
Esempio n. 5
0
bool MalcevSet::isNormalClosure() const {

  if( isNormal != dontknow ) return isNormal;

  if( ! isBasis )
    error("Attempt to use MalcevSet::isNormalClosure before the set is full.");

  const BasicCommutators& BC = theCollector.commutators();
  MalcevSet* This = (MalcevSet *)this;    // to break physical constness

  //the subgroup is normal iff any w^x is in the set

  for(int i = 1; i < BC.theFirstOfWeight(BC.nilpotencyClass() ); i++) {

    if( ! theSet.bound( Generator(i) ) ) continue;
    PolyWord W = theSet.valueOf( Generator(i) );
    
    for(int j = 1; j <= BC.numberOfGenerators(); j++) {

      PolyWord conj = collect( Letter(j, -1) * W * Letter(j, 1) );

      checkMembership(conj);

      if(! conj.isEmpty() ) {
	This->isNormal = no;
	return false;
      }
    }
  }
  This->isNormal = yes;
  return true;
}
Esempio n. 6
0
bool GetSharing::TestForScan(PolyWord *pt)
{
    PolyObject *obj;

    // This may be a forwarding pointer left over from a minor GC that did
    // not complete or it may be a sharing chain pointer that we've set up.
    while (1)
    {
        PolyWord p = *pt;
        ASSERT(p.IsDataPtr());
        obj = p.AsObjPtr();
        PolyWord *lengthWord = ((PolyWord*)obj) - 1;
        LocalMemSpace *space = gMem.LocalSpaceForAddress(lengthWord);
        if (space == 0)
            return false; // Ignore it if it points to a permanent area

        if (space->bitmap.TestBit(space->wordNo(lengthWord)))
            return false;

        // Wasn't marked - must be a forwarding pointer.
        if (obj->ContainsForwardingPtr())
        {
            obj = obj->GetForwardingPtr();
            *pt = obj;
        }
        else break;
    }

    ASSERT(obj->ContainsNormalLengthWord());

    totalVisited += 1;
    totalSize += obj->Length() + 1;

    return true;
}
Esempio n. 7
0
static Handle setRegistryKey(TaskData *taskData, Handle args, HKEY hkey)
{
    TCHAR valName[MAX_PATH];
    LONG lRes;
    PolyWord str = args->WordP()->Get(3);
    POLYUNSIGNED length = Poly_string_to_C(args->WordP()->Get(1), valName, MAX_PATH);
    DWORD dwType = get_C_unsigned(taskData, DEREFWORDHANDLE(args)->Get(2));
    if (length > MAX_PATH)
        raise_syscall(taskData, "Value name too long", ENAMETOOLONG);

    // The value is binary.  Strings will already have had a null added.
    if (IS_INT(str))
    {
        byte b = (byte)UNTAGGED(str);
        // Single byte value.
        lRes = RegSetValueEx(hkey, valName, 0, dwType, &b, 1);
    }
    else
    {
        PolyStringObject *ps = (PolyStringObject*)str.AsObjPtr();
        lRes = RegSetValueEx(hkey, valName, 0, dwType,
                            (CONST BYTE *)ps->chars, (DWORD)ps->length);
    }

    if (lRes != ERROR_SUCCESS)
        raise_syscall(taskData, "RegSetValue failed", -lRes);

    return Make_arbitrary_precision(taskData, 0);
}
Esempio n. 8
0
PolyWord MalcevSet::makeCommutator( PolyWord& pw1, PolyWord& pw2 ) {

  // commute words

  PolyWord comm = commutatorOfInverses(pw1, pw2);
  comm.freelyReduce();
  return comm;
}
Esempio n. 9
0
void DoCheck (const PolyWord pt)
{
    if (pt == PolyWord::FromUnsigned(0)) return;

    if (pt.IsTagged()) return;

    CheckAddress(pt.AsStackAddr());
} 
Esempio n. 10
0
Handle string_length_c(TaskData *mdTaskData, Handle string)    /* Length of a string */
{
    PolyWord str = string->Word();
    if (str.IsTagged()) // Short form
        return Make_arbitrary_precision(mdTaskData, 1);
    
    POLYUNSIGNED length = ((PolyStringObject *)str.AsObjPtr())->length;
    return Make_arbitrary_precision(mdTaskData, length);
}
Esempio n. 11
0
void PExport::printValue(PolyWord q)
{
    if (IS_INT(q) || q == PolyWord::FromUnsigned(0))
        fprintf(exportFile, "%" POLYSFMT, UNTAGGED(q));
    else if (OBJ_IS_CODEPTR(q))
        printCodeAddr(q.AsCodePtr());
    else
        printAddress(q.AsAddress());
}
Esempio n. 12
0
bool PImport::GetValue(PolyWord *result)
{
    int ch = getc(f);
    if (ch == '@')
    {
        /* Address of an object. */
        POLYUNSIGNED obj;
        fscanf(f, "%" POLYUFMT, &obj);
        ASSERT(obj < nObjects);
        *result = objMap[obj];
    }
    else if (ch == '$')
    {
        /* Code address. */
        POLYUNSIGNED obj, offset;
        fscanf(f, "%" POLYUFMT "+%" POLYUFMT, &obj, &offset);
        ASSERT(obj < nObjects);
        PolyObject *q = objMap[obj];
        ASSERT(q->IsCodeObject());
        *result = PolyWord::FromCodePtr((PolyWord(q)).AsCodePtr() + offset); /* The offset is in bytes. */
    }
    else if ((ch >= '0' && ch <= '9') || ch == '-')
    {
        /* Tagged integer. */
        POLYSIGNED j;
        ungetc(ch, f);
        fscanf(f, "%" POLYSFMT, &j);
        /* The assertion may be false if we are porting to a machine
           with a shorter tagged representation. */
        ASSERT(j >= -MAXTAGGED-1 && j <= MAXTAGGED);
        *result = TAGGED(j);
    }
    else if (ch == 'I')
    {
        /* IO entry number. */
        POLYUNSIGNED j;
        fscanf(f, "%" POLYUFMT, &j);
        ASSERT(j < POLY_SYS_vecsize);
        *result = (PolyObject*)&gMem.ioSpace->bottom[j * IO_SPACING];
    }
    else if (ch == 'J')
    {
        /* IO entry number with offset. */
        POLYUNSIGNED j, offset;
        fscanf(f, "%" POLYUFMT "+%" POLYUFMT, &j, &offset);
        ASSERT(j < POLY_SYS_vecsize);
        PolyWord base = (PolyObject*)&gMem.ioSpace->bottom[j * IO_SPACING];
        *result = PolyWord::FromCodePtr(base.AsCodePtr() + offset);
    }
    else
    {
        fprintf(stderr, "Unexpected character in stream");
        return false;
    }
    return true;
}
Esempio n. 13
0
void ProcessEnvModule::GarbageCollect(ScanAddress *process)
/* Ensures that all the objects are retained and their addresses updated. */
{
    if (at_exit_list.IsDataPtr())
    {
        PolyObject *obj = at_exit_list.AsObjPtr();
        process->ScanRuntimeAddress(&obj, ScanAddress::STRENGTH_STRONG);
        at_exit_list = obj;
    }
}
Esempio n. 14
0
// Returns the new address if the argument is the address of an object that
// has moved, otherwise returns the original.
PolyWord SaveFixupAddress::GetNewAddress(PolyWord old)
{
    if (old.IsTagged() || old == PolyWord::FromUnsigned(0) || gMem.IsIOPointer(old.AsAddress()))
        return old; //  Nothing to do.

    // When we are updating addresses in the stack or in code segments we may have
    // code pointers.
    if (old.IsCodePtr())
    {
        // Find the start of the code segment
        PolyObject *oldObject = ObjCodePtrToPtr(old.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = old.AsCodePtr() - (byte*)oldObject;
        PolyWord newObject = GetNewAddress(oldObject);
        return PolyWord::FromCodePtr(newObject.AsCodePtr() + offset);
    }

    ASSERT(old.IsDataPtr());

    PolyObject *obj = old.AsObjPtr();
    
    if (obj->ContainsForwardingPtr()) // tombstone is a pointer to a moved object
    {
        PolyObject *newp = obj->GetForwardingPtr();
        ASSERT (newp->ContainsNormalLengthWord());
        return newp;
    }
    
    ASSERT (obj->ContainsNormalLengthWord()); // object is not moved
    return old;
}
Esempio n. 15
0
void DoCheckPointer (const PolyWord pt)
{
    if (pt == PolyWord::FromUnsigned(0)) return;

    if (OBJ_IS_AN_INTEGER(pt)) return;

    DoCheck (pt);

    if (pt.IsDataPtr())
    {
        PolyObject *obj = pt.AsObjPtr();
        DoCheckObject (obj, obj->LengthWord());
    }
}
Esempio n. 16
0
// Process a value within the stack.
PolyWord ScanAddress::ScanStackAddress(PolyWord val, StackSpace *stack, bool isCode)
{
    PolyWord *base = stack->bottom;
    PolyWord *end = stack->top;

    // If isCode is set we definitely have a code address.  It may have the
    // bottom bit set or it may be word aligned.
    if (isCode || val.IsCodePtr())
    {
        /* Find the start of the code segment */
        PolyObject *oldObject = ObjCodePtrToPtr(val.AsCodePtr());
        // Calculate the byte offset of this value within the code object.
        POLYUNSIGNED offset = val.AsCodePtr() - (byte*)oldObject;
        PolyObject *newObject = ScanObjectAddress(oldObject);
        return PolyWord::FromCodePtr((byte*)newObject + offset);
    }

    else if (val.IsTagged() || val == PolyWord::FromUnsigned(0) || 
                 (val.AsAddress() > base && val.AsAddress() <= end))
            /* We don't need to process tagged integers (now we've checked it isn't
               a code address) and we don't need to process addresses within the
               current stack. */
            /* N.B. We have "<= end" rather than "< end" because it is possible for
               the stack to be completely empty on a terminated thread. */
           return val;

    else
    {
        ASSERT(val.IsDataPtr());
        return ScanObjectAddress(val.AsObjPtr());
    }
}
Esempio n. 17
0
// The initial entry to process the roots.  These may be RTS addresses or addresses in
// a thread stack.  Also called recursively to process the addresses of constants in
// code segments.  This is used in situations where a scanner may return the
// updated address of an object.
PolyObject *MTGCProcessMarkPointers::ScanObjectAddress(PolyObject *obj)
{
    PolyWord val = obj;
    LocalMemSpace *space = gMem.LocalSpaceForAddress(val.AsAddress());
    if (space == 0)
        return obj; // Ignore it if it points to a permanent area

    // We may have a forwarding pointer if this has been moved by the
    // minor GC.
    if (obj->ContainsForwardingPtr())
    {
        obj = FollowForwarding(obj);
        val = obj;
        space = gMem.LocalSpaceForAddress(val.AsAddress());
    }

    ASSERT(obj->ContainsNormalLengthWord());

    POLYUNSIGNED L = obj->LengthWord();
    if (L & _OBJ_GC_MARK)
        return obj; // Already marked
    obj->SetLengthWord(L | _OBJ_GC_MARK); // Mark it

    if (profileMode == kProfileLiveData || (profileMode == kProfileLiveMutables && obj->IsMutable()))
        AddObjectProfile(obj);

    POLYUNSIGNED n = OBJ_OBJECT_LENGTH(L);
    if (debugOptions & DEBUG_GC_DETAIL)
        Log("GC: Mark: %p %" POLYUFMT " %u\n", obj, n, GetTypeBits(L));

    if (OBJ_IS_BYTE_OBJECT(L))
        return obj;

    // If we already have something on the stack we must being called
    // recursively to process a constant in a code segment.  Just push
    // it on the stack and let the caller deal with it.
    if (msp != 0)
        PushToStack(obj); // Can't check this because it may have forwarding ptrs.
    else
    {
        MTGCProcessMarkPointers::ScanAddressesInObject(obj, L);

        // We can only check after we've processed it because if we
        // have addresses left over from an incomplete partial GC they
        // may need to forwarded.
        CheckObject (obj);
    }

    return obj;
}
Esempio n. 18
0
Chars SGOfFreeNilpotentGroupRep::asDecomposition( const PolyWord& w ) const {

  if( ! basisIsInitialized() )
    error("SGOfFreeNilpotentGroupRep::asDecomposition: the basis must be built");

  return w.toChars( theBasisNames );
}
Esempio n. 19
0
/* Get the index corresponding to an address. */
PolyWord MachoExport::createRelocation(PolyWord p, void *relocAddr)
{
    void *addr = p.AsAddress();
    unsigned addrArea = findArea(addr);
    POLYUNSIGNED offset = (char*)addr - (char*)memTable[addrArea].mtAddr;
    adjustOffset(addrArea, offset);

    // It looks as though struct relocation_info entries are only used
    // with GENERIC_RELOC_VANILLA types.
    struct relocation_info relInfo;
    setRelocationAddress(relocAddr, &relInfo.r_address);
    relInfo.r_symbolnum = addrArea+1; // Section numbers start at 1
    relInfo.r_pcrel = 0;
#if (SIZEOF_VOIDP == 8)
    relInfo.r_length = 3; // 8 bytes
    relInfo.r_type = X86_64_RELOC_UNSIGNED;
#else
    relInfo.r_length = 2; // 4 bytes
    relInfo.r_type = GENERIC_RELOC_VANILLA;
#endif
    relInfo.r_extern = 0; // r_symbolnum is a section number.  It should be 1 if we make the IO area a common.

    fwrite(&relInfo, sizeof(relInfo), 1, exportFile);
    relocationCount++;
    return PolyWord::FromUnsigned(offset);
}
Esempio n. 20
0
AbelianGroup MalcevSet::mapToQuotient(int k) const {

  if( ! isBasis )
    error("MalcevSet::mapToQuotient: the set must be full");

  // The generators of the quotient are basic commutators of weight k.

  const BasicCommutators& bc = theCollector.commutators();

  int numGen = bc.numberOfWeight(k);
  int firstGen = bc.theFirstOfWeight(k) - 1;

  // The relators are Malcev basis words of weight k

  SetOf<Word> relsForAbelian;

  QuickAssociationsIterator< Generator, PolyWord > iter(theSet);
  for( ; ! iter.done(); iter.next() ) {

    // take a word from Malcev basis

    PolyWord pw = iter.value();
    Letter first = pw.firstLetter();
    if( ord(first.gen) != firstGen ) continue; 
    
    //Ok, this is a word from the quotient. Abelianize it.

    ConstPolyWordIterator iter( pw );
    Word w;
    for(iter.startFromLeft(); ! iter.done(); iter.stepRight() ) {

      Letter s = iter.thisLetter();
      int newgen =  ord(s.gen) - firstGen;
      if( newgen > numGen ) break;
      s.gen = Generator( newgen );
      w *= Word(s);
    }
    relsForAbelian.adjoinElement(w);
  }

  // make the abelian quotient
  
  AbelianGroup abel( FPGroup(numGen, relsForAbelian) );
  abel.computeCyclicDecomposition();
  return abel;
}
Esempio n. 21
0
void print_string(PolyWord s)
{
    if (IS_INT(s))
        putc((char)UNTAGGED(s), stdout);
    else {
        PolyStringObject * str = (PolyStringObject *)s.AsObjPtr();
        fwrite(str->chars, 1, str->length, stdout);
    }
}
Esempio n. 22
0
void MalcevSet::makeNormalClosure() {

  if(isNormal == yes) return;

  const BasicCommutators& BC = theCollector.commutators();
  int nilClass = BC.nilpotencyClass();

  int upper_i = BC.theFirstOfWeight(nilClass);

  for(int i = 1; i <= upper_i; i++) {

    if( ! theSet.bound( Generator(i) ) ) continue;
    PolyWord Wi = theSet.valueOf( Generator(i) );
    PolyWord WiInv = Wi.inverse();

    // trying generators of the group

    for(int j = 1; j <= BC.numberOfGenerators(); j++) {

      Generator g(j); 
      PolyWord comm = collect( Wi * Letter(g,-1) * WiInv * Letter(g,1) ); 

      addWord(comm);
    }

    // trying basis elements

    int upper_j = BC.theFirstOfWeight(nilClass - BC.weightOf(i) + 1);
    if(upper_j > i) upper_j = i;

    for(int j = 1; j < upper_j; j++) {

      if( ! theSet.bound( Generator(j) ) ) continue;
      PolyWord Wj = theSet.valueOf( Generator(j) );

      PolyWord comm = collect( Wi * Wj * WiInv * Wj.inverse() );

      addWord(comm);
    }
  }
  isBasis = true;
  isNormal = yes;
}
Esempio n. 23
0
// This deals with weak references within the run-time system.
void MTGCCheckWeakRef::ScanRuntimeAddress(PolyObject **pt, RtsStrength weak)
{
    /* If the object has not been marked and this is only a weak reference */
    /* then the pointer is set to zero. This allows streams or windows     */
    /* to be closed if there is no other reference to them.                */
    
    PolyObject *val = *pt;
    PolyWord w = val;
    
    if (weak == STRENGTH_STRONG)
        return;

    LocalMemSpace *space = gMem.LocalSpaceForAddress(w.AsStackAddr());
    if (space == 0)
        return; // Not in local area
    // If it hasn't been marked set it to zero.
    if (! space->bitmap.TestBit(space->wordNo(w.AsStackAddr())))
         *pt = 0;
}
Esempio n. 24
0
void MalcevSet::checkMembership(PolyWord& remainder) const {

  while( ! remainder.isEmpty() && theSet.bound( leader(remainder) ) ) {
    PolyWord curWord = theSet.valueOf( leader(remainder) );
    if( absPower(remainder) % absPower(curWord) != 0 ) 
      break;

    // The rest can be reduced. Do it.
    reduceWords( curWord, remainder );
  }
}
Esempio n. 25
0
static PHANDLETAB get_handle(PolyWord token, HANDENTRYTYPE heType)
{
    StreamToken *handle_token = (StreamToken*)token.AsObjPtr();
    POLYUNSIGNED  handle_no    = handle_token->streamNo;

    if (handle_no >= maxHandleTab ||
        handleTable[handle_no].token != handle_token ||
        handleTable[handle_no].entryType != heType) 
        return 0;

    return &handleTable[handle_no];
}
Esempio n. 26
0
// These functions are used in the interpreter.  They are generally replaced by
// hand-coded versions in the assembly code section.
static int string_test(PolyWord x, PolyWord y) 
/* Returns -1, 0, +1 if the first string is less, equal to or greater than the
   second. These are addresses of the strings because calling
   fix_persistent_address could result in a garbage-collection which could
   move the other string. */
{
    POLYUNSIGNED i;
    PolyStringObject *xs, *ys;
    /* Deal with single characters. */
    if (IS_INT(x))
    {
        s_test_x.length = 1;
        s_test_x.chars[0] = (char)UNTAGGED(x);
        xs = &s_test_x;
    }
    else xs = (PolyStringObject*)x.AsObjPtr();

    if (IS_INT(y))
    {
        s_test_y.length = 1;
        s_test_y.chars[0] = (char)UNTAGGED(y);
        ys = &s_test_y;
    }
    else ys = (PolyStringObject*)y.AsObjPtr();
    /* Now do the comparison. */

    for(i = 0; i < xs->length && i < ys->length; i++)
    {
        if (xs->chars[i] != ys->chars[i])
            return xs->chars[i] < ys->chars[i] ? -1 : 1;
    }
    /* They must be equal or one must be a leading substring of the other. */
    if (i < xs->length)
        return 1; /* y must be the substring. */
    else if (i < ys->length)
        return -1; /* x must be the substring */
    else
        return 0; /* They must be equal. */
}
Esempio n. 27
0
// Create a relocation entry for an address at a given location.
PolyWord SaveStateExport::createRelocation(PolyWord p, void *relocAddr)
{
    RelocationEntry reloc;
    // Set the offset within the section we're scanning.
    setRelocationAddress(relocAddr, &reloc.relocAddress);
    void *addr = p.AsAddress();
    unsigned addrArea = findArea(addr);
    reloc.targetAddress = (char*)addr - (char*)memTable[addrArea].mtAddr;
    reloc.targetSegment = (unsigned)memTable[addrArea].mtIndex;
    reloc.relKind = PROCESS_RELOC_DIRECT;
    fwrite(&reloc, sizeof(reloc), 1, exportFile);
    relocationCount++;
    return p; // Don't change the contents
}
Esempio n. 28
0
bool MalcevSet::reduceWords(PolyWord& pw1, PolyWord& pw2) const {

  if(pw1.isEmpty() || pw2.isEmpty())
    error("MalcevSet::reduceWords: empty argument");

  bool firstChanged = false;

  int power1 = absPower(pw1);
  int power2 = absPower(pw2);

  // make both PolyWords to be of distinct signs

  if( sign(pw1) ^ sign(pw2) == 0)  // if they have the same sign
    pw2 = pw2.inverse();

  // in fact, this is Euclid algorithm for finding GCD
    
  do {

    if( power1 > power2 ) {
      // swapping two words
      PolyWord tmp = pw1;
      pw1 = pw2;
      pw2 = tmp;
      int t = power1;
      power1 = power2;
      power2 = t;	
      firstChanged = true;
    }      

    power2 -= power1;
    pw2 = theCollector.multiply(pw1, pw2);
 
  } while(power2 != 0);

  return firstChanged;
}  
Esempio n. 29
0
// This gets called in two circumstances.  It may be called for the roots
// in which case the stack will be empty and we want to process it completely
// or it is called for a constant address in which case it will have been
// called from RecursiveScan::ScanAddressesInObject and that can process
// any addresses.
PolyObject *RecursiveScan::ScanObjectAddress(PolyObject *obj)
{
    PolyWord pWord = obj;
    // Test to see if this needs to be scanned.
    // It may update the word.
    bool test = TestForScan(&pWord);
    obj = pWord.AsObjPtr();

    if (test)
    {
        MarkAsScanning(obj);
        if (obj->IsByteObject())
            Completed(obj); // Don't need to put it on the stack
        // If we already have something on the stack we must being called
        // recursively to process a constant in a code segment.  Just push
        // it on the stack and let the caller deal with it.
        else if (StackIsEmpty())
            RecursiveScan::ScanAddressesInObject(obj, obj->LengthWord());
        else
            PushToStack(obj);
    }

    return obj;
}
Esempio n. 30
0
POLYUNSIGNED Poly_string_to_C(PolyWord ps, WCHAR *buff, POLYUNSIGNED bufflen)
{
    if (IS_INT(ps))
    {
        buff[0] = (WCHAR)(UNTAGGED(ps));
        buff[1] = 0;
        return(1);
    }

    PolyStringObject *str = (PolyStringObject *)ps.AsObjPtr();
    POLYUNSIGNED chars = str->length >= bufflen ? bufflen-1 : str->length;
    for (POLYUNSIGNED i = 0; i < chars; i++) buff[i] = str->chars[i];
    buff[chars] = 0;
    return chars;
} /* Poly_string_to_C */