/**
 * Execute an IF/WHEN instruction.
 *
 * @param context The current execution context.
 * @param stack   The current evaluation stack.
 */
void RexxInstructionIf::execute(RexxActivation *context, ExpressionStack *stack)
{
    context->traceInstruction(this);

    // evaluate and trace the condition expression.
    RexxObject *result = condition->evaluate(context, stack);
    context->traceResult(result);

    // the comparison methods return either .true or .false, so we
    // can to a quick test against those.
    if (result == TheFalseObject)
    {
        // we execute the ELSE branch
        context->setNext(else_location->nextInstruction);
    }

    // if it is not the .true object, we need to perform a fuller
    // evaluation of the result.
    else if (result != TheTrueObject)
    {
        // evaluate and decide if we take the ELSE branch
        if (!result->truthValue(Error_Logical_value_if))
        {
            context->setNext(else_location->nextInstruction);
        }
    }

    // We do nothing for true...we just continue on to the next instruction.

    context->pauseInstruction();
}
/**
 * Do the actual invocation of the security manager.
 *
 * @param methodName The method name to invoke.
 * @param arguments  The arguments to the specific method.
 *
 * @return true if the security manager overrode this, false otherwise.
 */
bool SecurityManager::callSecurityManager(RexxString *methodName, DirectoryClass *arguments)
{
    ProtectedObject result;
    // invoke the manager
    RexxObject *resultObj = manager->sendMessage(methodName, arguments, result);
    // a result is required
    if (resultObj == OREF_NULL)
    {
        reportException(Error_No_result_object_message, methodName);
    }
    return resultObj->truthValue(Error_Logical_value_authorization);
}
예제 #3
0
/**
 * Return the current queue name.
 *
 * @return The name of the current queue.
 */
RexxString *Interpreter::getCurrentQueue()
{
    RexxObject *queue = ActivityManager::getLocalEnvironment(GlobalNames::STDQUE);

    if (queue == OREF_NULL)              // no queue set?  Default to session
    {
        return GlobalNames::SESSION;     // the session queue is the default
    }
    ProtectedObject result;
    // get the current name from the queue object.
    return(RexxString *)queue->sendMessage(GlobalNames::GET, result);
}
예제 #4
0
RexxObject  *RexxSupplierClass::newRexx(
    RexxObject **init_args,            /* subclass init arguments           */
    size_t argCount)                   /* count of arguments                */
/****************************************************************************/
/* Function:  Public REXX supplier new method                               */
/****************************************************************************/
{
    RexxObject *newObj = new RexxSupplier();
    ProtectedObject p(newObj);
    newObj->setBehaviour(this->getInstanceBehaviour());
    if (this->hasUninitDefined())
    {
        newObj->hasUninit();
    }
                                       /* Initialize the new instance       */
    newObj->sendMessage(OREF_INIT, init_args, argCount);
    return newObj;                       /* return the new supplier           */
}
예제 #5
0
size_t RexxEnvelope::copyBuffer(
    RexxObject *obj)                   /* object to copy                    */
/******************************************************************************/
/* Function:  Copy an object into our flatten buffer                          */
/******************************************************************************/
{
    // copy the object into the buffer, which might cause the buffer to
    // resize itself.
    size_t objOffset = this->buffer->copyData((void *)obj, obj->getObjectSize());
    // get a reference to the copied object
    RexxObject *newObj = (RexxObject *) (this->buffer->getBuffer()->getData() + objOffset);
    // if this is a non-primative behaviour, we need to flatten it as well.  The
    // offset is tagged as being a non-primitive behaviour that needs later inflating.
    if (newObj->behaviour->isNonPrimitive())
    {
        void *behavPtr = &newObj->behaviour;

        this->flattenReference(&newObj, objOffset, (RexxObject **)behavPtr);
    }
    else
    {
        // transient classes should never be flattened.  This is a problem if we encounter one
        if (newObj->behaviour->isTransientClass())
        {
            reportException(Error_Interpretation);
        }

        // just replace the behaviour with its normalized type number.  This will be used
        // to restore it later.
        newObj->behaviour = newObj->behaviour->getSavedPrimitiveBehaviour();
    }
    // if we flattened an object from oldspace, we just copied everything.  Make sure
    // this is no longer marked as oldspace
    newObj->setNewSpace();
    // the offset is what we need
    return objOffset;
}
예제 #6
0
/**
 * Execute a Delegate method forward operation.
 *
 * @param activity The current activity.
 * @param method   The method we're invoking.
 * @param receiver The receiver object.
 * @param messageName
 *                 The name of the message used to invoke the method.
 * @param argPtr   The pointer to the arguments.
 * @param count    The argument count.
 * @param result   The returned result.
 */
void DelegateCode::run(Activity *activity, MethodClass *method, RexxObject *receiver, RexxString *messageName,
    RexxObject **argPtr, size_t count, ProtectedObject &result)
{
    // get the variable pool and get
    VariableDictionary *objectVariables = receiver->getObjectVariables(method->getScope());
    RexxObject *target;

    // if this is a guarded method, we grab the guard only long enough to
    // get the target variable.  The message send is sent without holding the lock
    if (method->isGuarded())
    {
        objectVariables->reserve(activity);
        target = attribute->getValue(receiver->getObjectVariables(method->getScope()));
        // and ensure we release this afterwards
        objectVariables->release(activity);
    }
    else
    {
        target = attribute->getValue(receiver->getObjectVariables(method->getScope()));
    }

    // and finally, send the message to the resolved target
    target->sendMessage(messageName, argPtr, count, result);
}
예제 #7
0
void RexxEnvelope::flattenReference(
    void        *newThisVoid,          /* current pointer to flattening obj */
    size_t       newSelf,              /* offset of the flattening object   */
    void        *objRefVoid)           /* object to process                 */
/******************************************************************************/
/* Function: This method does the copy buffer,                                */
/******************************************************************************/
{
    RexxObject **newThis = (RexxObject **)newThisVoid;
    RexxObject **objRef  = (RexxObject **)objRefVoid;

    RexxObject *obj = *objRef;

                                          /* See if object has already been    */
    size_t objOffset = this->queryObj(obj); /* flattened.                        */
    // if this object has not been previously flattened, we need to
    // copy the object into the buffer and add the offset to the table.
    if (objOffset == 0)
    {
        // this is the sart of the buffer
        char *flattenBuffer = this->bufferStart();
        // this is the offset to the reference we're working with.  If the
        // buffer needs to reallocate after a copy, we need to be able to
        // locate this later
        size_t referenceOffset = (char *)objRef - flattenBuffer;

        // if this is a proxied object, we need to convert it to a proxy and
        // copy that object into the buffer and the reference table
        if (obj->isProxyObject())
        {
            // get a proxy and make sure it's in our protection table
            RexxObject *proxyObj = obj->makeProxy(this);
            savetable->put(proxyObj, proxyObj);

            // copy the proxy to the buffer and add it to the dup table
            // using the original object as the index.
            objOffset = this->copyBuffer(proxyObj);
            // it's not likely, but we might get a dup of the
            // proxy object too.  Add it to our resolution table.
            this->associateObject(proxyObj, objOffset);
        }
        else
        {

            // non-proxied object.  This gets copied to the buffer
            // directly and added to the dup table
            objOffset = this->copyBuffer(obj);
        }
        // regardless of how we handle this, add an association for the object to the offset
        this->associateObject(obj, objOffset);
        // We're pushing an object offset on to our live stack, so we want to make sure our debug traps
        // don't try to process this.
        memoryObject.disableOrefChecks();
        this->flattenStack->fastPush((RexxObject *)objOffset);
        memoryObject.enableOrefChecks();
        // if the buffer reallocated, we need to update the updating object pointer too.
        char *newBuffer = this->bufferStart();
        if (newBuffer != flattenBuffer)
        {
            *newThis = (RexxObject *) (newBuffer + newSelf);
        }
        // and update the reference with the offset
        *(RexxObject **)(newBuffer + referenceOffset) = (RexxObject *)objOffset;
    }
    else
    {
        // no copying means no reallocation...we just replace the
        // original object reference with the offset value
        *objRef = (RexxObject *)objOffset;
    }
}
예제 #8
0
/**
 * 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();
}
예제 #9
0
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;
}
예제 #10
0
void RexxInstructionForward::execute(
    RexxActivation      *context,      /* current activation context        */
    RexxExpressionStack *stack)        /* evaluation stack                  */
/******************************************************************************/
/* Function:  Execute a forward instruction                                   */
/******************************************************************************/
{
    RexxObject *_target;                  /* evaluated target                  */
    RexxString *_message;                 /* evaluated message                 */
    RexxObject *_superClass;              /* evaluated super class             */
    RexxObject *result;                  /* message result                    */
    RexxObject *temp;                    /* temporary object                  */
    size_t      count = 0;               /* count of array expressions        */
    size_t      i;                       /* loop counter                      */
    RexxObject **_arguments;

    ProtectedObject p_message;
    
    context->traceInstruction(this);     /* trace if necessary                */
    if (!context->inMethod())            /* is this a method clause?          */
    {
                                         /* raise an error                    */
        reportException(Error_Execution_forward);
    }
    _target = OREF_NULL;                  /* no object yet                     */
    _message = OREF_NULL;                 /* no message over ride              */
    _superClass = OREF_NULL;              /* no super class over ride          */
    _arguments = OREF_NULL;               /* no argument over ride             */

    if (this->target != OREF_NULL)       /* sent to a different object?       */
    {
                                         /* get the expression value          */
        _target = this->target->evaluate(context, stack);
    }
    if (this->message != OREF_NULL)    /* sending a different message?      */
    {
        /* get the expression value          */
        temp = this->message->evaluate(context, stack);
        _message = REQUEST_STRING(temp);    /* get the string version            */
        p_message = _message;
        _message = _message->upper();       /* and force to uppercase            */
        p_message = _message;
    }
    if (this->superClass != OREF_NULL)   /* overriding the super class?       */
    {
                                         /* get the expression value          */
        _superClass = this->superClass->evaluate(context, stack);
    }
    if (this->arguments != OREF_NULL)  /* overriding the arguments?         */
    {
        /* get the expression value          */
        temp = this->arguments->evaluate(context, stack);
        /* get an array version              */
        RexxArray *argArray = REQUEST_ARRAY(temp);
        stack->push(argArray);           /* protect this on the stack         */
        /* not an array item or a multiple   */
        /* dimension one?                    */
        if (argArray == TheNilObject || argArray->getDimension() != 1)
        {
            /* this is an error                  */
            reportException(Error_Execution_forward_arguments);
        }
        count = argArray->size();          /* get the size                      */
                                           /* omitted trailing arguments?       */
        if (count != 0 && argArray->get(count) == OREF_NULL)
        {
            count--;                         /* decrement the count               */
            while (count > 0)              /* loop down to first full one       */
            {
                /* find a real argument              */
                if (argArray->get(count) != OREF_NULL)
                {
                    break;                       /* break out of here                 */
                }
                count--;                       /* step back the count               */
            }
        }
        _arguments = argArray->data();    /* point directly to the argument data */
    }
    if (this->array != OREF_NULL)      /* have an array of extra info?      */
    {
        count = this->array->size();       /* get the expression count          */
        for (i = 1; i <= count; i++)     /* loop through the expression list  */
        {
            RexxObject *argElement = this->array->get(i);
            /* real argument?                    */
            if (argElement != OREF_NULL)
            {
                /* evaluate the expression           */
                argElement->evaluate(context, stack);
            }
            else
            {
                /* just push a null reference for the missing ones */
                stack->push(OREF_NULL);
            }
        }
        /* now point at the stacked values */
        _arguments = stack->arguments(count);
    }
    /* go forward this                   */
    result = context->forward(_target, _message, _superClass, _arguments, count, instructionFlags&forward_continue);
    if (instructionFlags&forward_continue)  /* not exiting?                      */
    {
        if (result != OREF_NULL)         /* result returned?                  */
        {
            context->traceResult(result);    /* trace if necessary                */
                                             /* set the RESULT variable to the    */
                                             /* message return value              */
            context->setLocalVariable(OREF_RESULT, VARIABLE_RESULT, result);
        }
        else                               /* drop the variable RESULT          */
        {
            context->dropLocalVariable(OREF_RESULT, VARIABLE_RESULT);
        }
        context->pauseInstruction();       /* do debug pause if necessary       */
    }
}