Bug 607751 - Compile JSOP_DEFCONST, JSOP_SETCONST (r=dvander)
authorBill McCloskey <wmccloskey@mozilla.com>
Thu, 11 Nov 2010 17:17:16 -0800
changeset 57795 638acb1aac5272a8315539d821b64555f5fb88c0
parent 57794 b07a1861acf2539b81bda452854497266c89555a
child 57796 6b22d236a218f14c2ceca8181e529eb9f1f9b679
push idunknown
push userunknown
push dateunknown
reviewersdvander
bugs607751
milestone2.0b8pre
Bug 607751 - Compile JSOP_DEFCONST, JSOP_SETCONST (r=dvander)
js/src/methodjit/Compiler.cpp
js/src/methodjit/StubCalls.cpp
js/src/methodjit/StubCalls.h
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1713,26 +1713,44 @@ mjit::Compiler::generateMethod()
 
             prepareStubCall(Uses(0));
             masm.move(ImmPtr(inner), Registers::ArgReg1);
             INLINE_STUBCALL(STRICT_VARIANT(stubs::DefFun));
           }
           END_CASE(JSOP_DEFFUN)
 
           BEGIN_CASE(JSOP_DEFVAR)
+          BEGIN_CASE(JSOP_DEFCONST)
           {
             uint32 index = fullAtomIndex(PC);
             JSAtom *atom = script->getAtom(index);
 
             prepareStubCall(Uses(0));
             masm.move(ImmPtr(atom), Registers::ArgReg1);
-            INLINE_STUBCALL(stubs::DefVar);
+            INLINE_STUBCALL(stubs::DefVarOrConst);
           }
           END_CASE(JSOP_DEFVAR)
 
+          BEGIN_CASE(JSOP_SETCONST)
+          {
+            uint32 index = fullAtomIndex(PC);
+            JSAtom *atom = script->getAtom(index);
+
+            if (fun) {
+                JSLocalKind localKind = fun->lookupLocal(cx, atom, NULL);
+                if (localKind != JSLOCAL_NONE)
+                    frame.syncAndForgetEverything();
+            }
+
+            prepareStubCall(Uses(1));
+            masm.move(ImmPtr(atom), Registers::ArgReg1);
+            INLINE_STUBCALL(stubs::SetConst);
+          }
+          END_CASE(JSOP_SETCONST)
+
           BEGIN_CASE(JSOP_DEFLOCALFUN_FC)
           {
             uint32 slot = GET_SLOTNO(PC);
             JSFunction *fun = script->getFunction(fullAtomIndex(&PC[SLOTNO_LEN]));
             prepareStubCall(Uses(frame.frameSlots()));
             masm.move(ImmPtr(fun), Registers::ArgReg1);
             INLINE_STUBCALL(stubs::DefLocalFun_FC);
             frame.takeReg(Registers::ReturnReg);
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -2642,50 +2642,72 @@ stubs::DelElem(VMFrame &f)
     if (!FetchElementId(f, obj, f.regs.sp[-1], id, &f.regs.sp[-1]))
         THROW();
 
     if (!obj->deleteProperty(cx, id, &f.regs.sp[-2], strict))
         THROW();
 }
 
 void JS_FASTCALL
-stubs::DefVar(VMFrame &f, JSAtom *atom)
+stubs::DefVarOrConst(VMFrame &f, JSAtom *atom)
 {
     JSContext *cx = f.cx;
     JSStackFrame *fp = f.fp();
 
     JSObject *obj = &fp->varobj(cx);
     JS_ASSERT(!obj->getOps()->defineProperty);
     uintN attrs = JSPROP_ENUMERATE;
     if (!fp->isEvalFrame())
         attrs |= JSPROP_PERMANENT;
+    if (JSOp(*f.regs.pc) == JSOP_DEFCONST)
+        attrs |= JSPROP_READONLY;
 
     /* Lookup id in order to check for redeclaration problems. */
     jsid id = ATOM_TO_JSID(atom);
     JSProperty *prop = NULL;
     JSObject *obj2;
 
-    /*
-     * Redundant declaration of a |var|, even one for a non-writable
-     * property like |undefined| in ES5, does nothing.
-     */
-    if (!obj->lookupProperty(cx, id, &obj2, &prop))
-        THROW();
+    if (JSOp(*f.regs.pc) == JSOP_DEFVAR) {
+        /*
+         * Redundant declaration of a |var|, even one for a non-writable
+         * property like |undefined| in ES5, does nothing.
+         */
+        if (!obj->lookupProperty(cx, id, &obj2, &prop))
+            THROW();
+    } else {
+        if (!CheckRedeclaration(cx, obj, id, attrs, &obj2, &prop))
+            THROW();
+    }
 
     /* Bind a variable only if it's not yet defined. */
     if (!prop) {
         if (!js_DefineNativeProperty(cx, obj, id, UndefinedValue(), PropertyStub, PropertyStub,
                                      attrs, 0, 0, &prop)) {
             THROW();
         }
         JS_ASSERT(prop);
         obj2 = obj;
     }
 }
 
+void JS_FASTCALL
+stubs::SetConst(VMFrame &f, JSAtom *atom)
+{
+    JSContext *cx = f.cx;
+    JSStackFrame *fp = f.fp();
+
+    JSObject *obj = &fp->varobj(cx);
+    const Value &ref = f.regs.sp[-1];
+    if (!obj->defineProperty(cx, ATOM_TO_JSID(atom), ref,
+                             PropertyStub, PropertyStub,
+                             JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY)) {
+        THROW();
+    }
+}
+
 JSBool JS_FASTCALL
 stubs::In(VMFrame &f)
 {
     JSContext *cx = f.cx;
 
     const Value &rref = f.regs.sp[-1];
     if (!rref.isObject()) {
         js_ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, rref, NULL);
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -149,17 +149,18 @@ template<JSBool strict> void JS_FASTCALL
 template<JSBool strict> void JS_FASTCALL IncElem(VMFrame &f);
 template<JSBool strict> void JS_FASTCALL DecElem(VMFrame &f);
 void JS_FASTCALL CallProp(VMFrame &f, JSAtom *atom);
 template <JSBool strict> void JS_FASTCALL DelProp(VMFrame &f, JSAtom *atom);
 template <JSBool strict> void JS_FASTCALL DelElem(VMFrame &f);
 void JS_FASTCALL DelName(VMFrame &f, JSAtom *atom);
 JSBool JS_FASTCALL In(VMFrame &f);
 
-void JS_FASTCALL DefVar(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL DefVarOrConst(VMFrame &f, JSAtom *atom);
+void JS_FASTCALL SetConst(VMFrame &f, JSAtom *atom);
 template<JSBool strict> void JS_FASTCALL DefFun(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL DefLocalFun(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL DefLocalFun_FC(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL RegExp(VMFrame &f, JSObject *regex);
 JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL LambdaForInit(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL LambdaForSet(VMFrame &f, JSFunction *fun);
 JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun);