void MethodInfo::setInterpImpl() { MethodSignaturep ms = getMethodSignature(); if (ms->returnTraitsBT() == BUILTIN_number) _implFPR = avmplus::interpFPR; else _implGPR = avmplus::interpGPR; AvmAssert(isInterpreted()); _invoker = hasTypedArgs(ms) ? MethodEnv::coerceEnter_interp : MethodEnv::coerceEnter_interp_nocoerce; }
void MethodInfo::verify(Toplevel *toplevel, AbcEnv* abc_env) { AvmAssert(declaringTraits()->isResolved()); resolveSignature(toplevel); AvmCore* core = this->pool()->core; if (isNative()) { union { GprMethodProc implGPR; AvmThunkNativeThunker thunker; AvmThunkNativeThunkerN thunkerN; } u; #ifdef DEBUGGER if (core->debugger()) { MethodSignaturep ms = getMethodSignature(); if (ms->returnTraitsBT() == BUILTIN_number) u.thunkerN = MethodInfo::debugEnterExitWrapperN; else u.thunker = MethodInfo::debugEnterExitWrapper32; } else #endif { u.thunker = this->thunker(); } this->setNativeImpl(u.implGPR); } else { #ifdef DEBUGGER // just a fake CallStackNode here, so that if we throw a verify error, // we get a stack trace with the method being verified as its top entry. CallStackNode callStackNode(this); #endif /* DEBUGGER */ PERFM_NTPROF("verify-ticks"); CodeWriter* coder = NULL; Verifier verifier(this, toplevel, abc_env); /* These "buf" declarations are an unfortunate but expedient hack: the existing CodeWriter classes (eg CodegenLIR, etc) have historically always been stack-allocated, thus they have no WB protection on member fields. Recent changes were made to allow for explicit cleanup() of them in the event of exception, but there was a latent bug waiting to happen: the actual automatic var was going out of scope, but still being referenced (via the 'coder' pointer) in the exception handler, but the area being pointed to may or may not still be valid. The ideal fix for this would simply be to heap-allocate the CodeWriters, but that would require going thru the existing code carefully and inserting WB where appropriate. Instead, this "expedient" hack uses placement new to ensure the memory stays valid into the exception handler. Note: the lack of a call to the dtor of the CodeWriter(s) is not an oversight. Calling cleanup() on coder is equivalent to running the dtor for all of the CodeWriters here. Note: allocated using arrays of intptr_t (rather than char) to ensure alignment is acceptable. */ #define MAKE_BUF(name, type) \ intptr_t name[(sizeof(type)+sizeof(intptr_t)-1)/sizeof(intptr_t)] #if defined FEATURE_NANOJIT MAKE_BUF(jit_buf, CodegenLIR); #if defined AVMPLUS_WORD_CODE MAKE_BUF(teeWriter_buf, TeeWriter); #endif #ifdef FEATURE_CFGWRITER MAKE_BUF(cfg_buf, CFGWriter); #endif #endif #if defined AVMPLUS_WORD_CODE MAKE_BUF(translator_buf, WordcodeEmitter); #else MAKE_BUF(stubWriter_buf, CodeWriter); #endif TRY(core, kCatchAction_Rethrow) { #if defined FEATURE_NANOJIT if ((core->IsJITEnabled()) && !suggestInterp()) { PERFM_NTPROF("verify & IR gen"); // note placement-new usage! CodegenLIR* jit = new(jit_buf) CodegenLIR(this); #if defined AVMPLUS_WORD_CODE WordcodeEmitter* translator = new(translator_buf) WordcodeEmitter(this, toplevel); TeeWriter* teeWriter = new(teeWriter_buf) TeeWriter(translator, jit); coder = teeWriter; #else coder = jit; #endif #ifdef FEATURE_CFGWRITER // analyze code and generate LIR CFGWriter* cfg = new(cfg_buf) CFGWriter(this, coder); coder = cfg; #endif verifier.verify(coder); PERFM_TPROF_END(); if (!jit->overflow) { // assembler LIR into native code jit->emitMD(); } // the MD buffer can overflow so we need to re-iterate // over the whole thing, since we aren't yet robust enough // to just rebuild the MD code. // mark it as interpreted and try to limp along if (jit->overflow) { if (core->JITMustSucceed()) { Exception* e = new (core->GetGC()) Exception(core, core->newStringLatin1("JIT failed")->atom()); e->flags |= Exception::EXIT_EXCEPTION; core->throwException(e); } setInterpImpl(); } #ifdef AVMPLUS_WORD_CODE else { if (_abc.word_code.translated_code) { set_word_code(core->GetGC(), NULL); } if (_abc.word_code.exceptions) { _abc.word_code.exceptions = NULL; } } #endif } else { // NOTE copied below #if defined AVMPLUS_WORD_CODE WordcodeEmitter* translator = new(translator_buf) WordcodeEmitter(this, toplevel); coder = translator; #else CodeWriter* stubWriter = new(stubWriter_buf) CodeWriter(); coder = stubWriter; #endif verifier.verify(coder); // pass2 dataflow setInterpImpl(); // NOTE end copy } #else // FEATURE_NANOJIT // NOTE copied from above #if defined AVMPLUS_WORD_CODE WordcodeEmitter* translator = new(translator_buf) WordcodeEmitter(this, toplevel); coder = translator; #else CodeWriter* stubWriter = new(stubWriter_buf) CodeWriter(); coder = stubWriter; #endif verifier.verify(coder); // pass2 dataflow setInterpImpl(); // NOTE end copy #endif // FEATURE_NANOJIT if (coder) { coder->cleanup(); coder = NULL; } } CATCH (Exception *exception) { // clean up verifier verifier.~Verifier(); // call cleanup all the way down the chain // each stage calls cleanup on the next one if (coder) coder->cleanup(); // re-throw exception core->throwException(exception); } END_CATCH END_TRY PERFM_TPROF_END(); }