void * JS_FASTCALL stubs::CompileFunction(VMFrame &f, uint32 nactual) { /* * We have a partially constructed frame. That's not really good enough to * compile though because we could throw, so get a full, adjusted frame. */ JSContext *cx = f.cx; JSStackFrame *fp = f.fp(); /* * Since we can only use members set by initCallFrameCallerHalf, * we must carefully extract the callee from the nactual. */ JSObject &callee = fp->formalArgsEnd()[-(int(nactual) + 2)].toObject(); JSFunction *fun = callee.getFunctionPrivate(); JSScript *script = fun->script(); /* * FixupArity/RemovePartialFrame expect to be called after the early * prologue. */ fp->initCallFrameEarlyPrologue(fun, nactual); if (nactual != fp->numFormalArgs()) { fp = (JSStackFrame *)FixupArity(f, nactual); if (!fp) return NULL; } /* Finish frame initialization. */ fp->initCallFrameLatePrologue(); /* These would have been initialized by the prologue. */ f.regs.fp = fp; f.regs.sp = fp->base(); f.regs.pc = script->code; if (fun->isHeavyweight() && !js::CreateFunCallObject(cx, fp)) THROWV(NULL); CompileStatus status = CanMethodJIT(cx, script, fp, CompileRequest_JIT); if (status == Compile_Okay) return script->getJIT(fp->isConstructing())->invokeEntry; /* Function did not compile... interpret it. */ JSBool ok = Interpret(cx, fp); InlineReturn(f); if (!ok) THROWV(NULL); return NULL; }
/* * This function must only be called after the early prologue, since it depends * on fp->exec.fun. */ void * JS_FASTCALL stubs::FixupArity(VMFrame &f, uint32 nactual) { JSContext *cx = f.cx; JSStackFrame *oldfp = f.fp(); JS_ASSERT(nactual != oldfp->numFormalArgs()); /* * Grossssss! *move* the stack frame. If this ends up being perf-critical, * we can figure out how to spot-optimize it. Be careful to touch only the * members that have been initialized by initCallFrameCallerHalf and the * early prologue. */ uint32 flags = oldfp->isConstructingFlag(); JSFunction *fun = oldfp->fun(); void *ncode = oldfp->nativeReturnAddress(); /* Pop the inline frame. */ f.fp() = oldfp->prev(); f.regs.sp = (Value*) oldfp; /* Reserve enough space for a callee frame. */ JSStackFrame *newfp = cx->stack().getInlineFrameWithinLimit(cx, (Value*) oldfp, nactual, fun, fun->script(), &flags, f.entryfp, &f.stackLimit); if (!newfp) { /* * The PC is not coherent with the current frame, so fix it up for * exception handling. */ f.regs.pc = f.jit()->nativeToPC(ncode); THROWV(NULL); } /* Reset the part of the stack frame set by the caller. */ newfp->initCallFrameCallerHalf(cx, flags, ncode); /* Reset the part of the stack frame set by the prologue up to now. */ newfp->initCallFrameEarlyPrologue(fun, nactual); /* The caller takes care of assigning fp to regs. */ return newfp; }