Mozilla/mozilla/js/tamarin/core/MethodInfo.cpp
gerv%gerv.net 0a3a70857a Bug 236613: fix formatting of MPL/LGPL/GPL tri-license.
git-svn-id: svn://10.0.0.236/trunk@220064 18797224-902f-48f8-a5cc-f745e15eee43
2007-02-13 18:05:02 +00:00

340 lines
9.2 KiB
C++

/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is [Open Source Virtual Machine.].
*
* The Initial Developer of the Original Code is
* Adobe System Incorporated.
* Portions created by the Initial Developer are Copyright (C) 2004-2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Adobe AS3 Team
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "avmplus.h"
namespace avmplus
{
using namespace MMgc;
MethodInfo::MethodInfo()
: AbstractFunction()
{
#ifdef DEBUGGER
this->local_count = 0;
this->max_scopes = 0;
this->localNames = 0;
this->firstSourceLine = 0;
this->lastSourceLine = 0;
this->offsetInAbc = 0;
#endif
this->impl32 = verifyEnter;
}
Atom MethodInfo::verifyEnter(MethodEnv* env, int argc, uint32 *ap)
{
MethodInfo* f = (MethodInfo*) env->method;
f->verify(env->vtable->toplevel);
#ifdef AVMPLUS_VERIFYALL
f->flags |= VERIFIED;
if (f->pool->core->verifyall && f->pool)
f->pool->processVerifyQueue(env->toplevel());
#endif
env->impl32 = f->impl32;
return f->impl32(env, argc, ap);
}
void MethodInfo::verify(Toplevel* toplevel)
{
AvmAssert(declaringTraits->linked);
resolveSignature(toplevel);
#ifdef DEBUGGER
CallStackNode callStackNode(NULL, this, NULL, NULL, 0, NULL, NULL);
#endif /* DEBUGGER */
if (!body_pos)
{
// no body was supplied in abc
toplevel->throwVerifyError(kNotImplementedError, toplevel->core()->toErrorString(this));
}
#ifdef AVMPLUS_MIR
Verifier verifier(this, toplevel);
AvmCore* core = this->core();
if (core->turbo && !isFlagSet(AbstractFunction::SUGGEST_INTERP))
{
CodegenMIR mir(this);
verifier.verify(&mir); // pass 2 - data flow
if (!mir.overflow)
mir.emitMD(); // pass 3 - generate code
// 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 (mir.overflow)
{
#ifdef AVMPLUS_INTERP
AvmCore* core = this->core();
if (returnTraits() == NUMBER_TYPE)
implN = Interpreter::interpN;
else
impl32 = Interpreter::interp32;
#else
toplevel()->throwError(kOutOfMemoryError);
#endif //AVMPLUS_INTERP
}
}
else
{
verifier.verify(NULL); // pass2 dataflow
}
#else
Verifier verifier(this, toplevel);
verifier.verify(NULL);
#endif
#ifdef DEBUGGER
callStackNode.exit();
#endif /* DEBUGGER */
}
#ifdef DEBUGGER
// reg names
Stringp MethodInfo::getLocalName(int index) const { return getRegName(index+param_count); }
Stringp MethodInfo::getArgName(int index) const { return getRegName(index); }
Stringp MethodInfo::getRegName(int slot) const
{
AvmAssert(slot >= 0 && slot < local_count);
Stringp name;
if (localNames)
name = localNames[slot];
else
name = core()->kundefined;
return name;
}
void MethodInfo::setRegName(int slot, Stringp name)
{
//AvmAssert(slot >= 0 && slot < local_count);
// @todo fix me. This is a patch for bug #112405
if (slot >= local_count)
return;
if (!localNames)
initLocalNames();
AvmCore* core = this->core();
// [mmorearty 5/3/05] temporary workaround for bug 123237: if the register
// already has a name, don't assign a new one
if (getRegName(slot) != core->kundefined)
return;
//localNames[slot] = core->internString(name);
WBRC(core->GetGC(), localNames, &localNames[slot], core->internString(name));
}
void MethodInfo::initLocalNames()
{
AvmCore* core = this->core();
localNames = (Stringp*) core->GetGC()->Calloc(local_count, sizeof(Stringp), GC::kZero|GC::kContainsPointers);
for(int i=0; i<local_count; i++)
{
//localNames[i] = core->kundefined;
WBRC(core->GetGC(), localNames, &localNames[i], core->kundefined);
}
}
/**
* convert ap[start]...ap[start+count-1] entries from their native types into
* Atoms. The result is placed into out[to]...out[to+count-1].
*
* The traitArr is used to determine the type of conversion that should take place.
* traitArr[start]...traitArr[start+count-1] are used.
*
* If the method is interpreted then we just copy the Atom, no conversion is needed.
*/
void MethodInfo::boxLocals(void* src, int srcPos, Traits** traitArr, Atom* dest, int destPos, int length)
{
int size = srcPos+length;
int at = destPos;
// if we are running mir then the types are native and we
// need to box em.
#ifdef AVMPLUS_INTERP
if (isFlagSet(TURBO))
#endif //AVMPLUS_INTERP
{
// each entry is a pointer into the function's stack frame
void **in = (void**)src; // WARNING this must match with MIR generator
// now probe each type and do the atom conversion.
AvmCore* core = this->core();
for (int i=srcPos; i<size; i++)
{
Traits* t = traitArr[i];
void *p = in[i];
if (t == NUMBER_TYPE)
{
dest[at] = core->doubleToAtom( *((double*)p) );
}
else if (t == INT_TYPE)
{
dest[at] = core->intToAtom( *((int*)p) );
}
else if (t == UINT_TYPE)
{
dest[at] = core->uintToAtom( *((uint32*)p) );
}
else if (t == BOOLEAN_TYPE)
{
dest[at] = *((int*)p) ? trueAtom : falseAtom;
}
else if (!t || t == OBJECT_TYPE || t == VOID_TYPE)
{
dest[at] = *((Atom*)p);
}
else
{
// it's a pointer type, either null or some specific atom tag.
void* ptr = *((void**)p); // unknown pointer
if (t == STRING_TYPE)
{
dest[at] = ((Stringp)ptr)->atom();
}
else if (t == NAMESPACE_TYPE)
{
dest[at] = ((Namespace*)ptr)->atom();
}
else
{
dest[at] = ((ScriptObject*)ptr)->atom();
}
}
at++;
}
}
#ifdef AVMPLUS_INTERP
else
{
// no MIR then we know they are Atoms and we just copy them
Atom* in = (Atom*)src;
for(int i=srcPos; i<size; i++)
dest[at++] = in[i];
}
#endif //AVMPLUS_INTERP
}
/**
* convert in[0]...in[count-1] entries from Atoms to native types placing them
* in ap[start]...out[start+count-1].
*
* The traitArr is used to determine the type of conversion that should take place.
* traitArr[start]...traitArr[start+count-1] are used.
*
* If the method is interpreted then we just copy the Atom, no conversion is needed.
*/
void MethodInfo::unboxLocals(Atom* src, int srcPos, Traits** traitArr, void* dest, int destPos, int length)
{
#ifdef AVMPLUS_64BIT
AvmDebugMsg (true, "are these ops right for 64-bit? alignment of int/uint/bool?\n");
#endif
int size = destPos+length;
int at = srcPos;
// If the method has been jit'd then we need to box em, otherwise just
// copy them
#ifdef AVMPLUS_INTERP
if (isFlagSet(TURBO))
#endif //AVMPLUS_srcTERP
{
// we allocated double sized entry for each local src CodegenMIR
void** out = (void**)dest; // WARNING this must match with MIR generator
// now probe each type and conversion.
AvmCore* core = this->core();
for (int i=destPos; i<size; i++)
{
Traits* t = traitArr[i];
void *p = out[i];
if (t == NUMBER_TYPE)
{
*((double*)p) = AvmCore::number_d(src[at++]);
}
else if (t == INT_TYPE)
{
*((int*)p) = AvmCore::integer_i(src[at++]);
}
else if (t == UINT_TYPE)
{
*((uint32*)p) = AvmCore::integer_u(src[at++]);
}
else if (t == BOOLEAN_TYPE)
{
*((int*)p) = src[at++]>>3;
}
else if (!t || t == OBJECT_TYPE || t == VOID_TYPE)
{
*((Atom*)p) = src[at++];
}
else
{
// ScriptObject, String, Namespace, or Null
*((sintptr*)p) = (src[at++] & ~7);
}
}
}
#ifdef AVMPLUS_INTERP
else
{
// no MIR then we know they are Atoms and we just copy them
Atom* out = (Atom*)dest;
for(int i=destPos; i<size; i++)
out[i] = src[at++];
}
#endif //AVMPLUS_srcTERP
}
uint32 MethodInfo::size() const
{
uint32 size = AbstractFunction::size();
size += (sizeof(MethodInfo) - sizeof(AbstractFunction));
size += codeSize;
return size;
}
#endif //DEBUGGER
}