bool SamplerScript::set_stack(ScriptObject* self, ClassFactoryClass* cf, const Sample& sample, SampleObject* sam) { if (sample.stack.depth > 0) { Toplevel* toplevel = self->toplevel(); AvmCore* core = toplevel->core(); Sampler* s = core->get_sampler(); StackFrameClass* sfcc = (StackFrameClass*)cf->get_StackFrameClass(); ArrayObject* stack = toplevel->arrayClass()->newArray(sample.stack.depth); StackTrace::Element* e = (StackTrace::Element*)sample.stack.trace; for(uint32_t i=0; i < sample.stack.depth; i++, e++) { StackFrameObject* sf = sfcc->constructObject(); // at every allocation the sample buffer could overflow and the samples could be deleted // the StackTrace::Element pointer is a raw pointer into that buffer so we need to check // that its still around before dereferencing e uint32_t num; if (s->getSamples(num) == NULL) return false; sf->setconst_name(e->name()); // NOT e->info()->name() because e->name() can be a fake name sf->setconst_file(e->filename()); sf->setconst_line(e->linenum()); sf->setconst_scriptID(static_cast<double>(e->functionId())); stack->setUintProperty(i, sf->atom()); } sam->setconst_stack(stack); } return true; }
ScriptObject* SamplerScript::makeSample(ScriptObject* self, ClassFactoryClass* cf, const Sample& sample) { Toplevel* toplevel = self->toplevel(); AvmCore* core = toplevel->core(); Sampler* s = core->get_sampler(); if (!s) return NULL; switch (sample.sampleType) { case Sampler::RAW_SAMPLE: { SampleClass* cls = (SampleClass*)cf->get_SampleClass(); SampleObject* sam = cls->constructObject(); sam->setconst_time(static_cast<double>(sample.micros)); if (!set_stack(self, cf, sample, sam)) return NULL; return sam; } case Sampler::DELETED_OBJECT_SAMPLE: { DeleteObjectSampleClass* cls = (DeleteObjectSampleClass*)cf->get_DeleteObjectSampleClass(); DeleteObjectSampleObject* dsam = cls->constructObject(); dsam->setconst_time(static_cast<double>(sample.micros)); dsam->setconst_id(static_cast<double>(sample.id)); dsam->setconst_size(static_cast<double>(sample.size)); return dsam; } case Sampler::NEW_OBJECT_SAMPLE: { NewObjectSampleClass* cls = (NewObjectSampleClass*)cf->get_NewObjectSampleClass(); NewObjectSampleObject* nsam = cls->constructObject(); nsam->setconst_time(static_cast<double>(sample.micros)); nsam->setconst_id(static_cast<double>(sample.id)); if (!set_stack(self, cf, sample, nsam)) return NULL; if (sample.ptr != NULL ) nsam->setRef((AvmPlusScriptableObject*)sample.ptr); nsam->setconst_type(getType(toplevel, sample.sot, sample.ptr)); nsam->setSize(sample.alloc_size); return nsam; } case Sampler::NEW_AUX_SAMPLE: { NewObjectSampleClass* cls = (NewObjectSampleClass*)cf->get_NewObjectSampleClass(); NewObjectSampleObject* nsam = cls->constructObject(); nsam->setconst_time(static_cast<double>(sample.micros)); nsam->setconst_id(static_cast<double>(sample.id)); if (!set_stack(self, cf, sample, nsam)) return NULL; nsam->setSize(sample.alloc_size); return nsam; } } AvmAssert(0); return NULL; }
double SamplerScript::getSize(ScriptObject* self, Atom a) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler* s = core->get_sampler(); if (!s) return 0; return _get_size(a); #else (void)self; (void)a; return 0; #endif }
/*static*/ Stringp SamplerScript::getMasterString(ScriptObject *self, Stringp str) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler *s = core->get_sampler(); if (!s || !trusted(self)) return NULL; if(str != NULL) return str->getMasterString(); else return NULL; #else (void)self; (void)str; return NULL; #endif }
/*static*/ ArrayObject* SamplerScript::getLexicalScopes(ScriptObject *self, FunctionObject *function) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler *s = core->get_sampler(); if (!s || !trusted(self)) return NULL; if(function != NULL && function->getCallMethodEnv()) return function->getCallMethodEnv()->getLexicalScopes(); else return NULL; #else (void)self; (void)function; return NULL; #endif }
Atom SamplerScript::_getSamples(ScriptObject* self, ClassClosure* cf) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler *s = core->get_sampler(); if (!s || !s->sampling() || s->sampleCount() == 0 || !trusted(self)) return undefinedAtom; if (s->sampleIteratorVTable == NULL) s->sampleIteratorVTable = _newVT(self->toplevel(), self->traits()->pool, sizeof(SampleIterator)); SampleIterator* iter = new (self->gc()) SampleIterator(self, s->sampleIteratorVTable); iter->cf = (ClassFactoryClass*)cf; return iter->atom(); #else (void)self; (void)cf; return undefinedAtom; #endif }
/*static*/ Atom SamplerScript::getSavedThis(ScriptObject *self, FunctionObject *method) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler *s = core->get_sampler(); if (!s || !trusted(self)) return undefinedAtom; MethodClosure* mc; if (method != NULL && ((mc = method->toMethodClosure()) != NULL)) return mc->get_savedThis(); else return undefinedAtom; #else (void)self; (void)method; return undefinedAtom; #endif }
bool SamplerScript::isGetterSetter(ScriptObject* self, Atom a, QNameObject *qname) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler* s = core->get_sampler(); if (!s) return false; if(!AvmCore::isObject(a) || !AvmCore::atomToScriptObject(a)) self->toplevel()->throwArgumentError(kInvalidArgumentError, "object"); ScriptObject *object = AvmCore::atomToScriptObject(a); if(!object || !qname) self->toplevel()->argumentErrorClass()->throwError(kInvalidArgumentError); Multiname multiname; qname->getMultiname(multiname); VTable *v = object->vtable; again: Binding b = self->toplevel()->getBinding(v->traits, &multiname); if(b == BIND_NONE && v->ivtable) { v = v->ivtable; goto again; } return AvmCore::hasSetterBinding(b) || AvmCore::hasGetterBinding(b); #else (void)self; (void)a; (void)qname; return false; #endif }
Atom SamplerScript::getMemberNames(ScriptObject* self, Atom o, bool instanceNames) { #ifdef DEBUGGER AvmCore* core = self->core(); MMgc::GC* gc = core->GetGC(); Sampler* s = core->get_sampler(); if (!s || !trusted(self)) return undefinedAtom; if (AvmCore::isObject(o)) { Traits *t = AvmCore::atomToScriptObject(o)->traits(); if(AvmCore::istype(o, CLASS_TYPE) && instanceNames && t->itraits) t = t->itraits; if (s->slotIteratorVTable == NULL) s->slotIteratorVTable = _newVT(self->toplevel(), self->traits()->pool, sizeof(SlotIterator)); return (new (gc) SlotIterator(t, s->slotIteratorVTable))->atom(); } #else (void)self; (void)o; (void)instanceNames; #endif return undefinedAtom; }
double SamplerScript::_getInvocationCount(ScriptObject* self, Atom a, QNameObject* qname, uint32_t type) { #ifdef DEBUGGER AvmCore* core = self->core(); Sampler* s = core->get_sampler(); if (!s || !trusted(self)) return -1; Multiname multiname; if(qname) qname->getMultiname(multiname); ScriptObject* object = self->toplevel()->global(); if(!AvmCore::isObject(a)) { // not sure if this will be true for standalone avmplus AvmAssert(core->codeContext() != NULL); DomainEnv *domainEnv = core->codeContext()->domainEnv(); ScriptEnv* script = (ScriptEnv*) core->domainMgr()->findScriptEnvInDomainEnvByMultiname(domainEnv, multiname); if (script != (ScriptEnv*)BIND_NONE) { if (script == (ScriptEnv*)BIND_AMBIGUOUS) self->toplevel()->throwReferenceError(kAmbiguousBindingError, &multiname); object = script->global; if (object == NULL) { object = script->initGlobal(); script->coerceEnter(script->global->atom()); } } } else { object = AvmCore::atomToScriptObject(a); if(AvmCore::istype(a, CLASS_TYPE) && !qname) { // return constructor count ClassClosure *cc = (ClassClosure*)object; if (cc->vtable->init) // Vector related crash here, Tommy says: I didn't think a type could ever not have a constructor but I guess there's no reason it has to. return (double)cc->vtable->init->invocationCount(); } } if(!object || !qname) return -1; VTable *v = object->vtable; again: MethodEnv *env = NULL; Binding b = self->toplevel()->getBinding(v->traits, &multiname); switch (AvmCore::bindingKind(b)) { case BKIND_VAR: case BKIND_CONST: { // only look at slots for first pass, otherwise we're applying instance traits to the Class if(v == object->vtable) { Atom method = object->getSlotAtom(AvmCore::bindingToSlotId(b)); if(AvmCore::isObject(method)) { env = AvmCore::atomToScriptObject(method)->getCallMethodEnv(); } } break; } case BKIND_METHOD: { int m = AvmCore::bindingToMethodId(b); env = v->methods[m]; break; } case BKIND_GET: case BKIND_GETSET: case BKIND_SET: { if(type == GET && AvmCore::hasGetterBinding(b)) env = v->methods[AvmCore::bindingToGetterId(b)]; else if(type == SET && AvmCore::hasSetterBinding(b)) env = v->methods[AvmCore::bindingToSetterId(b)]; break; } case BKIND_NONE: { Atom method = object->getStringProperty(multiname.getName()); if(AvmCore::isObject(method)) { env = AvmCore::atomToScriptObject(method)->getCallMethodEnv(); } else if(v->ivtable) { v = v->ivtable; goto again; } } default: break; } if(env) return (double)env->invocationCount(); #else (void)self; (void)type; (void)qname; (void)a; #endif return -1; }