Atom Stubs::do_abc_callsupernsx(MethodFrame* f, const Multiname* name, Atom ns, Atom index, int argc, Atom* args) { Multiname tempname; MethodEnv* e = env(f); initnamensx(e, name, ns, index, &tempname); return e->callsuper(&tempname, argc - 1, args); }
BoolKind Stubs::do_abc_deletepropns(MethodFrame* f, const Multiname* name, Atom ns, Atom object) { Multiname tempname; MethodEnv* e = env(f); initnamens(e, name, ns, &tempname); return boolKind(e->delproperty(object, &tempname) == trueAtom); }
void Stubs::do_abc_setsupernsx(MethodFrame* f, const Multiname* name, Atom ns, Atom index, Atom object, Atom value) { Multiname tempname; MethodEnv* e = env(f); initnamensx(e, name, ns, index, &tempname); e->setsuper(object, &tempname, value); }
void Stubs::do_abc_initpropnsx(MethodFrame* f, const Multiname* name, Atom ns, Atom index, Atom object, Atom value) { Multiname tempname; MethodEnv* e = env(f); initnamensx(e, name, ns, index, &tempname); e->initproperty(object, &tempname, value, toVTable(e, object)); }
inline uint8_t* rangeCheck(MethodFrame* f, int32_t addr, size_t bytes) { MethodEnv* e = env(f); const DomainEnv* d = e->domainEnv(); if (uint32_t(addr) > (d->globalMemorySize() - bytes)) avmplus::mop_rangeCheckFailed(e); return d->globalMemoryBase() + addr; }
Atom Stubs::do_abc_getsupernsx(MethodFrame* f, const Multiname* name, Atom ns, Atom index, Atom object) { Multiname tempname; MethodEnv* e = env(f); initnamensx(e, name, ns, index, &tempname); return e->getsuper(object, &tempname); }
BoolKind Stubs::do_abc_deletepropnsx(MethodFrame* f, const Multiname* name, Atom ns, Atom index, Atom object) { checkXMLList(f, index); Multiname tempname; MethodEnv* e = env(f); initnamensx(e, name, ns, index, &tempname); return boolKind(e->delproperty(object, &tempname) == trueAtom); }
ClassClosure* FunctionClass::createEmptyFunction() { // invoke AS3 private static function emptyCtor, which returns an empty function. TraitsBindingsp t = traits()->getTraitsBindings(); Binding b = t->findBinding(core()->internConstantStringLatin1("emptyCtor")); MethodEnv *f = vtable->methods[AvmCore::bindingToMethodId(b)]; return (ClassClosure*)AvmCore::atomToScriptObject(f->coerceEnter(this->atom())); }
CodeContext* getClassCodeContext(const ScriptObject* so) { if (!so) return NULL; if (so->core()->isFunction(so->atom())) { AvmAssert(!"Function or MC is not legal here."); return NULL; } avmplus::TraitsPosType t = so->traits()->posType(); if (t == avmplus::TRAITSTYPE_CATCH || t == avmplus::TRAITSTYPE_ACTIVATION) { AvmAssert(!"Activation and Catch objects are not legal here."); return NULL; } MethodEnv* init = so->vtable->init; if (!init) { AvmAssert(!"init method is null, should not be possible."); return NULL; } return init->scope()->abcEnv()->codeContext(); }
/** * This function is called by JIT code if OSR has been requested * if (exec->current_osr != 0). This function fills the JIT frame locals * to match the interpreter frame. The JIT code looks like this: * * if (*(&exec->current_osr)) { * adjustFrame(...); * goto loop_entry * } */ void OSR::adjustFrame(MethodFrame* jitMethodFrame, CallStackNode *callStack, FramePtr jitFramePointer, uint8_t *jitFrameTags) { MethodEnv* env = jitMethodFrame->env(); BaseExecMgr* exec = BaseExecMgr::exec(env); OSR *osr = exec->current_osr; AvmAssert(osr && "should not have gotten here"); Atom* interpFramePointer = osr->interp_frame; MethodSignaturep ms = env->method->getMethodSignature(); int nLocals = ms->local_count(); int stackBase = nLocals + ms->max_scope(); FrameState* frameState = osr->jit_frame_state; int scopeTop = nLocals + frameState->scopeDepth; int stackTop = stackBase + frameState->stackDepth; // OSR has been requested. #ifdef AVMPLUS_VERBOSE if (env->method->pool()->isVerbose(VB_interp)) { env->core()->console << "osr-adjust_frame " << env->method->method_id() << " " << env->method << " scopeTop=" << scopeTop << " stackTop=" << stackTop << "\n"; } #endif // Patch the JIT frame local variable slots and the scope slots in use to match the interpreter state. for (int i = 0; i < scopeTop; i++) unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i); // zero out stack area for unused scopes: if (scopeTop < stackBase) { void* p = ((char*) jitFramePointer + (scopeTop << VARSHIFT(env->method))); size_t nbytes = (stackBase - scopeTop) << VARSHIFT(env->method); VMPI_memset(p, 0, nbytes); } // Patch operand stack slots: for (int i = stackBase; i < stackTop; i++) unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i); MethodFrame *interpreterMethodFrame = jitMethodFrame->next; jitMethodFrame->dxns = interpreterMethodFrame->dxns; jitMethodFrame->next = interpreterMethodFrame->next; // Clean up non-local OSR parameterization data: mmfx_delete(frameState); exec->current_osr = NULL; #ifdef DEBUGGER // Call debugEnter if necessary, since the jit code won't. // We can safely pass NULL for &eip here, because OSR is disabled // for methods with catch blocks. if (callStack) env->debugEnter(jitFrameTags, callStack, jitFramePointer, NULL); #else (void) callStack; #endif }
void Stubs::do_abc_initprop(MethodFrame* f, const Multiname* name, Atom object, Atom value) { MethodEnv* e = env(f); e->initproperty(object, name, value, toVTable(e, object)); }
/** * This function detects if OSR has been requested or if this is a * subsequent normal call. In the latter case it has no side effect and * returns false and control flow is supposed to proceed normally. * If OSR is in the works, then it fills the JIT frame locals to match the * interpreter frame. Then it returns true, which indicates to the * generated code to jump to the OSR entry point. * * The JIT code looks like this: * * if (adjust_frame(...)) * goto loop_entry */ int32_t OSR::adjustFrame(MethodFrame* jitMethodFrame, CallStackNode *callStack, FramePtr jitFramePointer, uint8_t *jitFrameTags) { MethodEnv* env = jitMethodFrame->env(); BaseExecMgr* exec = BaseExecMgr::exec(env); OSR *osr = exec->current_osr; if (!osr) { // No OSR has been requested. // We are at the beginning of a normal AS method call. // Indicate proceeding with normal control flow. return 0; } Atom* interpFramePointer = osr->interp_frame; MethodSignaturep ms = env->method->getMethodSignature(); int nLocals = ms->local_count(); int stackBase = nLocals + ms->max_scope(); FrameState* frameState = osr->jit_frame_state; int scopeTop = nLocals + frameState->scopeDepth; int stackTop = stackBase + frameState->stackDepth; // OSR has been requested. #ifdef AVMPLUS_VERBOSE if (env->method->pool()->isVerbose(VB_interp)) { env->core()->console << "osr-adjust_frame " << env->method->method_id() << " " << env->method << " scopeTop=" << scopeTop << " stackTop=" << stackTop << "\n"; } #endif // Patch the JIT frame local variable slots and the scope slots in use to match the interpreter state. for (int i = 0; i < scopeTop; i++) unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i); // zero out stack area for unused scopes: if (scopeTop < stackBase) { void* p = ((char*) jitFramePointer + scopeTop * VARSIZE); size_t nbytes = (stackBase - scopeTop) * VARSIZE; VMPI_memset(p, 0, nbytes); } // Patch operand stack slots: for (int i = stackBase; i < stackTop; i++) unboxSlot(frameState, env, interpFramePointer, jitFramePointer, jitFrameTags, i); MethodFrame *interpreterMethodFrame = jitMethodFrame->next; jitMethodFrame->dxns = interpreterMethodFrame->dxns; jitMethodFrame->next = interpreterMethodFrame->next; // Clean up non-local OSR parameterization data: mmfx_delete(frameState); exec->current_osr = NULL; #ifdef DEBUGGER // Call debugEnter if necessary, since the jit code won't. // We can safely pass NULL for &eip here, because OSR is disabled // for methods with catch blocks. if (callStack) env->debugEnter(jitFrameTags, callStack, jitFramePointer, NULL); #else (void) callStack; #endif // Indicate taking a shortcut from the call site // to the OSR entry point instead of normal control flow: return 1; }
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; }