312 lines
7.9 KiB
C++
312 lines
7.9 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 ***** */
|
|
|
|
#ifndef __avmplus_AbstractFunction__
|
|
#define __avmplus_AbstractFunction__
|
|
|
|
|
|
#ifdef verify
|
|
#undef verify
|
|
#endif
|
|
|
|
namespace avmplus
|
|
{
|
|
/**
|
|
* AbstractFunction is the base class for all functions that
|
|
* can be executed by the VM: Actionscript functions,
|
|
* native functions, etc.
|
|
*/
|
|
class AbstractFunction : public MMgc::GCObject
|
|
{
|
|
public:
|
|
/** @name flags from .abc - limited to a BYTE */
|
|
/*@{*/
|
|
/** need arguments[0..argc] */
|
|
static const int NEED_ARGUMENTS = 0x00000001;
|
|
|
|
/** need activation object */
|
|
static const int NEED_ACTIVATION = 0x00000002;
|
|
|
|
/** need arguments[param_count+1..argc] */
|
|
static const int NEED_REST = 0x00000004;
|
|
|
|
/** has optional parameters */
|
|
static const int HAS_OPTIONAL = 0x00000008;
|
|
|
|
/** allow extra args, but dont capture them */
|
|
static const int IGNORE_REST = 0x00000010;
|
|
|
|
/** method is native */
|
|
static const int NATIVE = 0x00000020;
|
|
|
|
/** method sets default namespace */
|
|
static const int SETS_DXNS = 0x00000040;
|
|
|
|
/** method has table for parameter names */
|
|
static const int HAS_PARAM_NAMES = 0x00000080;
|
|
|
|
/*@}*/
|
|
|
|
/** @name internal flags - upper 3 BYTES available */
|
|
/*@{*/
|
|
static const int OVERRIDE = 0x00010000;
|
|
|
|
static const int NON_INTERRUPTABLE = 0x00020000;
|
|
|
|
static const int UNBOX_THIS = 0x00040000;
|
|
|
|
static const int NEEDS_CODECONTEXT = 0x00080000;
|
|
|
|
static const int HAS_EXCEPTIONS = 0x00100000;
|
|
|
|
#ifdef AVMPLUS_VERBOSE
|
|
static const int VERBOSE_VERIFY = 0x00200000;
|
|
#endif
|
|
|
|
static const int NEEDS_DXNS = 0x00400000;
|
|
|
|
static const int VERIFIED = 0x00800000;
|
|
#ifdef AVMPLUS_VERIFYALL
|
|
static const int VERIFY_PENDING = 0x01000000;
|
|
#endif
|
|
|
|
/** indicates method is final, no overrides allowed */
|
|
static const int FINAL = 0x02000000;
|
|
|
|
/** indicates the function is a method, that pushes the
|
|
receiver object onto the scope chain at method entry */
|
|
static const int NEED_CLOSURE = 0x04000000;
|
|
|
|
/** set to indicate that a function has no bytecode body. */
|
|
static const int ABSTRACT_METHOD = 0x08000000;
|
|
|
|
#ifdef AVMPLUS_INTERP
|
|
/**
|
|
* set to indicate that a function has been compiled
|
|
* to native code. In release mode we always compile
|
|
* so we don't need the flag.
|
|
*/
|
|
static const int TURBO = 0x80000000;
|
|
|
|
/**
|
|
* set to indictate that a function has been
|
|
* recommended to be interpreted.
|
|
*/
|
|
static const int SUGGEST_INTERP = 0x40000000;
|
|
#endif /* AVMPLUS_INTERP */
|
|
|
|
/**
|
|
* set once the signature types have been resolved and
|
|
* override signatures have been checked.
|
|
*/
|
|
static const int LINKED = 0x20000000;
|
|
|
|
/*@}*/
|
|
|
|
/**
|
|
* @name NativeMethod flags
|
|
* These are used in the NativeMethod subclass
|
|
*/
|
|
/*@{*/
|
|
/** cookie int passed into C++ code */
|
|
static const int NATIVE_COOKIE = 0x10000000;
|
|
/*@}*/
|
|
|
|
DWB(Traits*) declaringTraits;
|
|
DWB(Traits*) activationTraits;
|
|
DWB(PoolObject*) pool;
|
|
|
|
AvmCore* core() const
|
|
{
|
|
return pool->core;
|
|
}
|
|
|
|
uintptr iid() const
|
|
{
|
|
return ((uintptr)this)>>3;
|
|
}
|
|
|
|
bool usesCallerContext() const
|
|
{
|
|
return pool->isBuiltin && (!(flags & NATIVE) || (flags & NEEDS_CODECONTEXT));
|
|
}
|
|
|
|
// Builtin + non-native functions always need the dxns code emitted
|
|
// Builtin + native functions have flags to specify if they need the dxns code
|
|
bool usesDefaultXmlNamespace() const
|
|
{
|
|
return pool->isBuiltin && (!(flags & NATIVE) || (flags & NEEDS_DXNS));
|
|
}
|
|
|
|
/** number of declared parameters including optionals */
|
|
int param_count;
|
|
|
|
/** last optional_count params are optional */
|
|
int optional_count;
|
|
|
|
// offset to first rest arg,
|
|
// including the instance parameter.
|
|
// this is sum(sizeof(paramType(0..N)))
|
|
int restOffset;
|
|
|
|
/** see bitmask defs above */
|
|
int flags;
|
|
int method_id;
|
|
|
|
/** pointer to abc MethodInfo record */
|
|
const byte* info_pos;
|
|
|
|
void initParamTypes(int count);
|
|
void initDefaultValues(int count);
|
|
|
|
void resolveSignature(const Toplevel* toplevel);
|
|
|
|
bool argcOk(int argc)
|
|
{
|
|
return argc >= param_count-optional_count &&
|
|
(argc <= param_count || allowExtraArgs());
|
|
}
|
|
|
|
/**
|
|
* invoke this method. args are already coerced. argc
|
|
* is the number of arguments AFTER the instance, which
|
|
* is arg 0. ap will always have at least the instance.
|
|
*/
|
|
union {
|
|
Atom (*impl32)(MethodEnv*, int, uint32 *);
|
|
double (*implN)(MethodEnv*, int, uint32 *);
|
|
};
|
|
|
|
protected:
|
|
AbstractFunction();
|
|
|
|
public:
|
|
|
|
void setParamType(int index, Traits* t);
|
|
void setDefaultValue(int index, Atom defaultValue);
|
|
void makeIntoPrototypeFunction(const Toplevel* toplevel);
|
|
|
|
Traits* paramTraits(int index) const {
|
|
AvmAssert(index >= 0 && index <= param_count);
|
|
return m_types[index];
|
|
}
|
|
|
|
const Atom* getDefaultValues() const {
|
|
return m_values;
|
|
}
|
|
|
|
Atom getDefaultValue(int i) const {
|
|
return m_values[i];
|
|
}
|
|
|
|
void setReturnType(Traits* t) {
|
|
m_returnType = t;
|
|
}
|
|
|
|
Traits* returnTraits() const {
|
|
return m_returnType;
|
|
}
|
|
|
|
int requiredParamCount() const {
|
|
return param_count-optional_count;
|
|
}
|
|
|
|
int allowExtraArgs() const {
|
|
return isFlagSet(NEED_REST|NEED_ARGUMENTS|IGNORE_REST);
|
|
}
|
|
|
|
int hasMethodBody() const {
|
|
return !isFlagSet(ABSTRACT_METHOD);
|
|
}
|
|
|
|
int isFlagSet(int f) const {
|
|
return (flags & f);
|
|
}
|
|
|
|
int hasExceptions() const {
|
|
return flags & HAS_EXCEPTIONS;
|
|
}
|
|
|
|
int setsDxns() const {
|
|
return flags & SETS_DXNS;
|
|
}
|
|
|
|
bool makeMethodOf(Traits* type);
|
|
|
|
#ifdef AVMPLUS_VERIFYALL
|
|
int isVerified() const {
|
|
return flags & VERIFIED;
|
|
}
|
|
virtual void verify(Toplevel* toplevel) = 0;
|
|
#endif
|
|
|
|
void boxArgs(int argc, uint32 *ap, Atom* out);
|
|
|
|
protected:
|
|
DWB(Traits*) m_returnType;
|
|
DWB(Traits**) m_types; // actual length will be 1+param_count
|
|
DWB(Atom*) m_values; // default values for any optional params. size = optional_count
|
|
|
|
#ifdef AVMPLUS_VERBOSE
|
|
|
|
/** Dummy destructor to avoid warnings */
|
|
virtual ~AbstractFunction() {}
|
|
public:
|
|
virtual Stringp format(const AvmCore* core) const;
|
|
#endif
|
|
|
|
#if defined(AVMPLUS_VERBOSE) || defined(DEBUGGER)
|
|
public:
|
|
DRCWB(Stringp) name;
|
|
#endif
|
|
#ifdef DEBUGGER
|
|
virtual uint32 size() const;
|
|
#endif
|
|
};
|
|
|
|
#ifdef DEBUGGER
|
|
// for sampling
|
|
class FakeAbstractFunction : public AbstractFunction
|
|
{
|
|
public:
|
|
void verify(Toplevel *) {}
|
|
};
|
|
#endif
|
|
}
|
|
|
|
#endif /* __avmplus_AbstractFunction__ */
|