static void emonk_outputv(ErlDrvData handle, ErlIOVec *ev) { unsigned char cmd; emonk_drv_t* drv = (emonk_drv_t*) handle; ErlDrvBinary* args = ev->binv[1]; unsigned char* b = args->orig_bytes; int l = args->orig_size; emonk_req_t* req = read_req_info(drv->vm->cx, &cmd, b, l); void* data = NULL; int length; int resp; if(cmd == 0) { data = vm_eval(drv->vm, req, &length); } else { data = vm_call(drv->vm, req, &length); } if(data == NULL) { resp = send_undefined(drv, req); } else { resp = send_response(drv, req, data, length); } if(data != NULL) driver_free(data); if(req != NULL) free_req_info(req); }
int compar(struct context *context, const void *a, const void *b, struct variable *comparator) { struct variable *av = *(struct variable**)a; struct variable *bv = *(struct variable**)b; if (comparator) { byte_array_reset(comparator->str); vm_call(context, comparator, av, bv, NULL); struct variable *result = (struct variable*)stack_pop(context->operand_stack); if (result->type == VAR_SRC) result = array_get(result->list.ordered, 0); assert_message(result->type == VAR_INT, "non-integer comparison result"); return result->integer; } else { enum VarType at = av->type; enum VarType bt = bv->type; if (at == VAR_INT && bt == VAR_INT) { // DEBUGPRINT("compare %p:%d to %p:%d : %d\n", av, av->integer, bv, bv->integer, av->integer - bv->integer); return av->integer - bv->integer; } else DEBUGPRINT("can't compare %s to %s\n", var_type_str(at), var_type_str(bt)); vm_exit_message(context, "incompatible types for comparison"); return 0; } }
void *incoming_connection(void *arg) { char readline[MAXLINE]; struct thread_argument *ta = (struct thread_argument *)arg; struct context *context = context_new(true, true); context->find = ta->find; for (;;) { bzero(readline, sizeof(readline)); int n; if (((n = CyaSSL_read(ta->ssl, readline, MAXLINE)) <= 0)) { fprintf(stderr, "client closed connection\n"); goto free_ssl; } fprintf(stderr, "%d bytes received: %s\n", n, readline); struct byte_array *raw_message = byte_array_new_size(n); raw_message->data = (uint8_t*)readline; int32_t raw_message_length = serial_decode_int(raw_message); assert_message(raw_message_length < MAXLINE, "todo: handle long messages"); struct variable *message = variable_deserialize(context, raw_message); struct variable *listener = (struct variable *)map_get(server_listeners, (void*)(VOID_INT)ta->fd); vm_call(context, listener, message); } free_ssl: CyaSSL_free(ta->ssl); // Free CYASSL object free(ta); context_del(context); return NULL; }
bool custom_method(struct context *context, const char *method, struct variable *indexable, struct variable *index, struct variable *value) { struct variable *custom; struct byte_array *key = byte_array_from_string(method); if (indexable->map && (custom = (struct variable*)map_get(indexable->map, key))) { DEBUGPRINT("\n"); vm_call(context, custom, indexable, index, value, NULL); return true; } return false; }
static int emonk_control(ErlDrvData handle, uint ignore, char* b, int l, char **rb, int rl) { unsigned char cmd; emonk_drv_t* drv = (emonk_drv_t*) handle; emonk_req_t* req = read_req_info(drv->vm->cx, &cmd, (unsigned char*) b, l); void* data = NULL; int length; int resp; if(req == NULL) { *rb[0] = 0; return 1; } if(cmd == 0) { data = vm_eval(drv->vm, req, &length); } else { data = vm_call(drv->vm, req, &length); } if(data == NULL) { resp = send_undefined(drv, req); } else { resp = send_response(drv, req, data, length); } if(data != NULL) driver_free(data); if(req != NULL) free_req_info(req); if(resp < 0) { *rb[0] = 0; return 1; } return 0; }
int32_t net_host_send(char *pg, int len) { // LAB 8: Your code here. if (pg == NULL) pg = (void*) UTOP; uint64_t addr = (uint64_t)pg; if( (vpml4e[VPML4E(addr)] & PTE_P) && (vpde[VPDPE(addr)] & PTE_P) && (vpd[VPD(addr)] & PTE_P) && (vpt[VPN(addr)] & PTE_P) ) { pg = (void *) PTE_ADDR( vpt[VPN(addr)] ); } int ret = vm_call( VMX_VMCALL_NETSEND, (uint64_t) pg , (uint64_t) len, 0, 0, 0 ); return ret; }
void vm_exec(VM *vm, bool trace) { int a = 0; int i = 0; bool b1, b2; float f,g; char* c; PVector_ptr vptr,r,l; int x, y; Activation_Record *frame; Function_metadata *const main = vm_function(vm, "main"); vm_call(vm, main); // Define VM registers (C compiler probably ignores 'register' nowadays // but it's good documentation in this case. Keep as locals for // convenience but write them back to the vm object after each decode/execute. register addr32 ip = vm->ip; register int sp = vm->sp; register int fp = vm->fp; const byte *code = vm->code; element *stack = vm->stack; int opcode = code[ip]; while (opcode != HALT && ip < vm->code_size ) { if (trace) vm_print_instr(vm, ip); ip++; switch (opcode) { case IADD: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].i = x + y; break; case ISUB: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].i = x - y; break; case IMUL: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].i = x * y; break; case IDIV: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; if (y ==0 ) { zero_division_error(); break; } stack[sp].i = x / y; break; case FADD: validate_stack_address(sp-1); f = stack[sp--].f; g = stack[sp].f; stack[sp].f = g + f; break; case FSUB: validate_stack_address(sp-1); f = stack[sp--].f; g = stack[sp].f; stack[sp].f = g - f; break; case FMUL: validate_stack_address(sp-1); f = stack[sp--].f; g = stack[sp].f; stack[sp].f = g * f; break; case FDIV: validate_stack_address(sp-1); f = stack[sp--].f; g = stack[sp].f; if (f == 0) { zero_division_error(); break; } stack[sp].f = g / f; break; case VADD: validate_stack_address(sp-1); r = stack[sp--].vptr; l = stack[sp].vptr; vptr = Vector_add(l,r); stack[sp].vptr = vptr; break; case VADDI: validate_stack_address(sp-1); i = stack[sp--].i; vptr = stack[sp].vptr; vptr = Vector_add(vptr,Vector_from_int(i,vptr.vector->length)); stack[sp].vptr = vptr; break; case VADDF: validate_stack_address(sp-1); f = stack[sp--].f; vptr = stack[sp].vptr; vptr = Vector_add(vptr,Vector_from_float(f,vptr.vector->length)); stack[sp].vptr = vptr; break; case VSUB: validate_stack_address(sp-1); r = stack[sp--].vptr; l = stack[sp].vptr; vptr = Vector_sub(l,r); stack[sp].vptr = vptr; break; case VSUBI: validate_stack_address(sp-1); i = stack[sp--].i; vptr = stack[sp].vptr; vptr = Vector_sub(vptr,Vector_from_int(i,vptr.vector->length)); stack[sp].vptr = vptr; break; case VSUBF: validate_stack_address(sp-1); f = stack[sp--].f; vptr = stack[sp].vptr; vptr = Vector_sub(vptr,Vector_from_float(f,vptr.vector->length)); stack[sp].vptr = vptr; break; case VMUL: validate_stack_address(sp-1); r = stack[sp--].vptr; l = stack[sp].vptr; vptr = Vector_mul(l,r); stack[sp].vptr = vptr; break; case VMULI: validate_stack_address(sp-1); i = stack[sp--].i; vptr = stack[sp].vptr; vptr = Vector_mul(vptr,Vector_from_int(i,vptr.vector->length)); stack[sp].vptr = vptr; break; case VMULF: validate_stack_address(sp-1); f = stack[sp--].f; vptr = stack[sp].vptr; vptr = Vector_mul(vptr,Vector_from_float(f,vptr.vector->length)); stack[sp].vptr = vptr; break; case VDIV: validate_stack_address(sp-1); r = stack[sp--].vptr; l = stack[sp].vptr; vptr = Vector_div(l,r); stack[sp].vptr = vptr; break; case VDIVI: validate_stack_address(sp-1); i = stack[sp--].i; if (i == 0) { zero_division_error(); break; } vptr = stack[sp].vptr; vptr = Vector_div(vptr,Vector_from_int(i,vptr.vector->length)); stack[sp].vptr = vptr; break; case VDIVF: validate_stack_address(sp-1); f = stack[sp--].f; if (f == 0) { zero_division_error(); break; } vptr = stack[sp].vptr; vptr = Vector_div(vptr,Vector_from_float(f,vptr.vector->length)); stack[sp].vptr = vptr; break; case SADD: validate_stack_address(sp-1); char * right = stack[sp--].s; stack[sp].s = String_add(String_new(stack[sp].s),String_new(right))->str; break; case OR : validate_stack_address(sp-1); b2 = stack[sp--].b; b1 = stack[sp].b; stack[sp].b = b1 || b2; break; case AND : validate_stack_address(sp-1); b2 = stack[sp--].b; b1 = stack[sp].b; stack[sp].b = b1 && b2; break; case INEG: validate_stack_address(sp); stack[sp].i = -stack[sp].i; break; case FNEG: validate_stack_address(sp); stack[sp].f = -stack[sp].f; break; case NOT: validate_stack_address(sp); stack[sp].b = !stack[sp].b; break; case I2F: validate_stack_address(sp); stack[sp].f = stack[sp].i; break; case I2S: validate_stack_address(sp); stack[sp].s = String_from_int(stack[sp].i)->str; break; case F2I: validate_stack_address(sp); stack[sp].i = (int)stack[sp].f; break; case F2S: validate_stack_address(sp); stack[sp].s = String_from_float((float)stack[sp].f)->str; break; case V2S: validate_stack_address(sp); vptr = stack[sp].vptr; stack[sp].s = String_from_vector(vptr)->str; break; case IEQ: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].b = x == y; break; case INEQ: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].b = x != y; break; case ILT: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].b = x < y; break; case ILE: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].b = x <= y; break; case IGT: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].b = x > y; break; case IGE: validate_stack_address(sp-1); y = stack[sp--].i; x = stack[sp].i; stack[sp].b = x >= y; break; case FEQ: validate_stack_address(sp-1); g = stack[sp--].f; f = stack[sp].f; stack[sp].b = f == g; break; case FNEQ: validate_stack_address(sp-1); g = stack[sp--].f; f = stack[sp].f; stack[sp].b = f != g; break; case FLT: validate_stack_address(sp-1); g = stack[sp--].f; f = stack[sp].f; stack[sp].b = f < g; break; case FLE: validate_stack_address(sp-1); g = stack[sp--].f; f = stack[sp].f; stack[sp].b = f <= g; break; case FGT: validate_stack_address(sp-1); g = stack[sp--].f; f = stack[sp].f; stack[sp].b = f > g; break; case FGE: validate_stack_address(sp-1); g = stack[sp--].f; f = stack[sp].f; stack[sp].b = f >= g; break; case SEQ: validate_stack_address(sp-1); c = stack[sp--].s; b1 = String_eq(String_new(stack[sp--].s),String_new(c)); stack[++sp].b = b1; break; case SNEQ: validate_stack_address(sp-1); c = stack[sp--].s; b1 = String_neq(String_new(stack[sp--].s),String_new(c)); stack[++sp].b = b1; break; case SGT: validate_stack_address(sp-1); c = stack[sp--].s; b1 = String_gt(String_new(stack[sp--].s),String_new(c)); stack[++sp].b = b1; break; case SGE: validate_stack_address(sp-1); c = stack[sp--].s; b1 = String_ge(String_new(stack[sp--].s),String_new(c)); stack[++sp].b = b1; break; case SLT: validate_stack_address(sp-1); c = stack[sp--].s; b1 = String_lt(String_new(stack[sp--].s),String_new(c)); stack[++sp].b = b1; break; case SLE: validate_stack_address(sp-1); c = stack[sp--].s; b1 = String_le(String_new(stack[sp--].s),String_new(c)); stack[++sp].b = b1; break; case VEQ: validate_stack_address(sp-1); l = stack[sp--].vptr; r = stack[sp--].vptr; b1 = Vector_eq(l,r); stack[++sp].b = b1; break; case VNEQ: validate_stack_address(sp-1); l = stack[sp--].vptr; r = stack[sp--].vptr; b1 = Vector_neq(l,r); stack[++sp].b = b1; break; case BR: ip += int16(code,ip) - 1; break; case BRF: validate_stack_address(sp); if ( !stack[sp--].b ) { int offset = int16(code,ip); ip += offset - 1; } else { ip += 2; } break; case ICONST: stack[++sp].i = int32(code,ip); ip += 4; break; case FCONST: stack[++sp].f = float32(code,ip); ip += 4; break; case SCONST : i = int16(code,ip); ip += 2; stack[++sp].s = vm->strings[i]; break; case ILOAD: i = int16(code,ip); ip += 2; stack[++sp].i = vm->call_stack[vm->callsp].locals[i].i; break; case FLOAD: i = int16(code,ip); ip += 2; stack[++sp].f = vm->call_stack[vm->callsp].locals[i].f; break; case VLOAD: i = int16(code,ip); ip += 2; stack[++sp].vptr = vm->call_stack[vm->callsp].locals[i].vptr; break; case SLOAD: i = int16(code,ip); ip += 2; stack[++sp].s = vm->call_stack[vm->callsp].locals[i].s; break; case STORE: i = int16(code,ip); ip += 2; vm->call_stack[vm->callsp].locals[i] = stack[sp--]; // untyped store; it'll just copy all bits break; case VECTOR: i = stack[sp--].i; validate_stack_address(sp-i+1); double *data = (double*)malloc(i*sizeof(double)); for (int j = i-1; j >= 0;j--) { data[j] = stack[sp--].f; } vptr = Vector_new(data,i); stack[++sp].vptr = vptr; break; case VLOAD_INDEX: i = stack[sp--].i; vptr = stack[sp--].vptr; vm->stack[++sp].f = ith(vptr, i-1); break; case STORE_INDEX: f = stack[sp--].f; i = stack[sp--].i; vptr = stack[sp--].vptr; set_ith(vptr, i-1, f); break; case SLOAD_INDEX: i = stack[sp--].i; if (i-1 >= strlen(stack[sp].s)) { fprintf(stderr, "StringIndexOutOfRange: %d\n",(int)strlen(stack[sp].s)); break; } c = String_from_char(stack[sp--].s[i-1])->str; stack[++sp].s = c; break; case PUSH_DFLT_RETV: i = *&vm->call_stack[vm->callsp].func->return_type; sp = push_default_value(i, sp, stack); break; case POP: sp--; break; case CALL: a = int16(code,ip); // load index of function from code memory WRITE_BACK_REGISTERS(vm); // (ip has been updated) vm_call(vm, &vm->functions[a]); LOAD_REGISTERS(vm); break; case RET: frame = &vm->call_stack[vm->callsp--]; ip = frame->retaddr; break; case IPRINT: validate_stack_address(sp); printf("%d\n", stack[sp--].i); break; case FPRINT: validate_stack_address(sp); printf("%1.2f\n", stack[sp--].f); break; case BPRINT: validate_stack_address(sp); printf("%d\n", stack[sp--].b); break; case SPRINT: validate_stack_address(sp); printf("%s\n", stack[sp--].s); break; case VPRINT: validate_stack_address(sp); print_vector(stack[sp--].vptr); break; case VLEN: vptr = stack[sp--].vptr; i = Vector_len(vptr); stack[++sp].i = i; break; case SLEN: c = stack[sp--].s; i = String_len(String_new(c)); stack[++sp].i = i; break; case GC_START: vm->call_stack[vm->callsp].save_gc_roots = gc_num_roots(); break; case GC_END: gc_set_num_roots(vm->call_stack[vm->callsp].save_gc_roots); break; case SROOT: gc_add_root((void **)&stack[sp].s); break; case VROOT: gc_add_root((void **)&stack[sp].vptr); break; case COPY_VECTOR: if (vm->call_stack[vm->callsp].locals[i].vptr.vector != NULL) { stack[sp].vptr = Vector_copy(vm->call_stack[vm->callsp].locals[i].vptr); } else if (stack[sp].vptr.vector != NULL) { stack[sp].vptr = Vector_copy(stack[sp].vptr); } else { fprintf(stderr, "Vector reference cannot be found\n"); } break; case NOP : break; default: printf("invalid opcode: %d at ip=%d\n", opcode, (ip - 1)); exit(1); } WRITE_BACK_REGISTERS(vm); if (trace) vm_print_stack(vm); opcode = code[ip]; } if (trace) vm_print_instr(vm, ip); if (trace) vm_print_stack(vm); gc_check(); }
} tree = yyctx.__; IF_DEBUG(COMPILER, print_ast(tree, 0);) yyrelease(&yyctx); // TODO: use native_... methods to load and run the code bytecode = compile(tree, source_file_name, &len); // BROKEN SINCE BYTECODE FORMAT CHANGE // IF_DEBUG(COMPILER, decompile(bytecode, 0, len);) vm_init(&vm, argc, argv); set_global(&vm, "BOOTSTRAP_FILE", make_string(bootstrap_file_name)); ctx_init(&ctx); ip = vm_load_bytecode(&vm, bytecode); closure = make_closure_obj(ip, 0, 0, 0, 0, 0, NULL); mr = vm_call(&vm, &ctx, &result, closure, 0, NULL); if(mr == METHOD_OK) { return 0; } if(mr == METHOD_EXCEPTION) { if(obj_is_of_type(result, vm.Exception)) { printf("========= Uncaught exception of type '%s' =========\n", obj_to_cstring(NGS_TYPE_NAME(NORMAL_TYPE_INSTANCE_TYPE(result)))); print_exception(&vm, result); } else { dump_titled("Uncaught exception", result); } return 1; } assert(0 == "Unexpected exit from bootstrap code"); }
void* vm_run(void* arg) { vm_ptr vm = (vm_ptr) arg; JSContext* cx; JSObject* gl; job_ptr job; ENTERM resp; int flags; cx = JS_NewContext(vm->runtime, vm->stack_size); if(cx == NULL) { fprintf(stderr, "Failed to create context.\n"); goto done; } JS_BeginRequest(cx); flags = 0; flags |= JSOPTION_VAROBJFIX; flags |= JSOPTION_STRICT; flags |= JSVERSION_LATEST; flags |= JSOPTION_COMPILE_N_GO; flags |= JSOPTION_XML; JS_SetOptions(cx, JS_GetOptions(cx) | flags); gl = JS_NewObject(cx, &global_class, NULL, NULL); if(gl == NULL) { fprintf(stderr, "Failed to create global object.\n"); goto done; } if(!JS_InitStandardClasses(cx, gl)) { fprintf(stderr, "Failed to initialize classes.\n"); goto done; } if(!install_jserl(cx, gl)) { fprintf(stderr, "Failed to install erlang object."); goto done; } JS_SetErrorReporter(cx, vm_report_error); JS_SetContextPrivate(cx, (void*) vm); JS_EndRequest(cx); while(1) { job = queue_pop(vm->jobs); if(job->type == job_close) { job_destroy(job); break; } JS_BeginRequest(cx); assert(vm->curr_job == NULL && "vm already has a job set."); vm->curr_job = job; if(job->type == job_eval) { resp = vm_eval(cx, gl, job); } else if(job->type == job_call) { resp = vm_call(cx, gl, job); } else { assert(0 && "Invalid job type."); } vm->curr_job = NULL; JS_EndRequest(cx); JS_MaybeGC(cx); // XXX: If pid is not alive, we just ignore it. enif_send(NULL, &(job->pid), job->env, resp); job_destroy(job); } done: JS_BeginRequest(cx); if(cx != NULL) JS_DestroyContext(cx); return NULL; }