void free_clinit_memory(struct methodblock *mb) { /* This function is somewhat a hack. It fixes the problem in 1.1.3 * and before. sysFree may be called on the wrong memory block if * the exception attribute comes before the code attribute. */ /* If there is no exceptions attribute, or if both has already * been freed. */ if (mb->exceptions == NULL) { if (mb->code) { sysFree(mb->code); mb->code = NULL; } return; } /* If both attributes exist, free the one at the lower address */ if ((char *)mb->code < (char *)mb->exceptions) sysFree(mb->code); else sysFree(mb->exceptions); mb->code = NULL; mb->exceptions = NULL; }
/* * Unmap a range of virtual memory. Note that the size asked for here * is literally what the upper level has asked for. We need to do any * rounding, etc. here. If unmapping fails return 0, otherwise return * the address of the base of the unmapped memory. */ void * sysUnmapMem(void *requestedAddr, size_t requestedSize, size_t *unmappedSize) { void *unmappedAddr; int ret; *unmappedSize = roundUpToGrain(requestedSize); #ifdef USE_MALLOC sysFree(requestedAddr); ret = 1; #else ret = unmapChunk(requestedAddr, *unmappedSize); #endif /* USE_MALLOC */ if (ret) { unmappedAddr = requestedAddr; Log4(2, "sysUnmapMem: 0x%x bytes at 0x%x (request: 0x%x bytes at 0x%x)\n", *unmappedSize, unmappedAddr, requestedSize, requestedAddr); } else { unmappedAddr = 0; Log2(2, "sysUnmapMem failed: (request: 0x%x bytes at 0x%x)\n", requestedSize, requestedAddr); } return unmappedAddr; }
Object *createConstructorObject(MethodBlock *mb) { Object *reflect_ob, *vm_reflect_ob, *classes; char *signature, *sig; if((reflect_ob = allocObject(cons_reflect_class)) == NULL) return NULL; if((vm_reflect_ob = allocObject(vmcons_reflect_class)) == NULL) return NULL; signature = sig = sysMalloc(strlen(mb->type) + 1); strcpy(sig, mb->type); classes = convertSig2ClassArray(&sig, mb->class); sysFree(signature); if(classes == NULL) return NULL; INST_DATA(vm_reflect_ob, Class*, vm_cons_class_offset) = mb->class; INST_DATA(vm_reflect_ob, Object*, vm_cons_param_offset) = classes; INST_DATA(vm_reflect_ob, int, vm_cons_slot_offset) = mb - CLASS_CB(mb->class)->methods; /* Link the Java-level and VM-level objects together */ INST_DATA(vm_reflect_ob, Object*, vm_cons_cons_offset) = reflect_ob; INST_DATA(reflect_ob, Object*, cons_cons_offset) = vm_reflect_ob; return reflect_ob; }
int classlibInitialiseNatives() { Class *field_accessor; FieldBlock *base_fb = NULL; char *dll_path = getBootDllPath(); char *dll_name = getDllName("java"); char path[strlen(dll_path) + strlen(dll_name) + 2]; strcat(strcat(strcpy(path, dll_path), "/"), dll_name); sysFree(dll_name); if(!resolveDll(path, NULL)) { jam_fprintf(stderr, "Error initialising natives: couldn't open " "libjava.so: use -verbose:jni for more " "information\n"); return FALSE; } field_accessor = findSystemClass0(SYMBOL( sun_reflect_UnsafeStaticFieldAccessorImpl)); if(field_accessor != NULL) base_fb = findField(field_accessor, SYMBOL(base), SYMBOL(sig_java_lang_Object)); if(base_fb == NULL) { jam_fprintf(stderr, "Error initialising natives: %s " "missing or malformed\n", SYMBOL(sun_reflect_UnsafeStaticFieldAccessorImpl)); return FALSE; } hideFieldFromGC(base_fb); return initialiseJVMInterface(); }
void inlineBlockWrappedOpcode(MethodBlock *mb, Instruction *pc) { PrepareInfo *prepare_info = pc->operand.pntr; OpcodeInfo *info; int i; Thread *self = threadSelf(); rewriteLock(self); for(i = 0; i < HANDLERS; i++) if(pc->handler == handler_entry_points[i][OPC_INLINE_REWRITER]) break; if(i == HANDLERS) { rewriteUnlock(self); return; } pc->handler = handler_entry_points[0][GOTO_START]; rewriteUnlock(self); /* Unwrap the original handler's operand */ pc->operand = prepare_info->operand; MBARRIER(); /* Unwrap the original handler */ info = &prepare_info->block.opcodes[prepare_info->block.length-1]; pc->handler = handler_entry_points[info->cache_depth][info->opcode]; inlineBlock(mb, &prepare_info->block); sysFree(prepare_info); }
/* A method's quick prepare info list holds prepare information for all blocks within the method that end with a quickened instruction. If the quickened instruction being executed is in the list we must have reached the end of a block and we need to inline it */ void checkInliningQuickenedInstruction(Instruction *pc, MethodBlock *mb) { /* As there could be multiple threads executing this method, the list must be protected with a lock. However, the fast case of an empty list doesn't need locking. */ if(mb->quick_prepare_info) { QuickPrepareInfo *info, *last = NULL; Thread *self = threadSelf(); rewriteLock(self); /* Search list */ info = mb->quick_prepare_info; for(; info && info->quickened != pc; last = info, info = info->next); /* If prepare info found, remove it from the list */ if(info) { if(last) last->next = info->next; else mb->quick_prepare_info = info->next; } rewriteUnlock(self); /* If prepare info found, inline block (no need to hold lock) */ if(info) { inlineBlock(mb, &info->block); sysFree(info); } } }
static void freeBuffers(CICcontext * context) { if (context->pass == 1) { CICmallocs *mallocs = context->pass1.mallocs; while (mallocs) { CICmallocs *tmp = mallocs; mallocs = mallocs->next; sysFree(tmp); } context->pass1.mallocs = 0; } else { sysFree(context->pass2.malloc_buffer); context->pass2.malloc_buffer = 0; sysFree(context->pass2.clinit_buffer); context->pass2.clinit_buffer = 0; } }
/* * Cleanup the data structure allocated as above. * For JDK 1.2, this function is not called ... */ void FinalizeIO() { int i; for (i = 0; i < fd_limit; i++) { mutexDestroy(&fd_table[i].lock); } sysFree(fd_table); fd_table = 0; }
/* Load a .class file normally from the local disk */ static ClassClass * LoadClassFromFile(char *fn, char *dir, char *class_name) { extern int OpenCode(char *, char *, char *, struct stat*); struct stat st; ClassClass *cb = 0; int codefd = -1; int retryCount = 0; unsigned char *external_class; char *detail; codefd = OpenCode(fn, NULL, dir, &st); if (codefd < 0) /* open failed */ return 0; /* Snarf the file into memory. */ external_class = (unsigned char *)sysMalloc(st.st_size); if (external_class == 0) goto failed; if (sysRead(codefd, external_class, st.st_size) != st.st_size) goto failed; sysClose(codefd); codefd = -1; /* Create the internal class */ cb = allocClassClass(); if (cb == NULL || !createInternalClass(external_class, external_class + st.st_size, cb, NULL, class_name, &detail)) { sysFree(external_class); goto failed; } sysFree(external_class); if (verbose) jio_fprintf(stderr, "[Loaded %s]\n", fn); return cb; failed: if (codefd >= 0) sysClose(codefd); if (cb != 0) FreeClass(cb); return 0; }
char *copyUtf8(char *string) { char *buff = xi_strcpy(sysMalloc(xi_strlen(string) + 1), string); char *found = findHashedUtf8(buff, TRUE); if(found != buff) sysFree(buff); return found; }
char *mangleClassAndMethodName(MethodBlock *mb) { char *classname = CLASS_CB(mb->class)->name; char *methodname = mb->name; char *nonMangled = (char*) sysMalloc(strlen(classname) + strlen(methodname) + 7); char *mangled; sprintf(nonMangled, "Java/%s/%s", classname, methodname); mangled = mangleString(nonMangled); sysFree(nonMangled); return mangled; }
void FreeClass(ClassClass *cb) { int i; struct methodblock *mb; for (i = cbMethodsCount(cb), mb = cbMethods(cb); --i >= 0; mb++) { if (strcmp(mb->fb.name, "<clinit>") == 0 && strcmp(mb->fb.signature, "()V") == 0 && mb->code_length /* not external */ ) free_clinit_memory(mb); } sysFree(cbConstantPool(cb)); sysFree(cbMethodTableMem(cb)); sysFree(cbSlotTable(cb)); /* Interface method tables can be shared between child and super classes */ if (cbImplementsCount(cb) != 0 || cbIsInterface(cb)) sysFree(cbIntfMethodTable(cb)); }
void inlineSequence(MethodBlock *mb, CodeBlock *info, int start, int len) { int code_len = goto_len + sizeof(CodeBlockHeader); Instruction *instructions = &info->start[start]; OpcodeInfo *opcodes = &info->opcodes[start]; CodeBlockHeader *hashed_block, *block; int aligned_len, i; char *pntr; /* Calculate sequence length */ for(i = 0; i < len; i++) code_len += handler_sizes[opcodes[i].cache_depth][opcodes[i].opcode]; aligned_len = ALIGN(code_len); /* We malloc memory for the block rather than allocating code memory. This reduces fragmentation of the code memory in the case where we use an existing block and must free the new sequence */ block = sysMalloc(aligned_len); /* Store length at beginning of sequence */ block->len = aligned_len; pntr = (char *)(block + 1); /* Concatenate the handler bodies together */ for(i = 0; i < len; i++) { int size = handler_sizes[opcodes[i].cache_depth][opcodes[i].opcode]; memcpy(pntr, instructions[i].handler, size); pntr += size; } /* Add the dispatch onto the end of the super-instruction */ memcpy(pntr, goto_start, goto_len); /* Pad with zeros up to block length */ for(pntr += goto_len; code_len < aligned_len; code_len++) *pntr++ = 0; /* Look up new block in inlined block cache */ hashed_block = findCodeBlock(block); sysFree(block); if(hashed_block != NULL) { /* Replace first handler with new inlined block */ instructions[0].handler = hashed_block + 1; MBARRIER(); TRACE("InlineSequence %s start %p (%d) instruction len %d code len %d sequence %p\n", mb->name, instructions, start, len, code_len, instructions[0].handler); } }
char *mangleSignature(MethodBlock *mb) { char *type = mb->type; char *nonMangled; char *mangled; int i; /* find ending ) */ for(i = strlen(type) - 1; type[i] != ')'; i--); nonMangled = (char *) sysMalloc(i); strncpy(nonMangled, type + 1, i - 1); nonMangled[i - 1] = '\0'; mangled = mangleString(nonMangled); sysFree(nonMangled); return mangled; }
static void *shell(void *args) { void *start = ((void**)args)[1]; Thread *self = ((Thread**)args)[2]; if(main_exited) return NULL; /* VM helper threads should be added to the system group, but this doesn't exist. As the root group is main, we add it to that for now... */ attachThread(((char**)args)[0], TRUE, &self, self, //(Object*)INST_DATA(main_ee.thread)[group_offset]); (Object*)INST_DATA(main_thread.thread)[group_offset]); sysFree(args); (*(void(*)(Thread*))start)(self); return NULL; }
void inlineBlock(MethodBlock *mb, CodeBlock *block) { int start, len, i; for(start = i = 0; i < block->length; i++) { int cache_depth = block->opcodes[i].cache_depth; int opcode = block->opcodes[i].opcode; int op1, op2; /* The block opcodes contain the "un-quickened" opcode. This could have been quickened to one of several quick versions. */ switch(opcode) { case OPC_LDC: op1 = OPC_LDC_QUICK; op2 = OPC_LDC_W_QUICK; break; case OPC_GETSTATIC: op1 = OPC_GETSTATIC_QUICK; op2 = OPC_GETSTATIC2_QUICK; break; case OPC_PUTSTATIC: op1 = OPC_PUTSTATIC_QUICK; op2 = OPC_PUTSTATIC2_QUICK; break; case OPC_GETFIELD: op1 = OPC_GETFIELD_QUICK; op2 = OPC_GETFIELD2_QUICK; break; case OPC_PUTFIELD: op1 = OPC_PUTFIELD_QUICK; op2 = OPC_PUTFIELD2_QUICK; break; case OPC_NEW: case OPC_ANEWARRAY: case OPC_CHECKCAST: case OPC_INVOKESTATIC: case OPC_INVOKEINTERFACE: case OPC_INVOKEVIRTUAL: case OPC_INVOKESPECIAL: case OPC_MULTIANEWARRAY: case OPC_INSTANCEOF: op1 = op2 = GOTO_END; break; default: op1 = op2 = -1; break; } if(op1 > 0) { /* Match which quickened opcode */ opcode = handler_entry_points[cache_depth][op1] == (char*) block->start[i].handler ? op1 : op2; block->opcodes[i].opcode = opcode; } /* A non-relocatable opcode ends a sequence */ if(handler_sizes[cache_depth][opcode] < 0) { len = i - start; if(len > 0) inlineSequence(mb, block, start, len); start = i + 1; } } /* Inline the remaining sequence */ len = block->length - start; if(len > 0) inlineSequence(mb, block, start, len); sysFree(block->opcodes); }
char *mangleString(char *utf8) { int len = utf8Len(utf8); unsigned short *unicode = (unsigned short*) sysMalloc(len * 2); char *mangled, *mngldPtr; int i, mangledLen = 0; convertUtf8(utf8, unicode); /* Work out the length of the mangled string */ for(i = 0; i < len; i++) { unsigned short c = unicode[i]; switch(c) { case '_': case ';': case '[': mangledLen += 2; break; default: mangledLen += isalnum(c) ? 1 : 6; break; } } mangled = mngldPtr = (char*) sysMalloc(mangledLen + 1); /* Construct the mangled string */ for(i = 0; i < len; i++) { unsigned short c = unicode[i]; switch(c) { case '_': *mngldPtr++ = '_'; *mngldPtr++ = '1'; break; case ';': *mngldPtr++ = '_'; *mngldPtr++ = '2'; break; case '[': *mngldPtr++ = '_'; *mngldPtr++ = '3'; break; case '/': *mngldPtr++ = '_'; break; default: if(isalnum(c)) *mngldPtr++ = c; else mngldPtr += sprintf(mngldPtr, "_0%04x", c); break; } } *mngldPtr = '\0'; sysFree(unicode); return mangled; }
char *findArchiveEntry(char *pathname, ZipFile *zip, int *uncomp_len) { int offset, path_len, comp_len, extra_len, comp_method; unsigned char *decomp_buff, *comp_data; unsigned char *dir_entry; dir_entry = (unsigned char *)findArchiveDirEntry(pathname, zip); if(dir_entry == NULL) return NULL; /* Found the file -- the pathname points directly into the directory entry. Read the values relative to it */ /* Offset of the file entry relative to the start of the file */ offset = READ_LE_INT(dir_entry + (CEN_FILE_LOCALHDR_OFFSET - CEN_FILE_HEADER_LEN)); if((offset + LOC_FILE_HEADER_LEN) > zip->length) return NULL; /* Get the variable length part of the local file header */ extra_len = READ_LE_SHORT(zip->data + offset + LOC_FILE_EXTRA_OFFSET); /* Get the path_len again */ path_len = READ_LE_SHORT(dir_entry + (CEN_FILE_PATHLEN_OFFSET - CEN_FILE_HEADER_LEN)); /* The file's length when uncompressed -- this is passed out */ *uncomp_len = READ_LE_INT(dir_entry + (CEN_FILE_UNCOMPLEN_OFFSET - CEN_FILE_HEADER_LEN)); /* The compressed file's length, i.e. the data size in the file */ comp_len = READ_LE_INT(dir_entry + (CEN_FILE_COMPLEN_OFFSET - CEN_FILE_HEADER_LEN)); /* How the file is compressed */ comp_method = READ_LE_SHORT(dir_entry + (CEN_FILE_COMPMETH_OFFSET - CEN_FILE_HEADER_LEN)); /* Calculate the data start */ offset += LOC_FILE_HEADER_LEN + path_len + extra_len; /* Make sure we're not reading outside the file */ if((offset + comp_len) > zip->length) return NULL; comp_data = zip->data + offset; decomp_buff = sysMalloc(*uncomp_len); switch(comp_method) { case COMP_STORED: /* Data isn't compressed, so just return it "as is" */ memcpy(decomp_buff, comp_data, comp_len); return (char*)decomp_buff; case COMP_DEFLATED: { z_stream stream; int err; stream.next_in = comp_data; stream.avail_in = comp_len; stream.next_out = decomp_buff; stream.avail_out = *uncomp_len; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; /* Use a negative windowBits value to stop the inflator looking for a header */ if(inflateInit2(&stream, -MAX_WINDOW_BITS) != Z_OK) goto error; err = inflate(&stream, Z_SYNC_FLUSH); inflateEnd(&stream); if(err == Z_STREAM_END || (err == Z_OK && stream.avail_in == 0)) return (char*)decomp_buff; break; } default: break; } error: sysFree(decomp_buff); return NULL; }
/** * Ends use of va_list */ EXTERNAL void sysVaEnd(va_list *ap) { TRACE_PRINTF("%s: sysVaEnd\n", Me); va_end(*ap); sysFree(ap); }
bool_t createInternalClass1(unsigned char *ptr, unsigned char *end_ptr, ClassClass *cb, struct Hjava_lang_ClassLoader *loader, char *name, char **detail) { struct CICcontext context_block; struct CICcontext *context = &context_block; struct Classjava_lang_Class *ucb = unhand(cb); /* Set up the context */ context->ptr = ptr; context->end_ptr = end_ptr; context->cb = cb; context->detail = detail; if (setjmp(context->jump_buffer)) { /* We've gotten an error of some sort */ /* See comments below about zeroing these two fields before * freeing the temporary buffer. */ cbConstantPool(cb) = NULL; cbFields(cb) = NULL; /* Zero out the method out so that freeClass will not try to free the clinit method */ cbMethodsCount(cb) = 0; freeBuffers(context); return FALSE; } context->in_clinit = 0; context->pass1.mallocs = 0; context->malloc_size = 0; context->clinit_size = 0; /* The first pass allows us to uncover any class format errors and find out the size of the buffer needed. */ context->pass = 1; createInternalClass0(context, cb, loader, name); /* We must set the following two fields to zero before we free * the temporary buffers, because markClassClass may scan a * partially constructed class block in the second pass. * If these two fields are set to zero, markClassClass will * not scan the constant pool and field blocks, which may * point to freed memory. */ cbConstantPool(cb) = NULL; cbFields(cb) = NULL; /* Zero out the method out so that freeClass will not try to free the clinit method */ cbMethodsCount(cb) = 0; freeBuffers(context); context->ptr = ptr; /* rewind the raw class data */ context->pass2.malloc_buffer = sysCalloc(1, context->malloc_size); if (context->pass2.malloc_buffer == 0) JAVA_ERROR(context, "out of memory"); if (context->clinit_size) { context->pass2.clinit_buffer = sysCalloc(1, context->clinit_size); if (context->pass2.clinit_buffer == 0) { sysFree(context->pass2.malloc_buffer); JAVA_ERROR(context, "out of memory"); } } context->pass2.malloc_ptr = context->pass2.malloc_buffer; context->pass2.clinit_ptr = context->pass2.clinit_buffer; /* The second pass accomplishes the real task. */ context->pass = 2; createInternalClass0(context, cb, loader, name); /* Valid class - let's put it in the class table. */ AddBinClass(cb); return TRUE; }
native_netscape_javascript_JSObject_call( JRIEnv* env, struct netscape_javascript_JSObject* self, struct java_lang_String *method, jobjectArray args) { #ifndef JAVA return NULL; #else JSContext *cx; JSObject *jso; JSSavedState saved; const char *cstr; struct java_lang_Object *ret; int total_argc, argc, i; jsval *argv; jsval rval; int cost = 0; if (!enterJS(env, self, &cx, &jso, &saved)) return NULL; if (! method || ! (cstr = JRI_GetStringPlatformChars(env, method, (const jbyte *) cx->charSetName, (jint) cx->charSetNameLength))) { /* FIXME this should be an error of some sort */ js_throwJSException(env, "illegal member name"); ret = NULL; goto do_exit; } if (args) { total_argc = JRI_GetObjectArrayLength(env, args); argv = sysMalloc(total_argc * sizeof(jsval)); } else { total_argc = 0; argv = 0; } for (argc = 0; argc < total_argc; argc++) { jref arg = JRI_GetObjectArrayElement(env, args, argc); if (!js_convertJObjectToJSValue(cx, argv+argc, (HObject*)arg)) goto cleanup_argv; JS_AddRoot(cx, argv+argc); } if (! JS_CallFunctionName(cx, jso, cstr, argc, argv, &rval) || ! js_convertJSValueToJObject((HObject **) &ret, cx, rval, 0, 0, JS_FALSE, &cost)) { ret = NULL; } cleanup_argv: for (i = 0; i < argc; i++) JS_RemoveRoot(cx, argv+i); sysFree(argv); do_exit: if (!exitJS(env, self, cx, jso, &saved)) return NULL; return ret; #endif }