/** * 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); }
/** * 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); }
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 */ }
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; }
/** * 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); }
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; } }
/** * 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(); }
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; }
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 */ } }