Bug 604504 - Separate JSOP_EVAL code from JSOP_CALL/JSOP_APPLY code, to disentangle the core functionality of eval from the method in question. r=jorendorff
authorJeff Walden <jwalden@mit.edu>
Thu, 07 Oct 2010 13:59:56 -0700
changeset 56556 40d0afa071d68182638b9d2b0894ba7af98b16c3
parent 56555 c3b2efe4da3c737a554a118ed312bf497024111b
child 56557 1b8e50da7f24e43a9a98e6d5b0e8dbbb4b109351
push id16602
push userrsayre@mozilla.com
push dateWed, 27 Oct 2010 01:10:03 +0000
treeherdermozilla-central@7b83033bb6f8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs604504
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 604504 - Separate JSOP_EVAL code from JSOP_CALL/JSOP_APPLY code, to disentangle the core functionality of eval from the method in question. r=jorendorff
js/src/jsinterp.cpp
js/src/jsobj.cpp
js/src/jsobj.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -77,16 +77,17 @@
 #include "jsvector.h"
 #include "methodjit/MethodJIT.h"
 #include "methodjit/Logging.h"
 
 #include "jsatominlines.h"
 #include "jscntxtinlines.h"
 #include "jsinterpinlines.h"
 #include "jsobjinlines.h"
+#include "jsprobes.h"
 #include "jspropertycacheinlines.h"
 #include "jsscopeinlines.h"
 #include "jsscriptinlines.h"
 #include "jsstrinlines.h"
 #include "jsopcodeinlines.h"
 
 #if JS_HAS_XML_SUPPORT
 #include "jsxml.h"
@@ -4576,17 +4577,17 @@ BEGIN_CASE(JSOP_ENUMELEM)
     FETCH_ELEMENT_ID(obj, -1, id);
     Value rval = regs.sp[-3];
     if (!obj->setProperty(cx, id, &rval, script->strictModeCode))
         goto error;
     regs.sp -= 3;
 }
 END_CASE(JSOP_ENUMELEM)
 
-{
+{ // begin block around calling opcodes
     JSFunction *newfun;
     JSObject *callee;
     uint32 flags;
     uintN argc;
     Value *vp;
 
 BEGIN_CASE(JSOP_NEW)
 {
@@ -4621,26 +4622,47 @@ BEGIN_CASE(JSOP_NEW)
     regs.sp = vp + 1;
     CHECK_INTERRUPT_HANDLER();
     TRACE_0(NativeCallComplete);
 
   end_new:;
 }
 END_CASE(JSOP_NEW)
 
+BEGIN_CASE(JSOP_EVAL)
+{
+    argc = GET_ARGC(regs.pc);
+    vp = regs.sp - (argc + 2);
+
+    if (!IsFunctionObject(*vp, &callee))
+        goto call_using_invoke;
+
+    newfun = callee->getFunctionPrivate();
+    if (!IsBuiltinEvalFunction(newfun))
+        goto not_direct_eval;
+
+    Probes::enterJSFun(cx, newfun);
+    JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
+    Probes::exitJSFun(cx, newfun);
+    regs.sp = vp + 1;
+    if (!ok)
+        goto error;
+}
+END_CASE(JSOP_EVAL)
+
 BEGIN_CASE(JSOP_CALL)
-BEGIN_CASE(JSOP_EVAL)
 BEGIN_CASE(JSOP_APPLY)
 {
     argc = GET_ARGC(regs.pc);
     vp = regs.sp - (argc + 2);
 
     if (IsFunctionObject(*vp, &callee)) {
         newfun = callee->getFunctionPrivate();
 
+      not_direct_eval:
         /* Clear frame flags since this is not a constructor call. */
         flags = 0;
         if (newfun->isInterpreted())
       inline_call:
         {
             JSScript *newscript = newfun->u.i.script;
             if (JS_UNLIKELY(newscript->isEmpty())) {
                 vp->setUndefined();
@@ -4713,29 +4735,31 @@ BEGIN_CASE(JSOP_APPLY)
         Probes::exitJSFun(cx, newfun);
         regs.sp = vp + 1;
         if (!ok)
             goto error;
         TRACE_0(NativeCallComplete);
         goto end_call;
     }
 
+  call_using_invoke:
     bool ok;
     ok = Invoke(cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0);
     regs.sp = vp + 1;
     CHECK_INTERRUPT_HANDLER();
     if (!ok)
         goto error;
     JS_RUNTIME_METER(rt, nonInlineCalls);
     TRACE_0(NativeCallComplete);
 
   end_call:;
 }
 END_CASE(JSOP_CALL)
-}
+
+} // end block around calling opcodes
 
 BEGIN_CASE(JSOP_SETCALL)
 {
     uintN argc = GET_ARGC(regs.pc);
     Value *vp = regs.sp - argc - 2;
     JSBool ok = Invoke(cx, InvokeArgsAlreadyOnTheStack(vp, argc), 0);
     if (ok)
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_LEFTSIDE_OF_ASS);
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1087,18 +1087,19 @@ EvalCacheLookup(JSContext *cx, JSString 
         if (++count == EVAL_CACHE_CHAIN_LIMIT)
             return NULL;
         EVAL_CACHE_METER(step);
         scriptp = &script->u.nextToGC;
     }
     return NULL;
 }
 
+/* ES5 15.1.2.1. */
 static JSBool
-obj_eval(JSContext *cx, uintN argc, Value *vp)
+eval(JSContext *cx, uintN argc, Value *vp)
 {
     if (argc < 1) {
         vp->setUndefined();
         return true;
     }
 
     JSStackFrame *caller = js_GetScriptedCaller(cx, NULL);
     if (!caller) {
@@ -1248,16 +1249,26 @@ obj_eval(JSContext *cx, uintN argc, Valu
     *bucket = script;
 #ifdef CHECK_SCRIPT_OWNER
     script->owner = NULL;
 #endif
 
     return ok;
 }
 
+namespace js {
+
+bool
+IsBuiltinEvalFunction(JSFunction *fun)
+{
+    return fun->maybeNative() == eval;
+}
+
+}
+
 #if JS_HAS_OBJ_WATCHPOINT
 
 static JSBool
 obj_watch_handler(JSContext *cx, JSObject *obj, jsid id, jsval old,
                   jsval *nvp, void *closure)
 {
     JSObject *callable;
     JSSecurityCallbacks *callbacks;
@@ -3503,20 +3514,18 @@ JSObject *
 js_InitObjectClass(JSContext *cx, JSObject *obj)
 {
     JSObject *proto = js_InitClass(cx, obj, NULL, &js_ObjectClass, js_Object, 1,
                                    object_props, object_methods, NULL, object_static_methods);
     if (!proto)
         return NULL;
 
     /* ECMA (15.1.2.1) says 'eval' is a property of the global object. */
-    if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom, obj_eval, 1,
-                           JSFUN_STUB_GSOPS)) {
+    if (!js_DefineFunction(cx, obj, cx->runtime->atomState.evalAtom, eval, 1, JSFUN_STUB_GSOPS))
         return NULL;
-    }
 
     return proto;
 }
 
 static bool
 DefineStandardSlot(JSContext *cx, JSObject *obj, JSProtoKey key, JSAtom *atom,
                    const Value &v, uint32 attrs, bool &named)
 {
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -1715,17 +1715,16 @@ JSBool
 js_Object(JSContext *cx, uintN argc, js::Value *vp);
 
 
 namespace js {
 
 extern bool
 SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles);
 
-}
-
-namespace js {
-
 extern JSString *
 obj_toStringHelper(JSContext *cx, JSObject *obj);
 
+extern bool
+IsBuiltinEvalFunction(JSFunction *fun);
+
 }
 #endif /* jsobj_h___ */
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1150,18 +1150,21 @@ mjit::Compiler::generateMethod()
           BEGIN_CASE(JSOP_CALLNAME)
             prepareStubCall(Uses(0));
             masm.move(Imm32(fullAtomIndex(PC)), Registers::ArgReg1);
             stubCall(stubs::CallName);
             frame.pushSynced();
             frame.pushSynced();
           END_CASE(JSOP_CALLNAME)
 
+          BEGIN_CASE(JSOP_EVAL)
+            jsop_eval();
+          END_CASE(JSOP_EVAL)
+
           BEGIN_CASE(JSOP_CALL)
-          BEGIN_CASE(JSOP_EVAL)
           BEGIN_CASE(JSOP_APPLY)
           {
             JaegerSpew(JSpew_Insns, " --- SCRIPTED CALL --- \n");
             inlineCallHelper(GET_ARGC(PC), false);
             JaegerSpew(JSpew_Insns, " --- END SCRIPTED CALL --- \n");
           }
           END_CASE(JSOP_CALL)
 
@@ -4298,16 +4301,24 @@ mjit::Compiler::jsop_instanceof()
     frame.pushTypedPayload(JSVAL_TYPE_BOOLEAN, temp);
 
     if (firstSlow.isSet())
         firstSlow.getJump().linkTo(stubcc.masm.label(), &stubcc.masm);
     stubcc.rejoin(Changes(1));
     return true;
 }
 
+void
+mjit::Compiler::jsop_eval()
+{
+    JaegerSpew(JSpew_Insns, " --- SCRIPTED CALL --- \n");
+    inlineCallHelper(GET_ARGC(PC), false);
+    JaegerSpew(JSpew_Insns, " --- END SCRIPTED CALL --- \n");
+}
+
 /*
  * Note: This function emits tracer hooks into the OOL path. This means if
  * it is used in the middle of an in-progress slow path, the stream will be
  * hopelessly corrupted. Take care to only call this before linkExits() and
  * after rejoin()s.
  */
 void
 mjit::Compiler::jumpAndTrace(Jump j, jsbytecode *target, Jump *slow)
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -340,16 +340,17 @@ class Compiler : public BaseCompiler
     bool jsop_callprop_obj(JSAtom *atom);
     bool jsop_callprop_str(JSAtom *atom);
     bool jsop_callprop_generic(JSAtom *atom);
     bool jsop_instanceof();
     void jsop_name(JSAtom *atom);
     bool jsop_xname(JSAtom *atom);
     void enterBlock(JSObject *obj);
     void leaveBlock();
+    void jsop_eval();
 
     /* Fast arithmetic. */
     void jsop_binary(JSOp op, VoidStub stub);
     void jsop_binary_full(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
     void jsop_binary_full_simple(FrameEntry *fe, JSOp op, VoidStub stub);
     void jsop_binary_double(FrameEntry *lhs, FrameEntry *rhs, JSOp op, VoidStub stub);
     void slowLoadConstantDouble(Assembler &masm, FrameEntry *fe,
                                 FPRegisterID fpreg);