Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / extensions / SamplerScript.cpp
bloba909ca0207ce66411e607be9c588fb6bb1183215
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 1993-2006
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 // Adobe patent application tracking #P721, entitled Application Profiling, inventors: T. Reilly
43 #ifdef AVMSHELL_BUILD
44 #include "avmshell.h"
45 #else
46 // player
47 #include "platformbuild.h"
48 #include "avmplayer.h"
49 #include "SamplerScript.h"
50 #endif
52 using namespace MMgc;
54 namespace avmplus
56 TraceClass::TraceClass(VTable *cvtable)
57 : ClassClosure(cvtable)
59 createVanillaPrototype();
62 int TraceClass::getLevel(int target)
64 int lvl = 0 ; /*Debugger::TRACE_OFF;*/
65 #ifdef DEBUGGER
66 AvmCore *core = this->core();
67 if (core->debugger())
69 if (target > 1)
70 lvl = core->debugger()->astrace_callback;
71 else
72 lvl = core->debugger()->astrace_console;
74 #endif /* DEBUGGER */
75 (void)target;
76 return lvl;
79 Atom TraceClass::setLevel(int lvl, int target)
81 #ifdef DEBUGGER
82 AvmCore *core = this->core();
83 if (core->debugger())
85 if (target > 1)
86 core->debugger()->astrace_callback = (Debugger::TraceLevel) lvl;
87 else
88 core->debugger()->astrace_console = (Debugger::TraceLevel) lvl;
90 #endif /* DEBUGGER */
91 (void)lvl;
92 (void)target;
93 return undefinedAtom;
96 Atom TraceClass::setListener(FunctionObject* f)
98 #ifdef DEBUGGER
99 AvmCore *core = this->core();
100 if (core->debugger())
102 // Listeners MUST be functions or null
103 if ( core->isNullOrUndefined(f->atom()) )
105 f = 0;
107 else if (!AvmCore::istype(f->atom(), core->traits.function_itraits))
109 toplevel()->argumentErrorClass()->throwError( kInvalidArgumentError, core->toErrorString("Function"));
110 return undefinedAtom;
113 //MethodClosure* mc = f->toplevel()->methodClosureClass->create(f->getCallMethodEnv(), f->atom());
114 core->debugger()->trace_callback = f;
116 #endif /* DEBUGGER */
117 (void)f;
118 return undefinedAtom;
121 FunctionObject* TraceClass::getListener()
123 FunctionObject* f = 0;
124 #ifdef DEBUGGER
125 AvmCore *core = this->core();
126 if (core->debugger())
127 f = core->debugger()->trace_callback;
128 #endif /* DEBUGGER */
129 return f;
132 using namespace MMgc;
134 #ifdef DEBUGGER
136 class SampleIterator : public ScriptObject
138 public:
139 SampleIterator(ScriptObject* script, VTable *vt) :
140 ScriptObject(vt, NULL),
141 script(script)
143 Sampler* const sampler = script->core()->get_sampler();
144 sampleBufferId = sampler->getSampleBufferId();
145 cursor = sampler->getSamples(count);
148 int nextNameIndex(int index)
150 if(count == 0)
152 return 0;
155 Sampler* const sampler = script->core()->get_sampler();
156 if (sampler == NULL || sampleBufferId != sampler->getSampleBufferId())
158 // If the sampler is stopped
159 // while we are iterating on items
160 // the iterator should be invalidated
161 // because the Sampler::sampleBufferId is incremented
162 // each time the sample buffer is cleared.
163 count = 0;
164 return 0;
167 return index+1;
170 Atom nextValue(int i)
172 if (count == 0)
174 return undefinedAtom;
177 Sampler * const sampler = script->core()->get_sampler();
178 if (sampler == NULL || sampleBufferId != sampler->getSampleBufferId())
180 count = 0;
181 return undefinedAtom;
184 (void) i;
185 Sample s;
186 sampler->readSample(cursor, s);
187 count--;
188 ScriptObject* sam = SamplerScript::makeSample(script, cf, s);
189 if(!sam) {
190 count = 0;
191 return undefinedAtom;
193 return sam->atom();
197 Atom nextName(int)
199 // they are iterating over the names, bail
200 count = 0;
201 return undefinedAtom;
204 private:
205 uint64_t sampleBufferId;
206 uint32_t count;
207 uint8_t *cursor;
208 DRCWB(ScriptObject*) script;
209 public:
210 DRCWB(ClassFactoryClass*) cf;
213 class SlotIterator : public ScriptObject
215 public:
216 SlotIterator(Traits *t, VTable *vtable)
217 : ScriptObject(vtable, NULL)
218 , currTraits(t ? t->getTraitsBindings() : NULL)
222 int nextNameIndex(int index)
224 while (currTraits != NULL)
226 while ((index = currTraits->next(index)) != 0)
228 return index;
231 currTraits = currTraits->base;
234 return 0;
237 Atom nextValue(int index)
239 Multiname mn(currTraits->nsAt(index), currTraits->keyAt(index), true);
240 QNameObject *qname = QNameObject::create(gc(), toplevel()->qnameClass(), mn);
242 return qname->atom();
245 Atom nextName(int)
247 // they are iterating over the names, bail
248 currTraits = NULL;
249 return undefinedAtom;
252 private:
253 DWB(TraitsBindingsp) currTraits;
256 #endif // DEBUGGER
258 #ifdef DEBUGGER
259 static VTable* _newVT(Toplevel* toplevel, PoolObject* pool, uint16_t sz)
261 Traits* t = Traits::newTraits(pool, NULL, sz, 0, 0, TRAITSTYPE_RT);
262 t->verifyBindings(toplevel);
263 t->resolveSignatures(toplevel);
264 return toplevel->core()->newVTable(t, NULL, toplevel);
266 #endif
268 Atom SamplerScript::_getSamples(ScriptObject* self, ClassClosure* cf)
270 #ifdef DEBUGGER
271 AvmCore* core = self->core();
272 Sampler *s = core->get_sampler();
273 if (!s || !s->sampling() || s->sampleCount() == 0 || !trusted(self))
274 return undefinedAtom;
276 if (s->sampleIteratorVTable == NULL)
277 s->sampleIteratorVTable = _newVT(self->toplevel(), self->traits()->pool, sizeof(SampleIterator));
278 SampleIterator* iter = new (self->gc()) SampleIterator(self, s->sampleIteratorVTable);
279 iter->cf = (ClassFactoryClass*)cf;
280 return iter->atom();
281 #else
282 (void)self; (void)cf;
283 return undefinedAtom;
284 #endif
287 double SamplerScript::getSampleCount(ScriptObject* self)
289 #ifdef DEBUGGER
290 Sampler* s = self->core()->get_sampler();
291 if (!s)
292 return -1;
293 uint32_t num;
294 s->getSamples(num);
295 return (double)num;
296 #else
297 (void)self;
298 return -1;
299 #endif
302 #ifdef DEBUGGER
303 ClassClosure *SamplerScript::getType(Toplevel* ss_toplevel, SamplerObjectType sot, const void *ptr)
305 Toplevel* tl;
307 switch (sotGetKind(sot))
309 case kSOT_String:
311 // toplevel can be null here if there was no CodeContext active
312 // when the sample was taken (ie, string was allocated from C++ code).
313 // in that case, use the TL from the SamplerScript itself... it isn't
314 // technically the right one to use, but is adequate for our purposes here
315 // (it will return a stringClass or namespaceClass that will be valid
316 // for the sampler)
317 tl = sotGetToplevel(sot);
318 if (!tl) tl = ss_toplevel;
319 return tl->stringClass();
321 case kSOT_Namespace:
323 tl = sotGetToplevel(sot);
324 if (!tl) tl = ss_toplevel;
325 return tl->namespaceClass();
327 default:
328 AvmAssert(0);
329 case kSOT_Object:
330 break;
333 VTable* vt = sotGetVTable(sot);
334 tl = vt->toplevel();
335 AvmCore* core = tl->core();
337 ClassClosure *type;
338 ScriptObject* obj = (ScriptObject*)ptr;
339 if (obj && AvmCore::istype(obj->atom(), core->traits.class_itraits))
341 type = tl->classClass();
343 else if (obj && AvmCore::istype(obj->atom(), core->traits.function_itraits))
345 type = tl->functionClass();
347 else if (obj && obj->traits()->isActivationTraits())
349 type = tl->objectClass;
351 else
353 // fallback answer
354 type = tl->objectClass;
356 // note that note all types will have an init method,
357 // so those types may get reported as "objectClass" rather
358 // than something more specific. However, it's not clear
359 // that the Sampler ever really cared about reporting those
360 // objects well in the first place (eg activation or catch objects),
361 // so it doesn't seem we're a lot worse off than before.
362 ScopeChain* sc = NULL;
363 if (vt->init)
364 sc = vt->init->scope();
366 if (sc && sc->getSize() <= 1)
368 if(sc->getSize() == 1)
369 type = tl->classClass();
371 else if (sc)
373 Atom ccAtom = sc->getScope(sc->getSize()-1);
374 if(AvmCore::isObject(ccAtom))
376 type = (ClassClosure*) AvmCore::atomToScriptObject(ccAtom);
377 if(!AvmCore::istype(type->atom(), core->traits.class_itraits))
379 // obj is a ClassClosure
380 type = tl->classClass();
385 AvmAssert(AvmCore::istype(type->atom(), core->traits.class_itraits));
386 return type;
388 #endif // DEBUGGER
390 #ifdef DEBUGGER
391 bool SamplerScript::set_stack(ScriptObject* self, ClassFactoryClass* cf, const Sample& sample, SampleObject* sam)
393 if (sample.stack.depth > 0)
395 Toplevel* toplevel = self->toplevel();
396 AvmCore* core = toplevel->core();
397 Sampler* s = core->get_sampler();
399 StackFrameClass* sfcc = (StackFrameClass*)cf->get_StackFrameClass();
400 ArrayObject* stack = toplevel->arrayClass()->newArray(sample.stack.depth);
401 StackTrace::Element* e = (StackTrace::Element*)sample.stack.trace;
402 for(uint32_t i=0; i < sample.stack.depth; i++, e++)
404 StackFrameObject* sf = (StackFrameObject*)sfcc->newInstance();
406 // at every allocation the sample buffer could overflow and the samples could be deleted
407 // the StackTrace::Element pointer is a raw pointer into that buffer so we need to check
408 // that its still around before dereferencing e
409 uint32_t num;
410 if (s->getSamples(num) == NULL)
411 return false;
413 sf->set_name(e->name()); // NOT e->info()->name() because e->name() can be a fake name
414 if(e->filename())
415 sf->set_file(e->filename());
416 sf->set_line(e->linenum());
417 sf->set_scriptID(static_cast<double>(e->functionId()));
419 stack->setUintProperty(i, sf->atom());
421 sam->set_stack(stack);
423 return true;
426 ScriptObject* SamplerScript::makeSample(ScriptObject* self, ClassFactoryClass* cf, const Sample& sample)
428 Toplevel* toplevel = self->toplevel();
429 AvmCore* core = toplevel->core();
430 Sampler* s = core->get_sampler();
431 if (!s)
432 return NULL;
434 switch (sample.sampleType)
436 case Sampler::RAW_SAMPLE:
438 SampleObject* sam = (SampleObject*)cf->get_SampleClass()->newInstance();
439 sam->set_time(static_cast<double>(sample.micros));
440 if (!set_stack(self, cf, sample, sam))
441 return NULL;
442 return sam;
444 case Sampler::DELETED_OBJECT_SAMPLE:
446 DeleteObjectSampleObject* dsam = (DeleteObjectSampleObject*)cf->get_DeleteObjectSampleClass()->newInstance();
447 dsam->set_time(static_cast<double>(sample.micros));
448 dsam->set_id(static_cast<double>(sample.id));
449 dsam->set_size(static_cast<double>(sample.size));
450 return dsam;
452 case Sampler::NEW_OBJECT_SAMPLE:
454 NewObjectSampleObject* nsam = (NewObjectSampleObject*)cf->get_NewObjectSampleClass()->newInstance();
455 nsam->set_time(static_cast<double>(sample.micros));
456 nsam->set_id(static_cast<double>(sample.id));
457 if (!set_stack(self, cf, sample, nsam))
458 return NULL;
459 if (sample.ptr != NULL )
460 nsam->setRef((AvmPlusScriptableObject*)sample.ptr);
461 nsam->set_type(getType(toplevel, sample.sot, sample.ptr));
462 nsam->setSize(sample.alloc_size);
463 return nsam;
465 case Sampler::NEW_AUX_SAMPLE:
467 NewObjectSampleObject* nsam = (NewObjectSampleObject*)cf->get_NewObjectSampleClass()->newInstance();
468 nsam->set_time(static_cast<double>(sample.micros));
469 nsam->set_id(static_cast<double>(sample.id));
470 if (!set_stack(self, cf, sample, nsam))
471 return NULL;
472 nsam->setSize(sample.alloc_size);
473 return nsam;
477 AvmAssert(0);
478 return NULL;
480 #endif // DEBUGGER
483 Atom SamplerScript::getMemberNames(ScriptObject* self, Atom o, bool instanceNames)
485 #ifdef DEBUGGER
486 AvmCore* core = self->core();
487 MMgc::GC* gc = core->GetGC();
488 Sampler* s = core->get_sampler();
489 if (!s || !trusted(self))
490 return undefinedAtom;
492 if (AvmCore::isObject(o))
494 Traits *t = AvmCore::atomToScriptObject(o)->traits();
495 if(AvmCore::istype(o, CLASS_TYPE) && instanceNames && t->itraits)
496 t = t->itraits;
497 if (s->slotIteratorVTable == NULL)
498 s->slotIteratorVTable = _newVT(self->toplevel(), self->traits()->pool, sizeof(SlotIterator));
499 return (new (gc) SlotIterator(t, s->slotIteratorVTable))->atom();
501 #else
502 (void)self;
503 (void)o; (void)instanceNames;
504 #endif
505 return undefinedAtom;
508 static double _get_size(Atom a)
510 #ifdef DEBUGGER
511 switch(a&7)
513 case kDoubleType:
514 return 8;
515 case kObjectType:
516 case kStringType:
517 case kNamespaceType:
518 AvmPlusScriptableObject *o = (AvmPlusScriptableObject*)(a&~7);
519 if(o)
520 return (double)o->bytesUsed();
522 return 4;
523 #else
524 (void)a;
525 return 0;
526 #endif
529 double SamplerScript::getSize(ScriptObject* self, Atom a)
531 #ifdef DEBUGGER
532 AvmCore* core = self->core();
533 Sampler* s = core->get_sampler();
534 if (!s)
535 return 0;
536 return _get_size(a);
537 #else
538 (void)self;
539 (void)a;
540 return 0;
541 #endif
544 void SamplerScript::startSampling(ScriptObject* self)
546 #ifdef DEBUGGER
547 Sampler* s = self->core()->get_sampler();
548 if (!s || !trusted(self))
549 return;
550 s->startSampling();
551 #else
552 (void)self;
553 #endif
556 void SamplerScript::stopSampling(ScriptObject* self)
558 #ifdef DEBUGGER
559 Sampler* s = self->core()->get_sampler();
560 if (!s || !trusted(self))
561 return;
562 s->stopSampling();
563 #else
564 (void)self;
565 #endif
568 void SamplerScript::clearSamples(ScriptObject* self)
570 #ifdef DEBUGGER
571 Sampler* s = self->core()->get_sampler();
572 if (!s || !trusted(self))
573 return;
574 s->clearSamples();
575 #else
576 (void)self;
577 #endif
580 void SamplerScript::pauseSampling(ScriptObject* self)
582 #ifdef DEBUGGER
583 Sampler* s = self->core()->get_sampler();
584 if (!s || !trusted(self))
585 return;
586 s->pauseSampling();
587 #else
588 (void)self;
589 #endif
592 void SamplerScript::sampleInternalAllocs(ScriptObject* self, bool b)
594 #ifdef DEBUGGER
595 Sampler* s = self->core()->get_sampler();
596 if (!s || !trusted(self))
597 return;
598 s->sampleInternalAllocs(b);
599 #else
600 (void)self;
601 (void)b;
602 #endif
605 void SamplerScript::_setSamplerCallback(ScriptObject* self, ScriptObject *callback)
607 #ifdef DEBUGGER
608 Sampler* s = self->core()->get_sampler();
609 if (!s || !trusted(self))
610 return;
611 s->setCallback(callback);
612 #else
613 (void)self;
614 (void)callback;
615 #endif
618 double SamplerScript::_getInvocationCount(ScriptObject* self, Atom a, QNameObject* qname, uint32_t type)
620 #ifdef DEBUGGER
621 AvmCore* core = self->core();
622 Sampler* s = core->get_sampler();
623 if (!s || !trusted(self))
624 return -1;
626 Multiname multiname;
627 if(qname)
628 qname->getMultiname(multiname);
630 ScriptObject* object = self->toplevel()->global();
631 if(!AvmCore::isObject(a))
633 // not sure if this will be true for standalone avmplus
634 AvmAssert(core->codeContext() != NULL);
635 DomainEnv *domainEnv = core->codeContext()->domainEnv();
636 ScriptEnv* script = (ScriptEnv*) core->domainMgr()->findScriptEnvInDomainEnvByMultiname(domainEnv, multiname);
637 if (script != (ScriptEnv*)BIND_NONE)
639 if (script == (ScriptEnv*)BIND_AMBIGUOUS)
640 self->toplevel()->throwReferenceError(kAmbiguousBindingError, &multiname);
642 object = script->global;
643 if (object == NULL)
645 object = script->initGlobal();
646 script->coerceEnter(script->global->atom());
650 else
652 object = AvmCore::atomToScriptObject(a);
654 if(AvmCore::istype(a, CLASS_TYPE) && !qname) {
655 // return constructor count
656 ClassClosure *cc = (ClassClosure*)object;
657 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.
658 return (double)cc->vtable->init->invocationCount();
662 if(!object || !qname)
663 return -1;
665 VTable *v = object->vtable;
667 again:
669 MethodEnv *env = NULL;
670 Binding b = self->toplevel()->getBinding(v->traits, &multiname);
671 switch (AvmCore::bindingKind(b))
673 case BKIND_VAR:
674 case BKIND_CONST:
676 // only look at slots for first pass, otherwise we're applying instance traits to the Class
677 if(v == object->vtable) {
678 Atom method = object->getSlotAtom(AvmCore::bindingToSlotId(b));
679 if(AvmCore::isObject(method))
681 env = AvmCore::atomToScriptObject(method)->getCallMethodEnv();
684 break;
686 case BKIND_METHOD:
688 int m = AvmCore::bindingToMethodId(b);
689 env = v->methods[m];
690 break;
692 case BKIND_GET:
693 case BKIND_GETSET:
694 case BKIND_SET:
696 if(type == GET && AvmCore::hasGetterBinding(b))
697 env = v->methods[AvmCore::bindingToGetterId(b)];
698 else if(type == SET && AvmCore::hasSetterBinding(b))
699 env = v->methods[AvmCore::bindingToSetterId(b)];
700 break;
702 case BKIND_NONE:
704 Atom method = object->getStringProperty(multiname.getName());
705 if(AvmCore::isObject(method))
707 env = AvmCore::atomToScriptObject(method)->getCallMethodEnv();
709 else if(v->ivtable)
711 v = v->ivtable;
712 goto again;
715 default:
716 break;
719 if(env)
720 return (double)env->invocationCount();
721 #else
722 (void)self;
723 (void)type;
724 (void)qname;
725 (void)a;
726 #endif
728 return -1;
731 bool SamplerScript::isGetterSetter(ScriptObject* self, Atom a, QNameObject *qname)
733 #ifdef DEBUGGER
734 AvmCore* core = self->core();
735 Sampler* s = core->get_sampler();
736 if (!s)
737 return false;
739 if(!AvmCore::isObject(a) || !AvmCore::atomToScriptObject(a))
740 self->toplevel()->throwArgumentError(kInvalidArgumentError, "object");
742 ScriptObject *object = AvmCore::atomToScriptObject(a);
744 if(!object || !qname)
745 self->toplevel()->argumentErrorClass()->throwError(kInvalidArgumentError);
747 Multiname multiname;
748 qname->getMultiname(multiname);
750 VTable *v = object->vtable;
752 again:
754 Binding b = self->toplevel()->getBinding(v->traits, &multiname);
756 if(b == BIND_NONE && v->ivtable)
758 v = v->ivtable;
759 goto again;
762 return AvmCore::hasSetterBinding(b) || AvmCore::hasGetterBinding(b);
763 #else
764 (void)self;
765 (void)a; (void)qname;
766 return false;
767 #endif
771 SampleObject::SampleObject(VTable *vtable, ScriptObject *delegate)
772 : ScriptObject(vtable, delegate)
776 NewObjectSampleObject::NewObjectSampleObject(VTable *vtable, ScriptObject *delegate)
777 : SampleObject(vtable, delegate), size(0)
780 DeleteObjectSampleObject::DeleteObjectSampleObject(VTable *vtable, ScriptObject *delegate)
781 : SampleObject(vtable, delegate)
784 Atom NewObjectSampleObject::get_object()
786 if(obj) {
787 Atom a = obj->toAtom();
788 AvmAssert((a&~7) != 0);
789 return a;
791 return undefinedAtom;
794 double NewObjectSampleObject::get_size()
796 double s = (double)size;
797 if( !size ) {
798 Atom a = get_object();
799 s = _get_size(a);
801 return s;
804 SampleClass::SampleClass(VTable *vtable)
805 : ClassClosure(vtable)
807 createVanillaPrototype();
810 NewObjectSampleClass::NewObjectSampleClass(VTable *vtable)
811 : SampleClass(vtable)
815 DeleteObjectSampleClass::DeleteObjectSampleClass(VTable* vtable) : SampleClass(vtable)
819 /*static*/
820 ArrayObject* SamplerScript::getLexicalScopes(ScriptObject *self, FunctionObject *function)
822 #ifdef DEBUGGER
823 AvmCore* core = self->core();
824 Sampler *s = core->get_sampler();
825 if (!s || !trusted(self))
826 return NULL;
828 if(function != NULL && function->getCallMethodEnv())
829 return function->getCallMethodEnv()->getLexicalScopes();
830 else
831 return NULL;
832 #else
833 (void)self;
834 (void)function;
835 return NULL;
836 #endif
839 /*static*/
840 Atom SamplerScript::getSavedThis(ScriptObject *self, FunctionObject *method)
842 #ifdef DEBUGGER
843 AvmCore* core = self->core();
844 Sampler *s = core->get_sampler();
845 if (!s || !trusted(self))
846 return undefinedAtom;
848 MethodClosure* mc;
849 if (method != NULL && ((mc = method->toMethodClosure()) != NULL))
850 return mc->get_savedThis();
851 else
852 return undefinedAtom;
853 #else
854 (void)self;
855 (void)method;
856 return undefinedAtom;
857 #endif
860 /*static*/
861 Stringp SamplerScript::getMasterString(ScriptObject *self, Stringp str)
863 #ifdef DEBUGGER
864 AvmCore* core = self->core();
865 Sampler *s = core->get_sampler();
866 if (!s || !trusted(self))
867 return NULL;
869 if(str != NULL)
870 return str->getMasterString();
871 else
872 return NULL;
873 #else
874 (void)self;
875 (void)str;
876 return NULL;
877 #endif