Ejemplo n.º 1
0
void StackVM::execute() {
	if (typ == 0 || typ == 2) {
		sp++;
		memory[sp] = dat;
	} else {
		doPrimitive();
	}
}
Ejemplo n.º 2
0
Archivo: vm.cpp Proyecto: 0x7CFE/llst
SmalltalkVM::TExecuteResult SmalltalkVM::execute(TProcess* p, uint32_t ticks)
{
    // Protecting the process pointer
    hptr<TProcess> currentProcess = newPointer(p);

    assert(currentProcess->context != 0);
    assert(currentProcess->context->method != 0);

    // Initializing an execution context
    TVMExecutionContext ec(m_memoryManager, this);
    ec.currentContext = currentProcess->context;
    ec.loadPointers(); // Loads bytePointer & stackTop

    while (true)
    {
        assert(ec.currentContext != 0);
        assert(ec.currentContext->method != 0);
        assert(ec.currentContext->stack != 0);
        assert(ec.bytePointer <= ec.currentContext->method->byteCodes->getSize());
        assert(ec.currentContext->arguments->getSize() >= 1);
        assert(ec.currentContext->arguments->getField(0) != 0);

        // Initializing helper references
        TByteObject&  byteCodes = * ec.currentContext->method->byteCodes;

        TObjectArray& temporaries       = * ec.currentContext->temporaries;
        TObjectArray& arguments         = * ec.currentContext->arguments;
        TObjectArray& instanceVariables = * arguments.getField<TObjectArray>(0);
        TSymbolArray& literals          = * ec.currentContext->method->literals;

        if (ticks && (--ticks == 0)) {
            // Time frame expired
            ec.storePointers();
            currentProcess->context = ec.currentContext;
            currentProcess->result  = ec.returnedValue;

            return returnTimeExpired;
        }

        // Decoding the instruction
        const uint16_t lastBytePointer = ec.bytePointer;
        ec.instruction = st::InstructionDecoder::decodeAndShiftPointer(byteCodes, ec.bytePointer);

        // And executing it
        switch (ec.instruction.getOpcode()) {
            case opcode::pushInstance:    ec.stackPush(instanceVariables[ec.instruction.getArgument()]); break;
            case opcode::pushArgument:    ec.stackPush(arguments[ec.instruction.getArgument()]);         break;
            case opcode::pushTemporary:   ec.stackPush(temporaries[ec.instruction.getArgument()]);       break;
            case opcode::pushLiteral:     ec.stackPush(literals[ec.instruction.getArgument()]);          break;
            case opcode::pushConstant:    doPushConstant(ec);                                  break;
            case opcode::pushBlock:       doPushBlock(ec);                                     break;

            case opcode::assignTemporary: temporaries[ec.instruction.getArgument()] = ec.stackLast();    break;
            case opcode::assignInstance: {
                TObject*  newValue   =   ec.stackLast();
                TObject** objectSlot = & instanceVariables[ec.instruction.getArgument()];

                // Checking whether we need to register current object slot in the GC
                checkRoot(newValue, objectSlot);

                // Performing the assignment
                *objectSlot = newValue;
            } break;

            case opcode::markArguments: doMarkArguments(ec); break;

            case opcode::sendMessage:   doSendMessage(ec);   break;
            case opcode::sendUnary:     doSendUnary(ec);     break;
            case opcode::sendBinary:    doSendBinary(ec);    break;

            case opcode::doPrimitive: {
                TExecuteResult result = doPrimitive(currentProcess, ec);
                if (result != returnNoReturn)
                    return result;
            } break;

            case opcode::doSpecial: {
                TExecuteResult result = doSpecial(currentProcess, ec);
                if (result != returnNoReturn)
                    return result;
            } break;

            default:
                std::fprintf(stderr, "VM: Invalid opcode %d at offset %d in method ", ec.instruction.getOpcode(), lastBytePointer);
                std::fprintf(stderr, "'%s'\n", ec.currentContext->method->name->toString().c_str() );
                std::exit(1);
        }
    }
}
Ejemplo n.º 3
0
HOT void sendSuperMessage(VMGlobals *g, PyrSymbol *selector, long numArgsPushed)
{
	PyrMethod *meth = NULL;
	PyrMethodRaw *methraw;
	PyrSlot *recvrSlot, *sp;
	PyrClass *classobj;
	long index;
	PyrObject *obj;

	//postfl("->sendMessage\n");
#ifdef GC_SANITYCHECK
	g->gc->SanityCheck();
	CallStackSanity(g, "sendSuperMessage");
#endif
	recvrSlot = g->sp - numArgsPushed + 1;

	classobj = slotRawSymbol(&slotRawClass(&g->method->ownerclass)->superclass)->u.classobj;
	//assert(isKindOfSlot(recvrSlot, classobj));

	lookup_again:
	index = slotRawInt(&classobj->classIndex) + selector->u.index;
	meth = gRowTable[index];

	if (slotRawSymbol(&meth->name) != selector) {
		doesNotUnderstand(g, selector, numArgsPushed);
	} else {
		methraw = METHRAW(meth);
		//postfl("methraw->methType %d\n", methraw->methType);
		switch (methraw->methType) {
			case methNormal : /* normal msg send */
				executeMethod(g, meth, numArgsPushed);
				break;
			case methReturnSelf : /* return self */
				g->sp -= numArgsPushed - 1;
				break;
			case methReturnLiteral : /* return literal */
				sp = g->sp -= numArgsPushed - 1;
				slotCopy(sp, &meth->selectors); /* in this case selectors is just a single value */
				break;
			case methReturnArg : /* return an argument */
				sp = g->sp -= numArgsPushed - 1;
				index = methraw->specialIndex; // zero is index of the first argument
				if (index < numArgsPushed) {
					slotCopy(sp, sp + index);
				} else {
					slotCopy(sp, &slotRawObject(&meth->prototypeFrame)->slots[index]);
				}
				break;
			case methReturnInstVar : /* return inst var */
				sp = g->sp -= numArgsPushed - 1;
				index = methraw->specialIndex;
				slotCopy(sp, &slotRawObject(recvrSlot)->slots[index]);
				break;
			case methAssignInstVar : /* assign inst var */
				sp = g->sp -= numArgsPushed - 1;
				index = methraw->specialIndex;
				obj = slotRawObject(recvrSlot);
				if (obj->IsImmutable()) { StoreToImmutableB(g, sp, g->ip); }
				else {
					if (numArgsPushed >= 2) {
						slotCopy(&obj->slots[index], sp + 1);
						g->gc->GCWrite(obj, sp + 1);
					} else {
						SetNil(&obj->slots[index]);
					}
					slotCopy(sp, recvrSlot);
				}
				break;
			case methReturnClassVar : /* return class var */
				sp = g->sp -= numArgsPushed - 1;
				slotCopy(sp, &g->classvars->slots[methraw->specialIndex]);
				break;
			case methAssignClassVar : /* assign class var */
				sp = g->sp -= numArgsPushed - 1;
				if (numArgsPushed >= 2) {
					slotCopy(&g->classvars->slots[methraw->specialIndex], sp + 1);
					g->gc->GCWrite(g->classvars, sp + 1);
				} else {
					SetNil(&g->classvars->slots[methraw->specialIndex]);
				}
				slotCopy(sp, recvrSlot);
				break;
			case methRedirect : /* send a different selector to self, e.g. this.subclassResponsibility */
				if (numArgsPushed < methraw->numargs) { // not enough args pushed
					/* push default arg values */
					PyrSlot *pslot, *qslot;
					long m, mmax;
					pslot = g->sp;
					qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
					for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot);
					numArgsPushed = methraw->numargs;
					g->sp += mmax;
				}
				selector = slotRawSymbol(&meth->selectors);
				goto lookup_again;
			case methRedirectSuper : /* send a different selector to self, e.g. this.subclassResponsibility */
				if (numArgsPushed < methraw->numargs) { // not enough args pushed
					/* push default arg values */
					PyrSlot *pslot, *qslot;
					long m, mmax;
					pslot = g->sp;
					qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
					for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot);
					numArgsPushed = methraw->numargs;
					g->sp += mmax;
				}
				selector = slotRawSymbol(&meth->selectors);
				classobj = slotRawSymbol(&slotRawClass(&meth->ownerclass)->superclass)->u.classobj;
				goto lookup_again;
			case methForwardInstVar : /* forward to an instance variable */
				if (numArgsPushed < methraw->numargs) { // not enough args pushed
					/* push default arg values */
					PyrSlot *pslot, *qslot;
					long m, mmax;
					pslot = g->sp;
					qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
					for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot);
					numArgsPushed = methraw->numargs;
					g->sp += mmax;
				}
				selector = slotRawSymbol(&meth->selectors);
				index = methraw->specialIndex;
				slotCopy(recvrSlot, &slotRawObject(recvrSlot)->slots[index]);

				classobj = classOfSlot(recvrSlot);

				goto lookup_again;
			case methForwardClassVar : /* forward to a class variable */
				if (numArgsPushed < methraw->numargs) { // not enough args pushed
					/* push default arg values */
					PyrSlot *pslot, *qslot;
					long m, mmax;
					pslot = g->sp;
					qslot = slotRawObject(&meth->prototypeFrame)->slots + numArgsPushed - 1;
					for (m=0, mmax=methraw->numargs - numArgsPushed; m<mmax; ++m) slotCopy(++pslot, ++qslot);
					numArgsPushed = methraw->numargs;
					g->sp += mmax;
				}
				selector = slotRawSymbol(&meth->selectors);
				slotCopy(recvrSlot, &g->classvars->slots[methraw->specialIndex]);

				classobj = classOfSlot(recvrSlot);

				goto lookup_again;
			case methPrimitive : /* primitive */
				doPrimitive(g, meth, (int)numArgsPushed);
#ifdef GC_SANITYCHECK
	g->gc->SanityCheck();
#endif
				break;
			/*
			case methMultDispatchByClass : {
				index = methraw->specialIndex;
				if (index < numArgsPushed) {
					classobj = slotRawObject(sp + index)->classptr;
					selector = slotRawSymbol(&meth->selectors);
					goto lookup_again;
				} else {
					doesNotUnderstand(g, selector, numArgsPushed);
				}
			} break;
			case methMultDispatchByValue : {
				index = methraw->specialIndex;
				if (index < numArgsPushed) {
					index = arrayAtIdentityHashInPairs(array, b);
					meth = slotRawObject(&meth->selectors)->slots[index + 1].uom;
					goto meth_select_again;
				} else {
					doesNotUnderstand(g, selector, numArgsPushed);
				}
			} break;
			*/

		}
	}
#if TAILCALLOPTIMIZE
	g->tailCall = 0;
#endif
#ifdef GC_SANITYCHECK
	g->gc->SanityCheck();
	CallStackSanity(g, "<sendSuperMessage");
#endif
	//postfl("<-sendMessage\n");
}