void RexxBehaviour::merge( RexxBehaviour * source_behav) /* new behaviour to add in */ /*****************************************************************************/ /* Function: Merge the passed behaviour's mdict into this behaviour's mdict */ /* The method search order will be for the target(this) behaviour */ /* to be found before the source behaviour */ /*****************************************************************************/ { /* if there isn't a source mdict */ /* there isn't anything to do */ if (source_behav->methodDictionary == OREF_NULL) { return; } /* if there isn't a mdict yet just */ /* use the source for this one */ if (this->methodDictionary == OREF_NULL) { OrefSet(this, this->methodDictionary, source_behav->methodDictionary); } else { /* get a copy of the source mdict */ /* for the merge */ RexxTable *newMethods = (RexxTable *)source_behav->methodDictionary->copy(); ProtectedObject p(newMethods); /* merge this mdict with the copy */ this->methodDictionary->merge(newMethods); /* and put it into this behaviour */ OrefSet(this, this->methodDictionary, newMethods); } }
void RexxBehaviour::methodDictionaryMerge( RexxTable *sourceDictionary) /* dictionary to merge in */ /*****************************************************************************/ /* Function: Merge the passed mdict into this behaviour's mdict */ /* After this merge the method search order will find the source */ /* mdict methods prior to self(target) methods */ /*****************************************************************************/ { RexxTable *newDictionary; /* new method dictionary */ /* if there isn't a source mdict */ if (sourceDictionary == OREF_NULL) /* there isn't anything to do */ { return; /* just return */ } /* if there isn't a mdict yet just */ /* use the source for this one */ if (this->methodDictionary == OREF_NULL) { OrefSet(this, this->methodDictionary, sourceDictionary); } else { /* get a copy of the target mdict */ /* for the merge */ newDictionary = (RexxTable *)this->methodDictionary->copy(); ProtectedObject p(newDictionary); /* merge the source mdict and copy */ sourceDictionary->merge(newDictionary); /* and put it into this behaviour */ OrefSet(this, this->methodDictionary, newDictionary); } }
void RexxBehaviour::addMethod( RexxString *methodName, /* name of the defined method */ RexxMethod *method) /* method to add to the behaviour */ /******************************************************************************/ /* Function: Add a method to an object's behaviour */ /******************************************************************************/ { /* no method dictionary yet? */ if (this->methodDictionary == OREF_NULL) { /* allocate a table */ OrefSet(this, this->methodDictionary, new_table()); } /* now repeat for the instance */ if (this->instanceMethodDictionary == OREF_NULL) { /* methods to track additions */ OrefSet(this, this->instanceMethodDictionary, new_table()); } /* already added one by this name? */ if (this->instanceMethodDictionary->stringGet(methodName) != OREF_NULL) { /* remove from the method dictionary */ this->methodDictionary->remove(methodName); } /* now just add this directly */ this->methodDictionary->stringAdd(method, methodName); /* and also add to the instance one */ this->instanceMethodDictionary->stringPut(method, methodName); }
void RexxBehaviour::copyBehaviour(RexxBehaviour *source) /******************************************************************************/ /* Function: Copy the source behaviour object into this, inheriting all of */ /* the method dictionaries. */ /******************************************************************************/ { /* have an method dictionary */ if (source->methodDictionary != OREF_NULL) { /* make a copy of this too */ OrefSet(this, this->methodDictionary, (RexxTable *)source->methodDictionary->copy()); } if (source->scopes != OREF_NULL) /* scope information? */ { /* make a copy of it too */ OrefSet(this, this->scopes, (RexxIdentityTable *)source->scopes->copy()); } /* do we have added methods? */ if (source->instanceMethodDictionary != OREF_NULL) { /* copy those also */ OrefSet(this, this->instanceMethodDictionary, (RexxTable *)source->instanceMethodDictionary->copy()); } // this is the same class as the source also OrefSet(this, this->owningClass, source->owningClass); /* use default operator methods set */ this->operatorMethods = (PCPPM *)source->operatorMethods; }
RexxSupplier::RexxSupplier( RexxArray *_values, /* array of values */ RexxArray *_indexes ) /* array of indexes */ /****************************************************************************/ /* Function: Initialize a supplier */ /****************************************************************************/ { OrefSet(this, this->values, _values); /* store the values array */ /* and the index array also */ OrefSet(this, this->indexes, _indexes); this->position = 1; /* set the first position */ }
RexxInstructionAddress::RexxInstructionAddress( RexxObject *_expression, /* variable address expression */ RexxString *_environment, /* address environment name */ RexxObject *_command) /* command to issue */ /******************************************************************************/ /* Function : Complete address instruction initialization */ /******************************************************************************/ { /* store the instruction state */ OrefSet(this, this->expression, _expression); OrefSet(this, this->environment, _environment); OrefSet(this, this->command, _command); }
void RexxEnvelope::addTable( RexxObject *obj) /* table object to rehash */ /******************************************************************************/ /* Function: Add an object to the rehash table for later processing */ /******************************************************************************/ { /* the following table will be used */ /* by the table_unflatten method. */ /* */ /* Every table that gets unflattened */ /* place itself in this table. Once */ /* every object has been unflattened */ /* we traverse this table and allow */ /* the hashtables to re-hash their */ /* since some hash value may have */ /* change */ if (this->rehashtable == OREF_NULL) /* first table added? */ { /* create the table now */ OrefSet(this, this->rehashtable, new_identity_table()); } /* use put to make sure we only get */ /* a single version of each table */ this->rehashtable->put(TheNilObject, obj); }
RexxCode::RexxCode( RexxSource * _source, /* source object */ RexxInstruction * _start, /* start of the code tree */ RexxDirectory * _labels, /* method labels */ size_t maxstack, /* max operator stack size */ size_t variable_index) /* save of the vdict */ /******************************************************************************/ /* Function: Initialize a rexxmethod code object */ /******************************************************************************/ { OrefSet(this, this->source, _source); /* save the program source */ OrefSet(this, this->start, _start); /* the parse tree */ OrefSet(this, this->labels, _labels); /* the method's labels */ /* save the stack info */ this->maxStack = maxstack; this->vdictSize = variable_index; /* save the initial vdict size */ }
/** * Initialize a Trace instruction. * * @param _expression * A potential expression to evaluate. * @param trace The new trace setting (can be zero if numeric or dynamic form). * @param flags The translated trace flags for setting-based forms. * @param debug_skip A potential debug_skip value. */ RexxInstructionTrace::RexxInstructionTrace(RexxObject *_expression, size_t trace, size_t flags, wholenumber_t debug_skip ) { /* process the expression */ OrefSet(this, this->expression, _expression); this->debugskip = debug_skip; /* copy the skip value */ traceSetting = trace; /* and the trace setting */ traceFlags = flags; }
RexxInstructionReply::RexxInstructionReply( RexxObject *_expression) /******************************************************************************/ /* Function: Initialize a REXX REPLY instruction */ /******************************************************************************/ { /* do the common initialization */ OrefSet(this, this->expression, _expression); }
RexxInstructionCommand::RexxInstructionCommand( RexxObject *_expression) /* command expression */ /******************************************************************************/ /* Function: Complete initialzation a command instruction object */ /******************************************************************************/ { /* save the command expression */ OrefSet(this, this->expression, _expression); }
RexxObject *RexxBehaviour::setScopes( RexxIdentityTable *newscopes) /* new table of scopes */ /******************************************************************************/ /* Function: Set a new set of scoping information for an object */ /******************************************************************************/ { /* set the scoping info */ OrefSet(this, this->scopes, newscopes); return OREF_NULL; /* always return nothing */ }
/** * Place an item into a hash collection using a key. * This is the base virtual implementation, which uses * equality semantics for the retrieveal. Other implementations * may override this. * * @param _value The inserted value. * @param _index The insertion key. * * @return The retrieved object. Returns OREF_NULL if the object * was not found. */ RexxObject *RexxHashTableCollection::put(RexxObject *_value, RexxObject *_index) { /* try to place in existing hashtab */ RexxHashTable *newHash = this->contents->put(_value, _index); if (newHash != OREF_NULL) /* have a reallocation occur? */ { /* hook on the new hash table */ OrefSet(this, this->contents, newHash); } return OREF_NULL; /* always return nothing */ }
RexxObject *RexxHashTableCollection::copy(void) /******************************************************************************/ /* Function: Copy a hash based collection object */ /******************************************************************************/ { /* make a copy of ourself (this also */ /* copies the object variables */ RexxHashTableCollection *newObj = (RexxHashTableCollection *)this->RexxObject::copy(); /* We copy the Hash table as well */ OrefSet(newObj, newObj->contents, (RexxHashTable *)this->contents->copy()); return newObj; /* return the new object */ }
void RexxVariable::drop() /****************************************************************************/ /* Function: Drop a variable */ /****************************************************************************/ { /* clear out the value */ OrefSet(this, this->variableValue, OREF_NULL); if (this->dependents != OREF_NULL) /* have notifications to process? */ { this->notify(); /* notify any dependents */ } }
/** * Supplier initializer for suppliers created via * .supplier~new(values, indexes). * * @param values The values array object * @param indexes The indexes array object * * @return Nothing */ RexxObject *RexxSupplier::initRexx(RexxArray *_values, RexxArray *_indexes) { requiredArgument(_values, ARG_ONE); // both values are required requiredArgument(_indexes, ARG_TWO); // now verify both values RexxArray *new_values = REQUEST_ARRAY(_values); RexxArray *new_indexes = REQUEST_ARRAY(_indexes); if (new_values == (RexxArray *)TheNilObject || new_values->getDimension() != 1) { reportException(Error_Incorrect_method_noarray, values); } if (new_indexes == (RexxArray *)TheNilObject || new_indexes->getDimension() != 1) { reportException(Error_Incorrect_method_noarray, indexes); } OrefSet(this, this->values, new_values); OrefSet(this, this->indexes, new_indexes); this->position = 1; return OREF_NULL; }
RexxObject *RexxBehaviour::define( RexxString *methodName, /* name of the defined method */ RexxMethod *method) /* method to add to the behaviour */ /******************************************************************************/ /* Function: Add or remove a method from an object's behaviour */ /******************************************************************************/ { RexxMethod * tableMethod; /* method from the table */ /* no method dictionary yet? */ if (this->methodDictionary == OREF_NULL) { /* allocate a table */ OrefSet(this, this->methodDictionary, new_table()); } if (method == OREF_NULL || method == TheNilObject) { /* replace the method with .nil */ this->methodDictionary->stringPut(TheNilObject, methodName); } else { /* already have this method? */ if ((tableMethod = (RexxMethod *)this->methodDictionary->stringGet(methodName)) == OREF_NULL) { /* No, just add this directly */ this->methodDictionary->stringAdd(method, methodName); } else { /* are the scopes the same? */ if (tableMethod->getScope() == method->getScope()) { /* same scope, so replace existing */ /* method with the new one */ this->methodDictionary->stringPut(method, methodName); } else { /* new scope, for this, just replace */ this->methodDictionary->stringAdd(method, methodName); } } } return OREF_NULL; /* always return nothing */ }
void RexxVariable::inform( RexxActivity *informee) /* activity to inform of changes */ /****************************************************************************/ /* Function: Set up an activity notification for a variable change */ /****************************************************************************/ { if (this->dependents == OREF_NULL) /* no dependents yet? */ { /* set this up as an object table */ OrefSet(this, this->dependents, new_identity_table()); } /* add this to the table */ this->dependents->put(TheNilObject, (RexxObject *)informee); }
void RexxVariable::uninform( RexxActivity *informee) /* activity to inform of changes */ /****************************************************************************/ /* Function: Remove a dependent from the notification list */ /****************************************************************************/ { /* remove the entry */ this->dependents->remove((RexxObject *)informee); if (this->dependents->items() == 0) /* last one? */ { /* drop the dependents list */ OrefSet(this, this->dependents, OREF_NULL); } }
RexxObject *RexxBehaviour::copy() /******************************************************************************/ /* Function: Copy the behaviour object with an independent named method */ /* dictionary, but leave the original create_class. */ /******************************************************************************/ { /* Instead of calling new_object and memcpy, ask the memory object to make*/ /* a copy of ourself. This way, any header information can be correctly */ /* initialized by memory. */ /* first, clone the existing object */ RexxBehaviour *newBehaviour = (RexxBehaviour *)this->clone(); ProtectedObject p(newBehaviour); /* have an method dictionary */ if (this->methodDictionary != OREF_NULL) { /* make a copy of this too */ OrefSet(newBehaviour, newBehaviour->methodDictionary, (RexxTable *)this->methodDictionary->copy()); } if (this->scopes != OREF_NULL) /* scope information? */ { /* make a copy of it too */ OrefSet(newBehaviour, newBehaviour->scopes, (RexxIdentityTable *)this->scopes->copy()); } /* do we have added methods? */ if (this->instanceMethodDictionary != OREF_NULL) { /* copy those also */ OrefSet(newBehaviour, newBehaviour->instanceMethodDictionary, (RexxTable *)this->instanceMethodDictionary->copy()); } /* use default operator methods set */ newBehaviour->operatorMethods = RexxObject::operatorMethods; /* all copied behaviours are */ /* non-primitive ones */ newBehaviour->setNonPrimitive(); return(RexxObject *)newBehaviour; /* return the copied behaviour */ }
void RexxCompoundTable::setRoot( RexxCompoundElement *newRoot) /******************************************************************************/ /* Function: Set the root node for a compound table. N.B., this cannot be an*/ /* inline method because of circular header file dependencies between */ /* RexxCompoundTable and RexxStem. */ /******************************************************************************/ { // NOTE: This seems a little weird, but we're doing the set using the parent // object...which will actually set the value in our own object instance. // This is done because the if we have checkSetOref turned on, the validity // checker won't recognize our address as being a valid object because it's // embedded within another Rexx object. OrefSet(parent, parent->tails.root, newRoot); }
RexxInstructionDrop::RexxInstructionDrop( size_t varCount, /* number of variables to process */ RexxQueue *variable_list) /* list of variables to drop */ /******************************************************************************/ /* Complete initialization of a DROP instruction */ /******************************************************************************/ { /* get the variable size */ variableCount = varCount; /* save the variable count */ while (varCount > 0) /* loop through the variable list */ { /* copying each variable */ OrefSet(this, this->variables[--varCount], (RexxVariableBase *)variable_list->pop()); } }
RexxInstructionProcedure::RexxInstructionProcedure( size_t varCount, /* number of variables */ RexxQueue *variable_list) /* supplied variable list */ /******************************************************************************/ /* Function: Complete initialization of a PROCEDURE instruction object */ /******************************************************************************/ { /* get the variable size */ variableCount = varCount; while (varCount > 0) /* loop through the variable list */ { /* copying each variable */ OrefSet(this, this->variables[--varCount], (RexxVariableBase *)variable_list->pop()); } }
RexxObject *RexxHashTableCollection::mergeItem(RexxObject *_value, RexxObject *_index) /******************************************************************************/ /* Arguments: Value, index */ /* */ /* Returned: Nothing */ /******************************************************************************/ { // put this in with duplicate protection RexxHashTable *newHash = this->contents->putNodupe(_value, _index); // the put can expand, so protect against that if (newHash != OREF_NULL) { OrefSet(this, this->contents, newHash); } return OREF_NULL; }
RexxObject *RexxBehaviour::addScope( RexxObject *scope) /* new scope for the scope table */ /******************************************************************************/ /* Function: Set a new set of scoping information for an object */ /******************************************************************************/ { if (this->scopes == OREF_NULL) /* no scopes set? */ { /* add a scope table to add to */ OrefSet(this, this->scopes, new_identity_table()); } /* set the scoping info */ this->scopes->add(scope, TheNilObject); /* add the scope list for this scope */ this->scopes->add(this->scopes->allAt(TheNilObject), scope); return OREF_NULL; /* return the big nothing */ }
RexxObject *RexxHashTableCollection::add( RexxObject *_value, /* object to add */ RexxObject *_index) /* added index */ /******************************************************************************/ /* Arguments: Value, index */ /* */ /* Returned: Nothing */ /******************************************************************************/ { /* try to place in existing hashtab */ RexxHashTable *newHash = this->contents->add(_value, _index); if (newHash != OREF_NULL) /* have a reallocation occur? */ { /* hook on the new hash table */ OrefSet(this, this->contents, newHash); } return OREF_NULL; /* always return nothing */ }
RexxInstructionThen::RexxInstructionThen( RexxToken *token, /* THEN keyword token */ RexxInstructionIf *_parent) /* target parent IF or WHEN clause */ /******************************************************************************/ /* Function: Initialize a THEN object */ /******************************************************************************/ { SourceLocation location; /* clause token location */ OrefSet(this, this->parent, _parent); /* remember the parent IF instruction*/ /* parent an IF instruction? */ if (this->parent->instructionType == KEYWORD_IF) { /* this is an IF ... THEN clause */ this->instructionType = KEYWORD_IFTHEN; } else /* actually a WHEN */ { this->instructionType = KEYWORD_WHENTHEN; } location = token->getLocation(); /* get the token location info */ this->setLocation(location); /* set the clause location also */ }
inline void expose(RexxCompoundElement *real) { OrefSet(this, this->real_element, real); }
RexxBuffer *RexxEnvelope::pack( RexxObject *_receiver) /* the receiver object */ /******************************************************************************/ /* Function: Pack an envelope item */ /******************************************************************************/ { RexxObject *flattenObj; /* flattened object */ RexxObject *newSelf; /* the flattened envelope */ RexxObject *firstObject; /* first object to flatten */ OrefSet(this, this->receiver, _receiver); // create a save table to protect any objects (such as proxy // objects) we create during flattening. OrefSet(this, this->savetable, new_identity_table()); OrefSet(this, this->duptable, new_identity_table()); // this is a bit of a hack, but necessary. This allows us to store // object offsets into a hashtable without having the hashtable // attempt to mark the references. duptable->contents->setHasNoReferences(); OrefSet(this, this->buffer, new RexxSmartBuffer(DEFAULT_ENVELOPE_BUFFER)); // get a flatten stack from the memory object this->flattenStack = memoryObject.getFlattenStack(); // push unique terminator onto stack this->flattenStack->fastPush(OREF_NULL); // First, put a header into the buffer. This is necessary because without // it, the envelope object would be at 0 offset into the buffer, which is not // distinguishable from OREF_NULL when the objects are unpacked from buffer. // the header is just a dummy minimal object instance. We don't bother adding // this to the dup table, as it won't ever be duped. this->copyBuffer(TheObjectClass->newObject()); // we start the flattening process with the received object firstObject = this->receiver; this->currentOffset = this->copyBuffer(firstObject); // make sure we add this to the dup table in case it's self-referential at any point associateObject(firstObject, this->currentOffset); /* point to the copied one */ newSelf = (RexxObject *)(this->bufferStart() + this->currentOffset); // ok, keep flattening until will find our marker object on the stack newSelf->flatten(this); /* start the flatten process. */ for (flattenObj = this->flattenStack->fastPop(); flattenObj != OREF_NULL; flattenObj = this->flattenStack->fastPop()) { // the popped object is actuall an object offset. We need to convert this into a // real object pointer this->currentOffset = (size_t)flattenObj; flattenObj = (RexxObject *)(this->bufferStart() + this->currentOffset); // and flatten the next object flattenObj->flatten(this); /* let this obj flatten its refs */ } memoryObject.returnFlattenStack(); /* done with the flatten stack */ // now unwrap the smart buffer and fix the length of the real buffer // behind it to the size we've written to it. RexxBuffer *letter = buffer->getBuffer(); letter->setDataLength(buffer->getDataLength()); return letter; }
/** * Perform an in-place unflatten operation on an object * in a buffer. * * @param sourceBuffer * The buffer containing the flattened object. * @param startPointer * The starting data location in the buffer. * @param dataLength The length of the data to unflatten */ void RexxEnvelope::puff(RexxBuffer *sourceBuffer, char *startPointer, size_t dataLength) { size_t primitiveTypeNum = 0; /* primitive behaviour type number */ char *bufferPointer = startPointer; /* copy the starting point */ /* point to end of buffer */ char *endPointer = (char *)startPointer + dataLength; RexxObject *puffObject = OREF_NULL; /* Set objoffset to the real address of the new objects. This tells */ /* mark_general to fix the object's refs and set their live flags. */ memoryObject.setObjectOffset((size_t)bufferPointer); /* Now traverse the buffer fixing all of the behaviour pointers of the objects. */ while (bufferPointer < endPointer) { puffObject = (RexxObject *)bufferPointer; /* a non-primitive behaviour */ /* These are actually in flattened */ /* storgage. */ if (puffObject->isNonPrimitive()) { /* Yes, lets get the behaviour Object*/ RexxBehaviour *objBehav = (RexxBehaviour *)(((uintptr_t)puffObject->behaviour) + sourceBuffer->getData()); /* Resolve the static behaviour info */ objBehav->resolveNonPrimitiveBehaviour(); /* Set this objects behaviour. */ puffObject->behaviour = objBehav; /* get the behaviour's type number */ primitiveTypeNum = objBehav->getClassType(); } else { // convert this from a type number to the actuall class. This will unnormalize the // type number to the different object classes. puffObject->behaviour = RexxBehaviour::restoreSavedPrimitiveBehaviour(puffObject->behaviour); primitiveTypeNum = puffObject->behaviour->getClassType(); } /* Force fix-up of */ /*VirtualFunctionTable, */ ((RexxObject *)bufferPointer)->setVirtualFunctions(RexxMemory::virtualFunctionTable[primitiveTypeNum]); puffObject->setObjectLive(memoryObject.markWord); /* Then Mark this object as live. */ /* Mark other referenced objs */ /* Note that this flavor of */ /* mark_general should update the */ /* mark fields in the objects. */ puffObject->liveGeneral(UNFLATTENINGOBJECT); /* Point to next object in image. */ bufferPointer += puffObject->getObjectSize(); } memoryObject.setObjectOffset(0); /* all done with the fixups! */ // Prepare to reveal the objects in the buffer. // the first object in the buffer is a dummy added // for padding. We need to step past that one to the // beginning of the real unflattened objects OrefSet(this, this->receiver, (RexxObject *)(startPointer + ((RexxObject *)startPointer)->getObjectSize())); /* chop off end of buffer to reveal */ /* its contents to memory obj */ // this is the location of the next object after the buffer char *nextObject = ((char *)sourceBuffer) + sourceBuffer->getObjectSize(); // this is the size of any tailing buffer portion after the last unflattened object. size_t tailSize = nextObject - endPointer; // puffObject is the last object we processed. Add any tail data size on to that object // so we don't create an invalid gap in the heap. puffObject->setObjectSize(puffObject->getObjectSize() + tailSize); // now adjust the front portion of the buffer object to reveal all of the // unflattened data. sourceBuffer->setObjectSize((char *)startPointer - (char *)sourceBuffer + ((RexxObject *)startPointer)->getObjectSize()); // move past the header to the real unflattened data bufferPointer = (char *)this->receiver; /* Set envelope to the real address of the new objects. This tells */ /* mark_general to send unflatten to run any proxies. */ memoryObject.setEnvelope(this); /* tell memory to send unflatten */ /* Now traverse the buffer running any proxies. */ while (bufferPointer < endPointer) { puffObject = (RexxObject *)bufferPointer; // Since a GC could happen at anytime we need to check to make sure the object // we are going now unflatten is still alive, since all who reference it may have already // run and gotten the info from it and no longer reference it. if (puffObject->isObjectLive(memoryObject.markWord)) { // Note that this flavor of liveGeneral will run any proxies // created by unflatten and fixup the refs to them. puffObject->liveGeneral(UNFLATTENINGOBJECT); } // Point to next object in image. bufferPointer += puffObject->getObjectSize(); } // Tell memory we're done unflattening memoryObject.setEnvelope(OREF_NULL); // Before we run the method we need to give any tables a chance to rehash... this->rehash(); }