Bug 1511891 part 1 - Add BindVarOperation and use it for JSOP_BINDVAR in interpreter and JITs. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 11 Jan 2019 09:10:19 +0000
changeset 510558 582477c043dd5367a4acb02ca0b5032ad6d9997d
parent 510557 fa4d4678a56854c7edf887747d25546d0f6929a9
child 510559 3523e71282fd2bbb093866671f80cd923ba189b8
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1511891
milestone66.0a1
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 1511891 part 1 - Add BindVarOperation and use it for JSOP_BINDVAR in interpreter and JITs. r=tcampbell This also adds a GetVariablesObject helper so we don't have to duplicate the logic there. Differential Revision: https://phabricator.services.mozilla.com/D13698
js/src/jit/BaselineCompiler.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
js/src/vm/EnvironmentObject-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
js/src/vm/Stack-inl.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2654,19 +2654,19 @@ bool BaselineCodeGen<Handler>::emit_JSOP
     }
 
     // Otherwise we have to use the environment chain.
   }
 
   return emitBindName(JSOP_BINDGNAME);
 }
 
-typedef JSObject* (*BindVarFn)(JSContext*, HandleObject);
+typedef JSObject* (*BindVarFn)(JSContext*, JSObject*);
 static const VMFunction BindVarInfo =
-    FunctionInfo<BindVarFn>(jit::BindVar, "BindVar");
+    FunctionInfo<BindVarFn>(BindVarOperation, "BindVarOperation");
 
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_BINDVAR() {
   frame.syncStack(0);
   masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
 
   prepareVMCall();
   pushArg(R0.scratchReg());
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -10677,19 +10677,19 @@ void CodeGenerator::visitOutOfLineUnboxF
     masm.branchTestInt32(Assembler::NotEqual, value, &bail);
     bailoutFrom(&bail, ins->snapshot());
   }
   masm.int32ValueToFloatingPoint(value, ToFloatRegister(ins->output()),
                                  ins->type());
   masm.jump(ool->rejoin());
 }
 
-typedef JSObject* (*BindVarFn)(JSContext*, HandleObject);
+typedef JSObject* (*BindVarFn)(JSContext*, JSObject*);
 static const VMFunction BindVarInfo =
-    FunctionInfo<BindVarFn>(jit::BindVar, "BindVar");
+    FunctionInfo<BindVarFn>(BindVarOperation, "BindVarOperation");
 
 void CodeGenerator::visitCallBindVar(LCallBindVar* lir) {
   pushArg(ToRegister(lir->environmentChain()));
   callVM(BindVarInfo, lir);
 }
 
 typedef bool (*GetPropertyFn)(JSContext*, HandleValue, HandlePropertyName,
                               MutableHandleValue);
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -184,40 +184,31 @@ bool CheckOverRecursedBaseline(JSContext
   if (frame->overRecursed()) {
     ReportOverRecursed(cx);
     return false;
   }
 
   return CheckOverRecursed(cx);
 }
 
-JSObject* BindVar(JSContext* cx, HandleObject envChain) {
-  JSObject* obj = envChain;
-  while (!obj->isQualifiedVarObj()) {
-    obj = obj->enclosingEnvironment();
-  }
-  MOZ_ASSERT(obj);
-  return obj;
-}
-
 bool DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs,
             HandleObject envChain) {
   // Given the ScopeChain, extract the VarObj.
-  RootedObject obj(cx, BindVar(cx, envChain));
+  RootedObject obj(cx, &GetVariablesObject(envChain));
   return DefVarOperation(cx, obj, dn, attrs);
 }
 
 bool DefLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs,
                 HandleObject envChain) {
   // Find the extensible lexical scope.
   Rooted<LexicalEnvironmentObject*> lexicalEnv(
       cx, &NearestEnclosingExtensibleLexicalEnvironment(envChain));
 
   // Find the variables object.
-  RootedObject varObj(cx, BindVar(cx, envChain));
+  RootedObject varObj(cx, &GetVariablesObject(envChain));
   return DefLexicalOperation(cx, lexicalEnv, varObj, dn, attrs);
 }
 
 bool DefGlobalLexical(JSContext* cx, HandlePropertyName dn, unsigned attrs) {
   Rooted<LexicalEnvironmentObject*> globalLexical(
       cx, &cx->global()->lexicalEnvironment());
   return DefLexicalOperation(cx, globalLexical, cx->global(), dn, attrs);
 }
@@ -933,17 +924,17 @@ bool GeneratorThrowOrReturn(JSContext* c
       js::GeneratorThrowOrReturn(cx, frame, genObj, arg, resumeKind));
   return false;
 }
 
 bool CheckGlobalOrEvalDeclarationConflicts(JSContext* cx,
                                            BaselineFrame* frame) {
   RootedScript script(cx, frame->script());
   RootedObject envChain(cx, frame->environmentChain());
-  RootedObject varObj(cx, BindVar(cx, envChain));
+  RootedObject varObj(cx, &GetVariablesObject(envChain));
 
   if (script->isForEval()) {
     // Strict eval and eval in parameter default expressions have their
     // own call objects.
     //
     // Non-strict eval may introduce 'var' bindings that conflict with
     // lexical bindings in an enclosing lexical scope.
     if (!script->bodyScope()->hasEnvironment()) {
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -916,17 +916,16 @@ MOZ_MUST_USE bool InvokeFunctionShuffleN
 
 class InterpreterStubExitFrameLayout;
 bool InvokeFromInterpreterStub(JSContext* cx,
                                InterpreterStubExitFrameLayout* frame);
 
 bool CheckOverRecursed(JSContext* cx);
 bool CheckOverRecursedBaseline(JSContext* cx, BaselineFrame* frame);
 
-JSObject* BindVar(JSContext* cx, HandleObject scopeChain);
 MOZ_MUST_USE bool DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs,
                          HandleObject scopeChain);
 MOZ_MUST_USE bool DefLexical(JSContext* cx, HandlePropertyName dn,
                              unsigned attrs, HandleObject scopeChain);
 MOZ_MUST_USE bool DefGlobalLexical(JSContext* cx, HandlePropertyName dn,
                                    unsigned attrs);
 MOZ_MUST_USE bool MutatePrototype(JSContext* cx, HandlePlainObject obj,
                                   HandleValue value);
--- a/js/src/vm/EnvironmentObject-inl.h
+++ b/js/src/vm/EnvironmentObject-inl.h
@@ -19,16 +19,26 @@ inline LexicalEnvironmentObject& Nearest
   MOZ_ASSERT(env);
   while (!IsExtensibleLexicalEnvironment(env)) {
     env = env->enclosingEnvironment();
     MOZ_ASSERT(env);
   }
   return env->as<LexicalEnvironmentObject>();
 }
 
+// Returns the innermost "qualified var object" on the environment chain.
+// See the JSObject::isQualifiedVarObj comment for more info.
+inline JSObject& GetVariablesObject(JSObject* envChain) {
+  while (!envChain->isQualifiedVarObj()) {
+    envChain = envChain->enclosingEnvironment();
+  }
+  MOZ_ASSERT(envChain);
+  return *envChain;
+}
+
 inline void EnvironmentObject::setAliasedBinding(JSContext* cx, uint32_t slot,
                                                  PropertyName* name,
                                                  const Value& v) {
   if (isSingleton()) {
     MOZ_ASSERT(name);
     AddTypePropertyId(cx, this, NameToId(name), v);
 
     // Keep track of properties which have ever been overwritten.
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -2401,17 +2401,20 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_
 
       PUSH_OBJECT(*env);
 
       static_assert(JSOP_BINDNAME_LENGTH == JSOP_BINDGNAME_LENGTH,
                     "We're sharing the END_CASE so the lengths better match");
     }
     END_CASE(JSOP_BINDNAME)
 
-    CASE(JSOP_BINDVAR) { PUSH_OBJECT(REGS.fp()->varObj()); }
+    CASE(JSOP_BINDVAR) {
+      JSObject* varObj = BindVarOperation(cx, REGS.fp()->environmentChain());
+      PUSH_OBJECT(*varObj);
+    }
     END_CASE(JSOP_BINDVAR)
 
     CASE(JSOP_BITOR) {
       MutableHandleValue lhs = REGS.stackHandleAt(-2);
       MutableHandleValue rhs = REGS.stackHandleAt(-1);
       MutableHandleValue res = REGS.stackHandleAt(-2);
       if (!BitOr(cx, lhs, rhs, res)) {
         goto error;
@@ -4578,16 +4581,22 @@ JSObject* js::LambdaArrow(JSContext* cx,
 
   MOZ_ASSERT(clone->isArrow());
   clone->setExtendedSlot(0, newTargetv);
 
   MOZ_ASSERT(fun->global() == clone->global());
   return clone;
 }
 
+JSObject* js::BindVarOperation(JSContext* cx, JSObject* envChain) {
+  // Note: BindVarOperation has an unused cx argument because the JIT callVM
+  // machinery requires this.
+  return &GetVariablesObject(envChain);
+}
+
 bool js::DefFunOperation(JSContext* cx, HandleScript script,
                          HandleObject envChain, HandleFunction fun) {
   /*
    * We define the function as a property of the variable object and not the
    * current scope chain even for the case of function expression statements
    * and functions defined by eval inside let or with blocks.
    */
   RootedObject parent(cx, envChain);
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -439,16 +439,18 @@ bool AtomicIsLockFree(JSContext* cx, Han
 template <bool strict>
 bool DeletePropertyJit(JSContext* ctx, HandleValue val, HandlePropertyName name,
                        bool* bv);
 
 template <bool strict>
 bool DeleteElementJit(JSContext* cx, HandleValue val, HandleValue index,
                       bool* bv);
 
+JSObject* BindVarOperation(JSContext* cx, JSObject* envChain);
+
 bool DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain,
                      HandleFunction funArg);
 
 bool ThrowMsgOperation(JSContext* cx, const unsigned errorNum);
 
 bool GetAndClearException(JSContext* cx, MutableHandleValue res);
 
 bool DeleteNameOperation(JSContext* cx, HandlePropertyName name,
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -31,21 +31,17 @@ inline HandleObject InterpreterFrame::en
   return HandleObject::fromMarkedLocation(&envChain_);
 }
 
 inline GlobalObject& InterpreterFrame::global() const {
   return script()->global();
 }
 
 inline JSObject& InterpreterFrame::varObj() const {
-  JSObject* obj = environmentChain();
-  while (!obj->isQualifiedVarObj()) {
-    obj = obj->enclosingEnvironment();
-  }
-  return *obj;
+  return GetVariablesObject(environmentChain());
 }
 
 inline LexicalEnvironmentObject&
 InterpreterFrame::extensibleLexicalEnvironment() const {
   return NearestEnclosingExtensibleLexicalEnvironment(environmentChain());
 }
 
 inline void InterpreterFrame::initCallFrame(InterpreterFrame* prev,