Ejemplo n.º 1
0
    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;
    }
Ejemplo n.º 2
0
	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();
		}