/* [<][>][^][v][top][bottom][index][help] */
/* ***** 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_MethodEnv__
#define __avmplus_MethodEnv__
namespace avmplus
{
class MethodEnvProcHolder : public MMgc::GCObject
{
friend class CodegenLIR;
#if VMCFG_METHODENV_IMPL32
protected:
MethodEnvProcHolder(GprMethodProc p);
union {
GprMethodProc _implGPR;
FprMethodProc _implFPR;
};
#else
protected:
MethodEnvProcHolder(MethodInfo* m);
public:
MethodInfo* const method;
#endif
public:
GprMethodProc implGPR() const;
FprMethodProc implFPR() const;
};
class MethodEnv : public MethodEnvProcHolder
{
friend class CodegenLIR;
friend class MethodInfo;
friend class MethodInfoProcHolder;
#if VMCFG_METHODENV_IMPL32
static uintptr_t delegateInvoke(MethodEnv* env, int32_t argc, uint32_t *ap);
#endif
public:
/** vtable for the activation scope inside this method */
ScriptObject* newActivation();
/** getter lazily creates table which maps SO->MC */
WeakKeyHashtable *getMethodClosureTable();
MethodEnv(MethodInfo* method, ScopeChain* scope);
AbcEnv* abcEnv() const;
AvmCore* core() const;
CodeContext* codeContext() const;
DomainEnv* domainEnv() const;
ScopeChain* scope() const;
MethodEnv* super_init() const;
Toplevel* toplevel() const;
Stringp traitsName() const;
Namespacep traitsNs() const;
ScriptEnv* getScriptEnv(const Multiname *m) const;
/**
* Coerces an array of actual parameters to the types
* required by a function's formal parameters, then invokes
* the method. Args are provided as an array of atoms, not
* an array of native types.
*
* It is not well documented throughout, but it is generally
* assumed that argument arrays may /always/ be modified in
* place by the callee, thus coerceEnter may modify 'argv'
* (though not the ArrayObject 'a', of course).
*
* @param instance The "this" that the function
* is being invoked with; may be
* coerced by this method.
* @param argv The array of arguments to coerce
* @param argc The number of arguments
* @throws Exception May throw an ArgumentError or
* TypeError if an argument cannot be coerced
* to the required type
*/
Atom coerceEnter(Atom thisArg);
Atom coerceEnter(Atom thisArg, ArrayObject* a);
Atom coerceEnter(Atom thisArg, int32_t argc, Atom* argv);
Atom coerceEnter(int32_t argc, Atom* argv);
private:
static Atom coerceEnter_interp(MethodEnv* env, int32_t argc, Atom* argv);
static Atom coerceEnter_interp_nocoerce(MethodEnv* env, int32_t argc, Atom* argv);
static Atom coerceEnter_generic(MethodEnv* env, int32_t argc, Atom* argv);
MethodSignaturep get_ms();
bool isInterpreted();
Atom endCoerce(int32_t argc, uint32_t *ap, MethodSignaturep ms);
int32_t startCoerce(int32_t argc, MethodSignaturep ms);
Atom coerceUnboxEnter(int32_t argc, Atom* atomv);
void unboxCoerceArgs(Atom thisArg, ArrayObject *a, uint32_t *argv, MethodSignaturep ms);
void unboxCoerceArgs(int32_t argc, Atom* in, uint32_t *ap, MethodSignaturep ms);
void unboxCoerceArgs(Atom thisArg, int32_t argc, Atom* in, uint32_t *argv, MethodSignaturep ms);
void FASTCALL nullcheckfail(Atom atom);
Atom* FASTCALL coerceUnbox1(Atom atom, Traits* t, Atom* args);
Atom* FASTCALL unbox1(Atom atom, Traits* t, Atom* args);
VTable* getActivationVTable();
VTable* buildActivationVTable();
// helper functions used from compiled code
public:
void argcError(int32_t argc); // never returns; throws argument count error
void nullcheck(Atom atom); // null pointer check
void npe(); // never returns; throws null pointer error
ArrayObject* createRest(Atom* argv, int32_t argc);
Atom getpropertylate_i(Atom obj, int32_t index) const;
Atom getpropertylate_u(Atom obj, uint32_t index) const;
#if defined FEATURE_NANOJIT || defined VMCFG_AOT
void setpropertyHelper(Atom obj, /* not const */ Multiname *multi, Atom value, VTable *vtable, Atom index);
void initpropertyHelper(Atom obj, /* not const */ Multiname *multi, Atom value, VTable *vtable, Atom index);
Atom getpropertyHelper(Atom obj, /* not const */ Multiname *multi, VTable *vtable, Atom index);
Atom delpropertyHelper(Atom obj, /* not const */ Multiname *multi, Atom index);
void initMultinameLateForDelete(Multiname& name, Atom index);
ArrayObject* createArgumentsHelper(int32_t argc, uint32_t *ap);
ArrayObject* createRestHelper(int32_t argc, uint32_t *ap);
#endif
ScriptObject* newcatch(Traits *traits);
/**
* used for defining and resolving imported definitions.
*/
ScriptObject* finddef(const Multiname* name) const;
/**
* implementation of object initializers
*/
ScriptObject* op_newobject(Atom* sp, int32_t argc) const;
/** Implementation of OP_nextname */
Atom nextname(Atom objAtom, int32_t index) const;
/** Implementation of OP_nextvalue */
Atom nextvalue(Atom objAtom, int32_t index) const;
/** Implementation of OP_hasnext */
int32_t hasnext(Atom objAtom, int32_t index) const;
/** Implementation of OP_hasnext2 */
int32_t hasnextproto(Atom& objAtom, int& index) const;
/**
* OP_newfunction
* see 13.2 creating function objects
*/
ClassClosure* newfunction(MethodInfo *function,
ScopeChain* outer,
Atom* scopes) const;
/**
* OP_newclass
*/
ClassClosure* newclass(Traits* ctraits,
ClassClosure* base,
ScopeChain* outer,
Atom* scopes) const;
void initproperty(Atom obj, const Multiname* multiname, Atom value, VTable* vtable) const;
void setpropertylate_i(Atom obj, int32_t index, Atom value) const;
void setpropertylate_u(Atom obj, uint32_t index, Atom value) const;
/** same as callproperty but only considers the bindings in given vtable */
Atom callsuper(const Multiname* name, int32_t argc, Atom* atomv) const;
Atom delproperty(Atom obj, const Multiname* multiname) const;
/**
* Reads a property from an object, with the property
* to retrieve specified by its binding.
* The binding was likely retrieved using getBinding.
* @param obj Object to retrieve property from
* @param b The binding of the property
* @param traits The traits of the object
*/
Atom getsuper(Atom obj, const Multiname* name) const;
/**
* Write to a property of an object, with the property
* to modify specified by its binding.
* The binding was likely retrieved using getBinding.
* @param obj Object to modify property of
* @param b The binding of the property
* @param value The new value of the property
*/
void setsuper(Atom obj, const Multiname* name, Atom value) const;
/** Implementation of OP_findproperty */
Atom findproperty(ScopeChain* outer,
Atom* scopes,
int32_t extraScopes,
const Multiname* multiname,
bool strict,
Atom* withBase);
/** Like findproperty, but ignoring all lexical and 'this' scopes. Returns NULL if
* property could not be found; caller should signal strict error or return the
* target_global as appropriate.
*/
Atom findglobalproperty(Atom target_global, const Multiname* multiname);
Namespace* internRtns(Atom ns);
/** Creates the arguments array */
ArrayObject* createArguments(Atom *atomv, int32_t argc);
/**
* E4X descendants operator (..)
*/
Atom getdescendants(Atom obj, const Multiname* multiname);
/**
* E4X filter operator
*/
void checkfilter(Atom obj);
ScriptObject* coerceAtom2SO(Atom atom, Traits *expected) const;
#ifdef DEBUGGER
void debugEnter(Traits** frameTraits,
CallStackNode* callstack,
FramePtr framep,
volatile intptr_t *eip);
void debugEnterInner();
void debugExit(CallStackNode* callstack);
#endif
private:
Atom findWithProperty(Atom obj, const Multiname* multiname);
class ActivationMethodTablePair
{
public:
ActivationMethodTablePair(VTable *a, WeakKeyHashtable*wkh);
// ------------------------ DATA SECTION BEGIN
public:
VTable* const activation;
WeakKeyHashtable* const methodTable;
// ------------------------ DATA SECTION END
};
// low 2 bits of activationOrMCTable
enum { kActivation=0, kMethodTable, kActivationMethodTablePair };
// and the 3rd bit is a flag for "am I a ScriptEnv"
enum { kIsScriptEnv = 4 };
ActivationMethodTablePair* getPair() const;
int32_t getType() const;
void setActivationOrMCTable(void *ptr, int32_t type);
protected:
void setIsScriptEnv();
public:
bool isScriptEnv() const;
#ifdef DEBUGGER
uint64_t invocationCount() const;
#endif
protected:
VTable* vtable() const;
// ------------------------ DATA SECTION BEGIN
#if VMCFG_METHODENV_IMPL32
public:
MethodInfo* const method;
#else
// inherit "method" from MethodEnvProcHolder. yeah, this is ugly,
// but allows us to eliminate an otherwise-useless field from ImtThunkEnv.
#endif
protected:
// pointers are write-once so we don't need WB's
ScopeChain* const _scope;
private:
uintptr_t activationOrMCTable;
public:
#ifdef VMCFG_LOOKUP_CACHE
class LookupCache : public MMgc::GCObject
{
public:
uint32_t timestamp;
DRCWB(ScriptObject*) object;
};
DWB(LookupCache*) lookup_cache;
#endif
// ------------------------ DATA SECTION END
};
class ScriptEnv : public MethodEnv
{
public:
ScriptEnv(MethodInfo* _method, VTable* _vtable, AbcEnv* _abcEnv);
ScriptObject* initGlobal();
private:
static ScopeChain* createScriptScope(const ScopeTypeChain* stc, VTable* _vtable, AbcEnv* _abcEnv);
// ------------------------ DATA SECTION BEGIN
public:
DRCWB(ScriptObject*) global; // initially null, set after initialization
// ------------------------ DATA SECTION END
};
class FunctionEnv : public MethodEnv
{
public:
FunctionEnv(MethodInfo* _method, ScopeChain* _scope);
// ------------------------ DATA SECTION BEGIN
public:
DRCWB(ClassClosure*) closure;
// ------------------------ DATA SECTION END
};
#if defined FEATURE_NANOJIT
struct ImtThunkEntry
{
uintptr_t iid;
uintptr_t disp_id; // only needs to be uint32_t, is this size for alignment purposes
};
class ImtThunkEnv;
class ImtThunkEnv : public MethodEnvProcHolder
{
public:
ImtThunkEnv(GprImtThunkProc p, VTable* v);
ImtThunkEnv(GprImtThunkProc p, uint32_t c);
GprImtThunkProc implImtGPR() const;
ImtThunkEntry* entries() const;
// ------------------------ DATA SECTION BEGIN
public:
union
{
VTable* vtable;
uint32_t imtMapCount;
};
#if !VMCFG_METHODENV_IMPL32
MethodInfoProcHolder methodProcHolder;
#endif
// ------------------------ DATA SECTION END
};
#endif // FEATURE_NANOJIT
}
#endif // __avmplus_MethodEnv__