00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "avmplus.h"
00040 #ifdef AVMPLUS_MIR
00041 #include "CodegenMIR.h"
00042 #endif
00043
00044 #if (defined(_MSC_VER) || defined(__GNUC__)) && (defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64))
00045 #include <emmintrin.h>
00046 #endif
00047
00048 namespace avmplus
00049 {
00050 using namespace MMgc;
00051
00052 BEGIN_NATIVE_CLASSES(AvmCore)
00053 NATIVE_CLASS(abcclass_Object, ObjectClass, ScriptObject)
00054 NATIVE_CLASS(abcclass_Class, ClassClass, ClassClosure)
00055 NATIVE_CLASS(abcclass_Namespace, NamespaceClass, Namespace)
00056 NATIVE_CLASS(abcclass_Function, FunctionClass, ClassClosure)
00057 NATIVE_CLASS(abcclass_builtin_as_0_MethodClosure, MethodClosureClass, MethodClosure)
00058
00059 NATIVE_CLASS(abcclass_Error, ErrorClass, ErrorObject)
00060
00061
00062
00063 NATIVE_CLASS(abcclass_DefinitionError, NativeErrorClass, ErrorObject)
00064 NATIVE_CLASS(abcclass_EvalError, NativeErrorClass, ErrorObject)
00065 NATIVE_CLASS(abcclass_RangeError, NativeErrorClass, ErrorObject)
00066 NATIVE_CLASS(abcclass_ReferenceError, NativeErrorClass, ErrorObject)
00067 NATIVE_CLASS(abcclass_SecurityError, NativeErrorClass, ErrorObject)
00068 NATIVE_CLASS(abcclass_SyntaxError, NativeErrorClass, ErrorObject)
00069 NATIVE_CLASS(abcclass_TypeError, NativeErrorClass, ErrorObject)
00070 NATIVE_CLASS(abcclass_URIError, NativeErrorClass, ErrorObject)
00071 NATIVE_CLASS(abcclass_VerifyError, NativeErrorClass, ErrorObject)
00072 NATIVE_CLASS(abcclass_UninitializedError, NativeErrorClass, ErrorObject)
00073 NATIVE_CLASS(abcclass_ArgumentError, NativeErrorClass, ErrorObject)
00074
00075 NATIVE_CLASS(abcclass_String, StringClass, String)
00076 NATIVE_CLASS(abcclass_Boolean, BooleanClass, bool)
00077 NATIVE_CLASS(abcclass_Number, NumberClass, double)
00078 NATIVE_CLASS(abcclass_int, IntClass, int)
00079 NATIVE_CLASS(abcclass_uint, UIntClass, uint32)
00080 NATIVE_CLASS(abcclass_Math, MathClass, double)
00081 NATIVE_CLASS(abcclass_Array, ArrayClass, ArrayObject)
00082 NATIVE_CLASS(abcclass_RegExp, RegExpClass, RegExpObject)
00083 NATIVE_CLASS(abcclass_Date, DateClass, DateObject)
00084
00085
00086 NATIVE_CLASS(abcclass___AS3___vec_Vector_int, IntVectorClass, IntVectorObject)
00087 NATIVE_CLASS(abcclass___AS3___vec_Vector_uint, UIntVectorClass, UIntVectorObject)
00088 NATIVE_CLASS(abcclass___AS3___vec_Vector_double, DoubleVectorClass, DoubleVectorObject)
00089 NATIVE_CLASS(abcclass___AS3___vec_Vector, VectorClass, ObjectVectorObject)
00090 NATIVE_CLASS(abcclass___AS3___vec_Vector_object, ObjectVectorClass, ObjectVectorObject)
00091
00092
00093 NATIVE_CLASS(abcclass_XML, XMLClass, XMLObject)
00094 NATIVE_CLASS(abcclass_XMLList, XMLListClass, XMLListObject)
00095 NATIVE_CLASS(abcclass_QName, QNameClass, QNameObject)
00096 END_NATIVE_CLASSES()
00097
00098
00099 BEGIN_NATIVE_SCRIPTS(AvmCore)
00100 NATIVE_SCRIPT(0, Toplevel)
00101 END_NATIVE_SCRIPTS()
00102
00103 AvmCore::AvmCore(GC *g) : GCRoot(g), console(NULL), gc(g),
00104 #ifdef AVMPLUS_MIR
00105 mirBuffers(g, 4),
00106 #endif
00107 gcInterface(g)
00108 #ifdef FEATURE_SAMPLER
00109 ,_sampler(g)
00110 #endif
00111 #ifdef AVMPLUS_WORD_CODE
00112 , lookup_cache_timestamp(1)
00113 #endif
00114 {
00115
00116 AvmAssert (sizeof(int8) == 1);
00117 AvmAssert (sizeof(uint8) == 1);
00118 AvmAssert (sizeof(int16) == 2);
00119 AvmAssert (sizeof(uint16) == 2);
00120 AvmAssert (sizeof(int32) == 4);
00121 AvmAssert (sizeof(uint32) == 4);
00122 AvmAssert (sizeof(int64) == 8);
00123 AvmAssert (sizeof(uint64) == 8);
00124 AvmAssert (sizeof(sintptr) == sizeof(void *));
00125 AvmAssert (sizeof(uintptr) == sizeof(void *));
00126 #ifdef AVMPLUS_64BIT
00127 AvmAssert (sizeof(sintptr) == 8);
00128 AvmAssert (sizeof(uintptr) == 8);
00129 #else
00130 AvmAssert (sizeof(sintptr) == 4);
00131 AvmAssert (sizeof(uintptr) == 4);
00132 #endif
00133
00134
00135 #ifdef AVMPLUS_VERBOSE
00136 config.verbose = false;
00137 config.verbose_addrs = false;
00138 #endif
00139
00140 #ifdef AVMPLUS_ARM
00141 SetMIREnabled(false);
00142 #else
00143 SetMIREnabled(true);
00144 #endif
00145
00146 #ifdef AVMPLUS_VERIFYALL
00147 config.verifyall = false;
00148 #endif
00149
00150 #ifdef FEATURE_NANOJIT
00151 config.show_stats = false;
00152 config.tree_opt = false;
00153 config.verbose_live = false;;
00154 config.verbose_exits = false;
00155 #endif
00156
00157 #ifdef AVMPLUS_MIR
00158 config.dceopt = true;
00159 #ifdef AVMPLUS_VERBOSE
00160 config.bbgraph = false;
00161 #endif
00162 #endif
00163
00164 #if defined AVMPLUS_MIR || defined FEATURE_NANOJIT
00165
00166 config.jit = false;
00167 config.cseopt = true;
00168
00169 #if defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64)
00170 config.sse2 = true;
00171 #endif
00172 #endif
00173
00174 #ifdef VTUNE
00175 VTuneStatus = CheckVTuneStatus();
00176 #endif // VTUNE
00177
00178 config.interrupts = false;
00179
00180 gcInterface.SetCore(this);
00181 resources = NULL;
00182 xmlEntities = NULL;
00183 exceptionFrame = NULL;
00184 exceptionAddr = NULL;
00185 builtinPool = NULL;
00186 builtinDomain = NULL;
00187
00188 GetGC()->SetGCContextVariable (MMgc::GC::GCV_AVMCORE, this);
00189
00190 minstack = 0;
00191
00192 #ifdef FEATURE_SAMPLER
00193 _sampler.setCore(this);
00194 #endif
00195
00196 #ifdef DEBUGGER
00197 langID = -1;
00198 debugger = NULL;
00199 profiler = NULL;
00200 passAllExceptionsToDebugger = false;
00201 #endif
00202
00203 callStack = NULL;
00204
00205 #ifdef FEATURE_SAMPLER
00206 MMgc::m_sampler = sampler();
00207 #endif
00208
00209 interrupted = false;
00210
00211 codeContextAtom = CONTEXT_NONE;
00212 dxnsAddr = NULL;
00213
00214 strings = NULL;
00215 numStrings = 0;
00216 namespaces = NULL;
00217 numNamespaces = 0;
00218 stringCount = 0;
00219 deletedCount = 0;
00220 nsCount = 0;
00221
00222 numStrings = 1024;
00223 strings = new DRC(Stringp)[numStrings];
00224 memset(strings, 0, numStrings*sizeof(Stringp));
00225
00226 numNamespaces = 1024;
00227 namespaces = new DRC(Namespacep)[numNamespaces];
00228 memset(namespaces, 0, numNamespaces*sizeof(Namespace*));
00229
00230 console.setCore(this);
00231
00232 kEmptyString = constantString("");
00233 kconstructor = constantString("constructor");
00234 kundefined = constantString("undefined");
00235 knull = constantString("null");
00236 ktrue = constantString("true");
00237 kfalse = constantString("false");
00238 ktoString = constantString("toString");
00239 ktoLocaleString = constantString("toLocaleString");
00240 kvalueOf = constantString("valueOf");
00241 klength = constantString("length");
00242
00243 kobject = constantString("object");
00244 kboolean = constantString("boolean");
00245 knumber = constantString("number");
00246 kstring = constantString("string");
00247 kxml = constantString("xml");
00248 kfunction = constantString("function");
00249 kglobal = constantString("global");
00250 kcallee = constantString("callee");
00251
00252 kuri = constantString("uri");
00253 kprefix = constantString("prefix");
00254 kNaN = doubleToAtom(MathUtils::nan());
00255 kNeedsDxns = constantString("NeedsDxns");
00256 kAsterisk = constantString("*");
00257 kVersion = constantString("Version");
00258 kVector = constantString("Vector.<");
00259
00260 #ifdef AVMPLUS_VERBOSE
00261 knewline = newString("\n");
00262 krightbracket = newString("]");
00263 kleftbracket = newString("[");
00264 kcolon = newString(":");
00265 ktabat = newString("\tat ");
00266 kparens = newString("()");
00267 #endif
00268 #if defined AVMPLUS_VERBOSE || defined FEATURE_SAMPLER
00269 kanonymousFunc = newString("<anonymous>");
00270 #endif
00271 for (int i = 0; i < 128; i++)
00272 {
00273 char singleChar = (char)i;
00274
00275
00276
00277 cachedChars[i] = internString(newString(&singleChar, 1));
00278 }
00279
00280 booleanStrings[0] = kfalse;
00281 booleanStrings[1] = ktrue;
00282
00283 #ifdef AVMPLUS_INTERNINT_CACHE
00284
00285 for (int i=0 ; i < 256 ; i++ )
00286 index_strings[i] = NULL;
00287 #endif
00288
00289
00290 publicNamespace = internNamespace(newNamespace(kEmptyString));
00291
00292 #if defined AVMPLUS_MIR && defined(AVMPLUS_VERBOSE)
00293 codegenMethodNames = CodegenMIR::initMethodNames(this);
00294 #endif
00295
00296 #ifdef FEATURE_JNI
00297 java = NULL;
00298 #endif
00299 #ifdef SUPERWORD_PROFILING
00300 swprofStart();
00301 #endif
00302 }
00303
00304 AvmCore::~AvmCore()
00305 {
00306
00307 delete [] strings;
00308 if (gc)
00309 {
00310 gc->SetGCContextVariable(GC::GCV_AVMCORE, NULL);
00311 }
00312
00313 #if defined AVMPLUS_MIR && defined(AVMPLUS_VERBOSE)
00314 delete codegenMethodNames;
00315 #endif
00316
00317 strings = NULL;
00318
00319 delete [] namespaces;
00320 namespaces = NULL;
00321
00322 #ifdef AVMPLUS_MIR
00323
00324 while(mirBuffers.size() > 0)
00325 mirBuffers.removeFirst()->free();
00326 #endif
00327 #ifdef SUPERWORD_PROFILING
00328 swprofStop();
00329 #endif
00330 }
00331
00332 void AvmCore::initBuiltinPool()
00333 {
00334 using namespace NativeID;
00335
00336
00337 AbstractFunction* nativeMethods[builtin_abc_method_count];
00338 NativeClassInfop nativeClasses[builtin_abc_class_count];
00339 NativeScriptInfop nativeScripts[builtin_abc_script_count];
00340
00341 memset(nativeMethods, 0, sizeof(AbstractFunction*)*builtin_abc_method_count);
00342 memset(nativeClasses, 0, sizeof(NativeClassInfop)*builtin_abc_class_count);
00343 memset(nativeScripts, 0, sizeof(NativeScriptInfop)*builtin_abc_script_count);
00344
00345 initNativeTables(classEntries, scriptEntries,
00346 nativeMethods, nativeClasses, nativeScripts);
00347
00348 ScriptBuffer code = ScriptBuffer(new (GetGC()) ReadOnlyScriptBufferImpl (builtin_abc_data, builtin_abc_length));
00349
00350 builtinDomain = new (GetGC()) Domain(this, NULL);
00351
00352 builtinPool = parseActionBlock(code, 0, NULL,
00353 builtinDomain,
00354 nativeMethods,
00355 nativeClasses,
00356 nativeScripts);
00357
00358
00359 for(int i=0, size=builtinPool->methods.size(); i<size; i++)
00360 builtinPool->methods[i]->flags |= AbstractFunction::NON_INTERRUPTABLE;
00361
00362 for(int i=0, size=builtinPool->cinits.size(); i<size; i++)
00363 builtinPool->cinits[i]->flags |= AbstractFunction::NON_INTERRUPTABLE;
00364
00365 for(int i=0, size=builtinPool->scripts.size(); i<size; i++)
00366 builtinPool->scripts[i]->flags |= AbstractFunction::NON_INTERRUPTABLE;
00367
00368 #ifdef FEATURE_SAMPLER
00369
00370 _sampler.initSampling();
00371 #endif
00372 }
00373
00374 Toplevel* AvmCore::initTopLevel()
00375 {
00376 Toplevel* toplevel = NULL;
00377 handleActionPool(builtinPool, NULL, toplevel, NULL);
00378 return toplevel;
00379 }
00380
00381 ScriptEnv* AvmCore::prepareActionPool(PoolObject* pool,
00382 DomainEnv* domainEnv,
00383 Toplevel*& toplevel,
00384 CodeContext* codeContext)
00385 {
00386 AvmAssert(pool != NULL);
00387
00388
00389 if (pool->scriptCount == 0)
00390 {
00391 toplevel->verifyErrorClass()->throwError(kMissingEntryPointError);
00392 }
00393
00394 if (domainEnv == NULL)
00395 {
00396
00397 domainEnv = new (GetGC()) DomainEnv(this, builtinDomain, NULL);
00398 }
00399
00400 AbcEnv* abcEnv = new (GetGC(), AbcEnv::calcExtra(pool)) AbcEnv(pool, domainEnv, codeContext);
00401
00402
00403 Traits* mainTraits = pool->scripts[pool->scriptCount-1]->declaringTraits;
00404
00405
00406 ScopeChain* emptyScope = ScopeChain::create(GetGC(), mainTraits->scope, NULL, newNamespace(kEmptyString));
00407
00408 VTable* object_vtable;
00409 if (toplevel == NULL)
00410 {
00411
00412
00413
00414
00415 object_vtable = newVTable(traits.object_itraits, NULL, emptyScope, abcEnv, NULL);
00416 object_vtable->resolveSignatures();
00417 mainTraits->sizeofInstance = (uint32_t)getToplevelSize();
00418 }
00419 else
00420 {
00421 object_vtable = toplevel->object_vtable;
00422 }
00423
00424
00425 VTable* mainVTable = newVTable(mainTraits, object_vtable, emptyScope, abcEnv, toplevel);
00426 ScriptEnv* main = new (GetGC()) ScriptEnv(mainTraits->init, mainVTable);
00427 mainVTable->init = main;
00428
00429 if (toplevel == NULL)
00430 {
00431 mainVTable->resolveSignatures();
00432 main->global = toplevel = createToplevel(mainVTable);
00433
00434
00435 mainVTable->toplevel = toplevel;
00436 object_vtable->toplevel = toplevel;
00437 domainEnv->setToplevel(toplevel);
00438
00439
00440
00441
00442 toplevel->class_vtable = newVTable(traits.class_itraits,
00443 object_vtable, emptyScope, abcEnv, toplevel);
00444 toplevel->class_vtable->resolveSignatures();
00445
00446 traits.function_itraits->resolveSignatures(toplevel);
00447 }
00448
00449 exportDefs(mainTraits, main);
00450
00451
00452 for (int i=0, n=pool->scriptCount-1; i < n; i++)
00453 {
00454 AbstractFunction* script = pool->scripts[i];
00455
00456 Traits* scriptTraits = script->declaringTraits;
00457
00458
00459
00460 VTable* scriptVTable = newVTable(scriptTraits, object_vtable, emptyScope, abcEnv, toplevel);
00461 ScriptEnv* scriptEnv = new (GetGC()) ScriptEnv(scriptTraits->init, scriptVTable);
00462 scriptVTable->init = scriptEnv;
00463 exportDefs(scriptTraits, scriptEnv);
00464 }
00465
00466 return main;
00467 }
00468
00469 Atom AvmCore::handleActionPool(PoolObject* pool,
00470 DomainEnv* domainEnv,
00471 Toplevel* &toplevel,
00472 CodeContext* codeContext)
00473 {
00474 bool createdToplevel = (toplevel == NULL);
00475
00476 ScriptEnv* main = prepareActionPool(pool, domainEnv, toplevel, codeContext);
00477
00478 if (!createdToplevel)
00479 {
00480 main->initGlobal();
00481 }
00482
00483 Atom result = 0;
00484 #ifndef DEBUGGER
00485 result = main->coerceEnter(main->global->atom());
00486 #else
00487 TRY(this, kCatchAction_Rethrow)
00488 {
00489 result = main->coerceEnter(main->global->atom());
00490 }
00491 CATCH(Exception *exception)
00492 {
00493
00494 throwException(exception);
00495 }
00496 END_CATCH
00497 END_TRY
00498 #endif
00499
00500 return result;
00501 }
00502
00503 void AvmCore::exportDefs(Traits* scriptTraits, ScriptEnv* scriptEnv)
00504 {
00505 DomainEnv* domainEnv = scriptEnv->domainEnv();
00506 AbcEnv* abcEnv = scriptEnv->abcEnv();
00507
00508
00509 int i=0;
00510 while((i=scriptTraits->next(i)) != 0)
00511 {
00512
00513 AvmAssert(scriptTraits->keyAt(i) != NULL);
00514 Stringp name = scriptTraits->keyAt(i);
00515 Namespace* ns = scriptTraits->nsAt(i);
00516
00517
00518
00519 if (!ns->isPrivate())
00520 {
00521 if (!domainEnv->getNamedScript(name, ns))
00522 {
00523
00524
00525 #ifdef AVMPLUS_VERBOSE
00526 if (scriptTraits->pool->verbose)
00527 console << "exporting " << ns << "::" << name << "\n";
00528 #endif
00529 domainEnv->addNamedScript(name, ns, (Binding)scriptEnv);
00530 }
00531 }
00532 else
00533 {
00534 if (!abcEnv->privateScriptEnvs.get(name, ns))
00535 {
00536 abcEnv->privateScriptEnvs.add(name, ns, (Binding) scriptEnv);
00537 }
00538 }
00539 }
00540 #ifdef AVMPLUS_WORD_CODE
00541
00542 invalidateLookupCache();
00543 #endif
00544 }
00545
00546 PoolObject* AvmCore::parseActionBlock(ScriptBuffer code,
00547 int ,
00548 Toplevel* toplevel,
00549 Domain* domain,
00550 AbstractFunction *nativeMethods[],
00551 NativeClassInfop nativeClasses[],
00552 NativeScriptInfop nativeScripts[],
00553 List<Stringp>* include_versions)
00554 {
00555
00556 PoolObject* pool = AbcParser::decodeAbc(this,
00557 code,
00558 toplevel,
00559 domain,
00560 nativeMethods,
00561 nativeClasses,
00562 nativeScripts,
00563 include_versions);
00564
00565 #ifdef DEBUGGER
00566 if (debugger) {
00567 debugger->processAbc(pool, code);
00568 }
00569 #endif
00570
00571 return pool;
00572 }
00573
00574 Atom AvmCore::handleActionBlock(ScriptBuffer code,
00575 int start,
00576 DomainEnv* domainEnv,
00577 Toplevel* &toplevel,
00578 AbstractFunction *nativeMethods[],
00579 NativeClassInfop nativeClasses[],
00580 NativeScriptInfop nativeScripts[],
00581 CodeContext *codeContext)
00582 {
00583 resources = new (GetGC()) Hashtable(GetGC());
00584
00585
00586 PoolObject* pool;
00587 Atom resourceAtom = resources->get(start+1);
00588 if (resourceAtom != undefinedAtom)
00589 {
00590 pool = (PoolObject*) resourceAtom;
00591 }
00592 else
00593 {
00594 Domain* domain = domainEnv ? domainEnv->getDomain() : builtinDomain;
00595
00596
00597 pool = parseActionBlock(code,
00598 start,
00599 toplevel,
00600 domain,
00601 nativeMethods,
00602 nativeClasses,
00603 nativeScripts);
00604 if (pool != NULL)
00605 {
00606 resources->put(start+1, pool);
00607 }
00608 }
00609
00610 return handleActionPool(pool, domainEnv, toplevel, codeContext);
00611 }
00612
00613 Traits* AvmCore::makeParameterizedITraits(Stringp name, Namespace* ns, Traits* t)
00614 {
00615 Traits* newtraits = newTraits(t, 0, 0, t->sizeofInstance);
00616 newtraits->name = name;
00617 newtraits->ns = ns;
00618 newtraits->slotCount = t->slotCount;
00619 newtraits->methodCount = t->methodCount;
00620 newtraits->needsHashtable = t->needsHashtable;
00621 return newtraits;
00622 }
00623
00624 Traits* AvmCore::makeParameterizedCTraits(Stringp name, Namespace* ns, Traits* t)
00625 {
00626 Traits* newtraits = newTraits(t->base, 0, 0, t->sizeofInstance);
00627 newtraits->name = name;
00628 newtraits->ns = ns;
00629 newtraits->slotCount = t->base->slotCount;
00630 newtraits->methodCount = t->base->methodCount;
00631 newtraits->needsHashtable = t->needsHashtable;
00632 return newtraits;
00633 }
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683 Atom AvmCore::equals(Atom lhs, Atom rhs)
00684 {
00685 if (isNull(lhs)) lhs = 0;
00686 if (isNull(rhs)) rhs = 0;
00687
00688 int ltype = (int)(lhs & 7);
00689 int rtype = (int)(rhs & 7);
00690
00691
00692 if ((ltype == kObjectType) && (isXMLList(lhs)))
00693 return atomToXMLList (lhs)->_equals (rhs);
00694 else if ((rtype == kObjectType) && (isXMLList(rhs)))
00695 return atomToXMLList (rhs)->_equals (lhs);
00696
00697 if (ltype == rtype)
00698 {
00699
00700 switch (ltype)
00701 {
00702 case 0:
00703 case kSpecialType:
00704 return trueAtom;
00705 case kStringType:
00706 if (lhs == rhs) return trueAtom;
00707 return (*atomToString(lhs) == *atomToString(rhs)) ? trueAtom : falseAtom;
00708 case kBooleanType:
00709 case kIntegerType:
00710 return lhs == rhs ? trueAtom : falseAtom;
00711 case kNamespaceType:
00712
00713 return atomToNamespace(lhs)->EqualTo(atomToNamespace(rhs))? trueAtom : falseAtom;
00714 case kObjectType:
00715 {
00716
00717 if (lhs == rhs)
00718 return trueAtom;
00719 if (isXML(lhs) && isXML(rhs))
00720 {
00721 XMLObject *x = atomToXMLObject (lhs);
00722 XMLObject *y = atomToXMLObject (rhs);
00723 if ((((x->getClass() & (E4XNode::kText | E4XNode::kCDATA | E4XNode::kAttribute))) && y->hasSimpleContent()) ||
00724 (((y->getClass() & (E4XNode::kText | E4XNode::kCDATA | E4XNode::kAttribute))) && x->hasSimpleContent()))
00725 {
00726 return ((*string(lhs) == *string(rhs)) ? trueAtom : falseAtom);
00727 }
00728 else
00729 {
00730 return x->getNode()->_equals (this, y->getNode());
00731 }
00732 }
00733 else if (isQName(lhs) && isQName(rhs))
00734 {
00735 QNameObject *qn1 = atomToQName (lhs);
00736 QNameObject *qn2 = atomToQName (rhs);
00737 return (((qn1->getURI() == qn2->getURI()) && (qn1->getLocalName() == qn2->getLocalName()))? trueAtom : falseAtom);
00738 }
00739 else
00740 {
00741 return falseAtom;
00742 }
00743 }
00744 case kDoubleType:
00745
00746 return atomToDouble(lhs) == atomToDouble(rhs) ? trueAtom : falseAtom;
00747 }
00748 }
00749 else
00750 {
00751 if (isNullOrUndefined(lhs) && isNullOrUndefined(rhs))
00752 return trueAtom;
00753 if (ltype == kIntegerType && rtype == kDoubleType)
00754 return ((double)(lhs>>3)) == atomToDouble(rhs) ? trueAtom : falseAtom;
00755 if (ltype == kDoubleType && rtype == kIntegerType)
00756 return atomToDouble(lhs) == ((double)(rhs>>3)) ? trueAtom : falseAtom;
00757
00758
00759
00760 if (isNumber(lhs) && isString(rhs))
00761 return equals(lhs, doubleToAtom(number(rhs)));
00762
00763
00764
00765 if (isString(lhs) && isNumber(rhs))
00766 return equals(doubleToAtom(number(lhs)), rhs);
00767
00768
00769
00770
00771 if (((ltype == kObjectType) && isXML(lhs) && atomToXMLObject(lhs)->hasSimpleContent()) ||
00772 ((rtype == kObjectType) && isXML(rhs) && atomToXMLObject(rhs)->hasSimpleContent()))
00773 {
00774 return ((*string(lhs) == *string(rhs)) ? trueAtom : falseAtom);
00775 }
00776
00777
00778 if (ltype == kBooleanType)
00779 return equals(lhs&~7|kIntegerType, rhs);
00780
00781
00782 if (rtype == kBooleanType)
00783 return equals(lhs, rhs&~7|kIntegerType);
00784
00785
00786
00787
00788 if ((isString(lhs) || isNumber(lhs)) && rtype == kObjectType)
00789 return equals(lhs, atomToScriptObject(rhs)->defaultValue());
00790
00791
00792
00793 if ((isString(rhs) || isNumber(rhs)) && ltype == kObjectType)
00794 return equals(atomToScriptObject(lhs)->defaultValue(), rhs);
00795 }
00796 return falseAtom;
00797 }
00798
00805 Atom AvmCore::compare(Atom lhs, Atom rhs)
00806 {
00807
00808 if ((lhs&7)==kIntegerType && (rhs&7)==kIntegerType)
00809 {
00810
00811 return lhs < rhs ? trueAtom : falseAtom;
00812 }
00813
00814 lhs = primitive(lhs);
00815 rhs = primitive(rhs);
00816
00817 if (isString(lhs) && isString(rhs))
00818 {
00819
00820 return *string(lhs) < *string(rhs) ? trueAtom : falseAtom;
00821 }
00822
00823
00824 double dx = number(lhs);
00825 double dy = number(rhs);
00826 if (MathUtils::isNaN(dx)) return undefinedAtom;
00827 if (MathUtils::isNaN(dy)) return undefinedAtom;
00828 return dx < dy ? trueAtom : falseAtom;
00829 }
00830
00831 Atom AvmCore::stricteq(Atom lhs, Atom rhs)
00832 {
00833 if (isNull(lhs)) return isNull(rhs) ? trueAtom : falseAtom;
00834 if (isNull(rhs)) return falseAtom;
00835
00836 int ltype = lhs & 7;
00837 int rtype = rhs & 7;
00838 if (ltype == rtype)
00839 {
00840
00841 switch (ltype)
00842 {
00843 case kSpecialType:
00844 return trueAtom;
00845 case kStringType:
00846 return (lhs==rhs || *string(lhs) == *string(rhs)) ? trueAtom : falseAtom;
00847 case kBooleanType:
00848 case kIntegerType:
00849 case kNamespaceType:
00850 return lhs == rhs ? trueAtom : falseAtom;
00851 case kObjectType:
00852 {
00853 if (lhs == rhs)
00854 return trueAtom;
00855 if (isXML(lhs) && isXML(rhs))
00856 {
00857 E4XNode *lhn = atomToXML (lhs);
00858 E4XNode *rhn = atomToXML (rhs);
00859 return ((lhn == rhn) ? trueAtom : falseAtom);
00860 }
00861 return falseAtom;
00862 }
00863 case kDoubleType:
00864
00865 return atomToDouble(lhs) == atomToDouble(rhs) ? trueAtom : falseAtom;
00866 }
00867 }
00868
00869 else if ((ltype == kIntegerType) && (rtype == kDoubleType) ||
00870 (rtype == kIntegerType) && (ltype == kDoubleType))
00871 {
00872 return number(lhs) == number(rhs) ? trueAtom : falseAtom;
00873 }
00874
00875 return falseAtom;
00876 }
00877
00883 void AvmCore::throwException(Exception *exception)
00884 {
00885 #ifdef DEBUGGER
00886 if (debugger && !(exception->flags & Exception::SEEN_BY_DEBUGGER))
00887 {
00888
00889
00890
00891
00892 exception->flags |= Exception::SEEN_BY_DEBUGGER;
00893
00894 bool willBeCaught = willExceptionBeCaught(exception);
00895
00896 if (passAllExceptionsToDebugger || !willBeCaught)
00897 {
00898
00899
00900 if (debugger->filterException(exception, willBeCaught))
00901 exception->flags |= Exception::SEEN_BY_DEBUGGER;
00902 else
00903 exception->flags &= ~Exception::SEEN_BY_DEBUGGER;
00904 }
00905 else
00906 {
00907 exception->flags &= ~Exception::SEEN_BY_DEBUGGER;
00908 }
00909 }
00910 #endif
00911
00912
00913
00914
00915
00916 AvmAssert(exceptionFrame != NULL);
00917 exceptionFrame->throwException(exception);
00918 }
00919
00925 void AvmCore::throwAtom(Atom atom)
00926 {
00927 throwException(new (GetGC()) Exception(atom
00928 #ifdef DEBUGGER
00929 , this
00930 #endif
00931 ));
00932 }
00933
00934 #ifdef DEBUGGER
00935 bool AvmCore::willExceptionBeCaught(Exception* exception)
00936 {
00937 ExceptionFrame* ef;
00938
00939 for (ef = exceptionFrame; ef != NULL; ef = ef->prevFrame)
00940 {
00941 switch (ef->catchAction)
00942 {
00943
00944
00945 case kCatchAction_Ignore:
00946 return true;
00947
00948
00949
00950
00951 case kCatchAction_Rethrow:
00952 continue;
00953
00954
00955
00956
00957 case kCatchAction_ReportAsError:
00958 return false;
00959
00960
00961
00962
00963 case kCatchAction_Unknown:
00964 return true;
00965
00966
00967
00968
00969
00970 case kCatchAction_SearchForActionScriptExceptionHandler:
00971 {
00972 CallStackNode* callStackNode;
00973
00974
00975
00976 for (callStackNode = callStack; callStackNode; callStackNode = callStackNode->next)
00977 {
00978 MethodInfo* info = (MethodInfo*) callStackNode->info;
00979 #ifdef AVMPLUS_WORD_CODE
00980 ExceptionHandlerTable* exceptions = info->word_code.exceptions;
00981 #else
00982 ExceptionHandlerTable* exceptions = info->exceptions;
00983 #endif
00984 if (exceptions != NULL && callStackNode->eip && *callStackNode->eip)
00985 {
00986
00987
00988 if (findExceptionHandlerNoRethrow(info, *callStackNode->eip, exception) != NULL)
00989 return true;
00990 }
00991 }
00992
00993
00994
00995 continue;
00996 }
00997
00998 default:
00999 AvmAssert(false);
01000 break;
01001 }
01002 }
01003
01004 return false;
01005 }
01006
01010 int AvmCore::determineLanguage()
01011 {
01012 if (langID < 0)
01013 {
01014
01015 langID = LANG_en;
01016 }
01017 return langID;
01018 }
01019
01020 String* AvmCore::findErrorMessage(int errorID,
01021 int* mapTable,
01022 const char** errorTable,
01023 int numErrors)
01024 {
01025
01026 int lo = 0;
01027 int hi = numErrors-1;
01028
01029 while (lo <= hi) {
01030 int pivot = (lo+hi)>>1;
01031 int testID = mapTable[2*pivot];
01032 if (testID == errorID) {
01033 lo = pivot;
01034 break;
01035 } else if (errorID < testID) {
01036 hi = pivot-1;
01037 } else {
01038 lo = pivot+1;
01039 }
01040 }
01041
01042 int index = mapTable[2*lo+1];
01043 int id = mapTable[2*lo];
01044
01045 if (id == errorID) {
01046 return newString(errorTable[index]);
01047 } else {
01048 return NULL;
01049 }
01050 }
01051 #endif
01052
01053 String* AvmCore::getErrorMessage(int errorID)
01054 {
01055 Stringp buffer = newString("Error #");
01056 buffer = concatStrings(buffer, internInt(errorID));
01057
01058 #ifdef DEBUGGER
01059 Stringp out = findErrorMessage(errorID,
01060 errorMappingTable,
01061 errorConstants[determineLanguage()],
01062 kNumErrorConstants);
01063 if (out)
01064 {
01065 buffer = concatStrings(buffer, newString(": "));
01066 buffer = concatStrings(buffer, out);
01067 }
01068 else
01069 {
01070 AvmAssertMsg(0, "errorID not found in the message table; check ErrorConstants.cpp you may need to regenerate it");
01071 }
01072 #endif
01073
01074 return buffer;
01075 }
01076
01077 String* AvmCore::atomToErrorString(Atom a)
01078 {
01079 String* out = NULL;
01080 #ifdef DEBUGGER
01081 out = this->format(a);
01082 #else
01083 (void)a;
01084 out = kEmptyString;
01085 #endif
01086 return out;
01087 }
01088
01089 String* AvmCore::toErrorString(int d)
01090 {
01091 String* s = NULL;
01092 #ifdef DEBUGGER
01093 wchar buffer[256];
01094 buffer[255] = '\0';
01095 int len;
01096 if (MathUtils::convertIntegerToString(d, buffer, len))
01097 s = this->newString(buffer);
01098 else
01099 s = kEmptyString;
01100 #else
01101 s = kEmptyString;
01102 (void)d;
01103 #endif
01104 return s;
01105 }
01106
01107 String* AvmCore::toErrorString(const char* s)
01108 {
01109 String* out = NULL;
01110 #ifdef DEBUGGER
01111 if (s)
01112 out = this->newString(s);
01113 else
01114 out = kEmptyString;
01115 #else
01116 out = kEmptyString;
01117 (void)s;
01118 #endif
01119 return out;
01120 }
01121
01122 String* AvmCore::toErrorString(const wchar* s)
01123 {
01124 String* out = NULL;
01125 #ifdef DEBUGGER
01126 if (s)
01127 out = this->newString(s);
01128 else
01129 out = kEmptyString;
01130 #else
01131 out = kEmptyString;
01132 (void)s;
01133 #endif
01134 return out;
01135 }
01136
01137 String* AvmCore::toErrorString(AbstractFunction* m)
01138 {
01139 String* s = NULL;
01140 #ifdef DEBUGGER
01141 if (m)
01142 s = m->format(this);
01143 else
01144 s = kEmptyString;
01145 #else
01146 s = kEmptyString;
01147 (void)m;
01148 #endif
01149 return s;
01150 }
01151
01152 String* AvmCore::toErrorString(const Multiname* n)
01153 {
01154 String* s = NULL;
01155 #ifdef DEBUGGER
01156 if (n)
01157 s = n->format(this, Multiname::MULTI_FORMAT_NAME_ONLY);
01158 else
01159 s = kEmptyString;
01160 #else
01161 s = kEmptyString;
01162 (void)n;
01163 #endif
01164 return s;
01165 }
01166
01167 String* AvmCore::toErrorString(Namespace* ns)
01168 {
01169 String* s = NULL;
01170 #ifdef DEBUGGER
01171 if (ns)
01172 s = ns->format(this);
01173 else
01174 s = kEmptyString;
01175 #else
01176 s = kEmptyString;
01177 (void)ns;
01178 #endif
01179 return s;
01180 }
01181
01182 String* AvmCore::toErrorString(Traits* t)
01183 {
01184 #ifndef DEBUGGER
01185 (void)t;
01186 return kEmptyString;
01187 #else
01188 if (!t)
01189 {
01190 return newString("*");
01191 }
01192
01193 String* s = NULL;
01194 if (t->base == traits.class_itraits)
01195 {
01196 t = t->itraits;
01197 s = newString("class ");
01198 }
01199 else
01200 {
01201 s = kEmptyString;
01202 }
01203
01204 if (t->ns != NULL && t->ns != publicNamespace)
01205 s = concatStrings(s, concatStrings(toErrorString(t->ns), newString(".")));
01206
01207 if (t->name)
01208 s = concatStrings(s, t->name);
01209 else
01210 s = concatStrings(s, newString("(null)"));
01211 return s;
01212 #endif
01213 }
01214
01215 String* AvmCore::formatErrorMessageV( int errorID, Stringp arg1, Stringp arg2, Stringp arg3)
01216 {
01217 Stringp out = NULL;
01218
01219 Stringp errorMessage = getErrorMessage(errorID);
01220 if (errorMessage)
01221 {
01222 #ifdef DEBUGGER
01223 UTF8String *errorUTF8 = errorMessage->toUTF8String();
01224 const char *format = errorUTF8->c_str();
01225
01226
01227
01228 {
01229 StringBuffer buffer(this);
01230 buffer.formatP( format, arg1, arg2, arg3);
01231 out = newString(buffer.c_str());
01232 }
01233 #else
01234
01238 (void)arg1;
01239 (void)arg2;
01240 (void)arg3;
01241 out = errorMessage;
01242 #endif
01243 }
01244 else
01245 {
01246 AvmAssertMsg(errorMessage != NULL, "contract with getErrorMessage() broken, we should always get a string!");
01247 out = kEmptyString;
01248 }
01249 return out;
01250 }
01251
01252 void AvmCore::throwErrorV(ClassClosure *type, int errorID, Stringp arg1, Stringp arg2, Stringp arg3)
01253 {
01254 Stringp out = formatErrorMessageV( errorID, arg1, arg2, arg3);
01255
01256 #ifdef DEBUGGER
01257 if (type == NULL)
01258 {
01259
01260
01261 console << out << "\n";
01262 }
01263 #endif
01264
01265 Atom args[3] = { nullObjectAtom, out->atom(), intToAtom(errorID) };
01266 throwAtom(type->construct(2, args));
01267 }
01268
01269 Atom AvmCore::booleanAtom(Atom atom)
01270 {
01271 if (!AvmCore::isNullOrUndefined(atom))
01272 {
01273 switch (atom&7)
01274 {
01275 case kIntegerType:
01276 {
01277 Atom i = atom>>3;
01278 return urshift(i|-i,28)&~7 | kBooleanType;
01279 }
01280 case kBooleanType:
01281 return atom;
01282 case kObjectType:
01283 case kNamespaceType:
01284 return isNull(atom) ? falseAtom : trueAtom;
01285 case kStringType:
01286 if (isNull(atom)) return falseAtom;
01287 return (atomToString(atom)->length() > 0) ? trueAtom : falseAtom;
01288 default:
01289 {
01290 double d = atomToDouble(atom);
01291 return !MathUtils::isNaN(d) && d != 0.0 ? trueAtom : falseAtom;
01292 }
01293 }
01294 }
01295 else
01296 {
01297 return falseAtom;
01298 }
01299 }
01300
01301 int AvmCore::boolean(Atom atom)
01302 {
01303 if (!AvmCore::isNullOrUndefined(atom))
01304 {
01305 switch (atom&7)
01306 {
01307 case kIntegerType:
01308 case kBooleanType:
01309 return (atom & ~7) != 0;
01310 case kObjectType:
01311 case kNamespaceType:
01312 return !isNull(atom);
01313 case kStringType:
01314 return !isNull(atom) && atomToString(atom)->length() > 0;
01315 default:
01316 {
01317 double d = atomToDouble(atom);
01318 return !MathUtils::isNaN(d) && d != 0.0;
01319 }
01320 }
01321 }
01322 else
01323 {
01324 return false;
01325 }
01326 }
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337 Atom AvmCore::primitive(Atom atom)
01338 {
01339 return isObject(atom) ? atomToScriptObject(atom)->defaultValue() : atom;
01340 }
01341
01342 Atom AvmCore::numberAtom(Atom atom)
01343 {
01344 if (!isNull(atom))
01345 {
01346 double value;
01347 switch (atom&7)
01348 {
01349 case kSpecialType:
01350 return kNaN;
01351 case kStringType:
01352 value = atomToString(atom)->toNumber();
01353 break;
01354 default:
01355 AvmAssert(false);
01356 case kBooleanType:
01357 return (atom&~7) | kIntegerType;
01358 case kDoubleType:
01359 case kIntegerType:
01360 return atom;
01361 case kNamespaceType:
01362
01363 value = number(atomToNamespace(atom)->getURI()->atom());
01364 break;
01365 case kObjectType:
01366 value = number(atomToScriptObject(atom)->defaultValue());
01367 break;
01368 }
01369 return doubleToAtom(value);
01370 }
01371 else
01372 {
01373 return 0 | kIntegerType;
01374 }
01375 }
01376
01377 double AvmCore::number(Atom atom) const
01378 {
01379 int kind = atom&7;
01380
01381 if (kind == kIntegerType)
01382 return (double) ((sintptr)atom>>3);
01383 if (kind == kDoubleType)
01384 return atomToDouble(atom);
01385
01386 if (!isNull(atom))
01387 {
01388 switch (kind)
01389 {
01390 case kStringType:
01391 return atomToString(atom)->toNumber();
01392 case kSpecialType:
01393 return atomToDouble(kNaN);
01394 case kBooleanType:
01395 return atom == trueAtom ? 1.0 : 0.0;
01396 case kNamespaceType:
01397 return number(atomToNamespace(atom)->getURI()->atom());
01398 default:
01399 case kObjectType:
01400 return number(atomToScriptObject(atom)->defaultValue());
01401 }
01402 }
01403 else
01404 {
01405
01406 return 0.0;
01407 }
01408 }
01409
01410 Stringp AvmCore::intern(Atom atom)
01411 {
01412 if (!isNull(atom))
01413 {
01414 switch (atom&7)
01415 {
01416 case kBooleanType:
01417 return booleanStrings[atom>>3];
01418 case kStringType:
01419 return internString(atom);
01420 case kNamespaceType:
01421 return atomToNamespace(atom)->getURI();
01422 case kSpecialType:
01423 return kundefined;
01424 case kObjectType:
01425 return intern(atomToScriptObject(atom)->toString());
01426 case kIntegerType:
01427 return internInt((int)(atom>>3));
01428 case kDoubleType:
01429 default:
01430 return internDouble(atomToDouble(atom));
01431 }
01432 }
01433 else
01434 {
01435 return knull;
01436 }
01437 }
01438
01439 Namespace* AvmCore::internNamespace(Namespace* ns)
01440 {
01441 if (ns->isPrivate())
01442 {
01443
01444
01445 return ns;
01446 }
01447
01448 int i = findNamespace(ns);
01449 if (namespaces[i] == NULL)
01450 {
01451
01452 nsCount++;
01453 namespaces[i] = ns;
01454 return ns;
01455 }
01456
01457
01458 return namespaces[i];
01459 }
01460
01461 #ifdef AVMPLUS_VERBOSE
01462
01463 void AvmCore::formatMultiname(PrintWriter& out, uint32 index, PoolObject* pool)
01464 {
01465 if (index > 0 && index <= pool->constantMnCount)
01466 {
01467 Multiname name;
01468 pool->parseMultiname(name, index);
01469 out << &name;
01470 }
01471 else
01472 {
01473 out << "invalid multiname index " << index;
01474 }
01475 }
01476
01477 void AvmCore::formatOpcode(PrintWriter& buffer, const byte *pc, AbcOpcode opcode, ptrdiff_t off, PoolObject* pool)
01478 {
01479 pc++;
01480 switch (opcode)
01481 {
01482 case OP_debugfile:
01483 case OP_pushstring:
01484 {
01485 buffer << opNames[opcode];
01486 uint32 index = readU30(pc);
01487 String *s = format(pool->cpool_string[index]->atom());
01488 if (index < pool->cpool_string.size())
01489 buffer << " " << s;
01490 break;
01491 }
01492 case OP_pushbyte:
01493 buffer << opNames[opcode] << " " << int(int8(*pc));
01494 break;
01495 case OP_pushint:
01496 {
01497 buffer << opNames[opcode];
01498 uint32 index = readU30(pc);
01499 if (index < pool->cpool_int.size())
01500 buffer << " " << pool->cpool_int[index];
01501 break;
01502 }
01503 case OP_pushuint:
01504 {
01505 buffer << opNames[opcode];
01506 uint32 index = readU30(pc);
01507 if (index < pool->cpool_uint.size())
01508 buffer << " " << (double)pool->cpool_uint[index];
01509 break;
01510 }
01511 case OP_pushdouble:
01512 {
01513 buffer << opNames[opcode];
01514 uint32 index = readU30(pc);
01515 if (index < pool->cpool_double.size())
01516 buffer << " " << *pool->cpool_double[index];
01517 break;
01518 }
01519 case OP_pushnamespace:
01520 {
01521 buffer << opNames[opcode];
01522 uint32 index = readU30(pc);
01523 if (index < pool->cpool_ns.size())
01524 {
01525 buffer << " " << pool->cpool_ns[index]->getURI();
01526 }
01527 break;
01528 }
01529 case OP_getsuper:
01530 case OP_setsuper:
01531 case OP_getproperty:
01532 case OP_setproperty:
01533 case OP_initproperty:
01534 case OP_findpropstrict:
01535 case OP_findproperty:
01536 case OP_finddef:
01537 case OP_deleteproperty:
01538 case OP_istype:
01539 case OP_coerce:
01540 case OP_astype:
01541 {
01542 buffer << opNames[opcode] << " ";
01543 formatMultiname(buffer, readU30(pc), pool);
01544 break;
01545 }
01546 case OP_callproperty:
01547 case OP_callpropvoid:
01548 case OP_callproplex:
01549 case OP_callsuper:
01550 case OP_callsupervoid:
01551 {
01552 uint32 index = readU30(pc);
01553 int argc = readU30(pc);
01554 buffer << opNames[opcode] << " ";
01555 formatMultiname(buffer, index, pool);
01556 buffer << " " << argc;
01557 break;
01558 }
01559 case OP_callstatic:
01560 case OP_newfunction:
01561 {
01562 int method_id = readU30(pc);
01563 AbstractFunction* f = pool->methods[method_id];
01564 buffer << opNames[opcode] << " method_id=" << method_id;
01565 if (opcode == OP_callstatic)
01566 {
01567 buffer << " argc=" << (int)readU30(pc);
01568 }
01569 if (f->name)
01570 buffer << " " << f->name;
01571 else
01572 buffer << " null";
01573 break;
01574 }
01575
01576 case OP_newclass:
01577 {
01578 uint32_t id = readU30(pc);
01579 AbstractFunction* c = pool->cinits[id];
01580 buffer << opNames[opcode] << " " << c;
01581 break;
01582 }
01583 case OP_lookupswitch:
01584 {
01585 ptrdiff_t target = off + readS24(pc);
01586 pc += 3;
01587 int maxindex = readU30(pc);
01588 buffer << opNames[opcode] << " default:" << target << " maxcase:"<<maxindex;
01589 for (int i=0; i <= maxindex; i++)
01590 {
01591 target = off + readS24(pc);
01592 pc += 3;
01593 buffer << " " << target;
01594 }
01595 break;
01596 }
01597 break;
01598
01599 case OP_ifnlt:
01600 case OP_ifnle:
01601 case OP_ifngt:
01602 case OP_ifnge:
01603 case OP_jump:
01604 case OP_iftrue:
01605 case OP_iffalse:
01606 case OP_ifeq:
01607 case OP_ifge:
01608 case OP_ifgt:
01609 case OP_ifle:
01610 case OP_iflt:
01611 case OP_ifne:
01612 case OP_ifstricteq:
01613 case OP_ifstrictne:
01614 {
01615 int imm24 = 0, imm8 = 0;
01616 unsigned int imm30 = 0, imm30b = 0;
01617 const byte* p2 = pc-1;
01618 readOperands(p2, imm30, imm24, imm30b, imm8);
01619 int insWidth = (int)(p2-pc);
01620
01621 ptrdiff_t target = off + insWidth + imm24 + 1;
01622 buffer << opNames[opcode] << " " << (double)target;
01623 break;
01624 }
01625 default:
01626 switch (opOperandCount[opcode])
01627 {
01628 default:
01629 buffer << opNames[opcode];
01630 break;
01631 case 1:
01632 {
01633 buffer << opNames[opcode]
01634 << ' '
01635 << (int)readU30(pc);
01636 }
01637 break;
01638 case 2:
01639 {
01640 int first = readU30(pc);
01641 int second = readU30(pc);
01642 buffer << opNames[opcode]
01643 << ' '
01644 << first
01645 << ' '
01646 << second;
01647 }
01648 break;
01649 }
01650 }
01651 }
01652 #endif
01653
01654 ExceptionHandler* AvmCore::beginCatch(ExceptionFrame *ef,
01655 MethodInfo *info, sintptr pc, Exception *exception)
01656 {
01657 ef->beginCatch();
01658 ExceptionHandler* handler = findExceptionHandler(info,pc,exception);
01659 ef->beginTry(this);
01660 return handler;
01661 }
01662
01663 ExceptionHandler* AvmCore::findExceptionHandler(MethodInfo *info,
01664 sintptr pc,
01665 Exception *exception)
01666 {
01667 ExceptionHandler* handler = findExceptionHandlerNoRethrow(info, pc, exception);
01668 if (handler)
01669 return handler;
01670
01671
01672 throwException(exception);
01673 return NULL;
01674 }
01675
01676 ExceptionHandler* AvmCore::findExceptionHandlerNoRethrow(MethodInfo *info,
01677 sintptr pc,
01678 Exception *exception)
01679 {
01680
01681
01682 if (exception->flags & Exception::EXIT_EXCEPTION)
01683 {
01684 return NULL;
01685 }
01686
01687
01688
01689
01690
01691
01692
01693
01694 AvmAssert(info->exceptions != NULL);
01695 #ifdef AVMPLUS_WORD_CODE
01696
01697
01698
01699
01700 ExceptionHandlerTable* exceptions;
01701 if (info->impl32 == avmplus::interp32 || info->implN == avmplus::interpN)
01702 exceptions = info->word_code.exceptions;
01703 else
01704 exceptions = info->exceptions;
01705 AvmAssert(exceptions != NULL);
01706 #else
01707 ExceptionHandlerTable* exceptions = info->exceptions;
01708 #endif
01709
01710 int exception_count = exceptions->exception_count;
01711 ExceptionHandler* handler = exceptions->exceptions;
01712 Atom atom = exception->atom;
01713
01714 while (--exception_count >= 0)
01715 {
01716 if (pc >= handler->from &&
01717 pc < handler->to)
01718 {
01719
01720 if (istype(atom, handler->traits))
01721 {
01722 #ifdef AVMPLUS_VERBOSE
01723 if (config.verbose)
01724 {
01725 console << "enter " << info << " catch " << handler->traits << '\n';
01726 }
01727 #endif // DEBUGGER
01728
01729 return handler;
01730 }
01731 }
01732 handler++;
01733 }
01734
01735
01736 return NULL;
01737 }
01738
01739 void AvmCore::increment_d(Atom *ap, int delta)
01740 {
01741 AvmAssert(isNumber(*ap));
01742 if (isInteger(*ap))
01743 *ap = intToAtom(delta+((sint32)((sintptr)*ap>>3)));
01744 else
01745 *ap = doubleToAtom(atomToDouble(*ap)+delta);
01746 }
01747
01748 void AvmCore::increment_i(Atom *ap, int delta)
01749 {
01750 switch (*ap & 7)
01751 {
01752 case kBooleanType:
01753 case kIntegerType:
01754 *ap = intToAtom(delta+(sint32((sintptr)*ap>>3)));
01755 return;
01756 case kDoubleType:
01757 *ap = intToAtom((int)((sint32)atomToDouble(*ap)+delta));
01758 return;
01759 default:
01760 *ap = intToAtom(integer(*ap)+delta);
01761 return;
01762 }
01763 }
01764
01765 bool AvmCore::istype(Atom atom, Traits* itraits)
01766 {
01767 if (!itraits)
01768 return true;
01769
01770 if (isNull(atom))
01771 return itraits == traits.null_itraits;
01772
01773 Traits* lhs;
01774
01775 switch (atom&7)
01776 {
01777 case kNamespaceType:
01778 lhs = traits.namespace_itraits;
01779 break;
01780
01781 case kStringType:
01782 lhs = traits.string_itraits;
01783 break;
01784
01785 case kBooleanType:
01786 lhs = traits.boolean_itraits;
01787 break;
01788
01789 case kIntegerType:
01790
01791 if (itraits == traits.number_itraits)
01792 return true;
01793
01794 lhs = traits.int_itraits;
01795 if (itraits == traits.uint_itraits)
01796 {
01797 return (atom>>3) >= 0;
01798 }
01799 #ifdef AVMPLUS_64BIT
01800 if (itraits == traits.int_itraits)
01801 {
01802
01803 if ((int64)(atom>>3)!=(int)(atom>>3))
01804 return false;
01805 }
01806 #endif
01807 break;
01808
01809 case kDoubleType:
01810 lhs = traits.number_itraits;
01811
01812 if (itraits == traits.int_itraits)
01813 {
01814 double d = atomToDouble(atom);
01815 int i = MathUtils::real2int(d);
01816 return d == (double)i;
01817 }
01818 if (itraits == traits.uint_itraits)
01819 {
01820 double d = atomToDouble(atom);
01821
01822 unsigned i = (unsigned)d;
01823 return d == (double)i;
01824 }
01825 break;
01826
01827 case kSpecialType:
01828 return itraits == traits.void_itraits;
01829
01830 case kObjectType: {
01831 lhs = atomToScriptObject(atom)->traits();
01832 break;
01833 }
01834
01835 default:
01836
01837 AvmAssert(false);
01838 return false;
01839 }
01840
01841 return lhs->containsInterface(itraits)!=0;
01842 }
01843
01844 Stringp AvmCore::coerce_s(Atom atom)
01845 {
01846 if (isNullOrUndefined(atom))
01847 return NULL;
01848 return string(atom);
01849 }
01850
01851 Stringp AvmCore::string(Atom atom)
01852 {
01853 if (!isNull(atom))
01854 {
01855 switch (atom&7)
01856 {
01857 case kNamespaceType:
01858 return atomToNamespace(atom)->getURI();
01859 case kObjectType:
01860 return string(atomToScriptObject(atom)->toString());
01861 case kStringType:
01862 return atomToString(atom);
01863 case kSpecialType:
01864 return kundefined;
01865 case kBooleanType:
01866 return booleanStrings[atom>>3];
01867 case kIntegerType:
01868 #ifdef AVMPLUS_64BIT
01869 return intToString (int(intptr_t(atom)>>3));
01870 #else
01871 return intToString (int(sint32(atom)>>3));
01872 #endif
01873 case kDoubleType:
01874 default:
01875 return doubleToString(atomToDouble(atom));
01876 }
01877 }
01878 else
01879 {
01880 return knull;
01881 }
01882 }
01883
01884 void AvmCore::setConsoleStream(OutputStream *stream)
01885 {
01886 console.setOutputStream(stream);
01887 }
01888
01889 void AvmCore::registerNatives(NativeTableEntryp nativeMap, AbstractFunction *nativeMethods[])
01890 {
01891 while (nativeMap->method_id != -1)
01892 {
01893 #ifdef AVMTHUNK_VERSION
01894 AbstractFunction* f = new (GetGC()) NativeMethod(*nativeMap);
01895 #else
01896 AbstractFunction* f = new (GetGC()) NativeMethod(nativeMap->flags, (NativeMethod::Handler)nativeMap->handler, nativeMap->cookie);
01897 #endif
01898
01899
01900 AvmAssert(nativeMethods[nativeMap->method_id]==NULL);
01901 nativeMethods[nativeMap->method_id] = f;
01902 nativeMap++;
01903 }
01904 }
01905
01906 void AvmCore::initNativeTables(NativeClassInfop classEntry,
01907 NativeScriptInfop scriptEntry,
01908 AbstractFunction *nativeMethods[],
01909 NativeClassInfop nativeClasses[],
01910 NativeScriptInfop nativeScripts[])
01911 {
01912 while (classEntry->class_id != -1)
01913 {
01914 nativeClasses[classEntry->class_id] = classEntry;
01915 registerNatives(classEntry->nativeMap, nativeMethods);
01916 classEntry++;
01917 }
01918
01919 while (scriptEntry->script_id != -1)
01920 {
01921 nativeScripts[scriptEntry->script_id] = scriptEntry;
01922 registerNatives(scriptEntry->nativeMap, nativeMethods);
01923 scriptEntry++;
01924 }
01925 }
01926
01927 bool AvmCore::isXML (Atom atm)
01928 {
01929 if (!isObject(atm))
01930 return false;
01931
01932 AvmAssert (!traits.xml_itraits || traits.xml_itraits->final);
01933 Traits *lhs = atomToScriptObject(atm)->traits();
01934 return (lhs == traits.xml_itraits);
01935 }
01936
01937 bool AvmCore::isDate(Atom atm)
01938 {
01939 if (!isObject(atm))
01940 return false;
01941
01942 AvmAssert (!traits.date_itraits || traits.date_itraits->final);
01943 Traits *lhs = atomToScriptObject(atm)->traits();
01944 return (lhs == traits.date_itraits);
01945 }
01946
01947 bool AvmCore::isXMLList (Atom atm)
01948 {
01949 if (!isObject(atm))
01950 return false;
01951
01952 AvmAssert (!traits.xmlList_itraits || traits.xmlList_itraits->final);
01953 Traits *lhs = atomToScriptObject(atm)->traits();
01954 return (lhs == traits.xmlList_itraits);
01955 }
01956
01957 bool AvmCore::isQName (Atom atm)
01958 {
01959 if (!isObject(atm))
01960 return false;
01961
01962 AvmAssert (!traits.qName_itraits || traits.qName_itraits->final);
01963 Traits *lhs = atomToScriptObject(atm)->traits();
01964 return (lhs == traits.qName_itraits);
01965 }
01966
01967 bool AvmCore::isDictionary (Atom atm)
01968 {
01969 return isObject(atm) && atomToScriptObject(atm)->vtable->traits->isDictionary;
01970 }
01971
01972
01973
01974
01975 wchar letterTable[] = {
01976 0x0041, 0x005A,
01977 0x0061, 0x007A,
01978 0x00C0, 0x00D6,
01979 0x00D8, 0x00F6,
01980 0x00F8, 0x00FF,
01981 0x0100, 0x0131,
01982 0x0134, 0x013E,
01983 0x0141, 0x0148,
01984 0x014A, 0x017E,
01985 0x0180, 0x01C3,
01986 0x01CD, 0x01F0,
01987 0x01F4, 0x01F5,
01988 0x01FA, 0x0217,
01989 0x0250, 0x02A8,
01990 0x02BB, 0x02C1,
01991 0x0386, 0x0386,
01992 0x0388, 0x038A,
01993 0x038C, 0x038C,
01994 0x038E, 0x03A1,
01995 0x03A3, 0x03CE,
01996 0x03D0, 0x03D6,
01997 0x03DA, 0x03DA,
01998 0x03DC, 0x03DC,
01999 0x03DE, 0x03DE,
02000 0x03E0, 0x03E0,
02001 0x03E2, 0x03F3,
02002 0x0401, 0x040C,
02003 0x040E, 0x044F,
02004 0x0451, 0x045C,
02005 0x045E, 0x0481,
02006 0x0490, 0x04C4,
02007 0x04C7, 0x04C8,
02008 0x04CB, 0x04CC,
02009 0x04D0, 0x04EB,
02010 0x04EE, 0x04F5,
02011 0x04F8, 0x04F9,
02012 0x0531, 0x0556,
02013 0x0559, 0x0559,
02014 0x0561, 0x0586,
02015 0x05D0, 0x05EA,
02016 0x05F0, 0x05F2,
02017 0x0621, 0x063A,
02018 0x0641, 0x064A,
02019 0x0671, 0x06B7,
02020 0x06BA, 0x06BE,
02021 0x06C0, 0x06CE,
02022 0x06D0, 0x06D3,
02023 0x06D5, 0x06D5,
02024 0x06E5, 0x06E6,
02025 0x0905, 0x0939,
02026 0x093D, 0x093D,
02027 0x0958, 0x0961,
02028 0x0985, 0x098C,
02029 0x098F, 0x0990,
02030 0x0993, 0x09A8,
02031 0x09AA, 0x09B0,
02032 0x09B2, 0x09B2,
02033 0x09B6, 0x09B9,
02034 0x09DC, 0x09DD,
02035 0x09DF, 0x09E1,
02036 0x09F0, 0x09F1,
02037 0x0A05, 0x0A0A,
02038 0x0A0F, 0x0A10,
02039 0x0A13, 0x0A28,
02040 0x0A2A, 0x0A30,
02041 0x0A32, 0x0A33,
02042 0x0A35, 0x0A36,
02043 0x0A38, 0x0A39,
02044 0x0A59, 0x0A5C,
02045 0x0A5E, 0x0A5E,
02046 0x0A72, 0x0A74,
02047 0x0A85, 0x0A8B,
02048 0x0A8D, 0x0A8D,
02049 0x0A8F, 0x0A91,
02050 0x0A93, 0x0AA8,
02051 0x0AAA, 0x0AB0,
02052 0x0AB2, 0x0AB3,
02053 0x0AB5, 0x0AB9,
02054 0x0ABD, 0x0ABD,
02055 0x0AE0, 0x0AE0,
02056 0x0B05, 0x0B0C,
02057 0x0B0F, 0x0B10,
02058 0x0B13, 0x0B28,
02059 0x0B2A, 0x0B30,
02060 0x0B32, 0x0B33,
02061 0x0B36, 0x0B39,
02062 0x0B3D, 0x0B3D,
02063 0x0B5C, 0x0B5D,
02064 0x0B5F, 0x0B61,
02065 0x0B85, 0x0B8A,
02066 0x0B8E, 0x0B90,
02067 0x0B92, 0x0B95,
02068 0x0B99, 0x0B9A,
02069 0x0B9C, 0x0B9C,
02070 0x0B9E, 0x0B9F,
02071 0x0BA3, 0x0BA4,
02072 0x0BA8, 0x0BAA,
02073 0x0BAE, 0x0BB5,
02074 0x0BB7, 0x0BB9,
02075 0x0C05, 0x0C0C,
02076 0x0C0E, 0x0C10,
02077 0x0C12, 0x0C28,
02078 0x0C2A, 0x0C33,
02079 0x0C35, 0x0C39,
02080 0x0C60, 0x0C61,
02081 0x0C85, 0x0C8C,
02082 0x0C8E, 0x0C90,
02083 0x0C92, 0x0CA8,
02084 0x0CAA, 0x0CB3,
02085 0x0CB5, 0x0CB9,
02086 0x0CDE, 0x0CDE,
02087 0x0CE0, 0x0CE1,
02088 0x0D05, 0x0D0C,
02089 0x0D0E, 0x0D10,
02090 0x0D12, 0x0D28,
02091 0x0D2A, 0x0D39,
02092 0x0D60, 0x0D61,
02093 0x0E01, 0x0E2E,
02094 0x0E30, 0x0E30,
02095 0x0E32, 0x0E33,
02096 0x0E40, 0x0E45,
02097 0x0E81, 0x0E82,
02098 0x0E84, 0x0E84,
02099 0x0E87, 0x0E88,
02100 0x0E8A, 0x0E8A,
02101 0x0E8D, 0x0E8D,
02102 0x0E94, 0x0E97,
02103 0x0E99, 0x0E9F,
02104 0x0EA1, 0x0EA3,
02105 0x0EA5, 0x0EA5,
02106 0x0EA7, 0x0EA7,
02107 0x0EAA, 0x0EAB,
02108 0x0EAD, 0x0EAE,
02109 0x0EB0, 0x0EB0,
02110 0x0EB2, 0x0EB3,
02111 0x0EBD, 0x0EBD,
02112 0x0EC0, 0x0EC4,
02113 0x0F40, 0x0F47,
02114 0x0F49, 0x0F69,
02115 0x10A0, 0x10C5,
02116 0x10D0, 0x10F6,
02117 0x1100, 0x1100,
02118 0x1102, 0x1103,
02119 0x1105, 0x1107,
02120 0x1109, 0x1109,
02121 0x110B, 0x110C,
02122 0x110E, 0x1112,
02123 0x113C, 0x113C,
02124 0x113E, 0x113E,
02125 0x1140, 0x1140,
02126 0x114C, 0x114C,
02127 0x114E, 0x114E,
02128 0x1150, 0x1150,
02129 0x1154, 0x1155,
02130 0x1159, 0x1159,
02131 0x115F, 0x1161,
02132 0x1163, 0x1163,
02133 0x1165, 0x1165,
02134 0x1167, 0x1167,
02135 0x1169, 0x1169,
02136 0x116D, 0x116E,
02137 0x1172, 0x1173,
02138 0x1175, 0x1175,
02139 0x119E, 0x119E,
02140 0x11A8, 0x11A8,
02141 0x11AB, 0x11AB,
02142 0x11AE, 0x11AF,
02143 0x11B7, 0x11B8,
02144 0x11BA, 0x11BA,
02145 0x11BC, 0x11C2,
02146 0x11EB, 0x11EB,
02147 0x11F0, 0x11F0,
02148 0x11F9, 0x11F9,
02149 0x1E00, 0x1E9B,
02150 0x1EA0, 0x1EF9,
02151 0x1F00, 0x1F15,
02152 0x1F18, 0x1F1D,
02153 0x1F20, 0x1F45,
02154 0x1F48, 0x1F4D,
02155 0x1F50, 0x1F57,
02156 0x1F59, 0x1F59,
02157 0x1F5B, 0x1F5B,
02158 0x1F5D, 0x1F5D,
02159 0x1F5F, 0x1F7D,
02160 0x1F80, 0x1FB4,
02161 0x1FB6, 0x1FBC,
02162 0x1FBE, 0x1FBE,
02163 0x1FC2, 0x1FC4,
02164 0x1FC6, 0x1FCC,
02165 0x1FD0, 0x1FD3,
02166 0x1FD6, 0x1FDB,
02167 0x1FE0, 0x1FEC,
02168 0x1FF2, 0x1FF4,
02169 0x1FF6, 0x1FFC,
02170 0x2126, 0x2126,
02171 0x212A, 0x212B,
02172 0x212E, 0x212E,
02173 0x2180, 0x2182,
02174 0x3041, 0x3094,
02175 0x30A1, 0x30FA,
02176 0x3105, 0x312C,
02177 0xAC00, 0xD7A3,
02178
02179 0x4E00, 0x9FA5,
02180 0x3007, 0x3007,
02181 0x3021, 0x3029
02182 };
02183
02184 bool AvmCore::isLetter (wchar c)
02185 {
02186 int x = sizeof(letterTable) / (sizeof(wchar));
02187 for (int i = 0; i < x; i += 2)
02188 {
02189 if (c >= letterTable[i] && c <= letterTable[i+1])
02190 return true;
02191 }
02192 return false;
02193 }
02194
02195
02196 wchar combiningCharTable[] = {
02197 0x0300, 0x0345,
02198 0x0360, 0x0361,
02199 0x0483, 0x0486,
02200 0x0591, 0x05A1,
02201 0x05A3, 0x05B9,
02202 0x05BB, 0x05BD,
02203 0x05BF, 0x05BF,
02204 0x05C1, 0x05C2,
02205 0x05C4, 0x05C4,
02206 0x064B, 0x0652,
02207 0x0670, 0x0670,
02208 0x06D6, 0x06DC,
02209 0x06DD, 0x06DF,
02210 0x06E0, 0x06E4,
02211 0x06E7, 0x06E8,
02212 0x06EA, 0x06ED,
02213 0x0901, 0x0903,
02214 0x093C, 0x093C,
02215 0x093E, 0x094C,
02216 0x094D, 0x094D,
02217 0x0951, 0x0954,
02218 0x0962, 0x0963,
02219 0x0981, 0x0983,
02220 0x09BC, 0x09BC,
02221 0x09BE, 0x09BE,
02222 0x09BF, 0x09BF,
02223 0x09C0, 0x09C4,
02224 0x09C7, 0x09C8,
02225 0x09CB, 0x09CD,
02226 0x09D7, 0x09D7,
02227 0x09E2, 0x09E3,
02228 0x0A02, 0x0A02,
02229 0x0A3C, 0x0A3C,
02230 0x0A3E, 0x0A3E,
02231 0x0A3F, 0x0A3F,
02232 0x0A40, 0x0A42,
02233 0x0A47, 0x0A48,
02234 0x0A4B, 0x0A4D,
02235 0x0A70, 0x0A71,
02236 0x0A81, 0x0A83,
02237 0x0ABC, 0x0ABC,
02238 0x0ABE, 0x0AC5,
02239 0x0AC7, 0x0AC9,
02240 0x0ACB, 0x0ACD,
02241 0x0B01, 0x0B03,
02242 0x0B3C, 0x0B3C,
02243 0x0B3E, 0x0B43,
02244 0x0B47, 0x0B48,
02245 0x0B4B, 0x0B4D,
02246 0x0B56, 0x0B57,
02247 0x0B82, 0x0B83,
02248 0x0BBE, 0x0BC2,
02249 0x0BC6, 0x0BC8,
02250 0x0BCA, 0x0BCD,
02251 0x0BD7, 0x0BD7,
02252 0x0C01, 0x0C03,
02253 0x0C3E, 0x0C44,
02254 0x0C46, 0x0C48,
02255 0x0C4A, 0x0C4D,
02256 0x0C55, 0x0C56,
02257 0x0C82, 0x0C83,
02258 0x0CBE, 0x0CC4,
02259 0x0CC6, 0x0CC8,
02260 0x0CCA, 0x0CCD,
02261 0x0CD5, 0x0CD6,
02262 0x0D02, 0x0D03,
02263 0x0D3E, 0x0D43,
02264 0x0D46, 0x0D48,
02265 0x0D4A, 0x0D4D,
02266 0x0D57, 0x0D57,
02267 0x0E31, 0x0E31,
02268 0x0E34, 0x0E3A,
02269 0x0E47, 0x0E4E,
02270 0x0EB1, 0x0EB1,
02271 0x0EB4, 0x0EB9,
02272 0x0EBB, 0x0EBC,
02273 0x0EC8, 0x0ECD,
02274 0x0F18, 0x0F19,
02275 0x0F35, 0x0F35,
02276 0x0F37, 0x0F37,
02277 0x0F39, 0x0F39,
02278 0x0F3E, 0x0F3E,
02279 0x0F3F, 0x0F3F,
02280 0x0F71, 0x0F84,
02281 0x0F86, 0x0F8B,
02282 0x0F90, 0x0F95,
02283 0x0F97, 0x0F97,
02284 0x0F99, 0x0FAD,
02285 0x0FB1, 0x0FB7,
02286 0x0FB9, 0x0FB9,
02287 0x20D0, 0x20DC,
02288 0x20E1, 0x20E1,
02289 0x302A, 0x302F,
02290 0x3099, 0x3099,
02291 0x309A, 0x309A
02292 };
02293 bool AvmCore::isCombiningChar (wchar c)
02294 {
02295 int x = sizeof(combiningCharTable) / (sizeof(wchar));
02296 for (int i = 0; i < x; i += 2)
02297 {
02298 if (c >= combiningCharTable[i] && c <= combiningCharTable[i+1])
02299 return true;
02300 }
02301 return false;
02302 }
02303
02304
02305 wchar digitTable[] = {
02306 0x0030, 0x0039,
02307 0x0660, 0x0669,
02308 0x06F0, 0x06F9,
02309 0x0966, 0x096F,
02310 0x09E6, 0x09EF,
02311 0x0A66, 0x0A6F,
02312 0x0AE6, 0x0AEF,
02313 0x0B66, 0x0B6F,
02314 0x0BE7, 0x0BEF,
02315 0x0C66, 0x0C6F,
02316 0x0CE6, 0x0CEF,
02317 0x0D66, 0x0D6F,
02318 0x0E50, 0x0E59,
02319 0x0ED0, 0x0ED9,
02320 0x0F20, 0x0F29};
02321
02322 bool AvmCore::isDigit (wchar c)
02323 {
02324 int x = sizeof(digitTable) / (sizeof(wchar));
02325 for (int i = 0; i < x; i += 2)
02326 {
02327 if (c >= digitTable[i] && c <= digitTable[i+1])
02328 return true;
02329 }
02330 return false;
02331 }
02332
02333 wchar extenderTable[] = {
02334 0x00B7, 0x00B7,
02335 0x02D0, 0x02D0,
02336 0x02D1, 0x02D1,
02337 0x0387, 0x0387,
02338 0x0640, 0x0640,
02339 0x0E46, 0x0E46,
02340 0x0EC6, 0x0EC6,
02341 0x3005, 0x3005,
02342 0x3031, 0x3035,
02343 0x309D, 0x309E,
02344 0x30FC, 0x30FE};
02345 bool AvmCore::isExtender (wchar c)
02346 {
02347 int x = sizeof(extenderTable) / (sizeof(wchar));
02348 for (int i = 0; i < x; i += 2)
02349 {
02350 if (c >= extenderTable[i] && c <= extenderTable[i+1])
02351 return true;
02352 }
02353 return false;
02354 }
02355
02356 bool AvmCore::isXMLName(Atom arg)
02357 {
02358 if (isNullOrUndefined(arg))
02359 return false;
02360
02361 Stringp p = string(arg);
02362
02363
02364
02365
02366
02367 if (!p->length())
02368 return false;
02369
02370
02371
02372
02373 wchar c = (*p)[0];
02374 if (!isLetter (c) && c != '_' )
02375 return false;
02376
02377 for (int i = 1; i < p->length(); i++)
02378 {
02379 wchar c = (*p)[i];
02380
02381 if (isDigit(c) || isLetter(c) || (c == '.') || (c == '-') || (c == '_') ||
02382 isCombiningChar (c) || isExtender(c))
02383 continue;
02384
02385 return false;
02386 }
02387
02388 return true;
02389 }
02390
02391 Stringp AvmCore::ToXMLString (Atom a)
02392 {
02393 if (!isNull(a))
02394 {
02395 switch (a&7)
02396 {
02397 case kStringType:
02398 return EscapeElementValue (string(a), true);
02399 case kObjectType:
02400 case kNamespaceType:
02401 if (isXML(a))
02402 {
02403 XMLObject *x = atomToXMLObject (a);
02404 return x->toXMLString();
02405 }
02406 else if (isXMLList(a))
02407 {
02408 XMLListObject *x = atomToXMLList (a);
02409 return x->toXMLString();
02410 }
02411 else
02412 {
02413
02414
02415 return EscapeElementValue (string(a), true);
02416 }
02417 break;
02418 case kSpecialType:
02419 return kundefined;
02420 case kIntegerType:
02421 case kBooleanType:
02422 case kDoubleType:
02423 default:
02424 return string(a);
02425 }
02426 }
02427 else
02428 {
02429 return knull;
02430 }
02431 }
02432
02433 Stringp AvmCore::EscapeElementValue (const Stringp s, bool removeLeadingTrailingWhitespace)
02434 {
02435 StringBuffer output(this);
02436
02437 int i = 0;
02438 int last = s->length() - 1;
02439 if (removeLeadingTrailingWhitespace)
02440 {
02441
02442 while (last >= 0)
02443 {
02444 if (!String::isSpace ((*s)[last]))
02445 break;
02446
02447 last--;
02448 }
02449
02450 if (last < 0)
02451 return kEmptyString;
02452
02453
02454 for (i = 0; i <= last; i++)
02455 {
02456 if (!String::isSpace ((*s)[i]))
02457 break;
02458 }
02459 }
02460
02461 while (i <= last)
02462 {
02463 switch ((*s)[i])
02464 {
02465 case '<':
02466 output << "<";
02467 break;
02468 case '>':
02469 output << ">";
02470 break;
02471 case '&':
02472 output << "&";
02473 break;
02474 default:
02475 output << ((*s)[i]);
02476 }
02477
02478 i++;
02479 }
02480
02481 return newString (output.c_str());
02482 }
02483
02484 Stringp AvmCore::EscapeAttributeValue (Atom v)
02485 {
02486 StringBuffer output(this);
02487
02488 Stringp s = string (v);
02489
02490 for (int i = 0; i < s->length(); i++)
02491 {
02492 switch ((*s)[i])
02493 {
02494 case '"':
02495 output << """;
02496 break;
02497 case '<':
02498 output << "<";
02499 break;
02500 case '&':
02501 output << "&";
02502 break;
02503 case 0x000a:
02504 output << "
";
02505 break;
02506 case 0x000d:
02507 output << "
";
02508 break;
02509 case 0x0009:
02510 output << "	";
02511 break;
02512 default:
02513 output << ((*s)[i]);
02514 }
02515 }
02516
02517 return newString (output.c_str());
02518 }
02519
02520 XMLObject *AvmCore::atomToXMLObject (Atom atm)
02521 {
02522 if (!isXML (atm))
02523 return 0;
02524
02525 return (XMLObject*)(atomToScriptObject(atm));
02526 }
02527
02528 E4XNode *AvmCore::atomToXML (Atom atm)
02529 {
02530 if (!isXML (atm))
02531 return 0;
02532
02533 return ((XMLObject*)(atomToScriptObject(atm)))->getNode();
02534 }
02535
02536 XMLListObject *AvmCore::atomToXMLList (Atom atm)
02537 {
02538 if (!isXMLList (atm))
02539 return 0;
02540
02541 return (XMLListObject*)(atomToScriptObject(atm));
02542 }
02543
02544 QNameObject *AvmCore::atomToQName (Atom atm)
02545 {
02546 if (!isQName (atm))
02547 return 0;
02548
02549 return (QNameObject*)(atomToScriptObject(atm));
02550 }
02551
02552 Stringp AvmCore::_typeof (Atom arg)
02553 {
02554 if (!isNull(arg))
02555 {
02556 switch (arg&7)
02557 {
02558 default:
02559 case kObjectType:
02560 if (isXML (arg) || isXMLList(arg))
02561 {
02562 return kxml;
02563 }
02564 else if (isFunction(arg))
02565 {
02566 return kfunction;
02567
02568 }
02569 else
02570 {
02571 return kobject;
02572 }
02573
02574 case kBooleanType:
02575 return kboolean;
02576
02577 case kIntegerType:
02578 case kDoubleType:
02579 return knumber;
02580
02581 case kSpecialType:
02582 return kundefined;
02583
02584 case kStringType:
02585 return kstring;
02586
02587 case kNamespaceType:
02588 return kobject;
02589 }
02590 }
02591 else
02592 {
02593
02594 return kobject;
02595 }
02596 }
02597
02598 size_t AvmCore::getToplevelSize() const
02599 {
02600 return sizeof(Toplevel);
02601 }
02602
02603 Toplevel* AvmCore::createToplevel(VTable *vtable)
02604 {
02605 return new (GetGC(), vtable->getExtraSize()) Toplevel(vtable, NULL);
02606 }
02607
02608 void AvmCore::presweep()
02609 {
02610
02611 {
02612 for (int i=0, n=numStrings; i < n; i++)
02613 {
02614 if (strings[i] > AVMPLUS_STRING_DELETED && !GetGC()->GetMark(strings[i]))
02615 {
02616 strings[i] = AVMPLUS_STRING_DELETED;
02617 deletedCount++;
02618 stringCount--;
02619 }
02620 }
02621 }
02622
02623
02624
02625 {
02626 bool rehashFlag = false;
02627 for (int i=0, n=numNamespaces; i < n; i++)
02628 {
02629 if (namespaces[i] != NULL && !GetGC()->GetMark(namespaces[i]))
02630 {
02631 rehashFlag = true;
02632 namespaces[i] = NULL;
02633 }
02634 }
02635
02636
02637
02638 if (rehashFlag)
02639 rehashNamespaces(numNamespaces);
02640 }
02641
02642 #ifdef FEATURE_SAMPLER
02643 _sampler.presweep();
02644 #endif
02645 }
02646
02647 void AvmCore::postsweep()
02648 {
02649 #ifdef FEATURE_SAMPLER
02650 _sampler.postsweep();
02651 #endif
02652 }
02653
02654
02655 bool wcharEquals(const wchar *s1, const wchar *s2)
02656 {
02657 while (*s1) {
02658 if (*s1 != *s2) {
02659 return false;
02660 }
02661 s1++;
02662 s2++;
02663 }
02664 return true;
02665 }
02666
02667 int hashString(const wchar *ptr, int len)
02668 {
02669 int hashCode = 0;
02670 while (len--) {
02671 hashCode = (hashCode >> 28) ^ (hashCode << 4) ^ *ptr++;
02672 }
02673 return hashCode;
02674 }
02675
02676 int AvmCore::findString(const wchar *s, int len)
02677 {
02678 int m = numStrings;
02679
02680 if (5*(stringCount+deletedCount+1) > 4*m) {
02681 if (2*stringCount > m)
02682 rehashStrings(m = m << 1);
02683 else
02684 rehashStrings(m);
02685 }
02686
02687
02688 int hashCode = hashString(s, len);
02689
02690 int bitMask = m - 1;
02691
02692
02693 int i = (hashCode&0x7FFFFFFF) & bitMask;
02694 int n = 7;
02695 Stringp k;
02696 if (!deletedCount)
02697 {
02698 while ((k=strings[i]) != NULL && !k->FastEquals(s,len)) {
02699 i = (i + (n++)) & bitMask;
02700 }
02701 }
02702 else
02703 {
02704 int iFirstDeletedSlot = -1;
02705 while ((k=strings[i]) != NULL)
02706 {
02707 if (k == AVMPLUS_STRING_DELETED)
02708 {
02709 if (iFirstDeletedSlot == -1)
02710 {
02711 iFirstDeletedSlot = i;
02712 }
02713 }
02714 else if (k->FastEquals (s, len))
02715 {
02716 return i;
02717 }
02718 i = (i + (n++)) & bitMask;
02719 }
02720
02721 if ((k == NULL) && (iFirstDeletedSlot != -1))
02722 return iFirstDeletedSlot;
02723
02724 }
02725 return i;
02726 }
02727
02733 int AvmCore::findNamespace(const Namespace* ns)
02734 {
02735 int m = numNamespaces;
02736
02737 if (nsCount*5 >= 4*m) {
02738 rehashNamespaces(m = m << 1);
02739 }
02740
02741
02742 int hashCode = (int)(((uintptr)ns->getURI())>>3);
02743
02744 int bitMask = m - 1;
02745
02746
02747 int i = (hashCode&0x7FFFFFFF) & bitMask;
02748 int n = 7;
02749 Namespace* k;
02750 while ((k=namespaces[i]) != NULL && k->m_uri != ns->m_uri ) {
02751 i = (i + (n++)) & bitMask;
02752 }
02753 return i;
02754 }
02755
02756 Stringp AvmCore::constantString(const char *s)
02757 {
02758 return internString(newString(s));
02759 }
02760
02766 Stringp AvmCore::internString(Stringp o)
02767 {
02768 if (o->isInterned())
02769 return o;
02770
02771 int i = findString(o->c_str(), o->length());
02772 Stringp other;
02773 if ((other=strings[i]) <= AVMPLUS_STRING_DELETED)
02774 {
02775 if (other == AVMPLUS_STRING_DELETED)
02776 {
02777 deletedCount--;
02778 AvmAssert(deletedCount >= 0);
02779 }
02780 stringCount++;
02781 strings[i] = o;
02782 o->setInterned(this);
02783 return o;
02784 }
02785 else
02786 {
02787 return other;
02788 }
02789 }
02790
02791 Stringp AvmCore::internString(Atom atom)
02792 {
02793 AvmAssert(isString(atom));
02794 Stringp s = atomToString(atom);
02795 return s->isInterned() ? s : internString(s);
02796 }
02797
02798 Stringp AvmCore::internInt(int value)
02799 {
02800 #ifdef AVMPLUS_INTERNINT_CACHE
02801
02802
02803
02804
02805
02806
02807
02808
02809 int index = value & 255;
02810 if (value >= 0 && index_strings[index] != NULL && index_strings[index]->value == value)
02811 return index_strings[index]->string;
02812 #endif
02813 wchar buffer[65];
02814 int len;
02815 MathUtils::convertIntegerToString(value, buffer, len);
02816 Stringp s = internAlloc(buffer, len);
02817
02818 #ifdef AVMPLUS_INTERNINT_CACHE
02819 if (value >= 0) {
02820 if (index_strings[index] == NULL)
02821 index_strings[index] = new (GetGC()) IndexString;
02822 index_strings[index]->value = value;
02823 index_strings[index]->string = s;
02824 }
02825 #endif
02826
02827 return s;
02828
02829
02830
02831
02832
02833
02834 #if 0
02835
02836
02837 if ((uint32)value == 0x80000000)
02838 {
02839 UnicodeUtils::Utf8ToUtf16((uint8*)"-2147483648", 12, buffer, 24);
02840 return internAlloc(buffer, 11);
02841 }
02842
02843 wchar *src = &buffer[39];
02844 *src-- = '\0';
02845
02846 if (value == 0)
02847 {
02848 *src-- = '0';
02849 }
02850 else
02851 {
02852 uint32 uVal;
02853 bool negative = (value < 0);
02854 if (negative)
02855 value = -value;
02856
02857 uVal = (uint32)value;
02858
02859 while (uVal != 0)
02860 {
02861 uint32 j = uVal;
02862 uVal = uVal / 10;
02863 j -= (uVal * 10);
02864
02865 *src-- = (j + '0');
02866 }
02867
02868 if (negative)
02869 *src-- = '-';
02870 }
02871
02872 return internAlloc(src + 1, &buffer[39] - src - 1);
02873 #endif
02874 }
02875 Stringp AvmCore::internUint32 (uint32 ui)
02876 {
02877 if (ui & 0x80000000)
02878 return internDouble(ui);
02879 else
02880 return internInt((int)ui);
02881 }
02882
02883 Stringp AvmCore::internDouble(double d)
02884 {
02885
02886 wchar buffer[312];
02887 int len;
02888 MathUtils::convertDoubleToString(d, buffer, len);
02889 return internAlloc(buffer, len);
02890 }
02891
02892 #ifdef FEATURE_SAMPLER
02893 Stringp AvmCore::findInternedString(const char *cs, int len8)
02894 {
02895 int len16 = UnicodeUtils::Utf8Count((const uint8*)cs, len8);
02896
02897 wchar *buffer = (wchar*) alloca((len16+1)*sizeof(wchar));
02898
02899 if(!buffer) {
02900 AvmAssertMsg(false, "alloca failed!");
02901 return NULL;
02902 }
02903
02904 UnicodeUtils::Utf8ToUtf16((const uint8 *)cs, len8, buffer, len16);
02905 buffer[len16] = 0;
02906 int i = findString(buffer, len16);
02907 Stringp other;
02908 if ((other=strings[i]) > AVMPLUS_STRING_DELETED)
02909 {
02910 return other;
02911 }
02912 return NULL;
02913 }
02914 #endif
02915
02916 Stringp AvmCore::internAllocUtf8(const byte *cs, int len8)
02917 {
02918 int len16 = UnicodeUtils::Utf8Count((const uint8*)cs, len8);
02919
02920 wchar *buffer = 0;
02921 if (len16 < 1024)
02922 buffer = (wchar*) alloca((len16+1)*sizeof(wchar));
02923
02924 Stringp s = NULL;
02925 if(!buffer) {
02926 s = new (GetGC()) String((const char *)cs, len8, len16);
02927 buffer = (wchar*)s->c_str();
02928 } else {
02929 UnicodeUtils::Utf8ToUtf16((const uint8 *)cs, len8, buffer, len16);
02930 buffer[len16] = 0;
02931 }
02932
02933 int i = findString(buffer, len16);
02934 Stringp other;
02935 if ((other=strings[i]) <= AVMPLUS_STRING_DELETED)
02936 {
02937 if (other == AVMPLUS_STRING_DELETED)
02938 {
02939 deletedCount--;
02940 AvmAssert(deletedCount >= 0);
02941 }
02942
02943 stringCount++;
02944 if(!s)
02945 s = new (GetGC()) String(buffer, len16);
02946 strings[i] = s;
02947 s->setInterned(this);
02948 return s;
02949 }
02950 else
02951 {
02952
02953 delete s;
02954 return other;
02955 }
02956 }
02957
02958 Stringp AvmCore::internAlloc(const wchar *s, int len)
02959 {
02960 int i = findString(s, len);
02961 Stringp other;
02962 if ((other=strings[i]) <= AVMPLUS_STRING_DELETED)
02963 {
02964 if (other == AVMPLUS_STRING_DELETED)
02965 {
02966 deletedCount--;
02967 AvmAssert(deletedCount >= 0);
02968 }
02969
02970 #ifdef DEBUGGER
02971 DRC(Stringp) *oldStrings = strings;
02972 #endif
02973
02974 other = new (GetGC()) String(s,len);
02975
02976 #ifdef DEBUGGER
02977
02978 if(strings != oldStrings)
02979 i = findString(s, len);
02980 #endif
02981 strings[i] = other;
02982 stringCount++;
02983 other->setInterned(this);
02984 }
02985 return other;
02986 }
02987
02988 void AvmCore::rehashStrings(int newlen)
02989 {
02990
02991
02992 DRC(Stringp) *oldStrings = strings;
02993 int oldStringCount = numStrings;
02994
02995 strings = new DRC(Stringp)[newlen];
02996 memset(strings, 0, newlen*sizeof(Stringp));
02997 numStrings = newlen;
02998
02999 #ifdef _DEBUG // debug sanity checks
03000 int oldDeletedCount = deletedCount;
03001 int computedDeleteCount = 0;
03002 int computedStringCount = 0;
03003 #endif
03004
03005 deletedCount = 0;
03006
03007
03008
03009
03010
03011 int m = numStrings;
03012 int bitMask = m - 1;
03013
03014 for (int i=0; i < oldStringCount; i++)
03015 {
03016 Stringp o = oldStrings[i];
03017 if (o > AVMPLUS_STRING_DELETED)
03018 {
03019
03020 int hashCode = hashString(o->c_str(), o->length());
03021
03022
03023 int j = (hashCode&0x7FFFFFFF) & bitMask;
03024 int n = 7;
03025 while (strings[j] != NULL) {
03026 j = (j + (n++)) & bitMask;
03027 }
03028
03029 strings[j] = o;
03030 #ifdef _DEBUG
03031 computedStringCount++;
03032 #endif
03033 }
03034 #ifdef _DEBUG
03035 else if (o == AVMPLUS_STRING_DELETED)
03036 {
03037 computedDeleteCount++;
03038 }
03039 #endif
03040 }
03041
03042 #ifdef _DEBUG
03043 AvmAssert(computedStringCount == stringCount);
03044 AvmAssert(oldDeletedCount == computedDeleteCount);
03045 #endif
03046
03047
03048 delete [] oldStrings;
03049 }
03050
03051 void AvmCore::rehashNamespaces(int newlen)
03052 {
03053
03054
03055 DRC(Namespacep) *old = namespaces;
03056 int oldCount = numNamespaces;
03057
03058 namespaces = new DRC(Namespacep)[newlen];
03059 memset(namespaces, 0, newlen*sizeof(Namespace*));
03060 numNamespaces = newlen;
03061
03062 for (int i=0; i < oldCount; i++)
03063 {
03064 Namespace* o = old[i];
03065 if (o != NULL)
03066 namespaces[findNamespace(o)] = o;
03067 }
03068
03069
03070 delete [] old;
03071 }
03072
03073 ScriptBufferImpl* AvmCore::newScriptBuffer(size_t size)
03074 {
03075 return new (GetGC(), size) BasicScriptBufferImpl(size);
03076 }
03077
03078 VTable* AvmCore::newVTable(Traits* traits, VTable* base, ScopeChain* scope,
03079 AbcEnv* abcEnv, Toplevel* toplevel)
03080 {
03081 size_t extraSize = sizeof(MethodEnv*)*(traits->methodCount > 0 ? traits->methodCount-1 : 0);
03082 return new (GetGC(), extraSize) VTable(traits, base, scope, abcEnv, toplevel);
03083 }
03084
03085 RegExpObject* AvmCore::newRegExp(RegExpClass* regexpClass,
03086 Stringp pattern,
03087 Stringp options)
03088 {
03089 return new (GetGC(), regexpClass->ivtable()->getExtraSize()) RegExpObject(regexpClass,
03090 pattern, options);
03091 }
03092
03093 ScriptObject* AvmCore::newObject(VTable *vtable, ScriptObject *delegate)
03094 {
03095 return new (GetGC(), vtable->getExtraSize()) ScriptObject(vtable, delegate);
03096 }
03097
03098 Namespace* AvmCore::newNamespace(Atom prefix, Atom uri, Namespace::NamespaceType type)
03099 {
03100
03101
03102 Atom p;
03103 Stringp u;
03104 if (isQName (uri) && !isNull(atomToQName (uri)->getURI()))
03105 {
03106 u = atomToString(atomToQName (uri)->getURI());
03107 }
03108 else
03109 {
03110 u = internString (string (uri));
03111 }
03112 if (u == kEmptyString)
03113 {
03114 if (prefix == undefinedAtom)
03115 p = kEmptyString->atom();
03116 else if (!string (prefix)->length())
03117 p = kEmptyString->atom();
03118 else
03119 {
03120
03121
03122 return NULL;
03123 }
03124 }
03125 else if (prefix == undefinedAtom)
03126 {
03127 p = undefinedAtom;
03128 }
03129 else if (prefix != kEmptyString->atom() && !isXMLName (prefix))
03130 {
03131 p = undefinedAtom;
03132 }
03133 else
03134 {
03135 p = internString (string (prefix))->atom();
03136 }
03137
03138 return new (GetGC()) Namespace(p, u, type);
03139 }
03140
03141 Namespace* AvmCore::newNamespace(Atom uri, Namespace::NamespaceType type)
03142 {
03143
03144
03145
03146 if (isNamespace (uri))
03147 {
03148 Namespace *ns = atomToNamespace (uri);
03149 return new (GetGC()) Namespace (ns->getPrefix(), ns->getURI(), type);
03150 }
03151 else if (isObject(uri) && isQName (uri) && !isNull(atomToQName (uri)->getURI()))
03152 {
03153 return new (GetGC()) Namespace (undefinedAtom, atomToString(atomToQName (uri)->getURI()), type);
03154 }
03155 else
03156 {
03157 Stringp u = internString (string (uri));
03158 Atom prefix = (u == kEmptyString) ? kEmptyString->atom() : undefinedAtom;
03159 return new (GetGC()) Namespace (prefix, u, type);
03160 }
03161 }
03162
03163 Namespace* AvmCore::newNamespace(Stringp uri, Namespace::NamespaceType type)
03164 {
03165 uri = internString(uri);
03166 Atom prefix = (uri == kEmptyString) ? kEmptyString->atom() : undefinedAtom;
03167 return new (GetGC()) Namespace(prefix, uri, type);
03168 }
03169
03170 NamespaceSet* AvmCore::newNamespaceSet(int nsCount)
03171 {
03172 size_t extra = (nsCount >= 1 ? nsCount-1 : 0)*sizeof(Atom);
03173 return new (GetGC(), extra) NamespaceSet(nsCount);
03174 }
03175
03176 Atom AvmCore::uintToAtom(uint32 n)
03177 {
03178 #ifdef AVMPLUS_64BIT
03179
03180 return (((Atom)n)<<3) | kIntegerType;
03181 #else
03182
03183 if (!(n&0xF0000000)) {
03184 return uint32((n<<3) | kIntegerType);
03185 } else {
03186 return allocDouble(n);
03187 }
03188 #endif
03189 }
03190
03191 Atom AvmCore::intToAtom(int n)
03192 {
03193 #ifdef AVMPLUS_64BIT
03194
03195 return (((Atom)n)<<3) | kIntegerType;
03196 #else
03197
03198 int i29 = n << 3;
03199 if ((i29>>3) == n)
03200 {
03201 return uint32(i29 | kIntegerType);;
03202 }
03203 else
03204 {
03205 return allocDouble(n);
03206 }
03207 #endif
03208 }
03209
03210 #if defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64)
03211
03212 #ifdef _MSC_VER
03213 #pragma warning(disable: 4740)
03214 #endif
03215 Atom AvmCore::doubleToAtom_sse2(double n)
03216 {
03217
03218
03219
03220 #if defined(WIN32) || defined(__ICC)
03221 #ifdef AVMPLUS_AMD64
03222 int32_t id = _mm_cvttsd_si32(_mm_set_sd(n));
03223 if (id == n) {
03224
03225 if (id == 0 && MathUtils::isNegZero(n)) {
03226 return allocDouble(n);
03227 } else {
03228 return (intptr_t(id)<<3) | kIntegerType;
03229 }
03230 }
03231 return allocDouble(n);
03232 #else
03233 int id3;
03234 __asm {
03235 movsd xmm0,n
03236 cvttsd2si ecx,xmm0
03237 shl ecx,3
03238 mov eax,ecx
03239 sar ecx,3
03240 cvtsi2sd xmm1,ecx
03241 ucomisd xmm0,xmm1
03242 jne d2a_alloc
03243 jp d2a_alloc
03244 mov id3,eax
03245 }
03246
03247 if (id3 != 0 || !MathUtils::isNegZero(n))
03248 {
03249 return id3 | kIntegerType;
03250 }
03251 else
03252 {
03253 __asm d2a_alloc:
03254 return allocDouble(n);
03255 }
03256 #endif
03257 #elif defined(_MAC) && (defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64))
03258 int id = _mm_cvttsd_si32(_mm_set_sd(n));
03259
03260
03261
03262
03263 if (((id<<3)>>3) == n) {
03264
03265 if (id == 0 && MathUtils::isNegZero(n)) {
03266 return allocDouble(n);
03267 } else {
03268 #ifdef AVMPLUS_64BIT
03269 return (id<<3) | kIntegerType;
03270 #else
03271 return uint32((id<<3) | kIntegerType);
03272 #endif
03273
03274 }
03275 }
03276 return allocDouble(n);
03277 #elif defined(SOLARIS)
03278 return AvmCore::doubleToAtom(n);
03279 #elif defined(AVMPLUS_UNIX)
03280 #ifdef __amd64__
03281 int32_t id = _mm_cvttsd_si32(_mm_set_sd(n));
03282 if (id == n) {
03283
03284 if (id == 0 && MathUtils::isNegZero(n)) {
03285 return allocDouble(n);
03286 } else {
03287 return (intptr_t(id)<<3) | kIntegerType;
03288 }
03289 }
03290 return allocDouble(n);
03291 #else // __amd64__
03292 int id3;
03293 asm("movups %1, %%xmm0;"
03294 "cvttsd2si %%xmm0, %%ecx;"
03295 "shl $0x3, %%ecx;"
03296 "mov %%ecx, %%eax;"
03297 "sar $0x3, %%ecx;"
03298 "cvtsi2sd %%ecx, %%xmm1;"
03299 "ucomisd %%xmm1, %%xmm0;"
03300 "jne d2a_alloc;"
03301 "jp d2a_alloc;"
03302 "movl %%eax, %0" : "=r" (id3) : "m" (n));
03303
03304 if (id3 != 0 || !MathUtils::isNegZero(n))
03305 {
03306 return id3 | kIntegerType;
03307 }
03308
03309 asm("d2a_alloc:");
03310 return allocDouble(n);
03311 #endif // __amd64__
03312 #endif // defined(AVMPLUS_UNIX)
03313 }
03314 #endif
03315
03316 #ifndef AVMPLUS_AMD64
03317 Atom AvmCore::doubleToAtom(double n)
03318 {
03319
03320
03321
03322
03323
03324 #if defined(WIN32) && !defined(_ARM_)
03325 #ifdef AVMPLUS_AMD64
03326 int id = _mm_cvttsd_si32(_mm_set_sd(n));
03327 #else
03328
03329
03330 int id;
03331 _asm {
03332 fld [n];
03333 fistp [id];
03334 }
03335 #endif
03336 #elif defined(_MAC) && (defined (AVMPLUS_IA32) || defined(AVMPLUS_AMD64))
03337 int id = _mm_cvttsd_si32(_mm_set_sd(n));
03338 #else
03339 int id = MathUtils::real2int(n);
03340 #endif
03341
03342
03343 if (((id<<3)>>3) == n)
03344 {
03345
03346 if (id == 0 && MathUtils::isNegZero(n))
03347 return allocDouble(n);
03348 else
03349 {
03350 #ifdef AVMPLUS_64BIT
03351 return (id<<3) | kIntegerType;
03352 #else
03353 return uint32((id<<3) | kIntegerType);
03354 #endif
03355 }
03356 }
03357 else
03358 {
03359 return allocDouble(n);
03360 }
03361 }
03362 #endif // not AVMPLUS_AMD64
03363
03364 #ifdef AVMPLUS_VERBOSE
03365
03371 Stringp AvmCore::format(Atom atom)
03372 {
03373 if (!isNull(atom))
03374 {
03375 switch (atom&7)
03376 {
03377 default:
03378 case kNamespaceType:
03379 return atomToNamespace(atom)->format(this);
03380 case kObjectType:
03381 return atomToScriptObject(atom)->format(this);
03382 case kStringType:
03383 {
03384 Stringp quotes = newString("\"");
03385 return concatStrings(quotes,
03386 concatStrings(atomToString((atom&~7)==0 ? kEmptyString->atom() : atom),
03387 quotes));
03388 }
03389 case kSpecialType:
03390 return kundefined;
03391 case kBooleanType:
03392 return booleanStrings[atom>>3];
03393 case kIntegerType:
03394 #ifdef AVMPLUS_64BIT
03395 return intToString((int)(atom>>3));
03396 #else
03397 return intToString((int)(sint32(atom)>>3));
03398 #endif
03399 case kDoubleType:
03400 AvmAssert(atom != kDoubleType);
03401 return doubleToString(atomToDouble(atom));
03402 }
03403 }
03404 else
03405 {
03406 return knull;
03407 }
03408 }
03409
03410 Stringp AvmCore::formatAtomPtr(Atom atom)
03411 {
03412 wchar buffer[256];
03413 int len;
03414 MathUtils::convertIntegerToString((int)atom, buffer, len, 16);
03415 return new (GetGC()) String(buffer, len);
03416 }
03417 #endif
03418
03424 Traits* AvmCore::newTraits(Traits *base,
03425 int nameCount,
03426 int interfaceDelta,
03427 uint32 objectSize)
03428 {
03429 int interfaceCount = interfaceDelta;
03430 if (base)
03431 interfaceCount += base->interfaceCount+1;
03432 int interfaceCapacity = MathUtils::nextPowerOfTwo((5*interfaceCount >> 2) + 1);
03433 size_t extra = interfaceCapacity*sizeof(Traits*);
03434 Traits* traits = new (GetGC(), extra) Traits(this, base,
03435 nameCount,
03436 interfaceCount,
03437 interfaceCapacity,
03438 objectSize);
03439 return traits;
03440 }
03441
03442 Stringp AvmCore::newString(const char *s) const
03443 {
03444 int len = String::Length(s);
03445 int utf16len = UnicodeUtils::Utf8ToUtf16((const uint8*)s, len, NULL, 0);
03446 return new (GetGC()) String(s, len, utf16len);
03447 }
03448
03449 Stringp AvmCore::newString(const char *s, int len) const
03450 {
03451 int utf16len = UnicodeUtils::Utf8ToUtf16((const uint8*)s, len, NULL, 0);
03452 return new (GetGC()) String(s, len, utf16len);
03453 }
03454
03455 Stringp AvmCore::newString(const wchar *s) const
03456 {
03457 int len = String::Length(s);
03458 return new (GetGC()) String(s, len);
03459 }
03460
03461 Stringp AvmCore::concatStrings(Stringp s1, Stringp s2) const
03462 {
03463 if (!s1) s1 = knull;
03464 if (!s2) s2 = knull;
03465 if (s1->length() == 0) {
03466 return s2;
03467 } else if (s2->length() == 0) {
03468 return s1;
03469 }
03470 return new (GetGC()) String(s1, s2);
03471 }
03472
03473 Stringp AvmCore::intToString(int value)
03474 {
03475 wchar buffer[65];
03476 int len;
03477 MathUtils::convertIntegerToString(value, buffer, len);
03478 return new (GetGC()) String(buffer, len);
03479 }
03480
03481 Stringp AvmCore::uintToString(uint32 value)
03482 {
03483 wchar buffer[65];
03484 int len;
03485 if (value <= 0x7FFFFFFF)
03486 MathUtils::convertIntegerToString(value, buffer, len);
03487 else
03488 MathUtils::convertDoubleToString(value, buffer, len);
03489 return new (GetGC()) String(buffer, len);
03490 }
03491
03492 Stringp AvmCore::doubleToString(double d)
03493 {
03494
03495 wchar buffer[312];
03496 int len;
03497 MathUtils::convertDoubleToString(d, buffer, len, MathUtils::DTOSTR_NORMAL,15);
03498 return new (GetGC()) String(buffer, len);
03499 }
03500
03501 #ifdef DEBUGGER
03502 StackTrace* AvmCore::newStackTrace()
03503 {
03504 int depth = callStack ? callStack->depth : 0;
03505 int extra = depth > 0 ? sizeof(StackTrace::Element) * (depth-1) : 0;
03506 StackTrace* stackTrace = new (GetGC(), extra) StackTrace();
03507 if (stackTrace)
03508 {
03509 stackTrace->depth = depth;
03510 CallStackNode *curr = callStack;
03511 StackTrace::Element *element = stackTrace->elements;
03512 while (curr) {
03513 element->info = curr->info;
03514 element->filename = curr->filename;
03515 element->linenum = curr->linenum;
03516 element++;
03517 curr = curr->next;
03518 }
03519 }
03520 return stackTrace;
03521 }
03522
03523 #ifdef _DEBUG
03524 void AvmCore::dumpStackTrace()
03525 {
03526 StringBuffer buffer(this);
03527 buffer << "Stack Trace:\n" << newStackTrace()->format(this) << '\n';
03528 AvmDebugMsg(false, buffer.c_str());
03529 }
03530 #endif
03531 #endif
03532
03533 int AvmCore::integer(Atom atom) const
03534 {
03535 if ((atom & 7) == kIntegerType || (atom&7) == kBooleanType) {
03536 return (int32_t)(atom >> 3);
03537 } else {
03538
03539 double d = number(atom);
03540 return (int32_t)integer_d(d);
03541 }
03542 }
03543
03544
03545
03546 #ifndef AVMPLUS_AMD64
03547 int AvmCore::integer_d(double d)
03548 {
03549
03550
03551 #ifdef WIN32 // should be any intel build
03552
03553 int id = MathUtils::real2int (d);
03554 if (id != 0x80000000)
03555 return id;
03556 #elif AVMPLUS_SPARC
03557 int id = MathUtils::real2int (d);
03558 if (id != 0x7fffffff && id != 0x80000000)
03559 return id;
03560 #endif
03561
03562 return doubleToInt32(d);
03563 }
03564 #endif // not AVMPLUS_AMD64
03565
03566 #if defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64)
03567 int AvmCore::integer_d_sse2(double d)
03568 {
03569 int id;
03570 #ifdef WIN32
03571 #ifdef AVMPLUS_AMD64
03572 id = _mm_cvttsd_si32(_mm_set_sd(d));
03573 if (id != (int)0x80000000)
03574 return id;
03575 #else
03576 _asm {
03577 cvttsd2si eax,d
03578 mov id,eax
03579 }
03580 if (id != 0x80000000)
03581 return id;
03582 #endif
03583 #elif defined(_MAC) && (defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64))
03584 id = _mm_cvttsd_si32(_mm_set_sd(d));
03585 if (id != (int)0x80000000)
03586 return id;
03587 #elif defined(SOLARIS)
03588 #elif AVMPLUS_UNIX
03589 asm("movups %1, %%xmm0;"
03590 "cvttsd2si %%xmm0, %%eax;"
03591 "movl %%eax, %0" : "=r" (id) : "m" (d) : "%eax");
03592 if (id != (int) 0x80000000)
03593 return id;
03594 #endif
03595
03596 return doubleToInt32(d);
03597 }
03598 #endif // AVMPLUS_IA32 or AVMPLUS_AMD64
03599
03600
03601 #if !defined(AVMPLUS_IA32) && !defined(AVMPLUS_AMD64)
03602 int AvmCore::doubleToInt32(double d)
03603 {
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614 if (MathUtils::isNaN(d) || MathUtils::isInfinite(d) || d == 0) {
03615 return 0;
03616 }
03617
03618
03619 double ad = d < 0.0 ? MathUtils::floor(-d) : MathUtils::floor(d);
03620
03621
03622 if (ad > 4294967295.0)
03623 ad = MathUtils::mod(ad,4294967296.0);
03624
03625
03626 if (ad >= (double)2147483648.0)
03627 {
03628
03629
03630
03631
03632 if (d < 0.0)
03633 {
03634 int intVal = MathUtils::real2int (ad - 2147483648.0);
03635 return 0x80000000 - intVal;
03636 }
03637
03638 else
03639 {
03640 int intVal = MathUtils::real2int (ad - 2147483648.0);
03641 return 0x80000000 + intVal;
03642 }
03643 }
03644 else
03645 {
03646 return MathUtils::real2int(d < 0.0 ? -ad : ad);
03647 }
03648 }
03649 #else
03650
03651
03652
03653
03654
03655
03656
03657
03658 #if defined(AVMPLUS_AMD64)
03659 #define DBLTOINT32_INT64 1
03660 #else
03661 #define DBLTOINT32_INT64 0
03662 #endif
03663
03664 typedef union {
03665 double d;
03666 uint64 i;
03667 #if defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64)
03668 struct {
03669 uint32 il, ih;
03670 } i32;
03671 #else
03672 #error("this routine does not work in PowerPC processors");
03673 struct {
03674 uint32 ih, il;
03675 } i32;
03676 #endif
03677 } double_int;
03678
03679 #if DBLTOINT32_INT64
03680 int AvmCore::doubleToInt32(double d)
03681 {
03682 double_int du, duh, two32;
03683 uint64 sign_d;
03684 int64 MASK;
03685 uint32 DI_H, u_tmp, expon, shift_amount;
03686
03687
03688
03689
03690
03691
03692
03693
03694
03695
03696
03697 du.d = d;
03698 DI_H = du.i32.ih;
03699
03700 u_tmp = (DI_H & 0x7ff00000) - 0x3ff00000;
03701 if(u_tmp >= (0x45300000-0x3ff00000)) {
03702
03703 return 0;
03704 }
03705
03706 if(u_tmp < 0x01f00000) {
03707
03708 return int32(d);
03709 }
03710
03711 if(u_tmp > 0x01f00000) {
03712
03713 expon = u_tmp >> 20;
03714 shift_amount = expon - 21;
03715 duh.i = du.i;
03716 MASK = 0x8000000000000000ll;
03717 MASK = MASK >> shift_amount;
03718 duh.i &= (uint64)MASK;
03719 du.d -= duh.d;
03720 }
03721
03722 DI_H = du.i32.ih;
03723
03724
03725 u_tmp = (DI_H & 0x7ff00000);
03726 if(u_tmp >= 0x41e00000) {
03727
03728 expon = u_tmp >> 20;
03729 shift_amount = expon - (0x3ff - 11);
03730 MASK = 0x8000000000000000ll;
03731 MASK = MASK >> shift_amount;
03732 du.i &= (uint64)MASK;
03733 sign_d = du.i & 0x8000000000000000ull;
03734 two32.i = 0x41f0000000000000ull ^ sign_d;
03735 du.d -= two32.d;
03736 }
03737
03738 return int32(du.d);
03739 }
03740 #else // DBLTOINT32_INT64
03741 int AvmCore::doubleToInt32(double d)
03742 {
03743 double_int du, duh, two32;
03744 uint32 DI_H, u_tmp, expon, shift_amount;
03745 int32 mask32;
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757 du.d = d;
03758 DI_H = du.i32.ih;
03759
03760 u_tmp = (DI_H & 0x7ff00000) - 0x3ff00000;
03761 if(u_tmp >= (0x45300000-0x3ff00000)) {
03762
03763 return 0;
03764 }
03765
03766 if(u_tmp < 0x01f00000) {
03767
03768 return int32(d);
03769 }
03770
03771 if(u_tmp > 0x01f00000) {
03772
03773 expon = u_tmp >> 20;
03774 shift_amount = expon - 21;
03775 duh.i = du.i;
03776 mask32 = 0x80000000;
03777 if(shift_amount<32) {
03778 mask32 >>= shift_amount;
03779 duh.i32.ih = du.i32.ih & mask32;
03780 duh.i32.il = 0;
03781 }
03782 else {
03783 mask32 >>= (shift_amount-32);
03784 duh.i32.ih = du.i32.ih;
03785 duh.i32.il = du.i32.il & mask32;
03786 }
03787 du.d -= duh.d;
03788 }
03789
03790 DI_H = du.i32.ih;
03791
03792
03793 u_tmp = (DI_H & 0x7ff00000);
03794 if(u_tmp >= 0x41e00000) {
03795
03796 expon = u_tmp >> 20;
03797 shift_amount = expon - (0x3ff - 11);
03798 mask32 = 0x80000000;
03799 if(shift_amount<32) {
03800 mask32 >>= shift_amount;
03801 du.i32.ih &= mask32;
03802 du.i32.il = 0;
03803 }
03804 else {
03805 mask32 >>= (shift_amount-32);
03806 du.i32.il &= mask32;
03807 }
03808 two32.i32.ih = 0x41f00000 ^ (du.i32.ih & 0x80000000);
03809 two32.i32.il = 0;
03810 du.d -= two32.d;
03811 }
03812
03813 return int32(du.d);
03814 }
03815 #endif // DBLTOINT32_INT64
03816 #endif // !(defined(AVMPLUS_IA32) || defined(AVMPLUS_AMD64))
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827 bool AvmCore::getIndexFromString (Stringp s, uint32 *result)
03828 {
03829 int len = s->length();
03830 if (!len)
03831 return false;
03832
03833
03834
03835
03836
03837
03838 const wchar *c = s->c_str();
03839 if (*c == '0')
03840 {
03841 if (len == 1)
03842 {
03843 *result = 0;
03844 return true;
03845 }
03846 else
03847 {
03848 return false;
03849 }
03850 }
03851 else if ((*c < '0') || (*c > '9'))
03852 {
03853 return false;
03854 }
03855
03856
03857
03858 if (len > 10)
03859 {
03860 return false;
03861 }
03862
03863 uint32 res = 0;
03864 int i = 0;
03865 while (i < len)
03866 {
03867 wchar ch = c[i];
03868 if (ch < '0' || ch > '9')
03869 return false;
03870
03871 res = res * 10 + (ch - '0');
03872 i++;
03873 }
03874
03875 *result = res;
03876
03877
03878 if (len < 10)
03879 {
03880 return true;
03881 }
03882
03883
03884
03885
03886
03887
03888 int comp = String::Compare (c, "4294967295", 10);
03889 return (comp > 0);
03890 }
03891
03892 CodeContext* AvmCore::codeContext() const
03893 {
03894 if (codeContextAtom == CONTEXT_NONE) {
03895 return NULL;
03896 } else if ((codeContextAtom&7) == CONTEXT_ENV) {
03897 MethodEnv *env = (MethodEnv*)(codeContextAtom&~7);
03898 return env->vtable->abcEnv->codeContext;
03899 } else {
03900 return (CodeContext*)(codeContextAtom&~7);
03901 }
03902 }
03903
03904 #ifdef AVMPLUS_MIR
03905
03909 GrowableBuffer* AvmCore::requestMirBuffer()
03910 {
03911 GrowableBuffer* buffer = 0;
03912 if (mirBuffers.size() > 0)
03913 buffer = mirBuffers.removeFirst();
03914 else
03915 buffer = requestNewMirBuffer();
03916 return buffer;
03917 }
03918
03919 GrowableBuffer* AvmCore::requestNewMirBuffer()
03920 {
03921 return new (GetGC()) GrowableBuffer(GetGC()->GetGCHeap(),true);
03922 }
03923
03924 void AvmCore::releaseMirBuffer(GrowableBuffer* buffer)
03925 {
03926 buffer->free();
03927 mirBuffers.add(buffer);
03928 }
03929 #endif
03930
03931 #ifdef MMGC_DRC
03932
03933 void AvmCore::decrementAtomRegion(Atom *arr, int length)
03934 {
03935 for(int i=0; i < length; i++)
03936 {
03937 Atom a = arr[i];
03938 RCObject *obj = (RCObject*)(a&~7);
03939 if(obj) {
03940 switch(a&7) {
03941 case kStringType:
03942 case kObjectType:
03943 case kNamespaceType:
03944 ((RCObject*)(a&~7))->DecrementRef();
03945 break;
03946 }
03947 }
03948 arr[i] = 0;
03949 }
03950 }
03951 #endif
03952
03953
03954 void AvmCore::atomWriteBarrier(MMgc::GC *gc, const void *container, Atom *address, Atom atomNew)
03955 {
03956 #ifdef MMGC_DRC
03957 Atom atom = *address;
03958 if(!isNull(atom)) {
03959 switch(atom&7)
03960 {
03961 case kStringType:
03962 case kObjectType:
03963 case kNamespaceType:
03964 MMgc::RCObject *obj = (MMgc::RCObject*)(atom&~7);
03965 obj->DecrementRef();
03966 break;
03967 }
03968 }
03969 #endif
03970
03971 switch(atomNew&7)
03972 {
03973 case kStringType:
03974 case kObjectType:
03975 case kNamespaceType:
03976 #ifdef MMGC_DRC
03977 if(!isNull(atomNew))
03978 ((MMgc::RCObject*)(atomNew&~7))->IncrementRef();
03979
03980 #endif
03981 case kDoubleType:
03982 {
03983 gc->WriteBarrierNoSubstitute(container, (const void*)atomNew);
03984 }
03985 break;
03986
03987 }
03988 *address = atomNew;
03989 }
03990
03991 Atom AvmCore::gcObjectToAtom(const void* obj)
03992 {
03993 #ifdef _DEBUG
03994
03995 if (obj)
03996 {
03997 GC* gc = GC::GetGC(obj);
03998 AvmAssert(!gc->IsRCObject(obj));
03999 }
04000 #endif
04001
04002 return (Atom)obj|kDoubleType;
04003 }
04004
04005 #if defined AVMPLUS_MIR || defined FEATURE_NANOJIT
04006
04007 void AvmCore::initMultinameLate(Multiname& name, Atom index)
04008 {
04009 if (isObject(index))
04010 {
04011 ScriptObject* i = atomToScriptObject(index);
04012 if (i->traits() == traits.qName_itraits)
04013 {
04014 QNameObject* qname = (QNameObject*) i;
04015 bool attr = name.isAttr();
04016 qname->getMultiname(name);
04017 name.setAttr(attr);
04018 return;
04019 }
04020 }
04021
04022 name.setName(intern(index));
04023 }
04024 #endif // MIR or NANOJIT
04025 }