From 259242f46c452dc1c46afadd1933c14bebb2f3a8 Mon Sep 17 00:00:00 2001 From: Kannan Vijayan Date: Mon, 25 Feb 2013 00:57:39 -0500 Subject: [PATCH] Bug 844253 - Change useNewType to be a flag on StackFrame instead of an explicitly passed argument. r=bhackett --- js/src/ion/Ion.cpp | 5 ++--- js/src/ion/Ion.h | 3 +-- js/src/jsinterp.cpp | 25 +++++++++++++++++++++---- js/src/methodjit/InvokeHelpers.cpp | 4 +++- js/src/methodjit/StubCalls.cpp | 3 +-- js/src/vm/Stack-inl.h | 7 +++++++ js/src/vm/Stack.cpp | 4 ++-- js/src/vm/Stack.h | 24 +++++++++++++++++------- 8 files changed, 54 insertions(+), 21 deletions(-) diff --git a/js/src/ion/Ion.cpp b/js/src/ion/Ion.cpp index b5bb7452bc84..bd91164fceee 100644 --- a/js/src/ion/Ion.cpp +++ b/js/src/ion/Ion.cpp @@ -1472,8 +1472,7 @@ ion::CanEnterAtBranch(JSContext *cx, JSScript *script, AbstractFramePtr fp, } MethodStatus -ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, - bool isConstructing, bool newType) +ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing) { JS_ASSERT(ion::IsEnabled(cx)); @@ -1495,7 +1494,7 @@ ion::CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, if (isConstructing && fp.thisValue().isPrimitive()) { RootedScript scriptRoot(cx, script); RootedObject callee(cx, &fp.callee()); - RootedObject obj(cx, CreateThisForFunction(cx, callee, newType)); + RootedObject obj(cx, CreateThisForFunction(cx, callee, fp.useNewType())); if (!obj) return Method_Skipped; fp.thisValue().setObject(*obj); diff --git a/js/src/ion/Ion.h b/js/src/ion/Ion.h index 407e09cabb8e..c7b069a95cfd 100644 --- a/js/src/ion/Ion.h +++ b/js/src/ion/Ion.h @@ -261,8 +261,7 @@ bool SetIonContext(IonContext *ctx); MethodStatus CanEnterAtBranch(JSContext *cx, JSScript *script, AbstractFramePtr fp, jsbytecode *pc, bool isConstructing); -MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, - bool isConstructing, bool newType); +MethodStatus CanEnter(JSContext *cx, JSScript *script, AbstractFramePtr fp, bool isConstructing); MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs); enum IonExecStatus diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 16a27833f51e..e1a6c2fc8b40 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -276,6 +276,20 @@ js::RunScript(JSContext *cx, StackFrame *fp) JS_CHECK_RECURSION(cx, return false); + // Check to see if useNewType flag should be set for this frame. + if (fp->isFunctionFrame() && fp->isConstructing() && !fp->isGeneratorFrame()) { + StackIter iter(cx); + if (!iter.done()) { + ++iter; + if (iter.isScript()) { + RawScript script = iter.script(); + jsbytecode *pc = iter.pc(); + if (UseNewType(cx, script, pc)) + fp->setUseNewType(); + } + } + } + #ifdef DEBUG struct CheckStackBalance { JSContext *cx; @@ -294,7 +308,7 @@ js::RunScript(JSContext *cx, StackFrame *fp) #ifdef JS_ION if (ion::IsEnabled(cx)) { ion::MethodStatus status = ion::CanEnter(cx, script, AbstractFramePtr(fp), - fp->isConstructing(), false); + fp->isConstructing()); if (status == ion::Method_Error) return false; if (status == ion::Method_Compiled) { @@ -1159,7 +1173,7 @@ js::Interpret(JSContext *cx, StackFrame *entryFrame, InterpMode interpMode) if (interpMode == JSINTERP_NORMAL) { StackFrame *fp = regs.fp(); if (!fp->isGeneratorFrame()) { - if (!fp->prologue(cx, UseNewTypeAtEntry(cx, fp))) + if (!fp->prologue(cx)) goto error; } else { Probes::enterScript(cx, script, script->function(), fp); @@ -2361,6 +2375,9 @@ BEGIN_CASE(JSOP_FUNCALL) funScript = fun->nonLazyScript(); if (!cx->stack.pushInlineFrame(cx, regs, args, fun, funScript, initial)) goto error; + + if (newType) + regs.fp()->setUseNewType(); SET_SCRIPT(regs.fp()->script()); #ifdef JS_METHODJIT @@ -2370,7 +2387,7 @@ BEGIN_CASE(JSOP_FUNCALL) #ifdef JS_ION if (!newType && ion::IsEnabled(cx)) { ion::MethodStatus status = ion::CanEnter(cx, script, AbstractFramePtr(regs.fp()), - regs.fp()->isConstructing(), newType); + regs.fp()->isConstructing()); if (status == ion::Method_Error) goto error; if (status == ion::Method_Compiled) { @@ -2405,7 +2422,7 @@ BEGIN_CASE(JSOP_FUNCALL) } #endif - if (!regs.fp()->prologue(cx, newType)) + if (!regs.fp()->prologue(cx)) goto error; if (cx->compartment->debugMode()) { switch (ScriptDebugPrologue(cx, regs.fp())) { diff --git a/js/src/methodjit/InvokeHelpers.cpp b/js/src/methodjit/InvokeHelpers.cpp index 01677beaf98e..0c1ee81d9b36 100644 --- a/js/src/methodjit/InvokeHelpers.cpp +++ b/js/src/methodjit/InvokeHelpers.cpp @@ -940,7 +940,9 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM return js_InternalThrow(f); fp->initVarsToUndefined(); fp->scopeChain(); - if (!fp->prologue(cx, types::UseNewTypeAtEntry(cx, fp))) + if (types::UseNewTypeAtEntry(cx, fp)) + fp->setUseNewType(); + if (!fp->prologue(cx)) return js_InternalThrow(f); /* diff --git a/js/src/methodjit/StubCalls.cpp b/js/src/methodjit/StubCalls.cpp index 3f82f21e251f..496a6a59a159 100644 --- a/js/src/methodjit/StubCalls.cpp +++ b/js/src/methodjit/StubCalls.cpp @@ -808,8 +808,7 @@ stubs::TriggerIonCompile(VMFrame &f) compileStatus = ion::CanEnterAtBranch(f.cx, script, f.cx->fp(), osrPC, f.fp()->isConstructing()); } else { - compileStatus = ion::CanEnter(f.cx, script, f.cx->fp(), f.fp()->isConstructing(), - /* newType = */ false); + compileStatus = ion::CanEnter(f.cx, script, f.cx->fp(), f.fp()->isConstructing()); } if (compileStatus != ion::Method_Compiled) { diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 1ca3b328c7c1..ae947ae5ff66 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -738,6 +738,13 @@ AbstractFramePtr::hasCallObj() const return false; } inline bool +AbstractFramePtr::useNewType() const +{ + if (isStackFrame()) + return asStackFrame()->useNewType(); + return false; +} +inline bool AbstractFramePtr::isGeneratorFrame() const { if (isStackFrame()) diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 71020d99c335..d6ae424492d6 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -307,7 +307,7 @@ StackFrame::initFunctionScopeObjects(JSContext *cx) } bool -StackFrame::prologue(JSContext *cx, bool newType) +StackFrame::prologue(JSContext *cx) { RootedScript script(cx, this->script()); @@ -339,7 +339,7 @@ StackFrame::prologue(JSContext *cx, bool newType) if (isConstructing()) { RootedObject callee(cx, &this->callee()); - JSObject *obj = CreateThisForFunction(cx, callee, newType); + JSObject *obj = CreateThisForFunction(cx, callee, useNewType()); if (!obj) return false; functionThis() = ObjectValue(*obj); diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index 7241bb39739c..2f37e0909e41 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -297,6 +297,7 @@ class AbstractFramePtr inline bool hasArgsObj() const; inline ArgumentsObject &argsObj() const; inline void initArgsObj(ArgumentsObject &argsobj) const; + inline bool useNewType() const; inline bool copyRawFrameSlots(AutoValueVector *vec) const; @@ -389,10 +390,13 @@ class StackFrame HAS_PUSHED_SPS_FRAME = 0x100000, /* SPS was notified of enty */ /* Ion frame state */ - RUNNING_IN_ION = 0x200000, /* frame is running in Ion */ - CALLING_INTO_ION = 0x400000, /* frame is calling into Ion */ + RUNNING_IN_ION = 0x200000, /* frame is running in Ion */ + CALLING_INTO_ION = 0x400000, /* frame is calling into Ion */ - JIT_REVISED_STACK = 0x800000 /* sp was revised by JIT for lowered apply */ + JIT_REVISED_STACK = 0x800000, /* sp was revised by JIT for lowered apply */ + + /* Miscellaneous state. */ + USE_NEW_TYPE = 0x1000000 /* Use new type for constructed |this| object. */ }; private: @@ -489,12 +493,9 @@ class StackFrame * over-recursed) after pushing the stack frame but before 'prologue' is * called or completes fully. To simplify usage, 'epilogue' does not assume * 'prologue' has completed and handles all the intermediate state details. - * - * The 'newType' option indicates whether the constructed 'this' value (if - * there is one) should be given a new singleton type. */ - bool prologue(JSContext *cx, bool newType); + bool prologue(JSContext *cx); void epilogue(JSContext *cx); /* Subsets of 'prologue' called from jit code. */ @@ -1052,6 +1053,15 @@ class StackFrame return flags_ & HAS_ARGS_OBJ; } + void setUseNewType() { + JS_ASSERT(isConstructing()); + flags_ |= USE_NEW_TYPE; + } + bool useNewType() const { + JS_ASSERT(isConstructing()); + return flags_ & USE_NEW_TYPE; + } + /* * The method JIT call/apply optimization can erase Function.{call,apply} * invocations from the stack and push the callee frame directly. The base