void Interpreter::subInts() { int64_t top = popInt(); int64_t down = popInt(); int64_t sub = top - down; pushInt(sub); }
void Interpreter::iMul() { int64_t i1 = popInt(); int64_t i2 = popInt(); //cout << "Multiplying " << i1 << " " << i2 << endl; pushInt(i1*i2); }
void Interpreter::divInts() { int64_t right = popInt(); int64_t left = popInt(); //cout << "Dividing " << left << " " << right << endl; pushInt(left / right); }
/* * Execute the PUTFIELD instruction */ void op_putfield() { Ref field = resolve(u16(1), ID_FIELD); if (field == NULL) { return; } // rollback // read values from stack Int size = getInt(field, FIELD_SIZE); Int flag = getInt(field, FIELD_REFERENCE_FLAG); Int value2 = (size == 2) ? popInt() : 0; Word value1; if (flag) { value1.r = popRef(); } else { value1.i = popInt(); } Ref object = popRef(); // check for null pointer if (object == NULL) { throwException(CORE_THROW_NULL_POINTER); return; } // store the values Int index = getInt(field, FIELD_INDEX) + OBJECT_FIELDS; if (flag) { setRef(object, index, value1.r); } else { setInt(object, index, value1.i); } if (size == 2) { setInt(object, index + 1, value2); } pc += 3; }
void Interpreter::addInts() { int64_t top = popInt(); int64_t down = popInt(); int64_t sum = top + down; pushInt(sum); //cout << "adding ints" << endl; }
void Interpreter::GJump() { int64_t top = popInt(); int64_t down = popInt(); int16_t offset = getNext2SBytes(); if (down > top) { jump(offset); //cout << "Jumping " << offset << endl; } }
void Interpreter::intsNotEqualJMP() { int64_t top = popInt(); int64_t down = popInt(); int16_t offset = getNext2SBytes(); if (top != down) { jump(offset); //cout << "Jumping " << offset << endl; } }
int get_integer_parameter( StackFrame *stack, SimpleConstantPool *p) { int value = 0; if ( is_ref_entry(stack) ) { int index = popInt(stack); value = get_integer_from_constant_pool(p, index); } else { value = popInt(stack); } return value; }
// isub int op_isub( unsigned char **opCode, StackFrame *stack, SimpleConstantPool *p ) { int value2 = popInt(stack); int value1 = popInt(stack); int result = 0; result = value1 - value2; #if SIMPLE_JVM_DEBUG printf("isub : %d - %d = %d\n", value1, value2, result); #endif pushInt(stack, result); *opCode = *opCode + 1; return 0; }
void Interpreter::compareInts() { //cout << "Comparing "; int64_t top = popInt(); int64_t down = popInt(); //cout << down << " " << top << endl; int64_t result = (down > top) ? 1 : (down == top) ? 0 : -1; pushInt(result); }
/* irem */ static int op_irem(unsigned char **opCode, StackFrame *stack, SimpleConstantPool *p) { int value1 = popInt(stack); int value2 = popInt(stack); int result = 0; result = value2 % value1; #if SIMPLE_JVM_DEBUG printf("irem: %d mod %d = %d\n", value2, value1, result); #endif pushInt(stack, result); *opCode = *opCode + 1; return 0; }
/* * Execute the ANEWARRAY instruction */ void op_anewarray() { Ref type = resolve(u16(1), ID_TYPE); if (type == NULL) { return; } // rollback, gc done Ref arrayType = getRef(type, TYPE_ARRAY_TYPE); // resolve array type if (arrayType == NULL) { Ref target = getRef(core, OBJECT_TYPE); Ref method = getRef(core, CORE_RESOLVE_METHOD); executeMethod(target, method, 0); return; // rollback } // allocate space int length = peekInt(); // don't pop yet in case gc runs int numWords = ARRAY_DATA + length; Ref array = allocate(numWords, HEADER_OBJECT_ARRAY); if (array == NULL) { return; } // rollback, gc done popInt(); // pop length // initialise array object and push on stack int hash = (char*) array - (char*) core; setInt(array, OBJECT_HASHCODE, hash); setRef(array, OBJECT_TYPE, arrayType); setInt(array, ARRAY_LENGTH, length); pushRef(array); pc += 3; }
void Interpreter::loadFunParamsInCtx(uint16_t id) { BytecodeFunction* fun = ((BytecodeFunction*)_code->functionById(id)); uint16_t n = fun->parametersNumber(); FunctionContext* ctx = this->topContext(); //cout << "loading params: " << n << endl; //cout << "stack size " << _stack.size() << endl; for (uint16_t i = 0; i < n; ++i) { VarType type = fun->parameterType(i); switch (type) { case VT_INT: ctx->storeInt(ctx->getId(), i, popInt()); //cout << "int loaded from bc" << endl; break; case VT_DOUBLE: ctx->storeDouble(ctx->getId(), i, popDouble()); //cout << "double loaded from bc" << endl; break; default: //cout << "loading STRIG or INVALID from bc" << endl; assert(false); break; } } }
/* * Execute the PUTSTATIC instruction */ void op_putstatic() { Ref field = resolve(u16(1), ID_FIELD); if (field == NULL) { return; } // rollback // read field values Ref type = getRef(field, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); Int index = getInt(field, FIELD_INDEX); Int flag = getInt(field, FIELD_REFERENCE_FLAG); Int size = getInt(field, FIELD_SIZE); int offset = STATICS_FIELDS + index; // pop values from stack and store if (size == 2) { setInt(statics, offset, popInt()); } if (flag) { setRef(statics, offset, popRef()); } else { setInt(statics, offset, popInt()); } pc += 3; }
//istore_3 int op_istore_3( unsigned char **opCode, StackFrame *stack, SimpleConstantPool *p ) { int value = popInt(stack); #if SIMPLE_JVM_DEBUG printf("istore_3: store value into local variable 3(%d)\n", value); #endif localVariables.integer[3] = value; *opCode = *opCode + 1; return 0; }
//istore int op_istore( unsigned char **opCode, StackFrame *stack, SimpleConstantPool *p ) { int value = popInt(stack); int index = opCode[0][1]; #if SIMPLE_JVM_DEBUG printf("istore: store value into local variable %d(%d)\n", index, value); #endif localVariables.integer[index] = value; *opCode = *opCode + 2; return 0; }
long long get_long_parameter( StackFrame *stack, SimpleConstantPool *p) { long long value = 0; if ( is_ref_entry(stack) ) { int index = popInt(stack); value = get_long_from_constant_pool(p, index); } else { value = popLong(stack); } return value; }
static double get_double_parameter(StackFrame *stack, SimpleConstantPool *p) { double value = 0.0f; if (is_ref_entry(stack)) { int index = popInt(stack); value = get_double_from_constant_pool(p, index); #if SIMPLE_JVM_DEBUG printf("index %d\n", index); printf("get value from constant pool = %f\n", value); #endif } else { value = popDouble(stack); #if SIMPLE_JVM_DEBUG printf("get value from stack = %f\n", value); #endif } return value; }
/* * Execute the NEWARRAY instruction */ void op_newarray() { // figure out the required size int atype = u8(1); int width = getWidth(atype); int length = peekInt(); // don't pop in case rolled back later int numBytes = length * width; int extra = ((numBytes % 4) == 0) ? 0 : 1; int numDataWords = (numBytes / 4) + extra; int numWords = numDataWords + ARRAY_DATA; // allocate space Ref array = allocate(numWords, HEADER_DATA_ARRAY); if (array == NULL) { return; } // rollback, gc done popInt(); // can pop the length now // initialise new array and push address on stack int hash = (char*) array - (char*) core; Ref type = getRef(core, CORE_ARRAYS + atype); setInt(array, OBJECT_HASHCODE, hash); setRef(array, OBJECT_TYPE, type); setInt(array, ARRAY_LENGTH, length); pushRef(array); pc += 2; }
/************************************************************* * Function: postfixEvaluation () * Created: February 6th, 2012 * Last Revised: February 10th, 2012 * Description: This function evaluates a postfix expression * Input parameters: the postfix expression * Returns: the value of the expression * Preconditions: an expression needs to be evaluated * Postconditions: an expression has been evaluated *************************************************************/ int postfixEvaluation (char *postfixEquation) { // variables char *pPostfix, tempMulti[256] = "", tempSingle; IntDataStack *tempStack = NULL; int value = 0, numA = 0, numB = 0, i = 0, j = 0; // setup the infix pointers pPostfix = &postfixEquation[0]; // while we're not at the end of the postfix string... while (*pPostfix != '\0') { // remove any spaces if necessary... while(*pPostfix == ' ') { pPostfix++; } // if the next character is a digit... if(isdigit(*pPostfix)) { // build the integer... while (isdigit(*pPostfix)) { tempSingle = *pPostfix; tempMulti[i] = tempSingle; *pPostfix++; i++; } // push the built integer onto the stack pushInt(&tempStack, atoi(tempMulti)); // move through the integer builder array and clear it for (j = 0; j <= i; j++) { tempMulti[j] = '\0'; } // set i to 0 i = 0; } // otherwise... else { // if the next character is an operator... if ((*pPostfix == '+') || (*pPostfix == '-') || (*pPostfix == '/') || (*pPostfix == '*') || (*pPostfix == '%')) { // pop off the last two numbers from the stack numB = popInt(&tempStack); numA = popInt(&tempStack); // if the operator is a +, add the two numbers and push the value onto the stack if (*pPostfix == '+') { value = numA + numB; pushInt(&tempStack,value); } // if the operator is a -, add the two numbers and push the value onto the stack else if (*pPostfix == '-') { value = numA - numB; pushInt(&tempStack,value); } // if the operator is a *, add the two numbers and push the value onto the stack else if (*pPostfix == '*') { value = numA * numB; pushInt(&tempStack,value); } // if the operator is a /, add the two numbers and push the value onto the stack else if (*pPostfix == '/') { value = numA / numB; pushInt(&tempStack,value); } // if the operator is a %, add the two numbers and push the value onto the stack else if (*pPostfix == '%') { value = numA % numB; pushInt(&tempStack,value); } // otherwise, say that there was a problem evaluating the expression... else { printf ("Failed to evaluate Expression!\n"); return -1; } } } // if the character is not a null character move to the next if (*pPostfix != '\0') { pPostfix++; } } // pop the final value off the stack and return it... value = popInt(&tempStack); return value; }
/* * Execute the specified native method. Return true if the method * is executed, false if it is rolled back for garbage collection. */ int executeNativeMethod(Ref target, Ref method, int offset) { int magic = getInt(method, METHOD_MAGIC); if (magic == 0) { printf("Native method not supported\n"); debugTrace(); exit(1); } switch (magic) { // print a debug message case MAGIC_RUNTIME_CORE_DEBUG: debugLine(popRef()); pc += offset; break; // execute the given static method case MAGIC_RUNTIME_CORE_EXECUTE_STATIC: { Ref staticMethod = popRef(); if (staticMethod == NULL) { throwException(CORE_THROW_NULL_POINTER); return; } Ref owner = getRef(staticMethod, ENTRY_OWNER); if (!executeMethod(owner, staticMethod, offset)) { // restore stack if rolled back for gc pushRef(staticMethod); } } break; // return the current frame case MAGIC_RUNTIME_FRAME_CURRENT: pushRef(frame); pc += offset; break; // return the core object case MAGIC_RUNTIME_CORE_GET: pushRef(core); pc += offset; break; // create a statics object case MAGIC_RUNTIME_STATICS_CREATE: { // allocate space for statics object Ref type = popRef(); Int numStaticFields = getInt(type, TYPE_STATIC_FIELD_COUNT); Int numWords = STATICS_FIELDS + numStaticFields; Ref statics = allocate(numWords, HEADER_STATIC_FIELDS); if (statics == NULL) { pushRef(type); // restore stack return; // rollback, gc done } // initialise statics object and set in type object int hash = (char*) statics - (char*) core; setInt(statics, OBJECT_HASHCODE, hash); Ref staticsType = getRef(core, CORE_STATICS_TYPE); setRef(statics, OBJECT_TYPE, staticsType); Ref map = getRef(type, TYPE_STATIC_MAP); setRef(statics, STATICS_MAP, map); setRef(type, TYPE_STATICS, statics); } pc += offset; break; // read the type from a class case MAGIC_RUNTIME_CORE_GET_TYPE: { Ref class = popRef(); // type is first field in class... Ref type = getRef(class, OBJECT_FIELDS); pushRef(type); } pc += offset; break; // put system to sleep to avoid wasting processor time while idle case MAGIC_RUNTIME_IDLE_SLEEP: idleSleep(); pc += offset; break; // return the currently executing thread case MAGIC_RUNTIME_THREAD_CURRENT: pushRef(thread); pc += offset; break; // start a new thread case MAGIC_RUNTIME_THREAD_START_HOOK: startNewThread(offset); break; // return an object's class case MAGIC_JAVA_OBJECT_GET_CLASS: { Ref obj = popRef(); Ref type = getRef(obj, OBJECT_TYPE); Ref peer = getRef(type, TYPE_PEER); pushRef(peer); } pc += offset; break; // set system output stream case MAGIC_JAVA_SYSTEM_SET_OUT: { Ref arg = popRef(); Ref type = getRef(method, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); setRef(statics, STATICS_FIELDS + SYSTEM_OUT, arg); } pc += offset; break; // set system error stream case MAGIC_JAVA_SYSTEM_SET_ERR: { Ref arg = popRef(); Ref type = getRef(method, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); setRef(statics, STATICS_FIELDS + SYSTEM_ERR, arg); } pc += offset; break; // set system input stream case MAGIC_JAVA_SYSTEM_SET_IN: { Ref arg = popRef(); Ref type = getRef(method, ENTRY_OWNER); Ref statics = getRef(type, TYPE_STATICS); setRef(statics, STATICS_FIELDS + SYSTEM_IN, arg); } pc += offset; break; // read an ascii character from the console case MAGIC_TEST_READ_FROM_CONSOLE: { char c = readFromConsole(); pushInt(c); } pc += offset; break; // write an ascii character to the console case MAGIC_TEST_WRITE_TO_CONSOLE: { char c = popInt() & 0xFF; printf("%c", c); } pc += offset; break; // read a byte from the floppy drive case MAGIC_TEST_READ_FROM_FLOPPY: { Int pos = popInt(); pushInt(readFromFloppy(pos)); } pc += offset; break; // magic id not recognised default: printf("Invalid magic method id: %d\n", magic); exit(1); break; } }
/* Read Type 13 charstring. Initial seek to offset performed if offset != -1 */ static void t13Read(cffCtx h, Offset offset, int init, int csLen) { unsigned length; switch (init) { case cstr_GLYPH: /* Initialize glyph charstring */ h->stack.cnt = 0; h->path.nStems = 0; h->path.flags = GET_WIDTH|FIRST_MOVE|FIRST_MASK; break; case cstr_DICT: /* Initialize DICT charstring */ h->path.flags = DICT_CSTR; break; case cstr_METRIC: /* Initialize metric charstring */ h->stack.cnt = 0; h->path.flags = 0; break; } if (offset != -1) /* Seek to position of charstring if not already positioned */ seekbyte(h, offset); for (;;) { int j; Fixed a; Fixed b; int byte0 = GETBYTE(h); switch (byte0) { case t13_endchar: if (!(h->path.flags & DICT_CSTR)) { if (h->path.flags & FIRST_MOVE) { /* Non-marking glyph; set bounds */ h->path.left = h->path.right = 0; h->path.bottom = h->path.top = 0; } if ((h->path.flags & GET_WIDTH) && setAdvance(h)) return; /* Stop after getting width */ if (h->stack.cnt > 1) { /* Process seac components */ int base; int accent; j = (h->stack.cnt == 4)? 0: 1; a = indexFix(h, j++); b = indexFix(h, j++); base = indexInt(h, j++); accent = indexInt(h, j); setComponentBounds(h, 0, base, 0, 0); setComponentBounds(h, 1, accent, a, b); } } PATH_FUNC_CALL(endchar,(h->cb.ctx)); h->path.flags |= SEEN_END; return; case t13_reserved0: case t13_reserved236: case t13_reserved237: case t13_reserved244: case t13_reserved255: fatal(h, "reserved charstring op"); case t13_rlineto: for (j = 0; j < h->stack.cnt; j += 2) addLine(h, indexFix(h, j + 0), indexFix(h, j + 1)); h->stack.cnt = 0; break; case t13_hlineto: case t13_vlineto: { int horz = byte0 == t13_hlineto; for (j = 0; j < h->stack.cnt; j++) if (horz++ & 1) addLine(h, indexFix(h, j), 0); else addLine(h, 0, indexFix(h, j)); } h->stack.cnt = 0; break; case t13_rrcurveto: for (j = 0; j < h->stack.cnt; j += 6) addCurve(h, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4), indexFix(h, j + 5)); h->stack.cnt = 0; break; case t13_callsubr: { Offset save = TELL(h); Offset localOffset = INDEXGet(h, &h->index.Subrs, popInt(h) + h->index.Subrs.bias, &length); t13Read(h, localOffset, cstr_NONE, length); if (h->path.flags & SEEN_END) return; /* endchar operator terminated subr */ seekbyte(h, save); } break; case t13_return: return; case t13_rcurveline: for (j = 0; j < h->stack.cnt - 2; j += 6) addCurve(h, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4), indexFix(h, j + 5)); addLine(h, indexFix(h, j + 0), indexFix(h, j + 1)); h->stack.cnt = 0; break; case t13_rlinecurve: for (j = 0; j < h->stack.cnt - 6; j += 2) addLine(h, indexFix(h, j + 0), indexFix(h, j + 1)); addCurve(h, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4), indexFix(h, j + 5)); h->stack.cnt = 0; break; case t13_vvcurveto: if (h->stack.cnt & 1) { /* Add initial curve */ addCurve(h, 0, indexFix(h, 0), indexFix(h, 1), indexFix(h, 2), indexFix(h, 3), 0, indexFix(h, 4)); j = 5; } else j = 0; /* Add remaining curve(s) */ for (; j < h->stack.cnt; j += 4) addCurve(h, 0, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), 0, indexFix(h, j + 3)); h->stack.cnt = 0; break; case t13_hhcurveto: if (h->stack.cnt & 1) { /* Add initial curve */ addCurve(h, 0, indexFix(h, 1), indexFix(h, 0), indexFix(h, 2), indexFix(h, 3), indexFix(h, 4), 0); j = 5; } else j = 0; /* Add remaining curve(s) */ for (; j < h->stack.cnt; j += 4) addCurve(h, 0, indexFix(h, j + 0), 0, indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), 0); h->stack.cnt = 0; break; case t13_callgsubr: { Offset save = TELL(h); Offset localOffset = INDEXGet(h, &h->index.global, popInt(h) + h->index.global.bias, &length); t13Read(h, localOffset, cstr_NONE, length); if (h->path.flags & SEEN_END) return; /* endchar operator terminated subr */ seekbyte(h, save); } break; case t13_vhcurveto: case t13_hvcurveto: { int adjust = (h->stack.cnt & 1)? 5: 0; int horz = byte0 == t13_hvcurveto; /* Add initial curve(s) */ for (j = 0; j < h->stack.cnt - adjust; j += 4) if (horz++ & 1) addCurve(h, 0, indexFix(h, j + 0), 0, indexFix(h, j + 1), indexFix(h, j + 2), 0, indexFix(h, j + 3)); else addCurve(h, 0, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), 0); if (j < h->stack.cnt) { /* Add last curve */ if (horz & 1) addCurve(h, 0, indexFix(h, j + 0), 0, indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 4), indexFix(h, j + 3)); else addCurve(h, 0, 0, indexFix(h, j + 0), indexFix(h, j + 1), indexFix(h, j + 2), indexFix(h, j + 3), indexFix(h, j + 4)); } h->stack.cnt = 0; } break; case t13_rmoveto: b = popFix(h); a = popFix(h); if (addMove(h, a, b)) return; /* Stop after getting width */ h->stack.cnt = 0; break; case t13_hmoveto: if (addMove(h, popFix(h), 0)) return; /* Stop after getting width */ h->stack.cnt = 0; break; case t13_vmoveto: if (addMove(h, 0, popFix(h))) return; /* Stop after getting width */ h->stack.cnt = 0; break; case t13_hstem: case t13_vstem: case t13_hstemhm: case t13_vstemhm: if ((h->path.flags & GET_WIDTH) && setAdvance(h)) return; /* Stop after getting width */ h->path.nStems += h->stack.cnt / 2; if (PATH_FUNC_DEFINED(hintstem)) { int vert = byte0 == tx_vstem || byte0 == t2_vstemhm; b = vert? h->path.vstem: h->path.hstem; for (j = h->stack.cnt & 1; j < h->stack.cnt; j += 2) { a = b + indexFix(h, j); b = a + indexFix(h, j + 1); h->path.cb->hintstem(h->cb.ctx, vert, a, b); } if (vert) h->path.vstem = b; else h->path.hstem = b; } h->stack.cnt = 0; break; case t13_hintmask: case t13_cntrmask: { int cnt; if (h->path.flags & FIRST_MASK) { /* The vstem(hm) op may be omitted if stem list is followed by a mask op. In this case count the additional stems */ if (PATH_FUNC_DEFINED(hintstem)) { b = h->path.vstem; for (j = h->stack.cnt & 1; j < h->stack.cnt; j += 2) { a = b + indexFix(h, j); b = a + indexFix(h, j + 1); h->path.cb->hintstem(h->cb.ctx, 1, a, b); } } h->path.nStems += h->stack.cnt / 2; h->stack.cnt = 0; h->path.flags &= ~FIRST_MASK; } cnt = (h->path.nStems + 7) / 8; if (PATH_FUNC_DEFINED(hintmask)) { char mask[CFF_MAX_MASK_BYTES]; for (j = 0; j < cnt; j++) mask[j] = GETBYTE(h); h->path.cb->hintmask(h->cb.ctx, byte0 == t2_cntrmask, cnt, mask); } else while (cnt--) (void)GETBYTE(h); /* Discard mask bytes */ } break; case t13_escape: { double x; double y; switch (t13_ESC(GETBYTE(h))) { case t13_dotsection: break; default: case t13_reservedESC255: case t13_cntron: fatal(h, "reserved charstring op"); case t13_and: b = popFix(h); a = popFix(h); pushInt(h, a && b); break; case t13_or: b = popFix(h); a = popFix(h); pushInt(h, a || b); break; case t13_not: a = popFix(h); pushInt(h, !a); break; case t13_store: { int count = popInt(h); int i = popInt(h); int j = popInt(h); int iReg = popInt(h); int regSize; Fixed *reg = selRegItem(h, iReg, ®Size); if (i < 0 || i + count - 1 >= h->BCA.size || j < 0 || j + count - 1 >= regSize) fatal(h, "bounds check (store)\n"); memcpy(®[j], &h->BCA.array[i], sizeof(Fixed) * count); } break; case t13_abs: a = popFix(h); pushFix(h, (a < 0)? -a: a); break; case t13_add: b = popFix(h); a = popFix(h); pushFix(h, a + b); break; case t13_sub: b = popFix(h); a = popFix(h); pushFix(h, a - b); break; case t13_div: y = popDbl(h); x = popDbl(h); if (y == 0.0) fatal(h, "divide by zero (div)"); pushFix(h, DBL2FIX(x / y)); break; case t13_load: { int regSize; int count = popInt(h); int i = popInt(h); int iReg = popInt(h); Fixed *reg = selRegItem(h, iReg, ®Size); if (i < 0 || i + count - 1 >= h->BCA.size || count > regSize) fatal(h, "bounds check (load)\n"); memcpy(&h->BCA.array[i], reg, sizeof(Fixed) * count); } break; case t13_neg: a = popFix(h); pushFix(h, -a); break; case t13_eq: b = popFix(h); a = popFix(h); pushInt(h, a == b); break; case t13_drop: (void)popFix(h); break; case t13_put: { int i = popInt(h); if (i < 0 || i >= h->BCA.size) fatal(h, "bounds check (put)\n"); h->BCA.array[i] = popFix(h); } break; case t13_get: { int i = popInt(h); if (i < 0 || i >= h->BCA.size) fatal(h, "bounds check (get)\n"); pushFix(h, h->BCA.array[i]); } break; case t13_ifelse: { Fixed v2 = popFix(h); Fixed v1 = popFix(h); Fixed s2 = popFix(h); Fixed s1 = popFix(h); pushFix(h, (v1 > v2)? s2: s1); } break; case t13_random: pushFix(h, PMRand()); break; case t13_mul: y = popDbl(h); x = popDbl(h); pushFix(h, DBL2FIX(x * y)); break; case t13_sqrt: pushFix(h, FixedSqrt(popFix(h))); break; case t13_dup: pushFix(h, h->stack.array[h->stack.cnt - 1].f); break; case t13_exch: b = popFix(h); a = popFix(h); pushFix(h, b); pushFix(h, a); break; case t13_index: { int i = popInt(h); if (i < 0) i = 0; /* Duplicate top element */ if (i >= h->stack.cnt) fatal(h, "limit check (index)"); pushFix(h, h->stack.array[h->stack.cnt - 1 - i].f); } break; case t13_roll: { int j = popInt(h); int n = popInt(h); int iTop = h->stack.cnt - 1; int iBottom = h->stack.cnt - n; if (n < 0 || iBottom < 0) fatal(h, "limit check (roll)"); /* Constrain j to [0,n) */ if (j < 0) j = n - (-j % n); j %= n; reverse(h, iTop - j + 1, iTop); reverse(h, iBottom, iTop - j); reverse(h, iBottom, iTop); } break; case t13_hflex: addCurve(h, 1, indexFix(h, 0), 0, indexFix(h, 1), indexFix(h, 2), indexFix(h, 3), 0); addCurve(h, 1, indexFix(h, 4), 0, indexFix(h, 5), 0, indexFix(h, 6), -indexFix(h, 2)); h->stack.cnt = 0; break; case t13_flex: addCurve(h, 1, indexFix(h, 0), indexFix(h, 1), indexFix(h, 2), indexFix(h, 3), indexFix(h, 4), indexFix(h, 5)); addCurve(h, 1, indexFix(h, 6), indexFix(h, 7), indexFix(h, 8), indexFix(h, 9), indexFix(h, 10), indexFix(h, 11)); h->stack.cnt = 0; break; case t13_hflex1: { Fixed dy1 = indexFix(h, 1); Fixed dy2 = indexFix(h, 3); Fixed dy5 = indexFix(h, 7); addCurve(h, 1, indexFix(h, 0), dy1, indexFix(h, 2), dy2, indexFix(h, 4), 0); addCurve(h, 1, indexFix(h, 5), 0, indexFix(h, 6), dy5, indexFix(h, 8), -(dy1 + dy2 + dy5)); } h->stack.cnt = 0; break; case t13_flex1: { Fixed dx1 = indexFix(h, 0); Fixed dy1 = indexFix(h, 1); Fixed dx2 = indexFix(h, 2); Fixed dy2 = indexFix(h, 3); Fixed dx3 = indexFix(h, 4); Fixed dy3 = indexFix(h, 5); Fixed dx4 = indexFix(h, 6); Fixed dy4 = indexFix(h, 7); Fixed dx5 = indexFix(h, 8); Fixed dy5 = indexFix(h, 9); Fixed dx = dx1 + dx2 + dx3 + dx4 + dx5; Fixed dy = dy1 + dy2 + dy3 + dy4 + dy5; if (ABS(dx) > ABS(dy)) { dx = indexFix(h, 10); dy = -dy; } else { dx = -dx; dy = indexFix(h, 10); } addCurve(h, 1, dx1, dy1, dx2, dy2, dx3, dy3); addCurve(h, 1, dx4, dy4, dx5, dy5, dx, dy); } h->stack.cnt = 0; break; } } break; case t13_blend: blendValues(h); break; default: /* Matches 1..215, result -107..107 */ pushInt(h, 108 - byte0); break; case 241: /* 108..363 */ pushInt(h, 363 - GETBYTE(h)); break; case 239: /* 364..619 */ pushInt(h, 619 - GETBYTE(h)); break; case 246: /* 620..875 */ pushInt(h, GETBYTE(h) + 620); break; case 235: /* 876..1131 */ pushInt(h, 1131 - GETBYTE(h)); break; case 232: /* -108..-363 */ pushInt(h, GETBYTE(h) - 363); break; case 228: /* -364..-619 */ pushInt(h, GETBYTE(h) - 619); break; case 224: /* -620..-875 */ pushInt(h, GETBYTE(h) - 875); break; case 220: /* -876..-1131 */ pushInt(h, GETBYTE(h) - 1131); break; case t13_shortint: { /* 2 byte number */ long byte1 = GETBYTE(h); pushInt(h, byte1<<8 | GETBYTE(h)); } break; case t13_shftshort: { long byte1 = GETBYTE(h); pushFix(h, byte1<<23 | GETBYTE(h)<<15); } break; case 254: { /* 5 byte number */ long byte1 = GETBYTE(h); long byte2 = GETBYTE(h); long byte3 = GETBYTE(h); pushFix(h, byte1<<24 | byte2<<16 | byte3<<8 | GETBYTE(h)); } break; } } }
/* * Execute the specified method. Return true if the method is executed, * false if it is rolled back for garbage collection. * * target: object for instance methods, class for static * method: the method to be run * offset: amount to increment program counter */ int executeMethod(Ref target, Ref method, int offset) { /* printf("["); if (method[ENTRY_FLAGS].i & ACC_STATIC) { debugString(target[TYPE_NAME].s); } else { debugString(method[ENTRY_OWNER].s[TYPE_NAME].s); } printf("."); debugString(method[ENTRY_NAME].s); debugString(method[ENTRY_DESCRIPTOR].s); printf("]\n"); */ // check for native method Int argcount = getInt(method, METHOD_ARG_COUNT); Int flags = getInt(method, ENTRY_FLAGS); if (flags & ACC_NATIVE) { return executeNativeMethod(target, method, offset); } // if synchronized, acquire the lock Ref lock = NULL; if (flags & ACC_SYNCHRONIZED) { lock = getLock(target); if (lock == NULL) { return FALSE; } // rollback, gc done acquireLock(thread, lock, 0); if (thread == NULL) { return FALSE; } // rollback, wait for lock } // allocate space for new frame Int maxLocals = getInt(method, METHOD_MAX_LOCALS); Int maxStack = getInt(method, METHOD_MAX_STACK); int numWords = FRAME_LOCALS + 2*maxLocals + 2*maxStack; Ref newFrame = allocate(numWords, HEADER_STACK_FRAME); if (newFrame == NULL) { return FALSE; } // rollback, gc done // increment lock count now that instruction can't be rolled back if (flags & ACC_SYNCHRONIZED) { Int count = getInt(lock, LOCK_COUNT); setInt(lock, LOCK_COUNT, count + 1); } // initialise new frame int hash = (char*) newFrame - (char*) core; Ref frameType = getRef(frame, OBJECT_TYPE); setInt(newFrame, OBJECT_HASHCODE, hash); setRef(newFrame, OBJECT_LOCK, lock); setRef(newFrame, OBJECT_TYPE, frameType); setRef(newFrame, FRAME_RETURN_FRAME, frame); setRef(newFrame, FRAME_METHOD, method); setInt(newFrame, FRAME_RETURN_PC, pc + offset); setInt(newFrame, FRAME_PC, 0); setInt(newFrame, FRAME_SP, numWords * 4); // pop arguments off current stack and write to new frame int index = argcount; while (--index >= 0) { if (refOnStack()) { setLocalRef(index, popRef(), newFrame); } else { setLocalInt(index, popInt(), newFrame); } } // point current thread to new frame saveRegisters(); setRef(thread, THREAD_FRAME, newFrame); loadRegisters(); return TRUE; }
/*Procedure that interprets current frame bytecode * Uses loop with switch statement.*/ YValue* EXECUTE_PROC(YObject* scope, YThread* th) { ExecutionFrame* frame = (ExecutionFrame*) th->frame; frame->regs[0] = (YValue*) scope; YRuntime* runtime = th->runtime; ILBytecode* bc = frame->bytecode; size_t code_len = frame->proc->code_length; while (frame->pc + 13 <= code_len) { // If runtime is paused then execution should be paused too. if (runtime->state == RuntimePaused) { th->state = ThreadPaused; while (runtime->state == RuntimePaused) YIELD(); th->state = ThreadWorking; } // Decode opcode and arguments uint8_t opcode = frame->proc->code[frame->pc]; int32_t* args = (int32_t*) &(frame->proc->code[frame->pc + 1]); const int32_t iarg0 = args[0]; const int32_t iarg1 = args[1]; const int32_t iarg2 = args[2]; // Call debugger before each instruction if nescesarry YBreakpoint breakpoint = { .procid = frame->proc->id, .pc = frame->pc }; DEBUG(th->runtime->debugger, instruction, &breakpoint, th); // Interpret opcode // See virtual machine description switch (opcode) { case VM_Halt: break; case VM_LoadConstant: { /*All constants during execution should be stored in pool. * If pool contains constant id, then constant is returned*/ YObject* cpool = th->runtime->Constants.pool; if (cpool->contains(cpool, iarg1, th)) { SET_REGISTER(cpool->get(cpool, iarg1, th), iarg0, th); break; } /*Else it is created, added to pool and returned*/ Constant* cnst = bc->getConstant(bc, iarg1); YValue* val = getNull(th); if (cnst != NULL) { switch (cnst->type) { case IntegerC: val = newInteger(cnst->value.i64, th); break; case FloatC: val = newFloat(cnst->value.fp64, th); break; case StringC: val = newString( bc->getSymbolById(bc, cnst->value.string_id), th); break; case BooleanC: val = newBoolean(cnst->value.boolean, th); break; default: break; } } cpool->put(cpool, iarg1, val, true, th); SET_REGISTER(val, iarg0, th); } break; case VM_LoadInteger: { /*Load integer from argument directly to register*/ YValue* val = newInteger(iarg1, th); SET_REGISTER(val, iarg0, th); } break; case VM_Copy: { /*Copy register value to another*/ SET_REGISTER(getRegister(iarg1, th), iarg0, th); } break; case VM_Push: { /*Push register value to stack*/ push(getRegister(iarg0, th), th); } break; case VM_PushInteger: { push(newInteger(iarg0, th), th); } break; /*Next instructions load values from two registers, * perform polymorph binary operation and * save result to third register*/ case VM_Add: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.add_operation(v1, v2, th), iarg0, th); } break; case VM_Subtract: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.subtract_operation(v1, v2, th), iarg0, th); } break; case VM_Multiply: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.multiply_operation(v1, v2, th), iarg0, th); } break; case VM_Divide: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.divide_operation(v1, v2, th), iarg0, th); } break; case VM_Modulo: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.modulo_operation(v1, v2, th), iarg0, th); } break; case VM_Power: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.power_operation(v1, v2, th), iarg0, th); } break; case VM_ShiftRight: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.shr_operation(v1, v2, th), iarg0, th); } break; case VM_ShiftLeft: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.shl_operation(v1, v2, th), iarg0, th); } break; case VM_And: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.and_operation(v1, v2, th), iarg0, th); } break; case VM_Or: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.or_operation(v1, v2, th), iarg0, th); } break; case VM_Xor: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(v1->type->oper.xor_operation(v1, v2, th), iarg0, th); } break; case VM_Compare: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); SET_REGISTER(newInteger(v1->type->oper.compare(v1, v2, th), th), iarg0, th); } break; case VM_Test: { /*Take an integer from register and * check if certain bit is 1 or 0*/ YValue* arg = getRegister(iarg1, th); if (arg->type == &th->runtime->IntType) { int64_t i = ((YInteger*) arg)->value; YValue* res = newBoolean((i & iarg2) != 0, th); SET_REGISTER(res, iarg0, th); } else SET_REGISTER(getNull(th), iarg0, th); } break; case VM_FastCompare: { YValue* v1 = getRegister(iarg0, th); YValue* v2 = getRegister(iarg1, th); int i = v1->type->oper.compare(v1, v2, th); YValue* res = newBoolean((i & iarg2) != 0, th); SET_REGISTER(res, iarg0, th); } break; /*These instruction perform polymorph unary operations*/ case VM_Negate: { YValue* v1 = getRegister(iarg1, th); SET_REGISTER(v1->type->oper.negate_operation(v1, th), iarg0, th); } break; case VM_Not: { YValue* v1 = getRegister(iarg1, th); SET_REGISTER(v1->type->oper.not_operation(v1, th), iarg0, th); } break; case VM_Increment: { YValue* v1 = getRegister(iarg1, th); if (v1->type == &th->runtime->IntType) { int64_t i = getInteger(v1, th); i++; SET_REGISTER(newInteger(i, th), iarg0, th); } else if (v1->type==&th->runtime->FloatType) { double i = getFloat(v1, th); i++; SET_REGISTER(newFloat(i, th), iarg0, th); } else { SET_REGISTER(v1, iarg0, th); } } break; case VM_Decrement: { YValue* v1 = getRegister(iarg1, th); if (v1->type == &th->runtime->IntType) { int64_t i = getInteger(v1, th); i--; SET_REGISTER(newInteger(i, th), iarg0, th); } else if (v1->type==&th->runtime->FloatType) { double i = getFloat(v1, th); i--; SET_REGISTER(newFloat(i, th), iarg0, th); } else { SET_REGISTER(v1, iarg0, th); } } break; case VM_Call: { /*Invoke lambda from register. * Arguments stored in stack. * Argument count passed as argument*/ size_t argc = (size_t) popInt(th); /* YValue** args = malloc(sizeof(YValue*) * argc); for (size_t i = argc - 1; i < argc; i--) args[i] = pop(th);*/ YValue** args = &((ExecutionFrame*) th->frame)->stack[((ExecutionFrame*) th->frame)->stack_offset] - argc; ((ExecutionFrame*) th->frame)->stack_offset -= argc; YValue* val = getRegister(iarg1, th); YObject* scope = NULL; if (iarg2 != -1) { YValue* scl = getRegister(iarg2, th); if (scl->type == &th->runtime->ObjectType) scope = (YObject*) scl; else { scope = th->runtime->newObject(NULL, th); OBJECT_NEW(scope, L"value", scl, th); } } if (val->type == &th->runtime->LambdaType) { YLambda* l = (YLambda*) val; SET_REGISTER(invokeLambda(l, scope, args, argc, th), iarg0, th); } else { throwException(L"CallingNotALambda", NULL, 0, th); SET_REGISTER(getNull(th), iarg0, th); } //free(args); } break; case VM_Return: { /*Verify register value to be some type(if defined) * and return it. Execution has been ended*/ YValue* ret = getRegister(iarg0, th); if (((ExecutionFrame*) th->frame)->retType != NULL && !((ExecutionFrame*) th->frame)->retType->verify( ((ExecutionFrame*) th->frame)->retType, ret, th)) { wchar_t* wstr = toString(ret, th); throwException(L"Wrong return type", &wstr, 1, th); free(wstr); return getNull(th); } return ret; } case VM_NewObject: { /*Create object with parent(if defined)*/ YValue* p = getRegister(iarg1, th); if (iarg1 != -1 && p->type == &th->runtime->ObjectType) { YObject* obj = th->runtime->newObject((YObject*) p, th); SET_REGISTER((YValue*) obj, iarg0, th); } else SET_REGISTER((YValue*) th->runtime->newObject(NULL, th), iarg0, th); } break; case VM_NewArray: { /*Create empty array*/ SET_REGISTER((YValue*) newArray(th), iarg0, th); } break; case VM_NewLambda: { /*Create lambda. Lambda signature is stored in stack. * It is popped and formed as signature*/ // Check if lambda is vararg YValue* vmeth = pop(th); bool meth = (vmeth->type == &th->runtime->BooleanType) ? ((YBoolean*) vmeth)->value : false; YValue* vvararg = pop(th); bool vararg = (vvararg->type == &th->runtime->BooleanType) ? ((YBoolean*) vvararg)->value : false; // Get argument count and types size_t argc = (size_t) popInt(th); int32_t* argids = calloc(1, sizeof(int32_t) * argc); YoyoType** argTypes = calloc(1, sizeof(YoyoType*) * argc); for (size_t i = argc - 1; i < argc; i--) { argids[i] = (int32_t) popInt(th); YValue* val = pop(th); if (val->type == &th->runtime->DeclarationType) argTypes[i] = (YoyoType*) val; else argTypes[i] = val->type->TypeConstant; } // Get lambda return type YValue* retV = pop(th); YoyoType* retType = NULL; if (retV->type == &th->runtime->DeclarationType) retType = (YoyoType*) retV; else retType = retV->type->TypeConstant; // Get lambda scope from argument and create // lambda signature and lambda YValue* sp = getRegister(iarg2, th); if (sp->type == &th->runtime->ObjectType) { YObject* scope = (YObject*) sp; YLambda* lmbd = newProcedureLambda(iarg1, bc, scope, argids, newLambdaSignature(meth, argc, vararg, argTypes, retType, th), th); SET_REGISTER((YValue*) lmbd, iarg0, th); } else SET_REGISTER(getNull(th), iarg0, th); // Free allocated resources free(argids); free(argTypes); } break; case VM_NewOverload: { /*Pop lambdas from stack and * create overloaded lambda*/ // Pop lambda count and lambdas size_t count = (size_t) iarg1; YLambda** lambdas = malloc(sizeof(YLambda*) * count); for (size_t i = 0; i < count; i++) { YValue* val = pop(th); if (val->type == &th->runtime->LambdaType) lambdas[i] = (YLambda*) val; else lambdas[i] = NULL; } // If default lambda is defined then get it YLambda* defLmbd = NULL; if (iarg2 != -1) { YValue* val = getRegister(iarg2, th); if (val->type == &th->runtime->LambdaType) defLmbd = (YLambda*) val; } // Create overloaded lambda SET_REGISTER( (YValue*) newOverloadedLambda(lambdas, count, defLmbd, th), iarg0, th); // Free allocated resources free(lambdas); } break; case VM_NewComplexObject: { /*Pop mixin objects from stack and create complex object*/ // Get mixin count and pop mixins size_t count = (size_t) iarg2; YObject** mixins = malloc(sizeof(YObject*) * count); for (size_t i = 0; i < count; i++) { YValue* val = pop(th); if (val->type == &th->runtime->ObjectType) mixins[i] = (YObject*) val; else mixins[i] = NULL; } // Get base object YValue* basev = getRegister(iarg1, th); YObject* base = NULL; if (basev->type == &th->runtime->ObjectType) base = (YObject*) basev; else base = th->runtime->newObject(NULL, th); // Create complex object and free allocated resources SET_REGISTER((YValue*) newComplexObject(base, mixins, count, th), iarg0, th); free(mixins); } break; case VM_GetField: { /*Read value property and store it in register*/ YValue* val = getRegister(iarg1, th); if (val->type->oper.readProperty != NULL) { SET_REGISTER(val->type->oper.readProperty(iarg2, val, th), iarg0, th); } else SET_REGISTER(getNull(th), iarg0, th); } break; case VM_SetField: { /*Set objects field*/ YValue* val = getRegister(iarg0, th); if (val->type == &th->runtime->ObjectType) { YObject* obj = (YObject*) val; obj->put(obj, iarg1, getRegister(iarg2, th), false, th); } } break; case VM_NewField: { /*Create new field in object*/ YValue* val = getRegister(iarg0, th); if (val->type == &th->runtime->ObjectType) { YObject* obj = (YObject*) val; obj->put(obj, iarg1, getRegister(iarg2, th), true, th); } } break; case VM_DeleteField: { /*Delete field from object*/ YValue* val = getRegister(iarg0, th); if (val->type == &th->runtime->ObjectType) { YObject* obj = (YObject*) val; obj->remove(obj, iarg1, th); } } break; case VM_ArrayGet: { /*Get index from value. If can't then throw exception*/ YValue* val = getRegister(iarg1, th); YValue* val2 = getRegister(iarg2, th); // If value is array, but index is integer then // reads array element at index if (val->type == &th->runtime->ArrayType && val2->type == &th->runtime->IntType) { YArray* arr = (YArray*) val; size_t index = (size_t) ((YInteger*) val2)->value; SET_REGISTER(arr->get(arr, index, th), iarg0, th); } else if (val->type->oper.readIndex != NULL) { // Else calls readIndex on type(if readIndex is defined) SET_REGISTER(val->type->oper.readIndex(val, val2, th), iarg0, th); } else { throwException(L"AccesingNotAnArray", NULL, 0, th); SET_REGISTER(getNull(th), iarg0, th); } } break; case VM_ArraySet: { /*Set value to other value on index. If can't throw exception*/ YValue* val = getRegister(iarg0, th); YValue* val2 = getRegister(iarg1, th); // If value if array, but index is integer // then assigns value to an array if (val->type == &th->runtime->ArrayType && val2->type == &th->runtime->IntType) { YArray* arr = (YArray*) val; size_t index = (size_t) ((YInteger*) val2)->value; arr->set(arr, index, getRegister(iarg2, th), th); } else if (val->type->oper.readIndex != NULL) { // Else calls writeIndex on type(if writeIndex is defined) val->type->oper.writeIndex(val, val2, getRegister(iarg2, th), th); } else { throwException(L"ModifyingNotAnArray", NULL, 0, th); } } break; case VM_ArrayDelete: { /*If value is array but index is integer set array index * else throw an exception*/ YValue* val = getRegister(iarg0, th); YValue* val2 = getRegister(iarg1, th); if (val->type == &th->runtime->ArrayType && val2->type == &th->runtime->IntType) { YArray* arr = (YArray*) val; size_t index = (size_t) ((YInteger*) val2)->value; arr->remove(arr, index, th); } else if (val->type->oper.removeIndex !=NULL) { val->type->oper.removeIndex(val, val2, th); } else { throwException(L"ModifyingNotAnArray", NULL, 0, th); } } break; case VM_Goto: { /*Get label id from argument, get label address and jump*/ uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } break; case VM_GotoIfTrue: { /*Get label id from argument, get label address and jump * if condition is true*/ YValue* bln = getRegister(iarg1, th); if (bln->type == &th->runtime->BooleanType && ((YBoolean*) bln)->value) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_GotoIfFalse: { /*Get label id from argument, get label address and jump * if condition is false*/ YValue* bln = getRegister(iarg1, th); if (bln->type == &th->runtime->BooleanType && !((YBoolean*) bln)->value) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_Jump: { /*Goto to an address*/ frame->pc = iarg0; continue; } break; case VM_JumpIfTrue: { /*Goto to an address if condition is true*/ YValue* bln = getRegister(iarg1, th); if (bln->type == &th->runtime->BooleanType && ((YBoolean*) bln)->value) { frame->pc = iarg0; continue; } } break; case VM_JumpIfFalse: { /*Goto to an address if condition is false*/ YValue* bln = getRegister(iarg1, th); if (bln->type == &th->runtime->BooleanType && !((YBoolean*) bln)->value) { frame->pc = iarg0; continue; } } break; case VM_Throw: { /*Throw an exception*/ th->exception = newException(getRegister(iarg0, th), th); } break; case VM_Catch: { /*Save current exception in register and * set exception NULL*/ SET_REGISTER(th->exception, iarg0, th); th->exception = NULL; } break; case VM_OpenCatch: { /*Add next catch address to frame catch stack. * If exception is thrown then catch address being * popped from stack and interpreter * jump to it*/ CatchBlock* cb = malloc(sizeof(CatchBlock)); cb->prev = frame->catchBlock; cb->pc = iarg0; frame->catchBlock = cb; } break; case VM_CloseCatch: { /*Remove catch address from frame catch stack*/ CatchBlock* cb = frame->catchBlock; frame->catchBlock = cb->prev; free(cb); } break; case VM_Nop: { /*Does nothing*/ } break; case VM_Swap: { /*Swap two register values*/ YValue* r1 = getRegister(iarg0, th); YValue* r2 = getRegister(iarg1, th); SET_REGISTER(r1, iarg1, th); SET_REGISTER(r2, iarg0, th); } break; case VM_Subsequence: { /*Get subsequence from value if subseq method * is defined*/ YValue* reg = getRegister(iarg0, th); YValue* tfrom = getRegister(iarg1, th); YValue* tto = getRegister(iarg2, th); if (tfrom->type == &th->runtime->IntType&& tto->type == &th->runtime->IntType&& reg->type->oper.subseq!=NULL) { size_t from = (size_t) ((YInteger*) tfrom)->value; size_t to = (size_t) ((YInteger*) tto)->value; SET_REGISTER(reg->type->oper.subseq(reg, from, to, th), iarg0, th); } else SET_REGISTER(getNull(th), iarg0, th); } break; case VM_Iterator: { /*Get iterator from value if it is iterable*/ YValue* v = getRegister(iarg1, th); if (v->type->oper.iterator != NULL) { SET_REGISTER((YValue*) v->type->oper.iterator(v, th), iarg0, th);\ } else { SET_REGISTER(getNull(th), iarg0, th); } } break; case VM_Iterate: { /*If iterator has next value than get it and save * to register. If iterator doesn't has next value * then jump to a label*/ YValue* v = getRegister(iarg1, th); YValue* value = NULL; if (v->type->oper.iterator != NULL) { YoyoIterator* iter = v->type->oper.iterator(v, th); if (iter->hasNext(iter, th)) value = iter->next(iter, th); } if (value == NULL) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg2)->value; frame->pc = addr; } else SET_REGISTER(value, iarg0, th); } break; case VM_NewInterface: { /*Build new interface*/ YoyoAttribute* attrs = calloc(1, sizeof(YoyoAttribute) * iarg2); // Pop interface parents YoyoInterface** parents = calloc(1, sizeof(YoyoInterface*) * iarg1); for (int32_t i = 0; i < iarg1; i++) { YValue* val = pop(th); YoyoType* type = NULL; if (val->type == &th->runtime->DeclarationType) type = (YoyoType*) val; else type = val->type->TypeConstant; parents[i] = type->type == InterfaceDT ? (YoyoInterface*) type : NULL; } // Pop interface fields for (int32_t i = 0; i < iarg2; i++) { attrs[i].id = popInt(th); YValue* val = pop(th); YoyoType* type = NULL; if (val->type == &th->runtime->DeclarationType) type = (YoyoType*) val; else type = val->type->TypeConstant; attrs[i].type = type; } // Build interface and free allocated resources SET_REGISTER( (YValue*) newInterface(parents, (size_t) iarg1, attrs, (size_t) iarg2, th), iarg0, th); free(attrs); free(parents); } break; case VM_ChangeType: { /*Change field type*/ YValue* val = getRegister(iarg2, th); YoyoType* type = NULL; if (val->type == &th->runtime->DeclarationType) type = (YoyoType*) val; else type = val->type->TypeConstant; YValue* o = getRegister(iarg0, th); if (o->type == &th->runtime->ObjectType) { YObject* obj = (YObject*) o; obj->setType(obj, iarg1, type, th); } } break; case VM_GotoIfEquals: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_EQUALS) != 0) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_JumpIfEquals: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_EQUALS) != 0) { frame->pc = iarg0; continue; } } break; case VM_GotoIfNotEquals: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_NOT_EQUALS) != 0) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_JumpIfNotEquals: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_NOT_EQUALS) != 0) { frame->pc = iarg0; continue; } } break; case VM_GotoIfGreater: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_GREATER) != 0) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_JumpIfGreater: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_GREATER) != 0) { frame->pc = iarg0; continue; } } break; case VM_GotoIfLesser: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_LESSER) != 0) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_JumpIfLesser: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_LESSER) != 0) { frame->pc = iarg0; continue; } } break; case VM_GotoIfNotLesser: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_GREATER_OR_EQUALS) != 0) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_JumpIfNotLesser: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_GREATER_OR_EQUALS) != 0) { frame->pc = iarg0; continue; } } break; case VM_GotoIfNotGreater: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_LESSER_OR_EQUALS) != 0) { uint32_t addr = frame->proc->getLabel(frame->proc, iarg0)->value; frame->pc = addr; continue; } } break; case VM_JumpIfNotGreater: { YValue* v1 = getRegister(iarg1, th); YValue* v2 = getRegister(iarg2, th); int cmp = v1->type->oper.compare(v1, v2, th); if ((cmp & COMPARE_LESSER_OR_EQUALS) != 0) { frame->pc = iarg0; continue; } } break; case VM_CheckType: { YValue* value = getRegister(iarg0, th); YValue* tv = getRegister(iarg1, th); YoyoType* type = NULL; if (tv->type == &th->runtime->DeclarationType) type = (YoyoType*) tv; else type = tv->type->TypeConstant; if (!type->verify(type, value, th)) { wchar_t* wcs = getSymbolById(&th->runtime->symbols, iarg2); throwException(L"WrongFieldType", &wcs, 1, th); } } break; } /*If there is an exception then get last catch block * and jump to an address. If catch stack is empty * then return from procedure*/ if (th->exception != NULL) { if (frame->catchBlock != NULL) { frame->pc = frame->proc->getLabel(frame->proc, frame->catchBlock->pc)->value; continue; } else return getNull(th); } frame->pc += 13; } return getNull(th); }
void BenchmarkTcpClient::handle(Event &event, long long) { if (&event == &eventRead) { int prevSize = readBuffer.size(); readBuffer.reserve(1024); readBuffer.push(socket->read(readBuffer.end(), 1024)); receviedSize += readBuffer.size() - prevSize; eventRead.setTimeRelativeNow(); if (readBuffer.empty()) return; if (!writeBuffer.empty()) { formatError(); return; } if (server) { if (hasInt() && !requestsCount) { requestsCount = popInt(); if (requestsCount <= 0) { formatError(); return; } requestsCountRemain = requestsCount; } if (hasInt() && !requestSize) { requestSize = popInt(); if (requestSize <= 0) { formatError(); return; } if (requestsCountRemain <= 0) { formatError(); return; } --requestsCountRemain; } if (hasInt() && !answerSize) { answerSize = popInt(); if (answerSize <= 0) { formatError(); return; } requestSizeRemain = requestSize; } if (requestSizeRemain > 0) { currentCrc32 = Packet::crc32(readBuffer.begin(), readBuffer.size(), currentCrc32); requestSizeRemain -= readBuffer.size(); readBuffer.clear(); if (requestSizeRemain < 0) { formatError(); return; } if (requestSizeRemain == 0) { currentSeed = currentCrc32; currentCrc32 = 0; answerSizeRemain = answerSize; buildWriteChunk(); } } } else { while(!empty()) { if (answerSizeRemain <= 0 || pop() != (char)((int)random(currentSeed)%256 - 128)) { formatError(); return; } --answerSizeRemain; } if (answerSizeRemain == 0) { if (requestsCountRemain == 0) { socket->close(); return; } requestSizeRemain = requestSize; buildWriteChunk(); } } } else if (&event == &eventWrite) { if (writeBuffer.empty()) return; if (!readBuffer.empty()) { formatError(); return ; } if (!writeBuffer.empty()) writeBuffer.pop(socket->write(writeBuffer.begin(), writeBuffer.size())); buildWriteChunk(); if (!writeBuffer.empty()) eventWrite.setTimeRelativeNow(); } else if (&event == &eventClose) { if ( !socket->wasError() && requestsCountRemain == 0 && requestSizeRemain == 0 && answerSizeRemain == 0 && readBuffer.empty() && writeBuffer.empty()) endUs = Platform::nowUs(); delete this; } }
/* * Execute the IF_ICMPEQ instruction */ void op_if_icmpeq() { int value2 = popInt(); int value1 = popInt(); if (value1 == value2) { pc += s16(1); } else { pc += 3; } }
/* * Execute the IFLE instruction */ void op_ifle() { if (popInt() <= 0) { pc += s16(1); } else { pc += 3; } }
/* * Execute the IFGT instruction */ void op_ifgt() { if (popInt() > 0) { pc += s16(1); } else { pc += 3; } }
/* * Execute the IFNE instruction */ void op_ifne() { if (popInt() != 0) { pc += s16(1); } else { pc += 3; } }
/* * Execute the IFEQ instruction */ void op_ifeq() { if (popInt() == 0) { pc += s16(1); } else { pc += 3; } }