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
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.
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 ***** */
47 VTable::VTable(Traits
* traits
, VTable
* _base
, Toplevel
* toplevel
)
53 , createInstanceProc(_base
? _base
->createInstanceProc
: ClassClosure::impossibleCreateInstanceProc
)
56 , interfaceBindingFunction(traits
->m_interfaceBindingFunction
)
59 AvmAssert(toplevel
!= NULL
);
60 AvmAssert(traits
!= NULL
);
63 void VTable::resolveSignatures(ScopeChain
* scope
)
65 AvmAssert(scope
!= NULL
);
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
));
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
))
102 // this->methods[i] = base->methods[i];
103 WB(gc
, this, &methods
[i
], base
->methods
[i
]);
110 //this->methods[i] = new (gc) MethodEnv(method, this);
111 WB(gc
, this, &methods
[i
], makeMethodEnv(method
, scope
));
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";
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();
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";
156 uint64_t VTable::bytesUsed() const
158 uint64_t bytesUsed
= sizeof(VTable
);
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
))
176 else if(method
!= NULL
)
178 bytesUsed
+= method
->bytesUsed();
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
);
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
;
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
);
240 #ifdef AVMPLUS_VERBOSE
241 PrintWriter
& VTable::print(PrintWriter
& prw
) const
243 return prw
<< traits
;