Bug Summary

File:platform/mac/avmshell/../../../core/PoolObject.cpp
Location:line 551, column 13
Description:Value stored to 'index' is never read

Annotated Source Code

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
5 *
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/
10 *
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.
15 *
16 * The Original Code is [Open Source Virtual Machine.].
17 *
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2004-2006
21 * the Initial Developer. All Rights Reserved.
22 *
23 * Contributor(s):
24 * Adobe AS3 Team
25 *
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.
37 *
38 * ***** END LICENSE BLOCK ***** */
39
40
41#include "avmplus.h"
42
43#ifdef VMCFG_NANOJIT
44# include "CodegenLIR.h"
45#endif
46
47namespace avmplus
48{
49 // This assert is here to ensure that "GCDouble" is the same
50 // bit value as "double"; GCDouble exists solely to provide
51 // a GCObject-descended type to satisfy new constraints on List.
52 MMGC_STATIC_ASSERT(sizeof(GCDouble) == sizeof(double))typedef ::MMgc::static_assert_MMgc<sizeof (::MMgc::STATIC_ASSERTION_FAILED
<(bool)(sizeof(GCDouble) == sizeof(double))>)> MMgc_static_assert_line_52
;
53
54 PoolObject::PoolObject(AvmCore* core, ScriptBuffer& sb, const uint8_t* startPos, ApiVersion apiVersion) :
55 core(core),
56 cpool_int(core->GetGC(), 0),
57 cpool_uint(core->GetGC(), 0),
58 cpool_double(core->GetGC(), 0),
59 cpool_ns(core->GetGC(), 0),
60 cpool_ns_set(core->GetGC(), 0),
61#ifndef AVMPLUS_64BIT
62 cpool_int_atoms(core->GetGC(), 0),
63 cpool_uint_atoms(core->GetGC(), 0),
64#endif
65 cpool_mn_offsets(core->GetGC(), 0),
66 metadata_infos(core->GetGC(), 0),
67 m_loadedTraits(MultinameTraitsHashtable::create(core->GetGC())),
68 m_cachedTraits(MultinameTraitsHashtable::create(core->GetGC())),
69 m_loadedScripts(MultinameMethodInfoHashtable::create(core->GetGC())),
70 m_cachedScripts(MultinameMethodInfoHashtable::create(core->GetGC())),
71 _code(sb.getImpl()),
72 _abcStart(startPos),
73 _abcStringStart(NULL__null),
74 _abcStringEnd(NULL__null),
75 _abcStrings(NULL__null),
76 _classes(core->GetGC(), 0),
77 _scripts(core->GetGC(), 0),
78 _methods(core->GetGC(), 0)
79#ifdef DEBUGGER
80 , _method_dmi(core->GetGC(), 0)
81#endif
82 , _method_name_indices(core->GetGC(), 0)
83 , _apiVersion(apiVersion)
84 , _uniqueId(-1)
85#ifdef VMCFG_AOT
86 , aotInfo(NULL__null)
87 , aotRoot(NULL__null)
88#endif
89 {
90 version = AvmCore::readU16(&code()[0]) | AvmCore::readU16(&code()[2])<<16;
91 core->addLivePool(this);
92 }
93
94 PoolObject::~PoolObject()
95 {
96 #ifdef VMCFG_AOT
97 if (aotRoot)
98 delete aotRoot;
99 #endif
100#ifdef VMCFG_NANOJIT
101 mmfx_delete( codeMgr )::MMgcDestructTaggedScalarChecked(codeMgr);
102#endif
103 }
104
105 void PoolObject::dynamicizeStrings()
106 {
107 if (!MMgc::GC::GetGC(this)->Destroying())
108 {
109 // make all strings created so far dynamic,
110 // making sure that no pointers into ABC data persist
111 // (string 0 is always core->kEmptyString: skip it)
112 ConstantStringData* dataP = _abcStrings->data;
113 for (uint32_t i = 1; i < constantStringCount; i++)
114 {
115 ++dataP;
116
117 if (dataP->abcPtr >= _abcStringStart && dataP->abcPtr < _abcStringEnd)
118 {
119 // it's still a raw ABC ptr, not a String
120 continue;
121 }
122
123 Stringp s = dataP->str;
124
125 // in theory, only index 0 should be the empty string... but in practice,
126 // any index could be empty, and makeDynamic doesn't work on zero-length strings.
127 // since that call doesn't have easy access to an AvmCore, do the check here.
128 // (s can be null in the obscure case of a fuzzed ABC)
129 if (!s || s->isEmpty())
130 {
131 // all zero-length strings should be kEmptyString.
132 AvmAssert(!s || s == core->kEmptyString)do { } while (0);
133 continue;
134 }
135
136 s->makeDynamic(_abcStringStart, uint32_t(_abcStringEnd - _abcStringStart));
137 }
138 }
139 }
140
141 Namespace* PoolObject::getNamespace(int32_t index) const
142 {
143 return cpool_ns[index];
144 }
145
146 NamespaceSetp PoolObject::getNamespaceSet(int32_t index) const
147 {
148 return cpool_ns_set[index];
149 }
150
151 ////////////////////////////////////////////////////////////////////
152
153 boolbool ConstantStringContainer::gcTrace(MMgc::GC* gc, size_t cursor)
154 {
155 size_t cap = pool->constantStringCount;
156 const uint32_t work_increment = 2000/sizeof(void*);
157 if (work_increment * cursor >= cap)
158 return falsefalse;
159
160 size_t work = work_increment;
161 boolbool more = truetrue;
162 if (work_increment * (cursor + 1) >= cap) {
163 work = cap - (work_increment * cursor);
164 more = falsefalse;
165 }
166
167 const uint8_t *start = pool->_abcStringStart;
168 const uint8_t *end = pool->_abcStringEnd;
169
170 // Skip strings into the ABC data, everything else is a real String pointer
171 for ( size_t i=0 ; i < work ; i++ ) {
172 ConstantStringData& item = data[(work_increment * cursor) + i];
173 if (item.abcPtr >= start && item.abcPtr < end)
174 continue;
175 gc->TraceLocation(&item.str);
176 }
177 return more;
178 }
179
180 void PoolObject::setupConstantStrings(uint32_t count)
181 {
182 // Always allocate slot 0 in the data array, which will be
183 // initialized to an empty String* in AbcParser::parseCpool().
184 // We also avoid invoking Calloc() with a size of zero,
185 // which will cause an assertion to fail.
186 // TODO: If there are no strings, we should be able to set
187 // data = NULL, size = 0, and avoid calling the allocator.
188 // Slot 0 should never be accessed, and the code guards against
189 // such accesses generally, but there are presently exceptions.
190 // With the guards spread over much code, it is safer to do
191 // as we do here. This problem extends to other constant pool
192 // entry types, and should be cleaned up. See bug 557684.
193 //
194 // Be sure to zero the memory or garbage will be touched by
195 // the presweep handler that cleans up the string pool, see
196 // Bugzilla 574427.
197 if (count == 0)
198 count = 1;
199 // FIXME: worry about overflow in the 'extra' computation
200 _abcStrings = ConstantStringContainer::create(core->gc, (count-1) * sizeof(ConstantStringData), this);
201 constantStringCount = count;
202 }
203
204 Stringp PoolObject::getString(int32_t index) const
205 {
206 ConstantStringData* dataP = _abcStrings->data + index;
207 if (dataP->abcPtr >= _abcStringStart && dataP->abcPtr < _abcStringEnd)
208 {
209 // String not created yet; grab the pointer to the (verified) ABC data
210 uint32_t len = AvmCore::readU32(dataP->abcPtr);
211 // strict=false for bug-compatibility with swfs with incorrect utf8 encoding of strings
212 Stringp s = core->internStringUTF8((const char*) dataP->abcPtr, len, truetrue, falsefalse);
213 s->Stick(); // FIXME - Bugzilla 596918: The Stick() call is dodgy.
214 dataP->abcPtr = NULL__null; // Important to clear it - what's there is not an RCObject*, don't let WBRC see it
215 WBRC(core->gc, _abcStrings, &dataP->str, s)core->gc->privateWriteBarrierRC(_abcStrings, &dataP
->str, (const void *) (s))
;
216 }
217 return dataP->str;
218 }
219
220 /*static*/ boolbool PoolObject::isLegalDefaultValue(BuiltinType bt, Atom value)
221 {
222 switch (bt)
223 {
224 case BUILTIN_any:
225 return truetrue;
226
227 case BUILTIN_object:
228 return (value != undefinedAtom);
229
230 case BUILTIN_number:
231 return AvmCore::isNumber(value);
232
233 case BUILTIN_boolean:
234 return AvmCore::isBoolean(value);
235
236 case BUILTIN_uint:
237 if (AvmCore::isDouble(value))
238 {
239 const double d = AvmCore::number_d(value);
240 if (d == (uint32_t)d)
241 return truetrue;
242 }
243
244 return atomIsIntptr(value) && atomCanBeUint32(value);
245
246 case BUILTIN_int:
247 if (AvmCore::isDouble(value))
248 {
249 const double d = AvmCore::number_d(value);
250 if (d == (int32_t)d)
251 return truetrue;
252 }
253
254 return atomIsIntptr(value) && atomCanBeInt32(value);
255
256 case BUILTIN_string:
257 return AvmCore::isNull(value) || AvmCore::isString(value);
258
259 case BUILTIN_namespace:
260 return AvmCore::isNull(value) || AvmCore::isNamespace(value);
261
262 default:
263 return AvmCore::isNull(value);
264 }
265
266 //return false; // unreachable
267 }
268
269 Atom PoolObject::getLegalDefaultValue(const Toplevel* toplevel, uint32_t index, CPoolKind kind, Traits* t)
270 {
271 // toplevel actually can be null, when resolving the builtin classes...
272 // but they should never cause verification errors in functioning builds
273 //AvmAssert(toplevel != NULL);
274
275 const BuiltinType bt = Traits::getBuiltinType(t);
276 uint32_t maxcount = 0;
277 Atom value;
278 if (index)
279 {
280 // Look in the cpool specified by kind
281 switch (kind)
282 {
283 case CONSTANT_Int:
284 {
285 if (index >= (maxcount = constantIntCount))
286 goto range_error;
287 const int32_t i = cpool_int[index];
288#ifdef AVMPLUS_64BIT
289 value = core->intToAtom(i);
290 AvmAssert(atomIsIntptr(value) && atomCanBeInt32(value))do { } while (0);
291#else
292 // LIR relies on the return values from this being "sticky" so it can insert them inline.
293 // that's true for everything but int/uints that overflow, so special-case them.
294 // @todo this can/should go away when we convert to 64-bit Box atoms.
295 if (!cpool_int_atoms.length())
296 {
297 cpool_int_atoms.ensureCapacity(constantIntCount);
298 for (uint32_t j = 0; j < constantIntCount; ++j)
299 cpool_int_atoms.set(j, 0);
300 AvmAssert(cpool_int_atoms.length() == constantIntCount)do { } while (0);
301 }
302 value = (Atom)cpool_int_atoms[index];
303 if (value == 0)
304 {
305 value = core->intToAtom(i);
306 if (AvmCore::isDouble(value))
307 {
308 cpool_int_atoms.set(index, value);
309 }
310 AvmAssert(AvmCore::isNumber(value))do { } while (0);
311 }
312 else
313 {
314 AvmAssert(AvmCore::isDouble(value))do { } while (0);
315 }
316#endif
317 break;
318 }
319 case CONSTANT_UInt:
320 {
321 if (index >= (maxcount = constantUIntCount))
322 goto range_error;
323 const int32_t u = cpool_uint[index];
324#ifdef AVMPLUS_64BIT
325 value = core->uintToAtom(u);
326 AvmAssert(atomIsIntptr(value) && atomCanBeUint32(value))do { } while (0);
327#else
328 // LIR relies on the return values from this being "sticky" so it can insert them inline.
329 // that's true for everything but int/uints that overflow, so special-case them.
330 // @todo this can/should go away when we convert to 64-bit Box atoms.
331 if (!cpool_uint_atoms.length())
332 {
333 cpool_uint_atoms.ensureCapacity(constantUIntCount);
334 for (uint32_t j = 0; j < constantUIntCount; ++j)
335 cpool_uint_atoms.set(j, 0);
336 AvmAssert(cpool_uint_atoms.length() == constantUIntCount)do { } while (0);
337 }
338 value = (Atom)cpool_uint_atoms[index];
339 if (value == 0)
340 {
341 value = core->uintToAtom(u);
342 if (AvmCore::isDouble(value))
343 {
344 cpool_uint_atoms.set(index, value);
345 }
346 AvmAssert(AvmCore::isNumber(value))do { } while (0);
347 }
348 else
349 {
350 AvmAssert(AvmCore::isDouble(value))do { } while (0);
351 }
352#endif
353 break;
354 }
355 case CONSTANT_Double:
356 if (index >= (maxcount = constantDoubleCount))
357 goto range_error;
358 value = kDoubleType|(uintptr_t)cpool_double[index];
359 break;
360
361 case CONSTANT_Utf8:
362 if (index >= (maxcount = constantStringCount))
363 goto range_error;
364 value = getString(index)->atom();
365 break;
366
367 case CONSTANT_True:
368 value = trueAtom;
369 break;
370
371 case CONSTANT_False:
372 value = falseAtom;
373 break;
374
375 case CONSTANT_Namespace:
376 case CONSTANT_PackageNamespace:
377 case CONSTANT_PackageInternalNs:
378 case CONSTANT_ProtectedNamespace:
379 case CONSTANT_ExplicitNamespace:
380 case CONSTANT_StaticProtectedNs:
381 case CONSTANT_PrivateNs:
382 if (index >= (maxcount = constantNsCount))
383 goto range_error;
384 value = cpool_ns[index]->atom();
385 break;
386
387 case CONSTANT_Null:
388 value = nullObjectAtom;
389 break;
390
391 default:
392 // Multinames & NamespaceSets are invalid default values.
393 goto illegal_default_error;
394 }
395 }
396 else
397 {
398 switch (bt)
399 {
400 case BUILTIN_any:
401 value = undefinedAtom;
402 break;
403 case BUILTIN_number:
404 value = core->kNaN;
405 break;
406 case BUILTIN_boolean:
407 value = falseAtom;
408 break;
409 case BUILTIN_int:
410 case BUILTIN_uint:
411 value = (zeroIntAtom);
412 break;
413 case BUILTIN_string:
414 value = nullStringAtom;
415 break;
416 case BUILTIN_namespace:
417 value = nullNsAtom;
418 break;
419 case BUILTIN_object:
420 default:
421 value = nullObjectAtom;
422 break;
423 }
424 }
425
426 if (!isLegalDefaultValue(bt, value))
427 goto illegal_default_error;
428
429 return value;
430
431illegal_default_error:
432 if (toplevel)
433 {
434 if (t)
435 {
436 toplevel->throwVerifyError(kIllegalDefaultValue, core->toErrorString(Multiname(t->ns(), t->name())));
437 }
438 else
439 {
440 toplevel->throwVerifyError(kCorruptABCError);
441 }
442 }
443 AvmAssert(!"unhandled verify error")do { } while (0);
444 return undefinedAtom; // not reached
445
446range_error:
447 if (toplevel)
448 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(maxcount));
449 AvmAssert(!"unhandled verify error")do { } while (0);
450 return undefinedAtom; // not reached
451 }
452
453 void PoolObject::parseMultiname(const uint8_t *pos, Multiname& m) const
454 {
455 // the multiname has already been validated so we don't do
456 // any checking here, we just fill in the Multiname object
457 // with the information we have parsed.
458
459 int32_t index;
460 CPoolKind kind = (CPoolKind) *(pos++);
461 switch (kind)
462 {
463 case CONSTANT_Qname:
464 case CONSTANT_QnameA:
465 {
466 // U16 namespace_index
467 // U16 name_index
468 // parse a multiname with one namespace (aka qname)
469
470 index = AvmCore::readU32(pos);
471 if (!index)
472 m.setAnyNamespace();
473 else
474 m.setNamespace(getNamespace(index));
475
476 index = AvmCore::readU32(pos);
477 if (!index)
478 m.setAnyName();
479 else
480 m.setName(getString(index));
481
482 m.setQName();
483 m.setAttr(kind==CONSTANT_QnameA);
484 break;
485 }
486
487 case CONSTANT_RTQname:
488 case CONSTANT_RTQnameA:
489 {
490 // U16 name_index
491 // parse a multiname with just a name; ns fetched at runtime
492
493 index = AvmCore::readU32(pos);
494 if (!index)
495 m.setAnyName();
496 else
497 m.setName(getString(index));
498
499 m.setQName();
500 m.setRtns();
501 m.setAttr(kind==CONSTANT_RTQnameA);
502 break;
503 }
504
505 case CONSTANT_RTQnameL:
506 case CONSTANT_RTQnameLA:
507 {
508 m.setQName();
509 m.setRtns();
510 m.setRtname();
511 m.setAttr(kind==CONSTANT_RTQnameLA);
512 break;
513 }
514
515 case CONSTANT_Multiname:
516 case CONSTANT_MultinameA:
517 {
518 index = AvmCore::readU32(pos);
519 if (!index)
520 m.setAnyName();
521 else
522 m.setName(getString(index));
523
524 index = AvmCore::readU32(pos);
525 AvmAssert(index != 0)do { } while (0);
526 m.setNsset(getNamespaceSet(index));
527 m.setAttr(kind==CONSTANT_MultinameA);
528 break;
529 }
530
531 case CONSTANT_MultinameL:
532 case CONSTANT_MultinameLA:
533 {
534 m.setRtname();
535
536 index = AvmCore::readU32(pos);
537 AvmAssert(index != 0)do { } while (0);
538 m.setNsset(getNamespaceSet(index));
539
540 m.setAttr(kind==CONSTANT_MultinameLA);
541 break;
542 }
543
544 case CONSTANT_TypeName:
545 {
546 index = AvmCore::readU32(pos);
547 // Note that AbcParser ensures that the Multiname we're parsing can't
548 // be a CONSTANT_TypeName, thus the recursion here can't be more
549 // than a single level deep.
550 parseMultiname(_abcStart + cpool_mn_offsets[index], m);
551 index = AvmCore::readU32(pos);
Value stored to 'index' is never read
552 AvmAssert(index==1)do { } while (0);
553 m.setTypeParameter(AvmCore::readU32(pos));
554 break;
555 }
556
557 default:
558 AvmAssert(false)do { } while (0);
559 }
560
561 return;
562 }
563
564 void PoolObject::resolveBindingNameNoCheck(uint32_t index, Multiname &m, const Toplevel* toplevel) const
565 {
566 // FIXME: should only assert and not throw, pending correctness verification, see bug https://bugzilla.mozilla.org/show_bug.cgi?id=557541
567
568 if (index == 0 || index >= cpool_mn_offsets.length())
569 {
570 if (toplevel)
571 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(cpool_mn_offsets.length()));
572 AvmAssert(!"unhandled verify error")do { } while (0);
573 }
574
575 parseMultiname(m, index);
576
577 if (!(m.isBinding() && (m.isQName() || isBuiltin)))
578 {
579 if (toplevel)
580 toplevel->throwVerifyError(kCpoolEntryWrongTypeError, core->toErrorString(index));
581 AvmAssert(!"unhandled verify error")do { } while (0);
582 }
583 }
584
585 Traits* PoolObject::resolveTypeName(uint32_t index, const Toplevel* toplevel, boolbool allowVoid/*=false*/)
586 {
587 // only save the type name for now. verifier will resolve to traits
588 if (index == 0)
589 {
590 return NULL__null;
591 }
592
593 // check contents is a multiname. in the cpool, and type system, kObjectType means multiname.
594 if (index >= cpool_mn_offsets.length())
595 {
596 if (toplevel)
597 toplevel->throwVerifyError(kCpoolIndexRangeError, core->toErrorString(index), core->toErrorString(cpool_mn_offsets.length()));
598 AvmAssert(!"unhandled verify error")do { } while (0);
599 }
600
601 Multiname m;
602 parseMultiname(m, index);
603
604 Traits* t = core->domainMgr()->findTraitsInPoolByMultiname(this, m);
605 if (t == (Traits*)BIND_AMBIGUOUS)
606 {
607 if (toplevel)
608 toplevel->throwReferenceError(kAmbiguousBindingError, m);
609 AvmAssert(!"unhandled verify error")do { } while (0);
610 }
611 if(m.isParameterizedType())
612 {
613 core->stackCheck(const_cast<Toplevel*>(toplevel));
614 Traits* param_traits = resolveTypeName(m.getTypeParameter(), toplevel);
615 t = resolveParameterizedType(toplevel, t, param_traits);
616 }
617 if (!t)
618 {
619 #ifdef AVMPLUS_VERBOSE
620 if (!toplevel || !toplevel->verifyErrorClass())
621 core->console << "class not found: " << m << " index=" << (uint32_t)index << "\n";
622 #endif
623 if (toplevel)
624 toplevel->throwVerifyError(kClassNotFoundError, core->toErrorString(&m));
625 AvmAssert(!"unhandled verify error")do { } while (0);
626 }
627 if (!allowVoid && t == VOID_TYPE(core->traits.void_itraits))
628 {
629 if (toplevel)
630 toplevel->throwVerifyError(kIllegalVoidError);
631 AvmAssert(!"unhandled verify error")do { } while (0);
632 }
633
634 return t;
635 }
636
637 Traits* PoolObject::resolveParameterizedType(const Toplevel* toplevel, Traits* base, Traits* param_traits) const
638 {
639 Traits* r = NULL__null;
640 if (base == core->traits.vector_itraits)
641 {
642 // Only vector is parameterizable for now...
643 switch (Traits::getBuiltinType(param_traits))
644 {
645 case BUILTIN_any:
646 r = core->traits.vectorobj_itraits;
647 break;
648 case BUILTIN_int:
649 r = core->traits.vectorint_itraits;
650 break;
651 case BUILTIN_uint:
652 r = core->traits.vectoruint_itraits;
653 break;
654 case BUILTIN_number:
655 r = core->traits.vectordouble_itraits;
656 break;
657 default:
658 {
659 PoolObject* pool = param_traits->pool;
660 Stringp fullname = VectorClass::makeVectorClassName(core, param_traits);
661 r = core->domainMgr()->findTraitsInPoolByNameAndNS(pool, fullname, base->ns());
662 if (!r)
663 {
664 r = core->traits.vectorobj_itraits->newParameterizedITraits(fullname, base->ns());
665 r->verifyBindings(toplevel);
666 core->domainMgr()->addNamedTraits(pool, fullname, base->ns(), r);
667 }
668 break;
669 }
670 }
671 }
672 return r;
673 }
674
675 // search metadata record at meta_pos for name, return true if present
676 boolbool PoolObject::hasMetadataName(const uint8_t* meta_pos, const String* name)
677 {
678 AvmAssert(meta_pos && name->isInterned())do { } while (0);
679 uint32_t metadata_count = AvmCore::readU32(meta_pos);
680 for (uint32_t i=0; i < metadata_count; i++) {
681 uint32_t metadata_index = AvmCore::readU32(meta_pos);
682 const uint8_t* metadata_pos = getMetadataInfoPos(metadata_index);
683 if (metadata_pos) {
684 uint32_t name_index = AvmCore::readU32(metadata_pos);
685 AvmCore::skipU32(metadata_pos, 1); // skip val_count
686 if (name_index > 0 && name_index < constantStringCount &&
687 getString(name_index) == name)
688 return truetrue;
689 }
690 }
691 return falsefalse;
692 }
693
694 void PoolObject::initPrecomputedMultinames()
695 {
696 if (precompNames == NULL__null)
697 {
698 MMgc::GC* gc = core->GetGC();
699 uint32_t nNames = cpool_mn_offsets.length();
700 precompNames = ExactStructContainer<HeapMultiname>::create(gc, destroyPrecomputedMultinames, nNames);
701 for (uint32_t i=1; i < nNames; i++) {
702 Multiname mn;
703 parseMultiname(mn, i);
704 precompNames->get(i).setMultiname(gc, precompNames, mn);
705 }
706 }
707 }
708
709 void PoolObject::destroyPrecomputedMultinames(ExactStructContainer<HeapMultiname>* self)
710 {
711 // Destroy each HeapMultiname to properly decrement reference counts on
712 // RC'd parts of HeapMultiname as soon as possible.
713 MMgc::GC* gc = MMgc::GC::GetGC(self);
714 Multiname mn;
715 uint32_t nNames = self->capacity();
716 for (uint32_t i=1; i < nNames; i++)
717 self->get(i).setMultiname(gc, self, mn);
718 }
719
720 Stringp PoolObject::getMethodInfoName(uint32_t i)
721 {
722 Stringp name = NULL__null;
723 if (core->config.methodNames && (uint32_t(i) < uint32_t(this->_method_name_indices.length())))
724 {
725 const int32_t index = this->_method_name_indices[i];
726 if (index >= 0)
727 {
728 if (hasString(index))
729 name = this->getString(index);
730 }
731 else
732 {
733 // Precomputed multinames may not be inited yet, but we'll need them eventually,
734 // so go ahead and init them now
735 this->initPrecomputedMultinames();
736 const Multiname& mn = precompNames->get(-index);
737 StringBuffer sb(core);
738 sb << Multiname::Format(&mn);
739 name = sb.toString();
740 }
741 }
742 return name;
743 }
744}