BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1) { Module* modp; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } if ((modp = erts_get_module(BIF_ARG_1)) == NULL) { return am_undefined; } return (is_native(modp->code) || (modp->old_code != 0 && is_native(modp->old_code))) ? am_true : am_false; }
bool signal_from_native(void *ctx) { ucontext_t *uc; uc = ctx; return is_native(uc->uc_mcontext.gregs[REG_IP]); }
BIF_RETTYPE code_is_module_native_1(BIF_ALIST_1) { Module* modp; Eterm res; ErtsCodeIndex code_ix; if (is_not_atom(BIF_ARG_1)) { BIF_ERROR(BIF_P, BADARG); } code_ix = erts_active_code_ix(); if ((modp = erts_get_module(BIF_ARG_1, code_ix)) == NULL) { return am_undefined; } erts_rlock_old_code(code_ix); res = ((modp->curr.code && is_native(modp->curr.code)) || (modp->old.code != 0 && is_native(modp->old.code))) ? am_true : am_false; erts_runlock_old_code(code_ix); return res; }
// ------------------------------------------------------------------ // ciMethod::build_method_data // // Generate new methodDataOop objects at compile time. void ciMethod::build_method_data(methodHandle h_m) { EXCEPTION_CONTEXT; if (is_native() || is_abstract() || h_m()->is_accessor()) return; if (h_m()->method_data() == NULL) { methodOopDesc::build_interpreter_method_data(h_m, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; } } if (h_m()->method_data() != NULL) { _method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data(); _method_data->load_data(); } else { _method_data = CURRENT_ENV->get_empty_methodData(); } }
void AccessFlags::print_on(outputStream* st) const { if (is_public ()) st->print("public " ); if (is_private ()) st->print("private " ); if (is_protected ()) st->print("protected " ); if (is_static ()) st->print("static " ); if (is_final ()) st->print("final " ); if (is_synchronized()) st->print("synchronized "); if (is_volatile ()) st->print("volatile " ); if (is_transient ()) st->print("transient " ); if (is_native ()) st->print("native " ); if (is_interface ()) st->print("interface " ); if (is_abstract ()) st->print("abstract " ); if (is_strict ()) st->print("strict " ); if (is_synthetic ()) st->print("synthetic " ); if (is_old ()) st->print("{old} " ); if (is_obsolete ()) st->print("{obsolete} " ); }
static char * purple_plugin_get_basename(const char *filename) { const char *basename; const char *last_period; basename = strrchr(filename, G_DIR_SEPARATOR); if (basename != NULL) basename++; else basename = filename; if (is_native(basename) && ((last_period = strrchr(basename, '.')) != NULL)) return g_strndup(basename, (last_period - basename)); return g_strdup(basename); }
// ------------------------------------------------------------------ // ciMethod::ensure_method_data // // Generate new MethodData* objects at compile time. // Return true if allocation was successful or no MDO is required. bool ciMethod::ensure_method_data(methodHandle h_m) { EXCEPTION_CONTEXT; if (is_native() || is_abstract() || h_m()->is_accessor()) { return true; } if (h_m()->method_data() == NULL) { Method::build_interpreter_method_data(h_m, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; } } if (h_m()->method_data() != NULL) { _method_data = CURRENT_ENV->get_method_data(h_m()->method_data()); _method_data->load_data(); return true; } else { _method_data = CURRENT_ENV->get_empty_methodData(); return false; } }
void init_stack_trace_elem(struct stack_trace_elem *elem, unsigned long addr, void *frame) { elem->is_native = is_native(addr); elem->addr = addr; elem->frame = frame; if (elem->is_native) elem->type = STACK_TRACE_ELEM_TYPE_OTHER; else elem->type = STACK_TRACE_ELEM_TYPE_JIT; elem->vm_native_stack_index = vm_native_stack_index() - 1; elem->jni_stack_index = jni_stack_index() - 1; if (vm_native_stack_get_frame() == frame) { elem->type = STACK_TRACE_ELEM_TYPE_VM_NATIVE; elem->vm_native_stack_index--; } }
// ------------------------------------------------------------------ // ciFlags::print_member_flags void ciFlags::print_member_flags(outputStream* st) { if (is_public()) { st->print("public"); } else if (is_private()) { st->print("private"); } else if (is_protected()) { st->print("protected"); } else { st->print("DEFAULT_ACCESS"); } if (is_static()) { st->print(",static"); } if (is_final()) { st->print(",final"); } if (is_synchronized()) { st->print(",synchronized"); } if (is_volatile()) { st->print(",volatile"); } if (is_transient()) { st->print(",transient"); } if (is_native()) { st->print(",native"); } if (is_abstract()) { st->print(",abstract"); } if (is_strict()) { st->print(",strict"); } }
void Method::_set_nop() { bool verbose = false; Global_Env *env = VM_Global_State::loader_env; if (get_name() != env->Init_String || get_descriptor() != env->VoidVoidDescriptor_String) { return; } if(is_native()) { return; } unsigned len = _byte_code_length; if(!len) { return; } U_8* bc = _byte_codes; Nop_Stack_State stack_state = NS_StackEmpty; if(verbose) { printf("=========== nop[%d]: %s.%s%s\n", len, get_class()->get_name()->bytes, get_name()->bytes, get_descriptor()->bytes); } for (unsigned idx = 0; idx < len; idx++) { U_8 b = bc[idx]; if(verbose) { printf("\tbc[%d]=%d, state=%d\n", idx, b, stack_state); } if(b == 0xb1) { // return if(verbose) { printf("+++++++ nop: %s.%s%s\n", get_class()->get_name()->bytes, get_name()->bytes, get_descriptor()->bytes); } _flags.is_nop = TRUE; return; } switch(stack_state) { case NS_StackEmpty: switch(b) { case 0x2a: // aload_0 stack_state = NS_ThisPushed; break; default: return; } break; case NS_ThisPushed: switch(b) { case 0x01: // aconst_null case 0x03: // iconst_0 stack_state = NS_ThisAndZeroPushed; break; case 0xb7: // invokespecial { unsigned index = (bc[idx + 1] << 8) + bc[idx + 2]; if(verbose) { printf("\tinvokespecial, index=%d\n", index); } Method_Handle mh = resolve_special_method_env(VM_Global_State::loader_env, get_class(), index, false); Method *callee = (Method *)mh; if(!callee) { if(verbose) { printf("\tinvokespecial, callee==null\n"); } return; } if(callee == this) { return; } if(verbose) { printf("invokespecial: %s.%s%s\n", callee->get_class()->get_name()->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes); } if(!callee->is_nop()) { return; } const char *descr = callee->get_descriptor()->bytes; if(descr[1] != ')') { return; } if(verbose) { printf("invokespecial nop: %s.%s%s\n", callee->get_class()->get_name()->bytes, callee->get_name()->bytes, callee->get_descriptor()->bytes); } } stack_state = NS_StackEmpty; idx += 2; break; default: return; } break; case NS_ThisAndZeroPushed: switch(b) { case 0xb5: // putfield stack_state = NS_StackEmpty; if(verbose) { printf("\tputfield\n"); } idx += 2; break; default: return; } break; default: LDIE(57, "Unexpected stack state"); return; } } LDIE(56, "should'nt get here"); } //Method::_set_nop
/** * stack_trace_elem_next - sets @elem to the next call stack element. * * Returns 0 on success and -1 when bottom of stack is reached. */ int stack_trace_elem_next(struct stack_trace_elem *elem) { unsigned long new_addr; unsigned long ret_addr; void *new_frame; /* If previous element was a JNI call then we move to the JNI * caller's frame. We use the JNI stack_entry info to get the * frame because we don't trust JNI methods's frame * pointers. */ if (elem->type == STACK_TRACE_ELEM_TYPE_JNI) { struct jni_stack_entry *tr = &jni_stack[elem->jni_stack_index--]; new_frame = tr->caller_frame; new_addr = tr->return_address - 1; goto out; } if (elem->frame == NULL) return -1; /* Check if we hit the JNI interface frame */ if (elem->jni_stack_index >= 0) { struct jni_stack_entry *tr = &jni_stack[elem->jni_stack_index]; if (tr->vm_frame == elem->frame) { if (!tr->method) { /* This happens for JNI_OnLoad invocations */ elem->type = STACK_TRACE_ELEM_TYPE_OTHER; elem->is_native = true; elem->addr = tr->return_address; elem->frame = tr->caller_frame; return 0; } elem->type = STACK_TRACE_ELEM_TYPE_JNI; elem->is_native = false; elem->cu = tr->method->compilation_unit; elem->frame = NULL; struct native_stack_frame *vm_frame = tr->vm_frame; elem->addr = vm_frame->return_address; return 0; } } if (elem->is_native) { struct native_stack_frame *frame; frame = elem->frame; new_frame = frame->prev; ret_addr = frame->return_address; } else { struct jit_stack_frame *frame; frame = elem->frame; new_frame = frame->prev; ret_addr = frame->return_address; } /* * We know only return addresses and we don't know the size of * call instruction that was used. Therefore we don't know * address of the call site beggining. We store address of the * last byte of the call site instead which is enough * information to obtain bytecode offset. */ new_addr = ret_addr - 1; out: /* Check if we hit the VM native caller frame */ if (elem->vm_native_stack_index >= 0) { struct vm_native_stack_entry *tr = &vm_native_stack[elem->vm_native_stack_index]; if (tr->stack_ptr - sizeof(struct native_stack_frame) == new_frame) { elem->type = STACK_TRACE_ELEM_TYPE_VM_NATIVE; elem->is_native = true; new_addr = (unsigned long) tr->target; --elem->vm_native_stack_index; goto out2; } } /* Check if previous elemement was called from JIT trampoline. */ if (elem->is_native && called_from_jit_trampoline(elem->frame)) { elem->type = STACK_TRACE_ELEM_TYPE_TRAMPOLINE; elem->is_native = true; goto out2; } elem->is_native = is_native(new_addr); if (elem->is_native) elem->type = STACK_TRACE_ELEM_TYPE_OTHER; else elem->type = STACK_TRACE_ELEM_TYPE_JIT; out2: elem->addr = new_addr; elem->frame = new_frame; return 0; }
/** * @param classRecord Record for method class. * @param methodRecord Calle's method record. * @param retAddr What the PC should be upon return. * @return true iff the stack frame was pushed. */ boolean dispatch_special (MethodRecord *methodRecord, byte *retAddr) { #if DEBUG_METHODS int debug_ctr; #endif StackFrame *stackFrame; byte newStackFrameIndex; #if DEBUG_BYTECODE printf ("\n------ dispatch special - %d ------------------\n\n", methodRecord->signatureId); #endif #if DEBUG_METHODS printf ("dispatch_special: %d, %d\n", (int) methodRecord, (int) retAddr); printf ("-- signature id = %d\n", methodRecord->signatureId); printf ("-- code offset = %d\n", methodRecord->codeOffset); printf ("-- flags = %d\n", methodRecord->mflags); printf ("-- num params = %d\n", methodRecord->numParameters); printf ("-- stack ptr = %d\n", (int) get_stack_ptr()); printf ("-- max stack ptr= %d\n", (int) (currentThread->stackArray + (get_array_size(currentThread->stackArray))*2)); #endif pop_words (methodRecord->numParameters); pc = retAddr; if (is_native (methodRecord)) { #if DEBUG_METHODS printf ("-- native\n"); #endif dispatch_native (methodRecord->signatureId, get_stack_ptr() + 1); // Stack frame not pushed return false; } newStackFrameIndex = currentThread->stackFrameArraySize; if (newStackFrameIndex >= get_array_length((Object *) word2ptr (currentThread->stackFrameArray))) { #if !FIXED_STACK_SIZE // int len = get_array_length((Object *) word2ptr (currentThread->stackFrameArray)); int newlen = get_array_length((Object *) word2ptr (currentThread->stackFrameArray)) * 3 / 2; JINT newStackFrameArray = JNULL; // Stack frames are indexed by a byte value so limit the size. if (newlen <= 255) { // increase the stack frame size newStackFrameArray = ptr2word(reallocate_array(word2ptr(currentThread->stackFrameArray), newlen)); } // If can't allocate new stack, give in! if (newStackFrameArray == JNULL) { #endif throw_exception (stackOverflowError); return false; #if !FIXED_STACK_SIZE } // Assign new array currentThread->stackFrameArray = newStackFrameArray; #endif } if (newStackFrameIndex == 0) { // Assign NEW stack frame stackFrame = stackframe_array(); } else { #if DEBUG_METHODS for (debug_ctr = 0; debug_ctr < methodRecord->numParameters; debug_ctr++) printf ("-- param[%d] = %ld\n", debug_ctr, (long) get_stack_ptr()[debug_ctr+1]); #endif // Save OLD stackFrame state stackFrame = stackframe_array() + (newStackFrameIndex - 1); update_stack_frame (stackFrame); // Push NEW stack frame stackFrame++; } // Increment size of stack frame array currentThread->stackFrameArraySize++; // Initialize rest of new stack frame stackFrame->methodRecord = methodRecord; stackFrame->monitor = null; stackFrame->localsBase = get_stack_ptr() + 1; // Initialize auxiliary global variables (registers) pc = get_code_ptr(methodRecord); #if DEBUG_METHODS printf ("pc set to 0x%X\n", (int) pc); #endif init_sp (stackFrame, methodRecord); update_constant_registers (stackFrame); //printf ("m %d stack = %d\n", (int) methodRecord->signatureId, (int) (localsBase - stack_array())); // Check for stack overflow // (stackTop + methodRecord->maxOperands) >= (stack_array() + STACK_SIZE); if (is_stack_overflow (methodRecord)) { #if !FIXED_STACK_SIZE StackFrame *stackBase; int i; // Need at least this many bytes // int len = (int)(stackTop + methodRecord->maxOperands) - (int)(stack_array()) - HEADER_SIZE; // Need to compute new array size (as distinct from number of bytes in array). int newlen = (((int)(stackTop + methodRecord->maxOperands) - (int)(stack_array()) - HEADER_SIZE + 1) / 4) * 3 / 2; JINT newStackArray = ptr2word(reallocate_array(word2ptr(currentThread->stackArray), newlen)); // If can't allocate new stack, give in! if (newStackArray == JNULL) { #endif throw_exception (stackOverflowError); return false; #if !FIXED_STACK_SIZE } // Adjust pointers. newlen = newStackArray - currentThread->stackArray; stackBase = stackframe_array(); stackTop = word2ptr(ptr2word(stackTop) + newlen); localsBase = word2ptr(ptr2word(localsBase) + newlen); #if DEBUG_MEMORY printf("thread=%d, stackTop(%d), localsBase(%d)=%d\n", currentThread->threadId, (int)stackTop, (int)localsBase, (int)(*localsBase)); #endif for (i=currentThread->stackFrameArraySize-1; i >= 0; i--) { stackBase[i].localsBase = word2ptr(ptr2word(stackBase[i].localsBase) + newlen); stackBase[i].stackTop = word2ptr(ptr2word(stackBase[i].stackTop) + newlen); #if DEBUG_MEMORY printf("stackBase[%d].localsBase(%d) = %d\n", i, (int)stackBase[i].localsBase, (int)(*stackBase[i].localsBase)); #endif } // Assign new array currentThread->stackArray = newStackArray; #endif } return true; }
/** * @param classRecord Record for method class. * @param methodRecord Calle's method record. * @param retAddr What the PC should be upon return. * @return true iff the stack frame was pushed. */ boolean dispatch_special (MethodRecord *methodRecord, byte *retAddr) { /** * Note: This code is a little tricky, particularly when used with * a garbage collector. It manipulates the stack frame and in some cases * may need to perform memory allocation. In all cases we must take care * to ensure that if an allocation can be made then any live objects * on the stack must be below the current stack pointer. * In addition to the above we take great care so that this function can * be restarted (to allow us to wait for available memory). To enable this * we avoid making any commitments to changes to global state until both * stacks have been commited. */ #if DEBUG_METHODS int debug_ctr; #endif Object *stackFrameArray; StackFrame *stackFrame; StackFrame *stackBase; int newStackFrameIndex; STACKWORD *newStackTop; #if DEBUG_BYTECODE printf("call method %d ret %x\n", methodRecord - get_method_table(get_class_record(0)), retAddr); printf ("\n------ dispatch special - %d ------------------\n\n", methodRecord->signatureId); #endif #if DEBUG_METHODS printf ("dispatch_special: %d, %d\n", (int) methodRecord, (int) retAddr); printf ("-- signature id = %d\n", methodRecord->signatureId); printf ("-- code offset = %d\n", methodRecord->codeOffset); printf ("-- flags = %d\n", methodRecord->mflags); printf ("-- num params = %d\n", methodRecord->numParameters); //printf ("-- stack ptr = %d\n", (int) get_stack_ptr()); //printf ("-- max stack ptr= %d\n", (int) (currentThread->stackArray + (get_array_size(currentThread->stackArray))*2)); #endif // First deal with the easy case of a native call... if (is_native (methodRecord)) { #if DEBUG_METHODS printf ("-- native\n"); #endif // WARNING: Once the instruction below has been executed we may have // references on the stack that are above the stack pointer. If a GC // gets run when in this state the reference may get collected as // grabage. This means that any native functions that take a reference // parameter and that may end up allocating memory *MUST* protect that // reference before calling the allocator... pop_words_cur (methodRecord->numParameters); switch(dispatch_native (methodRecord->signatureId, get_stack_ptr_cur() + 1)) { case EXEC_RETRY: // Need to re-start the instruction, so reset the state of the stack curStackTop += methodRecord->numParameters; break; case EXEC_CONTINUE: // Normal completion return to the requested point. curPc = retAddr; break; case EXEC_RUN: // We are running new code, curPc will be set. Nothing to do. break; case EXEC_EXCEPTION: // An exception has been thrown. The PC will be set correctly and // the stack may have been adjusted... break; } // Stack frame not pushed return false; } // Now start to build the new stack frames. We start by placing the // the new stack pointer below any params. The params will become locals // in the new frame. newStackTop = get_stack_ptr_cur() - methodRecord->numParameters; newStackFrameIndex = (int)(byte)currentThread->stackFrameIndex; if (newStackFrameIndex >= 255) { throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR); return false; } #if DEBUG_METHODS //for (debug_ctr = 0; debug_ctr < methodRecord->numParameters; debug_ctr++) // printf ("-- param[%d] = %ld\n", debug_ctr, (long) get_stack_ptr()[debug_ctr+1]); #endif stackFrameArray = ref2obj(currentThread->stackFrameArray); stackBase = (StackFrame *)array_start(stackFrameArray); // Setup OLD stackframe ready for return stackFrame = stackBase + (newStackFrameIndex); stackFrame->stackTop = newStackTop; stackFrame->pc = retAddr; // Push NEW stack frame // Increment size of stack frame array but do not commit to it until we have // completely built both new stacks. newStackFrameIndex++; stackFrame++; if (((byte *)stackFrame - (byte *)stackBase) >= get_array_length(stackFrameArray)) { #if FIXED_STACK_SIZE throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR); return false; #else if (expand_call_stack(currentThread) < 0) return false; stackFrame = (StackFrame *)array_start(currentThread->stackFrameArray) + newStackFrameIndex; #endif } // Initialize rest of new stack frame stackFrame->methodRecord = methodRecord; stackFrame->monitor = null; stackFrame->localsBase = newStackTop + 1; // Allocate space for locals etc. newStackTop = init_sp(stackFrame, methodRecord); stackFrame->stackTop = newStackTop; currentThread->stackFrameIndex = newStackFrameIndex; // Check for stack overflow if (is_stack_overflow (newStackTop, methodRecord)) { #if FIXED_STACK_SIZE throw_new_exception (JAVA_LANG_STACKOVERFLOWERROR); return false; #else if (expand_value_stack(currentThread, methodRecord->maxOperands+methodRecord->numLocals) < 0) { currentThread->stackFrameIndex--; return false; } // NOTE at this point newStackTop is no longer valid! newStackTop = stackFrame->stackTop; #endif } // All set. So now we can finally commit to the new stack frames update_constant_registers (stackFrame); curStackTop = newStackTop; // and jump to the start of the new code curPc = get_code_ptr(methodRecord); return true; }