Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / core / VTable.cpp
bloba189c4fc4f40cdb5fcd92d0e7b41558c4f8ba3d0
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 1993-2006
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #include "avmplus.h"
42 //#define DOPROF
43 //#include "vprof.h"
45 namespace avmplus
47 VTable::VTable(Traits* traits, VTable* _base, Toplevel* toplevel)
48 : _toplevel(toplevel)
49 , init(NULL)
50 , base(_base)
51 , ivtable(NULL)
52 , traits(traits)
53 , createInstanceProc(_base ? _base->createInstanceProc : ClassClosure::impossibleCreateInstanceProc)
54 , linked(false)
55 #ifdef VMCFG_AOT
56 , interfaceBindingFunction(traits->m_interfaceBindingFunction)
57 #endif
59 AvmAssert(toplevel != NULL);
60 AvmAssert(traits != NULL);
63 void VTable::resolveSignatures(ScopeChain* scope)
65 AvmAssert(scope != NULL);
67 if( this->linked )
68 return;
69 linked = true;
70 if (!traits->isResolved())
72 traits->resolveSignatures(toplevel());
73 traits->setDeclaringScopes(scope->scopeTraits());
76 #if defined(DEBUG) || defined(_DEBUG)
77 // have to use local variables for CodeWarrior
78 Traits* traitsBase = traits->base;
79 Traits* baseTraits = base ? base->traits : 0;
80 // make sure the traits of the base vtable matches the base traits
81 AvmAssert((base == NULL && traits->base == NULL) || (base != NULL && traitsBase == baseTraits));
82 #endif // DEBUG
84 AvmCore* core = traits->core;
85 MMgc::GC* gc = core->GetGC();
87 if (traits->init && !this->init)
89 this->init = makeMethodEnv(traits->init, scope);
92 // populate method table
93 const TraitsBindingsp td = traits->getTraitsBindings();
94 const TraitsBindingsp btd = td->base;
95 for (uint32_t i = 0, n = td->methodCount; i < n; i++)
97 MethodInfo* method = td->getMethod(i);
99 if (btd && i < btd->methodCount && method == btd->getMethod(i))
101 // inherited method
102 // this->methods[i] = base->methods[i];
103 WB(gc, this, &methods[i], base->methods[i]);
104 continue;
107 // new definition
108 if (method != NULL)
110 //this->methods[i] = new (gc) MethodEnv(method, this);
111 WB(gc, this, &methods[i], makeMethodEnv(method, scope));
112 continue;
114 #ifdef AVMPLUS_VERBOSE
115 if (traits->pool->isVerbose(VB_traits))
117 // why would the compiler assign sparse disp_id's?
118 traits->core->console << "WARNING: empty disp_id " << i << " on " << traits << "\n";
120 #endif
123 // this is done here b/c this property of the traits isn't set until the
124 // Dictionary's ClassClosure is called
125 if (base && base->traits->isDictionary())
126 traits->set_isDictionary();
128 traits->core->exec->notifyVTableResolved(this);
131 MethodEnv* VTable::makeMethodEnv(MethodInfo* func, ScopeChain* scope)
133 AvmCore* core = this->core();
134 AbcEnv* abcEnv = scope->abcEnv();
135 MethodEnv* methodEnv = MethodEnv::create(core->GetGC(), func, scope);
136 // register this env in the callstatic method table
137 int method_id = func->method_id();
138 if (method_id != -1)
140 AvmAssert(abcEnv->pool() == func->pool());
141 if (abcEnv->getMethod(method_id) == NULL)
143 abcEnv->setMethod(method_id, methodEnv);
145 #ifdef AVMPLUS_VERBOSE
146 else if (func->pool()->isVerbose(VB_traits))
148 core->console << "WARNING: tried to re-register global MethodEnv for " << func << "\n";
150 #endif
152 return methodEnv;
155 #ifdef DEBUGGER
156 uint64_t VTable::bytesUsed() const
158 uint64_t bytesUsed = sizeof(VTable);
160 if(ivtable != NULL)
161 bytesUsed += ivtable->bytesUsed();
163 const TraitsBindingsp td = traits->getTraitsBindings();
164 const uint32_t n = td->methodCount;
165 const uint32_t baseMethodCount = base ? td->base->methodCount : 0;
166 bytesUsed += td->methodCount*sizeof(MethodInfo*);
168 for (uint32_t i=0; i < n; i++)
170 MethodInfo* method = td->getMethod(i);
172 if (i < baseMethodCount && td->base && method == td->base->getMethod(i))
174 continue;
176 else if(method != NULL)
178 bytesUsed += method->bytesUsed();
181 return bytesUsed;
183 #endif
185 VTable* VTable::newParameterizedVTable(Traits* param_traits, Stringp fullname)
187 Toplevel* toplevel = this->toplevel();
188 AvmCore* core = toplevel->core();
189 Namespacep traitsNs = this->traits->ns();
191 VTable* objVecVTable = toplevel->objectVectorClass()->vtable;
192 AbcEnv* objVecAbcEnv = toplevel->vectorobj_cscope->abcEnv();
193 Toplevel* objVecToplevel = objVecVTable->toplevel();
194 VTable* objVecIVTable = objVecVTable->ivtable;
196 // these cases should all be filtered out by the caller;
197 // we only want to handle Vector<SomeObject> here
198 AvmAssert(param_traits != NULL &&
199 param_traits != toplevel->intClass()->vtable->traits->itraits &&
200 param_traits != toplevel->uintClass()->vtable->traits->itraits &&
201 param_traits != toplevel->numberClass()->vtable->traits->itraits);
203 PoolObject* traitsPool = this->traits->pool;
205 Stringp classname = core->internString(fullname->appendLatin1("$"));
206 Traits* ctraits = core->domainMgr()->findTraitsInPoolByNameAndNS(traitsPool, classname, traitsNs);
207 Traits* itraits;
208 if (!ctraits)
210 // important: base the new ctraits on objVecVTable->traits, *not* this->traits;
211 // we want the result to be based off ObjectVectorClass, not VectorClass
212 // (otherwise sizeofInstance would be too small and we'd be crashy)
213 ctraits = objVecVTable->traits->newParameterizedCTraits(classname, traitsNs);
214 ctraits->verifyBindings(toplevel);
216 itraits = traitsPool->resolveParameterizedType(toplevel, this->ivtable->traits, param_traits);
217 ctraits->itraits = itraits;
219 else
221 itraits = ctraits->itraits;
224 AvmAssert(itraits != NULL);
226 VTable* cvtab = core->newVTable(ctraits, objVecToplevel->class_ivtable, objVecToplevel);
227 ScopeChain* cvtab_cscope = toplevel->vectorobj_cscope->cloneWithNewVTable(core->GetGC(), cvtab, objVecAbcEnv);
229 VTable* ivtab = core->newVTable(itraits, objVecIVTable, objVecToplevel);
230 ScopeChain* ivtab_iscope = toplevel->vectorobj_iscope->cloneWithNewVTable(core->GetGC(), ivtab, objVecAbcEnv);
231 cvtab->ivtable = ivtab;
232 ivtab->init = objVecIVTable->init;
234 cvtab->resolveSignatures(cvtab_cscope);
235 ivtab->resolveSignatures(ivtab_iscope);
237 return cvtab;
240 #ifdef AVMPLUS_VERBOSE
241 PrintWriter& VTable::print(PrintWriter& prw) const
243 return prw << traits;
245 #endif