Bug 1522051 - Stop giving singleton types to call objects. r=tcampbell
authorJan de Mooij <jdemooij@mozilla.com>
Wed, 23 Jan 2019 16:55:27 +0000
changeset 515239 7259ee92e345359164baba67b035cc5d98b76ff4
parent 515238 42246dc57f621bdf3f28790f28c940d64e809b92
child 515240 2a6e063c6ea28c7703996c123c2f1bfa0b23b650
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1522051, 864218
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 1522051 - Stop giving singleton types to call objects. r=tcampbell This optimization was added in bug 864218 to optimize asm.js-like code in Ion. We're removing it now because: * WebAssembly happened and we've been focusing more on page load than on hot loop performance. * It complicates the interpreter work because JSOP_SETALIASEDVAR can't do the fast thing on singleton call objects and needs to fall back to an IC. * JSOP_SETALIASEDVAR and JSOP_INITALIASEDLEXICAL are currently marked as JOF_IC so they always get a SetProp IC allocated for them. With this patch that no longer happens. * The patch removes a lot of complexity. * It doesn't seem to affect Speedometer, Octane, other benchmarks. Note that this also removes the EnvironmentCoordinateNameCache because EnvironmentCoordinateName is now only called in debug-only or error-handling code. I renamed it to EnvironmentCoordinateNameSlow to emphasize this. Differential Revision: https://phabricator.services.mozilla.com/D17339
js/src/frontend/BytecodeEmitter.cpp
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineCompiler.h
js/src/jit/BaselineIC.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/Lowering.cpp
js/src/jit/MIR.h
js/src/jit/VMFunctions.cpp
js/src/jit/VMFunctions.h
js/src/jit/shared/LIR-shared.h
js/src/vm/BytecodeUtil.cpp
js/src/vm/Caches.h
js/src/vm/EnvironmentObject-inl.h
js/src/vm/EnvironmentObject.cpp
js/src/vm/EnvironmentObject.h
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
js/src/vm/Opcodes.h
js/src/vm/TypeSet.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -2409,30 +2409,22 @@ bool BytecodeEmitter::emitFunctionScript
   if (funbox->namedLambdaBindings()) {
     namedLambdaEmitterScope.emplace(this);
     if (!namedLambdaEmitterScope->enterNamedLambda(this, funbox)) {
       return false;
     }
   }
 
   /*
-   * Emit a prologue for run-once scripts which will deoptimize JIT code
-   * if the script ends up running multiple times via foo.caller related
-   * shenanigans.
-   *
-   * Also mark the script so that initializers created within it may be
-   * given more precise types.
+   * Mark the script so that initializers created within it may be given more
+   * precise types.
    */
   if (isRunOnceLambda()) {
     script->setTreatAsRunOnce();
     MOZ_ASSERT(!script->hasRunOnce());
-
-    if (!emit1(JSOP_RUNONCE)) {
-      return false;
-    }
   }
 
   setFunctionBodyEndPos(body->pn_pos);
   if (!emitTree(body)) {
     return false;
   }
 
   if (!updateSourceCoordNotes(body->pn_pos.end)) {
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -2879,38 +2879,16 @@ bool BaselineCodeGen<Handler>::emit_JSOP
   }
 
   frame.push(R0);
   return true;
 }
 
 template <>
 bool BaselineCompilerCodeGen::emit_JSOP_SETALIASEDVAR() {
-  jsbytecode* pc = handler.pc();
-  JSScript* outerScript = EnvironmentCoordinateFunctionScript(script, pc);
-  if (outerScript && outerScript->treatAsRunOnce()) {
-    // Type updates for this operation might need to be tracked, so treat
-    // this as a SETPROP.
-
-    // Load rhs into R1.
-    frame.syncStack(0);
-    masm.loadValue(frame.addressOfStackValue(-1), R1);
-
-    // Load and box lhs into R0.
-    getEnvironmentCoordinateObject(R2.scratchReg());
-    masm.tagValue(JSVAL_TYPE_OBJECT, R2.scratchReg(), R0);
-
-    // Call SETPROP IC.
-    if (!emitNextIC()) {
-      return false;
-    }
-
-    return true;
-  }
-
   // Keep rvalue in R0.
   frame.popRegsAndSync(1);
   Register objReg = R2.scratchReg();
 
   getEnvironmentCoordinateObject(objReg);
   Address address =
       getEnvironmentCoordinateAddressFromObject(objReg, R1.scratchReg());
   masm.guardedCallPreBarrier(address, MIRType::Value);
@@ -4719,33 +4697,16 @@ bool BaselineCodeGen<Handler>::emit_JSOP
     return false;
   }
 
   masm.bind(&done);
   frame.push(R0);
   return true;
 }
 
-typedef bool (*RunOnceScriptPrologueFn)(JSContext*, HandleScript);
-static const VMFunction RunOnceScriptPrologueInfo =
-    FunctionInfo<RunOnceScriptPrologueFn>(js::RunOnceScriptPrologue,
-                                          "RunOnceScriptPrologue");
-
-template <typename Handler>
-bool BaselineCodeGen<Handler>::emit_JSOP_RUNONCE() {
-  frame.syncStack(0);
-
-  prepareVMCall();
-
-  masm.movePtr(ImmGCPtr(script), R0.scratchReg());
-  pushArg(R0.scratchReg());
-
-  return callVM(RunOnceScriptPrologueInfo);
-}
-
 template <typename Handler>
 bool BaselineCodeGen<Handler>::emit_JSOP_REST() {
   frame.syncStack(0);
 
   if (!emitNextIC()) {
     return false;
   }
 
@@ -5643,16 +5604,17 @@ MethodStatus BaselineCompiler::emitBody(
     }
 
     switch (op) {
       // ===== NOT Yet Implemented =====
       case JSOP_FORCEINTERPRETER:
         // Intentionally not implemented.
       case JSOP_SETINTRINSIC:
         // Run-once opcode during self-hosting initialization.
+      case JSOP_UNUSED71:
       case JSOP_UNUSED151:
       case JSOP_LIMIT:
         // === !! WARNING WARNING WARNING !! ===
         // Do you really want to sacrifice performance by not implementing
         // this operation in the BaselineCompiler?
         JitSpew(JitSpew_BaselineAbort, "Unhandled op: %s", CodeName[op]);
         return Method_CantCompile;
 
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -183,17 +183,16 @@ namespace jit {
   _(JSOP_FRESHENLEXICALENV)     \
   _(JSOP_RECREATELEXICALENV)    \
   _(JSOP_DEBUGLEAVELEXICALENV)  \
   _(JSOP_PUSHVARENV)            \
   _(JSOP_POPVARENV)             \
   _(JSOP_EXCEPTION)             \
   _(JSOP_DEBUGGER)              \
   _(JSOP_ARGUMENTS)             \
-  _(JSOP_RUNONCE)               \
   _(JSOP_REST)                  \
   _(JSOP_TOASYNC)               \
   _(JSOP_TOASYNCGEN)            \
   _(JSOP_TOASYNCITER)           \
   _(JSOP_TOID)                  \
   _(JSOP_TOSTRING)              \
   _(JSOP_TABLESWITCH)           \
   _(JSOP_ITER)                  \
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -253,19 +253,17 @@ void ICEntry::trace(JSTracer* trc) {
         if (!addIC(pc, stubCompiler.getStub(&stubSpace))) {
           return nullptr;
         }
         break;
       }
       case JSOP_INITPROP:
       case JSOP_INITLOCKEDPROP:
       case JSOP_INITHIDDENPROP:
-      case JSOP_SETALIASEDVAR:
       case JSOP_INITGLEXICAL:
-      case JSOP_INITALIASEDLEXICAL:
       case JSOP_SETPROP:
       case JSOP_STRICTSETPROP:
       case JSOP_SETNAME:
       case JSOP_STRICTSETNAME:
       case JSOP_SETGNAME:
       case JSOP_STRICTSETGNAME: {
         ICSetProp_Fallback::Compiler compiler(cx);
         if (!addIC(pc, compiler.getStub(&stubSpace))) {
@@ -2994,26 +2992,19 @@ static bool DoSetPropFallback(JSContext*
   jsbytecode* pc = stub->icEntry()->pc(script);
   JSOp op = JSOp(*pc);
   FallbackICSpew(cx, stub, "SetProp(%s)", CodeName[op]);
 
   MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP ||
              op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
              op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME ||
              op == JSOP_INITPROP || op == JSOP_INITLOCKEDPROP ||
-             op == JSOP_INITHIDDENPROP || op == JSOP_SETALIASEDVAR ||
-             op == JSOP_INITALIASEDLEXICAL || op == JSOP_INITGLEXICAL);
-
-  RootedPropertyName name(cx);
-  if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
-    name = EnvironmentCoordinateName(cx->caches().envCoordinateNameCache,
-                                     script, pc);
-  } else {
-    name = script->getName(pc);
-  }
+             op == JSOP_INITHIDDENPROP || op == JSOP_INITGLEXICAL);
+
+  RootedPropertyName name(cx, script->getName(pc));
   RootedId id(cx, NameToId(name));
 
   RootedObject obj(cx, ToObjectFromStack(cx, lhs));
   if (!obj) {
     return false;
   }
   RootedShape oldShape(cx, obj->maybeShape());
   RootedObjectGroup oldGroup(cx, JSObject::getGroup(cx, obj));
@@ -3068,19 +3059,16 @@ static bool DoSetPropFallback(JSContext*
     if (!InitPropertyOperation(cx, op, obj, name, rhs)) {
       return false;
     }
   } else if (op == JSOP_SETNAME || op == JSOP_STRICTSETNAME ||
              op == JSOP_SETGNAME || op == JSOP_STRICTSETGNAME) {
     if (!SetNameOperation(cx, script, pc, obj, rhs)) {
       return false;
     }
-  } else if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
-    obj->as<EnvironmentObject>().setAliasedBinding(
-        cx, EnvironmentCoordinate(pc), name, rhs);
   } else if (op == JSOP_INITGLEXICAL) {
     RootedValue v(cx, rhs);
     LexicalEnvironmentObject* lexicalEnv;
     if (script->hasNonSyntacticScope()) {
       lexicalEnv = &NearestEnclosingExtensibleLexicalEnvironment(
           frame->environmentChain());
     } else {
       lexicalEnv = &cx->global()->lexicalEnvironment();
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -6573,39 +6573,16 @@ void CodeGenerator::visitNewCallObject(L
   TemplateObject templateObject(templateObj);
   bool initContents = ShouldInitFixedSlots(lir, templateObject);
   masm.createGCObject(objReg, tempReg, templateObject, gc::DefaultHeap,
                       ool->entry(), initContents);
 
   masm.bind(ool->rejoin());
 }
 
-typedef JSObject* (*NewSingletonCallObjectFn)(JSContext*, HandleShape);
-static const VMFunction NewSingletonCallObjectInfo =
-    FunctionInfo<NewSingletonCallObjectFn>(NewSingletonCallObject,
-                                           "NewSingletonCallObject");
-
-void CodeGenerator::visitNewSingletonCallObject(LNewSingletonCallObject* lir) {
-  Register objReg = ToRegister(lir->output());
-
-  JSObject* templateObj = lir->mir()->templateObject();
-
-  OutOfLineCode* ool;
-  ool =
-      oolCallVM(NewSingletonCallObjectInfo, lir,
-                ArgList(ImmGCPtr(templateObj->as<CallObject>().lastProperty())),
-                StoreRegisterTo(objReg));
-
-  // Objects can only be given singleton types in VM calls.  We make the call
-  // out of line to not bloat inline code, even if (naively) this seems like
-  // extra work.
-  masm.jump(ool->entry());
-  masm.bind(ool->rejoin());
-}
-
 typedef JSObject* (*NewStringObjectFn)(JSContext*, HandleString);
 static const VMFunction NewStringObjectInfo =
     FunctionInfo<NewStringObjectFn>(NewStringObject, "NewStringObject");
 
 void CodeGenerator::visitNewStringObject(LNewStringObject* lir) {
   Register input = ToRegister(lir->input());
   Register output = ToRegister(lir->output());
   Register temp = ToRegister(lir->temp());
@@ -10108,26 +10085,16 @@ void CodeGenerator::visitSetFrameArgumen
 
 void CodeGenerator::visitSetFrameArgumentV(LSetFrameArgumentV* lir) {
   const ValueOperand val = ToValue(lir, LSetFrameArgumentV::Input);
   size_t argOffset = frameSize() + JitFrameLayout::offsetOfActualArgs() +
                      (sizeof(Value) * lir->mir()->argno());
   masm.storeValue(val, Address(masm.getStackPointer(), argOffset));
 }
 
-typedef bool (*RunOnceScriptPrologueFn)(JSContext*, HandleScript);
-static const VMFunction RunOnceScriptPrologueInfo =
-    FunctionInfo<RunOnceScriptPrologueFn>(js::RunOnceScriptPrologue,
-                                          "RunOnceScriptPrologue");
-
-void CodeGenerator::visitRunOncePrologue(LRunOncePrologue* lir) {
-  pushArg(ImmGCPtr(lir->mir()->block()->info().script()));
-  callVM(RunOnceScriptPrologueInfo, lir);
-}
-
 typedef JSObject* (*InitRestParameterFn)(JSContext*, uint32_t, Value*,
                                          HandleObject, HandleObject);
 static const VMFunction InitRestParameterInfo =
     FunctionInfo<InitRestParameterFn>(InitRestParameter, "InitRestParameter");
 
 void CodeGenerator::emitRest(LInstruction* lir, Register array,
                              Register numActuals, Register temp0,
                              Register temp1, unsigned numFormals,
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -183,22 +183,16 @@ IonBuilder::IonBuilder(JSContext* analys
   if (!info->isAnalysis()) {
     script()->baselineScript()->setIonCompiledOrInlined();
   }
 }
 
 void IonBuilder::clearForBackEnd() {
   MOZ_ASSERT(!analysisContext);
   baselineFrame_ = nullptr;
-
-  // The caches below allocate data from the malloc heap. Release this before
-  // later phases of compilation to avoid leaks, as the top level IonBuilder
-  // is not explicitly destroyed. Note that builders for inner scripts are
-  // constructed on the stack and will release this memory on destruction.
-  envCoordinateNameCache.purge();
 }
 
 mozilla::GenericErrorResult<AbortReason> IonBuilder::abort(AbortReason r) {
   auto res = this->MIRGenerator::abort(r);
 #ifdef DEBUG
   JitSpew(JitSpew_IonAbort, "aborted @ %s:%d", script()->filename(),
           PCToLineNumber(script(), pc));
 #else
@@ -1985,19 +1979,16 @@ AbortReasonOr<Ok> IonBuilder::inspectOpc
 
     case JSOP_TRUE:
       pushConstant(BooleanValue(true));
       return Ok();
 
     case JSOP_ARGUMENTS:
       return jsop_arguments();
 
-    case JSOP_RUNONCE:
-      return jsop_runonce();
-
     case JSOP_REST:
       return jsop_rest();
 
     case JSOP_GETARG:
       if (info().argsObjAliasesFormals()) {
         MGetArgumentsObjectArg* getArg = MGetArgumentsObjectArg::New(
             alloc(), current->argumentsObject(), GET_ARGNO(pc));
         current->add(getArg);
@@ -2527,16 +2518,17 @@ AbortReasonOr<Ok> IonBuilder::inspectOpc
       // Do you really want to sacrifice performance by not implementing this
       // operation in the optimizing compiler?
       break;
 
     case JSOP_FORCEINTERPRETER:
       // Intentionally not implemented.
       break;
 
+    case JSOP_UNUSED71:
     case JSOP_UNUSED151:
     case JSOP_LIMIT:
       break;
   }
 
   // Track a simpler message, since the actionable abort message is a
   // static string, and the internal opcode name isn't an actionable
   // thing anyways.
@@ -5026,24 +5018,18 @@ AbortReasonOr<MInstruction*> IonBuilder:
                                                           MDefinition* env) {
   // Get a template CallObject that we'll use to generate inline object
   // creation.
   CallObject* templateObj = inspector->templateCallObject();
   MConstant* templateCst =
       MConstant::NewConstraintlessObject(alloc(), templateObj);
   current->add(templateCst);
 
-  // Allocate the object. Run-once scripts need a singleton type, so always do
-  // a VM call in such cases.
-  MNewCallObjectBase* callObj;
-  if (script()->treatAsRunOnce() || templateObj->isSingleton()) {
-    callObj = MNewSingletonCallObject::New(alloc(), templateCst);
-  } else {
-    callObj = MNewCallObject::New(alloc(), templateCst);
-  }
+  // Allocate the object.
+  MNewCallObject* callObj = MNewCallObject::New(alloc(), templateCst);
   current->add(callObj);
 
   // Initialize the object's reserved slots. No post barrier is needed here,
   // for the same reason as in createNamedLambdaObject.
   current->add(MStoreFixedSlot::New(
       alloc(), callObj, CallObject::enclosingEnvironmentSlot(), env));
   current->add(
       MStoreFixedSlot::New(alloc(), callObj, CallObject::calleeSlot(), callee));
@@ -7775,19 +7761,17 @@ AbortReasonOr<Ok> IonBuilder::getStaticN
                                             MDefinition* lexicalCheck) {
   MOZ_ASSERT(*emitted == false);
 
   jsid id = NameToId(name);
 
   bool isGlobalLexical =
       staticObject->is<LexicalEnvironmentObject>() &&
       staticObject->as<LexicalEnvironmentObject>().isGlobal();
-  MOZ_ASSERT(isGlobalLexical || staticObject->is<GlobalObject>() ||
-             staticObject->is<CallObject>() ||
-             staticObject->is<ModuleEnvironmentObject>());
+  MOZ_ASSERT(isGlobalLexical || staticObject->is<GlobalObject>());
   MOZ_ASSERT(staticObject->isSingleton());
 
   // Always emit the lexical check. This could be optimized, but is
   // currently not for simplicity's sake.
   if (lexicalCheck) {
     return Ok();
   }
 
@@ -7892,18 +7876,17 @@ bool IonBuilder::needsPostBarrier(MDefin
 
 AbortReasonOr<Ok> IonBuilder::setStaticName(JSObject* staticObject,
                                             PropertyName* name) {
   jsid id = NameToId(name);
 
   bool isGlobalLexical =
       staticObject->is<LexicalEnvironmentObject>() &&
       staticObject->as<LexicalEnvironmentObject>().isGlobal();
-  MOZ_ASSERT(isGlobalLexical || staticObject->is<GlobalObject>() ||
-             staticObject->is<CallObject>());
+  MOZ_ASSERT(isGlobalLexical || staticObject->is<GlobalObject>());
 
   MDefinition* value = current->peek(-1);
 
   TypeSet::ObjectKey* staticKey = TypeSet::ObjectKey::get(staticObject);
   if (staticKey->unknownProperties()) {
     return jsop_setprop(name);
   }
 
@@ -8084,31 +8067,23 @@ AbortReasonOr<Ok> IonBuilder::jsop_intri
 AbortReasonOr<Ok> IonBuilder::jsop_getimport(PropertyName* name) {
   ModuleEnvironmentObject* env = GetModuleEnvironmentForScript(script());
   MOZ_ASSERT(env);
 
   Shape* shape;
   ModuleEnvironmentObject* targetEnv;
   MOZ_ALWAYS_TRUE(env->lookupImport(NameToId(name), &targetEnv, &shape));
 
-  PropertyName* localName =
-      JSID_TO_STRING(shape->propid())->asAtom().asPropertyName();
-  bool emitted = false;
-  MOZ_TRY(getStaticName(&emitted, targetEnv, localName));
-
-  if (!emitted) {
-    // This can happen if we don't have type information.
-    TypeSet::ObjectKey* staticKey = TypeSet::ObjectKey::get(targetEnv);
-    TemporaryTypeSet* types = bytecodeTypes(pc);
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(
-        analysisContext, alloc(), constraints(), staticKey, name, types,
-        /* updateObserved = */ true);
-
-    MOZ_TRY(loadStaticSlot(targetEnv, barrier, types, shape->slot()));
-  }
+  TypeSet::ObjectKey* staticKey = TypeSet::ObjectKey::get(targetEnv);
+  TemporaryTypeSet* types = bytecodeTypes(pc);
+  BarrierKind barrier = PropertyReadNeedsTypeBarrier(
+      analysisContext, alloc(), constraints(), staticKey, name, types,
+      /* updateObserved = */ true);
+
+  MOZ_TRY(loadStaticSlot(targetEnv, barrier, types, shape->slot()));
 
   // In the rare case where this import hasn't been initialized already (we
   // have an import cycle where modules reference each other's imports), emit
   // a check.
   if (targetEnv->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL)) {
     MDefinition* checked;
     MOZ_TRY_VAR(checked, addLexicalCheck(current->pop()));
     current->push(checked);
@@ -10093,22 +10068,16 @@ uint32_t IonBuilder::getUnboxedOffset(Te
       trackOptimizationOutcome(TrackedOutcome::InconsistentFieldType);
       return UINT32_MAX;
     }
   }
 
   return offset;
 }
 
-AbortReasonOr<Ok> IonBuilder::jsop_runonce() {
-  MRunOncePrologue* ins = MRunOncePrologue::New(alloc());
-  current->add(ins);
-  return resumeAfter(ins);
-}
-
 AbortReasonOr<Ok> IonBuilder::jsop_not() {
   MDefinition* value = current->pop();
 
   MNot* ins = MNot::New(alloc(), value, constraints());
   current->add(ins);
   current->push(ins);
   return Ok();
 }
@@ -13084,70 +13053,16 @@ MDefinition* IonBuilder::walkEnvironment
     MInstruction* ins = MEnclosingEnvironment::New(alloc(), env);
     current->add(ins);
     env = ins;
   }
 
   return env;
 }
 
-bool IonBuilder::hasStaticEnvironmentObject(JSObject** pcall) {
-  JSScript* outerScript = EnvironmentCoordinateFunctionScript(script(), pc);
-  if (!outerScript || !outerScript->treatAsRunOnce()) {
-    return false;
-  }
-
-  TypeSet::ObjectKey* funKey =
-      TypeSet::ObjectKey::get(outerScript->functionNonDelazifying());
-  if (funKey->hasFlags(constraints(), OBJECT_FLAG_RUNONCE_INVALIDATED)) {
-    return false;
-  }
-
-  // The script this aliased var operation is accessing will run only once,
-  // so there will be only one call object and the aliased var access can be
-  // compiled in the same manner as a global access. We still need to find
-  // the call object though.
-
-  // Look for the call object on the current script's function's env chain.
-  // If the current script is inner to the outer script and the function has
-  // singleton type then it should show up here.
-
-  MDefinition* envDef = current->getSlot(info().environmentChainSlot());
-  envDef->setImplicitlyUsedUnchecked();
-
-  JSObject* environment = script()->functionNonDelazifying()->environment();
-  while (environment && !environment->is<GlobalObject>()) {
-    if (environment->is<CallObject>() &&
-        environment->as<CallObject>().callee().nonLazyScript() == outerScript) {
-      MOZ_ASSERT(environment->isSingleton());
-      *pcall = environment;
-      return true;
-    }
-    environment = environment->enclosingEnvironment();
-  }
-
-  // Look for the call object on the current frame, if we are compiling the
-  // outer script itself. Don't do this if we are at entry to the outer
-  // script, as the call object we see will not be the real one --- after
-  // entering the Ion code a different call object will be created.
-
-  if (script() == outerScript && baselineFrame_ && info().osrPc()) {
-    JSObject* singletonScope = baselineFrame_->singletonEnvChain;
-    if (singletonScope && singletonScope->is<CallObject>() &&
-        singletonScope->as<CallObject>().callee().nonLazyScript() ==
-            outerScript) {
-      MOZ_ASSERT(singletonScope->isSingleton());
-      *pcall = singletonScope;
-      return true;
-    }
-  }
-
-  return true;
-}
-
 MDefinition* IonBuilder::getAliasedVar(EnvironmentCoordinate ec) {
   MDefinition* obj = walkEnvironmentChain(ec.hops());
 
   Shape* shape = EnvironmentCoordinateToEnvironmentShape(script(), pc);
 
   MInstruction* load;
   if (shape->numFixedSlots() <= ec.slot()) {
     MInstruction* slots = MSlots::New(alloc(), obj);
@@ -13158,67 +13073,28 @@ MDefinition* IonBuilder::getAliasedVar(E
     load = MLoadFixedSlot::New(alloc(), obj, ec.slot());
   }
 
   current->add(load);
   return load;
 }
 
 AbortReasonOr<Ok> IonBuilder::jsop_getaliasedvar(EnvironmentCoordinate ec) {
-  JSObject* call = nullptr;
-  if (hasStaticEnvironmentObject(&call) && call) {
-    PropertyName* name =
-        EnvironmentCoordinateName(envCoordinateNameCache, script(), pc);
-    bool emitted = false;
-    MOZ_TRY(getStaticName(&emitted, call, name, takeLexicalCheck()));
-    if (emitted) {
-      return Ok();
-    }
-  }
-
   // See jsop_checkaliasedlexical.
   MDefinition* load = takeLexicalCheck();
   if (!load) {
     load = getAliasedVar(ec);
   }
   current->push(load);
 
   TemporaryTypeSet* types = bytecodeTypes(pc);
   return pushTypeBarrier(load, types, BarrierKind::TypeSet);
 }
 
 AbortReasonOr<Ok> IonBuilder::jsop_setaliasedvar(EnvironmentCoordinate ec) {
-  JSObject* call = nullptr;
-  if (hasStaticEnvironmentObject(&call)) {
-    uint32_t depth = current->stackDepth() + 1;
-    if (depth > current->nslots()) {
-      if (!current->increaseSlots(depth - current->nslots())) {
-        return abort(AbortReason::Alloc);
-      }
-    }
-    MDefinition* value = current->pop();
-    PropertyName* name =
-        EnvironmentCoordinateName(envCoordinateNameCache, script(), pc);
-
-    if (call) {
-      // Push the object on the stack to match the bound object expected in
-      // the global and property set cases.
-      pushConstant(ObjectValue(*call));
-      current->push(value);
-      return setStaticName(call, name);
-    }
-
-    // The call object has type information we need to respect but we
-    // couldn't find it. Just do a normal property assign.
-    MDefinition* obj = walkEnvironmentChain(ec.hops());
-    current->push(obj);
-    current->push(value);
-    return jsop_setprop(name);
-  }
-
   MDefinition* rval = current->peek(-1);
   MDefinition* obj = walkEnvironmentChain(ec.hops());
 
   Shape* shape = EnvironmentCoordinateToEnvironmentShape(script(), pc);
 
   if (needsPostBarrier(rval)) {
     current->add(MPostWriteBarrier::New(alloc(), obj, rval));
   }
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -230,17 +230,16 @@ class IonBuilder : public MIRGenerator,
                                        BailoutKind bailoutKind);
   MInstruction* addSharedTypedArrayGuard(MDefinition* obj);
 
   MInstruction* addGuardReceiverPolymorphic(
       MDefinition* obj, const BaselineInspector::ReceiverVector& receivers);
 
   bool invalidatedIdempotentCache();
 
-  bool hasStaticEnvironmentObject(JSObject** pcall);
   AbortReasonOr<Ok> loadSlot(MDefinition* obj, size_t slot, size_t nfixed,
                              MIRType rvalType, BarrierKind barrier,
                              TemporaryTypeSet* types);
   AbortReasonOr<Ok> loadSlot(MDefinition* obj, Shape* shape, MIRType rvalType,
                              BarrierKind barrier, TemporaryTypeSet* types);
   AbortReasonOr<Ok> storeSlot(MDefinition* obj, size_t slot, size_t nfixed,
                               MDefinition* value, bool needsBarrier,
                               MIRType slotType = MIRType::None);
@@ -583,17 +582,16 @@ class IonBuilder : public MIRGenerator,
       MDefinition* index, MDefinition* value, bool writeHole, bool* emitted);
   AbortReasonOr<Ok> jsop_setelem_typed(ScalarTypeDescr::Type arrayType,
                                        MDefinition* object, MDefinition* index,
                                        MDefinition* value);
   AbortReasonOr<Ok> jsop_length();
   bool jsop_length_fastPath();
   AbortReasonOr<Ok> jsop_arguments();
   AbortReasonOr<Ok> jsop_arguments_getelem();
-  AbortReasonOr<Ok> jsop_runonce();
   AbortReasonOr<Ok> jsop_rest();
   AbortReasonOr<Ok> jsop_not();
   AbortReasonOr<Ok> jsop_envcallee();
   AbortReasonOr<Ok> jsop_superbase();
   AbortReasonOr<Ok> jsop_getprop_super(PropertyName* name);
   AbortReasonOr<Ok> jsop_getelem_super();
   AbortReasonOr<Ok> jsop_getprop(PropertyName* name);
   AbortReasonOr<Ok> jsop_setprop(PropertyName* name);
@@ -1026,18 +1024,16 @@ class IonBuilder : public MIRGenerator,
   CompilerConstraintList* constraints_;
 
   TemporaryTypeSet* thisTypes;
   TemporaryTypeSet* argTypes;
   TemporaryTypeSet* typeArray;
   uint32_t typeArrayHint;
   uint32_t* bytecodeTypeMap;
 
-  EnvironmentCoordinateNameCache envCoordinateNameCache;
-
   jsbytecode* pc;
   MBasicBlock* current;
   uint32_t loopDepth_;
   Vector<MBasicBlock*, 0, JitAllocPolicy> blockWorklist;
   const CFGBlock* cfgCurrent;
   const ControlFlowGraph* cfg;
 
   Vector<BytecodeSite*, 0, JitAllocPolicy> trackedOptimizationSites_;
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -221,22 +221,16 @@ void LIRGenerator::visitNewNamedLambdaOb
 }
 
 void LIRGenerator::visitNewCallObject(MNewCallObject* ins) {
   LNewCallObject* lir = new (alloc()) LNewCallObject(temp());
   define(lir, ins);
   assignSafepoint(lir, ins);
 }
 
-void LIRGenerator::visitNewSingletonCallObject(MNewSingletonCallObject* ins) {
-  LNewSingletonCallObject* lir = new (alloc()) LNewSingletonCallObject(temp());
-  define(lir, ins);
-  assignSafepoint(lir, ins);
-}
-
 void LIRGenerator::visitNewDerivedTypedObject(MNewDerivedTypedObject* ins) {
   LNewDerivedTypedObject* lir = new (alloc()) LNewDerivedTypedObject(
       useRegisterAtStart(ins->type()), useRegisterAtStart(ins->owner()),
       useRegisterAtStart(ins->offset()));
   defineReturn(lir, ins);
   assignSafepoint(lir, ins);
 }
 
@@ -4031,22 +4025,16 @@ void LIRGenerator::visitSetFrameArgument
     add(lir, ins);
   } else {
     LSetFrameArgumentT* lir =
         new (alloc()) LSetFrameArgumentT(useRegister(input));
     add(lir, ins);
   }
 }
 
-void LIRGenerator::visitRunOncePrologue(MRunOncePrologue* ins) {
-  LRunOncePrologue* lir = new (alloc()) LRunOncePrologue;
-  add(lir, ins);
-  assignSafepoint(lir, ins);
-}
-
 void LIRGenerator::visitRest(MRest* ins) {
   MOZ_ASSERT(ins->numActuals()->type() == MIRType::Int32);
 
   LRest* lir = new (alloc()) LRest(
       useFixedAtStart(ins->numActuals(), CallTempReg0), tempFixed(CallTempReg1),
       tempFixed(CallTempReg2), tempFixed(CallTempReg3));
   defineReturn(lir, ins);
   assignSafepoint(lir, ins);
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -3569,27 +3569,16 @@ class MSetArgumentsObjectArg
 
   size_t argno() const { return argno_; }
 
   AliasSet getAliasSet() const override {
     return AliasSet::Store(AliasSet::Any);
   }
 };
 
-class MRunOncePrologue : public MNullaryInstruction {
- protected:
-  MRunOncePrologue() : MNullaryInstruction(classOpcode) { setGuard(); }
-
- public:
-  INSTRUCTION_HEADER(RunOncePrologue)
-  TRIVIAL_NEW_WRAPPERS
-
-  bool possiblyCalls() const override { return true; }
-};
-
 // Given a MIRType::Value A and a MIRType::Object B:
 // If the Value may be safely unboxed to an Object, return Object(A).
 // Otherwise, return B.
 // Used to implement return behavior for inlined constructors.
 class MReturnFromCtor : public MBinaryInstruction,
                         public MixPolicy<BoxPolicy<0>, ObjectPolicy<1>>::Data {
   MReturnFromCtor(MDefinition* value, MDefinition* object)
       : MBinaryInstruction(classOpcode, value, object) {
@@ -10397,55 +10386,38 @@ class MNewNamedLambdaObject : public MNu
 
   LexicalEnvironmentObject* templateObj() { return templateObj_; }
   AliasSet getAliasSet() const override { return AliasSet::None(); }
   bool appendRoots(MRootList& roots) const override {
     return roots.append(templateObj_);
   }
 };
 
-class MNewCallObjectBase : public MUnaryInstruction,
-                           public SingleObjectPolicy::Data {
- protected:
-  MNewCallObjectBase(Opcode op, MConstant* templateObj)
-      : MUnaryInstruction(op, templateObj) {
-    setResultType(MIRType::Object);
-  }
-
- public:
-  CallObject* templateObject() const {
-    return &getOperand(0)->toConstant()->toObject().as<CallObject>();
-  }
-  AliasSet getAliasSet() const override { return AliasSet::None(); }
-};
-
-class MNewCallObject : public MNewCallObjectBase {
+class MNewCallObject : public MUnaryInstruction,
+                       public SingleObjectPolicy::Data {
  public:
   INSTRUCTION_HEADER(NewCallObject)
   TRIVIAL_NEW_WRAPPERS
 
   explicit MNewCallObject(MConstant* templateObj)
-      : MNewCallObjectBase(classOpcode, templateObj) {
+      : MUnaryInstruction(classOpcode, templateObj) {
     MOZ_ASSERT(!templateObject()->isSingleton());
-  }
+    setResultType(MIRType::Object);
+  }
+
+  CallObject* templateObject() const {
+    return &getOperand(0)->toConstant()->toObject().as<CallObject>();
+  }
+  AliasSet getAliasSet() const override { return AliasSet::None(); }
 
   MOZ_MUST_USE bool writeRecoverData(
       CompactBufferWriter& writer) const override;
   bool canRecoverOnBailout() const override { return true; }
 };
 
-class MNewSingletonCallObject : public MNewCallObjectBase {
- public:
-  INSTRUCTION_HEADER(NewSingletonCallObject)
-  TRIVIAL_NEW_WRAPPERS
-
-  explicit MNewSingletonCallObject(MConstant* templateObj)
-      : MNewCallObjectBase(classOpcode, templateObj) {}
-};
-
 class MNewStringObject : public MUnaryInstruction,
                          public ConvertToStringPolicy<0>::Data {
   CompilerObject templateObj_;
 
   MNewStringObject(MDefinition* input, JSObject* templateObj)
       : MUnaryInstruction(classOpcode, input), templateObj_(templateObj) {
     setResultType(MIRType::Object);
   }
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -511,32 +511,16 @@ JSObject* NewCallObject(JSContext* cx, H
   // the call object tenured, so barrier as needed before re-entering.
   if (!IsInsideNursery(obj)) {
     cx->runtime()->gc.storeBuffer().putWholeCell(obj);
   }
 
   return obj;
 }
 
-JSObject* NewSingletonCallObject(JSContext* cx, HandleShape shape) {
-  JSObject* obj = CallObject::createSingleton(cx, shape);
-  if (!obj) {
-    return nullptr;
-  }
-
-  // The JIT creates call objects in the nursery, so elides barriers for
-  // the initializing writes. The interpreter, however, may have allocated
-  // the call object tenured, so barrier as needed before re-entering.
-  MOZ_ASSERT(!IsInsideNursery(obj),
-             "singletons are created in the tenured heap");
-  cx->runtime()->gc.storeBuffer().putWholeCell(obj);
-
-  return obj;
-}
-
 JSObject* NewStringObject(JSContext* cx, HandleString str) {
   return StringObject::create(cx, str);
 }
 
 bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out) {
   RootedId id(cx);
   return ToPropertyKey(cx, key, &id) && HasProperty(cx, obj, id, out);
 }
--- a/js/src/jit/VMFunctions.h
+++ b/js/src/jit/VMFunctions.h
@@ -971,17 +971,16 @@ MOZ_MUST_USE bool SetProperty(JSContext*
                               HandlePropertyName name, HandleValue value,
                               bool strict, jsbytecode* pc);
 
 MOZ_MUST_USE bool InterruptCheck(JSContext* cx);
 
 void* MallocWrapper(JS::Zone* zone, size_t nbytes);
 JSObject* NewCallObject(JSContext* cx, HandleShape shape,
                         HandleObjectGroup group);
-JSObject* NewSingletonCallObject(JSContext* cx, HandleShape shape);
 JSObject* NewStringObject(JSContext* cx, HandleString str);
 
 bool OperatorIn(JSContext* cx, HandleValue key, HandleObject obj, bool* out);
 bool OperatorInI(JSContext* cx, uint32_t index, HandleObject obj, bool* out);
 
 MOZ_MUST_USE bool GetIntrinsicValue(JSContext* cx, HandlePropertyName name,
                                     MutableHandleValue rval);
 
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -454,33 +454,16 @@ class LNewCallObject : public LInstructi
     setTemp(0, temp);
   }
 
   const LDefinition* temp() { return getTemp(0); }
 
   MNewCallObject* mir() const { return mir_->toNewCallObject(); }
 };
 
-// Performs a callVM to allocate a new CallObject with singleton type.
-class LNewSingletonCallObject : public LInstructionHelper<1, 0, 1> {
- public:
-  LIR_HEADER(NewSingletonCallObject)
-
-  explicit LNewSingletonCallObject(const LDefinition& temp)
-      : LInstructionHelper(classOpcode) {
-    setTemp(0, temp);
-  }
-
-  const LDefinition* temp() { return getTemp(0); }
-
-  MNewSingletonCallObject* mir() const {
-    return mir_->toNewSingletonCallObject();
-  }
-};
-
 class LNewDerivedTypedObject : public LCallInstructionHelper<1, 3, 0> {
  public:
   LIR_HEADER(NewDerivedTypedObject);
 
   LNewDerivedTypedObject(const LAllocation& type, const LAllocation& owner,
                          const LAllocation& offset)
       : LCallInstructionHelper(classOpcode) {
     setOperand(0, type);
@@ -5626,25 +5609,16 @@ class LSetFrameArgumentV : public LInstr
     setBoxOperand(Input, input);
   }
 
   static const size_t Input = 0;
 
   MSetFrameArgument* mir() const { return mir_->toSetFrameArgument(); }
 };
 
-class LRunOncePrologue : public LCallInstructionHelper<0, 0, 0> {
- public:
-  LIR_HEADER(RunOncePrologue)
-
-  MRunOncePrologue* mir() const { return mir_->toRunOncePrologue(); }
-
-  LRunOncePrologue() : LCallInstructionHelper(classOpcode) {}
-};
-
 // Create the rest parameter.
 class LRest : public LCallInstructionHelper<1, 1, 3> {
  public:
   LIR_HEADER(Rest)
 
   LRest(const LAllocation& numActuals, const LDefinition& temp1,
         const LDefinition& temp2, const LDefinition& temp3)
       : LCallInstructionHelper(classOpcode) {
--- a/js/src/vm/BytecodeUtil.cpp
+++ b/js/src/vm/BytecodeUtil.cpp
@@ -1437,18 +1437,17 @@ static unsigned Disassemble1(JSContext* 
       }
       if (!sp->jsprintf(" %s", bytes.get())) {
         return 0;
       }
       break;
     }
 
     case JOF_ENVCOORD: {
-      RootedValue v(cx, StringValue(EnvironmentCoordinateName(
-                            cx->caches().envCoordinateNameCache, script, pc)));
+      RootedValue v(cx, StringValue(EnvironmentCoordinateNameSlow(script, pc)));
       UniqueChars bytes = ToDisassemblySource(cx, v);
       if (!bytes) {
         return 0;
       }
       EnvironmentCoordinate ec(pc);
       if (!sp->jsprintf(" %s (hops = %u, slot = %u)", bytes.get(), ec.hops(),
                         ec.slot())) {
         return 0;
@@ -1765,18 +1764,17 @@ bool ExpressionDecompiler::decompilePC(j
       return write(atom);
     }
     case JSOP_GETLOCAL: {
       JSAtom* atom = FrameSlotName(script, pc);
       MOZ_ASSERT(atom);
       return write(atom);
     }
     case JSOP_GETALIASEDVAR: {
-      JSAtom* atom = EnvironmentCoordinateName(
-          cx->caches().envCoordinateNameCache, script, pc);
+      JSAtom* atom = EnvironmentCoordinateNameSlow(script, pc);
       MOZ_ASSERT(atom);
       return write(atom);
     }
 
     case JSOP_DELPROP:
     case JSOP_STRICTDELPROP:
     case JSOP_LENGTH:
     case JSOP_GETPROP:
--- a/js/src/vm/Caches.h
+++ b/js/src/vm/Caches.h
@@ -38,31 +38,16 @@ struct GSNCache {
   jsbytecode* code;
   Map map;
 
   GSNCache() : code(nullptr) {}
 
   void purge();
 };
 
-/*
- * EnvironmentCoordinateName cache to avoid O(n^2) growth in finding the name
- * associated with a given aliasedvar operation.
- */
-struct EnvironmentCoordinateNameCache {
-  typedef HashMap<uint32_t, jsid, DefaultHasher<uint32_t>, SystemAllocPolicy>
-      Map;
-
-  Shape* shape;
-  Map map;
-
-  EnvironmentCoordinateNameCache() : shape(nullptr) {}
-  void purge();
-};
-
 struct EvalCacheEntry {
   JSLinearString* str;
   JSScript* script;
   JSScript* callerScript;
   jsbytecode* pc;
 
   // We sweep this cache before a nursery collection to remove entries with
   // string keys in the nursery.
@@ -234,17 +219,16 @@ class NewObjectCache {
     dst->initGroup(src->group());
     dst->initShape(src->shape());
   }
 };
 
 class RuntimeCaches {
  public:
   js::GSNCache gsnCache;
-  js::EnvironmentCoordinateNameCache envCoordinateNameCache;
   js::NewObjectCache newObjectCache;
   js::UncompressedSourceCache uncompressedSourceCache;
   js::EvalCache evalCache;
 
   void purgeForMinorGC(JSRuntime* rt) {
     newObjectCache.clearNurseryObjects(rt);
     evalCache.sweep();
   }
@@ -252,16 +236,15 @@ class RuntimeCaches {
   void purgeForCompaction() {
     newObjectCache.purge();
     evalCache.clear();
   }
 
   void purge() {
     purgeForCompaction();
     gsnCache.purge();
-    envCoordinateNameCache.purge();
     uncompressedSourceCache.purge();
   }
 };
 
 }  // namespace js
 
 #endif /* vm_Caches_h */
--- a/js/src/vm/EnvironmentObject-inl.h
+++ b/js/src/vm/EnvironmentObject-inl.h
@@ -30,44 +30,32 @@ inline JSObject& GetVariablesObject(JSOb
   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.
-    if (!getSlot(slot).isUndefined()) {
-      Shape* shape = lookup(cx, name);
-      shape->setOverwritten();
-    }
-  }
-
+  MOZ_ASSERT(!isSingleton());
   setSlot(slot, v);
 }
 
 inline void EnvironmentObject::setAliasedBinding(JSContext* cx,
                                                  EnvironmentCoordinate ec,
-                                                 PropertyName* name,
                                                  const Value& v) {
-  setAliasedBinding(cx, ec.slot(), name, v);
+  setAliasedBinding(cx, ec.slot(), v);
 }
 
 inline void EnvironmentObject::setAliasedBinding(JSContext* cx,
                                                  const BindingIter& bi,
                                                  const Value& v) {
   MOZ_ASSERT(bi.location().kind() == BindingLocation::Kind::Environment);
-  setAliasedBinding(cx, bi.location().slot(), bi.name()->asPropertyName(), v);
+  setAliasedBinding(cx, bi.location().slot(), v);
 }
 
 inline void CallObject::setAliasedFormalFromArguments(JSContext* cx,
                                                       const Value& argsValue,
                                                       jsid id, const Value& v) {
   setSlot(ArgumentsObject::SlotFromMagicScopeSlotValue(argsValue), v);
   if (isSingleton()) {
     AddTypePropertyId(cx, this, id, v);
--- a/js/src/vm/EnvironmentObject.cpp
+++ b/js/src/vm/EnvironmentObject.cpp
@@ -45,119 +45,51 @@ Shape* js::EnvironmentCoordinateToEnviro
       }
       hops--;
     }
     si++;
   }
   return si.environmentShape();
 }
 
-static const uint32_t ENV_COORDINATE_NAME_THRESHOLD = 20;
-
-void EnvironmentCoordinateNameCache::purge() {
-  shape = nullptr;
-  map.clearAndCompact();
-}
-
-PropertyName* js::EnvironmentCoordinateName(
-    EnvironmentCoordinateNameCache& cache, JSScript* script, jsbytecode* pc) {
+PropertyName* js::EnvironmentCoordinateNameSlow(JSScript* script,
+                                                jsbytecode* pc) {
   Shape* shape = EnvironmentCoordinateToEnvironmentShape(script, pc);
-  if (shape != cache.shape && shape->slot() >= ENV_COORDINATE_NAME_THRESHOLD) {
-    cache.purge();
-    if (cache.map.reserve(shape->slot())) {
-      cache.shape = shape;
-      Shape::Range<NoGC> r(shape);
-      while (!r.empty()) {
-        cache.map.putNewInfallible(r.front().slot(), r.front().propid());
-        r.popFront();
-      }
-    }
+  EnvironmentCoordinate ec(pc);
+
+  Shape::Range<NoGC> r(shape);
+  while (r.front().slot() != ec.slot()) {
+    r.popFront();
   }
-
-  jsid id;
-  EnvironmentCoordinate ec(pc);
-  if (shape == cache.shape) {
-    EnvironmentCoordinateNameCache::Map::Ptr p = cache.map.lookup(ec.slot());
-    id = p->value();
-  } else {
-    Shape::Range<NoGC> r(shape);
-    while (r.front().slot() != ec.slot()) {
-      r.popFront();
-    }
-    id = r.front().propidRaw();
-  }
+  jsid id = r.front().propidRaw();
 
   /* Beware nameless destructuring formal. */
   if (!JSID_IS_ATOM(id)) {
     return script->runtimeFromAnyThread()->commonNames->empty;
   }
   return JSID_TO_ATOM(id)->asPropertyName();
 }
 
-JSScript* js::EnvironmentCoordinateFunctionScript(JSScript* script,
-                                                  jsbytecode* pc) {
-  MOZ_ASSERT(JOF_OPTYPE(JSOp(*pc)) == JOF_ENVCOORD);
-  ScopeIter si(script->innermostScope(pc));
-  uint32_t hops = EnvironmentCoordinate(pc).hops();
-  while (true) {
-    if (si.hasSyntacticEnvironment()) {
-      if (!hops) {
-        break;
-      }
-      hops--;
-    }
-    si++;
-  }
-  if (si.kind() != ScopeKind::Function) {
-    return nullptr;
-  }
-  return si.scope()->as<FunctionScope>().script();
-}
-
 /*****************************************************************************/
 
 CallObject* CallObject::create(JSContext* cx, HandleShape shape,
                                HandleObjectGroup group) {
-  MOZ_ASSERT(!group->singleton(),
-             "passed a singleton group to create() (use createSingleton() "
-             "instead)");
+  MOZ_ASSERT(!group->singleton());
 
   gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
   MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
   kind = gc::GetBackgroundAllocKind(kind);
 
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(
       cx, obj, NativeObject::create(cx, kind, gc::DefaultHeap, shape, group));
 
   return &obj->as<CallObject>();
 }
 
-CallObject* CallObject::createSingleton(JSContext* cx, HandleShape shape) {
-  gc::AllocKind kind = gc::GetGCObjectKind(shape->numFixedSlots());
-  MOZ_ASSERT(CanBeFinalizedInBackground(kind, &CallObject::class_));
-  kind = gc::GetBackgroundAllocKind(kind);
-
-  RootedObjectGroup group(
-      cx, ObjectGroup::lazySingletonGroup(cx, /* oldGroup = */ nullptr, &class_,
-                                          TaggedProto(nullptr)));
-  if (!group) {
-    return nullptr;
-  }
-
-  JSObject* obj;
-  JS_TRY_VAR_OR_RETURN_NULL(
-      cx, obj, NativeObject::create(cx, kind, gc::TenuredHeap, shape, group));
-
-  MOZ_ASSERT(obj->isSingleton(),
-             "group created inline above must be a singleton");
-
-  return &obj->as<CallObject>();
-}
-
 /*
  * Create a CallObject for a JSScript that is not initialized to any particular
  * callsite. This object can either be initialized (with an enclosing scope and
  * callee) or used as a template for jit compilation.
  */
 CallObject* CallObject::createTemplateObject(JSContext* cx, HandleScript script,
                                              HandleObject enclosing,
                                              gc::InitialHeap heap) {
@@ -201,34 +133,25 @@ CallObject* CallObject::createTemplateOb
  * Construct a call object for the given bindings.  If this is a call object
  * for a function invocation, callee should be the function being called.
  * Otherwise it must be a call object for eval of strict mode code, and callee
  * must be null.
  */
 CallObject* CallObject::create(JSContext* cx, HandleFunction callee,
                                HandleObject enclosing) {
   RootedScript script(cx, callee->nonLazyScript());
-  gc::InitialHeap heap =
-      script->treatAsRunOnce() ? gc::TenuredHeap : gc::DefaultHeap;
+  gc::InitialHeap heap = gc::DefaultHeap;
   CallObject* callobj =
       CallObject::createTemplateObject(cx, script, enclosing, heap);
   if (!callobj) {
     return nullptr;
   }
 
   callobj->initFixedSlot(CALLEE_SLOT, ObjectValue(*callee));
 
-  if (script->treatAsRunOnce()) {
-    Rooted<CallObject*> ncallobj(cx, callobj);
-    if (!JSObject::setSingleton(cx, ncallobj)) {
-      return nullptr;
-    }
-    return ncallobj;
-  }
-
   return callobj;
 }
 
 CallObject* CallObject::create(JSContext* cx, AbstractFramePtr frame) {
   MOZ_ASSERT(frame.isFunctionFrame());
   cx->check(frame);
 
   RootedObject envChain(cx, frame.environmentChain());
@@ -345,18 +268,17 @@ const Class CallObject::class_ = {
     MOZ_ASSERT_IF(
         frame.callee()->needsCallObject(),
         &frame.environmentChain()->as<CallObject>().callee() == frame.callee());
   }
 #endif
 
   RootedScript script(cx, frame.script());
   RootedObject envChain(cx, frame.environmentChain());
-  gc::InitialHeap heap =
-      script->treatAsRunOnce() ? gc::TenuredHeap : gc::DefaultHeap;
+  gc::InitialHeap heap = gc::DefaultHeap;
   RootedShape shape(cx, scope->environmentShape());
   VarEnvironmentObject* env = create(cx, shape, envChain, heap);
   if (!env) {
     return nullptr;
   }
   env->initScope(scope);
   return env;
 }
@@ -445,19 +367,16 @@ const Class ModuleEnvironmentObject::cla
 
   JSObject* obj;
   JS_TRY_VAR_OR_RETURN_NULL(
       cx, obj, NativeObject::create(cx, kind, gc::TenuredHeap, shape, group));
 
   RootedModuleEnvironmentObject env(cx, &obj->as<ModuleEnvironmentObject>());
 
   env->initReservedSlot(MODULE_SLOT, ObjectValue(*module));
-  if (!JSObject::setSingleton(cx, env)) {
-    return nullptr;
-  }
 
   // Initialize this early so that we can manipulate the env object without
   // causing assertions.
   env->initEnclosingEnvironment(&cx->global()->lexicalEnvironment());
 
   // Initialize all lexical bindings and imports as uninitialized. Imports
   // get uninitialized because they have a special TDZ for cyclic imports.
   for (BindingIter bi(script); bi; bi++) {
@@ -3829,18 +3748,17 @@ static bool RemoveReferencedNames(JSCont
           name = script->getName(pc);
         } else {
           name = nullptr;
         }
         break;
 
       case JSOP_GETALIASEDVAR:
       case JSOP_SETALIASEDVAR:
-        name = EnvironmentCoordinateName(cx->caches().envCoordinateNameCache,
-                                         script, pc);
+        name = EnvironmentCoordinateNameSlow(script, pc);
         break;
 
       default:
         name = nullptr;
         break;
     }
 
     if (name) {
--- a/js/src/vm/EnvironmentObject.h
+++ b/js/src/vm/EnvironmentObject.h
@@ -26,25 +26,20 @@ typedef Handle<ModuleObject*> HandleModu
 
 /*
  * Return a shape representing the static scope containing the variable
  * accessed by the ALIASEDVAR op at 'pc'.
  */
 extern Shape* EnvironmentCoordinateToEnvironmentShape(JSScript* script,
                                                       jsbytecode* pc);
 
-// Return the name being accessed by the given ALIASEDVAR op.
-extern PropertyName* EnvironmentCoordinateName(
-    EnvironmentCoordinateNameCache& cache, JSScript* script, jsbytecode* pc);
-
-// Return the function script accessed by the given ALIASEDVAR op, or nullptr.
-extern JSScript* EnvironmentCoordinateFunctionScript(JSScript* script,
-                                                     jsbytecode* pc);
-
-/*** Environment objects ****************************************************/
+// Return the name being accessed by the given ALIASEDVAR op. This function is
+// relatively slow so it should not be used on hot paths.
+extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
+                                                   jsbytecode* pc);
 
 /*** Environment objects ****************************************************/
 
 // clang-format off
 /*
  * [SMDOC] Environment Objects
  *
  * About environments
@@ -259,18 +254,17 @@ extern JSScript* EnvironmentCoordinateFu
 // clang-format on
 
 class EnvironmentObject : public NativeObject {
  protected:
   // The enclosing environment. Either another EnvironmentObject, a
   // GlobalObject, or a non-syntactic environment object.
   static const uint32_t ENCLOSING_ENV_SLOT = 0;
 
-  inline void setAliasedBinding(JSContext* cx, uint32_t slot,
-                                PropertyName* name, const Value& v);
+  inline void setAliasedBinding(JSContext* cx, uint32_t slot, const Value& v);
 
   void setEnclosingEnvironment(JSObject* enclosing) {
     setReservedSlot(ENCLOSING_ENV_SLOT, ObjectOrNullValue(enclosing));
   }
 
  public:
   // Since every env chain terminates with a global object, whether
   // GlobalObject or a non-syntactic one, and since those objects do not
@@ -290,17 +284,17 @@ class EnvironmentObject : public NativeO
   }
 
   const Value& aliasedBinding(const BindingIter& bi) {
     MOZ_ASSERT(bi.location().kind() == BindingLocation::Kind::Environment);
     return getSlot(bi.location().slot());
   }
 
   inline void setAliasedBinding(JSContext* cx, EnvironmentCoordinate ec,
-                                PropertyName* name, const Value& v);
+                                const Value& v);
 
   inline void setAliasedBinding(JSContext* cx, const BindingIter& bi,
                                 const Value& v);
 
   // For JITs.
   static size_t offsetOfEnclosingEnvironment() {
     return getFixedSlotOffset(ENCLOSING_ENV_SLOT);
   }
@@ -317,28 +311,22 @@ class CallObject : public EnvironmentObj
 
  public:
   static const uint32_t RESERVED_SLOTS = 2;
   static const Class class_;
 
   /* These functions are internal and are exposed only for JITs. */
 
   /*
-   * Construct a bare-bones call object given a shape and a non-singleton
-   * group.  The call object must be further initialized to be usable.
+   * Construct a bare-bones call object given a shape and a group.
+   * The call object must be further initialized to be usable.
    */
   static CallObject* create(JSContext* cx, HandleShape shape,
                             HandleObjectGroup group);
 
-  /*
-   * Construct a bare-bones call object given a shape and make it into
-   * a singleton.  The call object must be initialized to be usable.
-   */
-  static CallObject* createSingleton(JSContext* cx, HandleShape shape);
-
   static CallObject* createTemplateObject(JSContext* cx, HandleScript script,
                                           HandleObject enclosing,
                                           gc::InitialHeap heap);
 
   static CallObject* create(JSContext* cx, HandleFunction callee,
                             HandleObject enclosing);
   static CallObject* create(JSContext* cx, AbstractFramePtr frame);
 
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -299,25 +299,17 @@ inline bool SetIntrinsicOperation(JSCont
   return GlobalObject::setIntrinsicValue(cx, cx->global(), name, val);
 }
 
 inline void SetAliasedVarOperation(JSContext* cx, JSScript* script,
                                    jsbytecode* pc, EnvironmentObject& obj,
                                    EnvironmentCoordinate ec, const Value& val,
                                    MaybeCheckTDZ checkTDZ) {
   MOZ_ASSERT_IF(checkTDZ, !IsUninitializedLexical(obj.aliasedBinding(ec)));
-
-  // Avoid computing the name if no type updates are needed, as this may be
-  // expensive on scopes with large numbers of variables.
-  PropertyName* name =
-      obj.isSingleton() ? EnvironmentCoordinateName(
-                              cx->caches().envCoordinateNameCache, script, pc)
-                        : nullptr;
-
-  obj.setAliasedBinding(cx, ec, name, val);
+  obj.setAliasedBinding(cx, ec, val);
 }
 
 inline bool SetNameOperation(JSContext* cx, JSScript* script, jsbytecode* pc,
                              HandleObject env, HandleValue val) {
   MOZ_ASSERT(*pc == JSOP_SETNAME || *pc == JSOP_STRICTSETNAME ||
              *pc == JSOP_SETGNAME || *pc == JSOP_STRICTSETGNAME);
   MOZ_ASSERT_IF((*pc == JSOP_SETGNAME || *pc == JSOP_STRICTSETGNAME) &&
                     !script->hasNonSyntacticScope(),
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -1954,16 +1954,17 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_
       SANITY_CHECKS();
       DISPATCH_TO(op);
     }
 
     /* Various 1-byte no-ops. */
     CASE(JSOP_NOP)
     CASE(JSOP_NOP_DESTRUCTURING)
     CASE(JSOP_TRY_DESTRUCTURING)
+    CASE(JSOP_UNUSED71)
     CASE(JSOP_UNUSED151)
     CASE(JSOP_CONDSWITCH) {
       MOZ_ASSERT(CodeSpec[*REGS.pc].length == 1);
       ADVANCE_AND_DISPATCH(1);
     }
 
     CASE(JSOP_TRY)
     CASE(JSOP_JUMPTARGET)
@@ -3390,23 +3391,16 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_
         }
         PUSH_COPY(ObjectValue(*obj));
       } else {
         PUSH_COPY(MagicValue(JS_OPTIMIZED_ARGUMENTS));
       }
     }
     END_CASE(JSOP_ARGUMENTS)
 
-    CASE(JSOP_RUNONCE) {
-      if (!RunOnceScriptPrologue(cx, script)) {
-        goto error;
-      }
-    }
-    END_CASE(JSOP_RUNONCE)
-
     CASE(JSOP_REST) {
       ReservedRooted<JSObject*> rest(&rootObject0,
                                      REGS.fp()->createRestParameter(cx));
       if (!rest) {
         goto error;
       }
       PUSH_COPY(ObjectValue(*rest));
     }
@@ -3414,18 +3408,17 @@ static MOZ_NEVER_INLINE JS_HAZ_JSNATIVE_
 
     CASE(JSOP_GETALIASEDVAR) {
       EnvironmentCoordinate ec = EnvironmentCoordinate(REGS.pc);
       ReservedRooted<Value> val(
           &rootValue0, REGS.fp()->aliasedEnvironment(ec).aliasedBinding(ec));
 #ifdef DEBUG
       // Only the .this slot can hold the TDZ MagicValue.
       if (IsUninitializedLexical(val)) {
-        PropertyName* name = EnvironmentCoordinateName(
-            cx->caches().envCoordinateNameCache, script, REGS.pc);
+        PropertyName* name = EnvironmentCoordinateNameSlow(script, REGS.pc);
         MOZ_ASSERT(name == cx->names().dotThis);
         JSOp next = JSOp(*GetNextPc(REGS.pc));
         MOZ_ASSERT(next == JSOP_CHECKTHIS || next == JSOP_CHECKRETURN ||
                    next == JSOP_CHECKTHISREINIT);
       }
 #endif
       PUSH_COPY(val);
       TypeScript::Monitor(cx, script, REGS.pc, REGS.sp[-1]);
@@ -4919,36 +4912,16 @@ bool js::ImplicitThisOperation(JSContext
   if (!LookupNameWithGlobalDefault(cx, name, scopeObj, &obj)) {
     return false;
   }
 
   res.set(ComputeImplicitThis(obj));
   return true;
 }
 
-bool js::RunOnceScriptPrologue(JSContext* cx, HandleScript script) {
-  MOZ_ASSERT(script->treatAsRunOnce());
-
-  if (!script->hasRunOnce()) {
-    script->setHasRunOnce();
-    return true;
-  }
-
-  // Force instantiation of the script's function's group to ensure the flag
-  // is preserved in type information.
-  RootedFunction fun(cx, script->functionNonDelazifying());
-  if (!JSObject::getGroup(cx, fun)) {
-    return false;
-  }
-
-  MarkObjectGroupFlags(cx, script->functionNonDelazifying(),
-                       OBJECT_FLAG_RUNONCE_INVALIDATED);
-  return true;
-}
-
 unsigned js::GetInitDataPropAttrs(JSOp op) {
   switch (op) {
     case JSOP_INITPROP:
     case JSOP_INITELEM:
       return JSPROP_ENUMERATE;
     case JSOP_INITLOCKEDPROP:
       return JSPROP_PERMANENT | JSPROP_READONLY;
     case JSOP_INITHIDDENPROP:
@@ -5306,18 +5279,17 @@ void js::ReportRuntimeLexicalError(JSCon
   if (op == JSOP_THROWSETCALLEE) {
     name = script->functionNonDelazifying()->explicitName()->asPropertyName();
   } else if (IsLocalOp(op)) {
     name = FrameSlotName(script, pc)->asPropertyName();
   } else if (IsAtomOp(op)) {
     name = script->getName(pc);
   } else {
     MOZ_ASSERT(IsAliasedVarOp(op));
-    name = EnvironmentCoordinateName(cx->caches().envCoordinateNameCache,
-                                     script, pc);
+    name = EnvironmentCoordinateNameSlow(script, pc);
   }
 
   ReportRuntimeLexicalError(cx, errorNumber, name);
 }
 
 void js::ReportRuntimeRedeclaration(JSContext* cx, HandlePropertyName name,
                                     const char* redeclKind) {
   if (UniqueChars printable = AtomToPrintableString(cx, name)) {
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -503,18 +503,16 @@ bool ThrowMsgOperation(JSContext* cx, co
 bool GetAndClearException(JSContext* cx, MutableHandleValue res);
 
 bool DeleteNameOperation(JSContext* cx, HandlePropertyName name,
                          HandleObject scopeObj, MutableHandleValue res);
 
 bool ImplicitThisOperation(JSContext* cx, HandleObject scopeObj,
                            HandlePropertyName name, MutableHandleValue res);
 
-bool RunOnceScriptPrologue(JSContext* cx, HandleScript script);
-
 bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj,
                                HandleId id, HandleObject val);
 
 bool InitGetterSetterOperation(JSContext* cx, jsbytecode* pc, HandleObject obj,
                                HandlePropertyName name, HandleObject val);
 
 unsigned GetInitDataPropAttrs(JSOp op);
 
--- a/js/src/vm/Opcodes.h
+++ b/js/src/vm/Opcodes.h
@@ -705,25 +705,18 @@
      *   Type: Switch Statement
      *   Operands: int32_t len, int32_t low, int32_t high,
      *             uint24_t firstResumeIndex
      *   Stack: i =>
      *   len: len
      */ \
     MACRO(JSOP_TABLESWITCH, 70, "tableswitch", NULL, 16, 1, 0, JOF_TABLESWITCH|JOF_DETECTING) \
     /*
-     * Prologue emitted in scripts expected to run once, which deoptimizes code
-     * if it executes multiple times.
-     *
-     *   Category: Statements
-     *   Type: Function
-     *   Operands:
-     *   Stack: =>
      */ \
-    MACRO(JSOP_RUNONCE, 71, "runonce", NULL, 1, 0, 0, JOF_BYTE) \
+    MACRO(JSOP_UNUSED71, 71, "unused71", NULL, 1, 0, 0, JOF_BYTE) \
     /*
      * Pops the top two values from the stack, then pushes the result of
      * applying the operator to the two values.
      *
      *   Category: Operators
      *   Type: Comparison Operators
      *   Operands:
      *   Stack: lval, rval => (lval OP rval)
@@ -1482,17 +1475,17 @@
     /*
      * Sets aliased variable as the top of stack value.
      *
      *   Category: Variables and Scopes
      *   Type: Aliased Variables
      *   Operands: uint8_t hops, uint24_t slot
      *   Stack: v => v
      */ \
-    MACRO(JSOP_SETALIASEDVAR, 137, "setaliasedvar", NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME|JOF_PROPSET|JOF_DETECTING|JOF_IC) \
+    MACRO(JSOP_SETALIASEDVAR, 137, "setaliasedvar", NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME|JOF_PROPSET|JOF_DETECTING) \
     /*
      * Checks if the value of the local variable is the
      * JS_UNINITIALIZED_LEXICAL magic, throwing an error if so.
      *
      *   Category: Variables and Scopes
      *   Type: Local Variables
      *   Operands: uint24_t localno
      *   Stack: =>
@@ -1522,17 +1515,17 @@
      * Initializes an uninitialized aliased lexical binding with the top of
      * stack value.
      *
      *   Category: Variables and Scopes
      *   Type: Aliased Variables
      *   Operands: uint8_t hops, uint24_t slot
      *   Stack: v => v
      */ \
-    MACRO(JSOP_INITALIASEDLEXICAL, 141, "initaliasedlexical", NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME|JOF_PROPINIT|JOF_DETECTING|JOF_IC) \
+    MACRO(JSOP_INITALIASEDLEXICAL, 141, "initaliasedlexical", NULL, 5, 1, 1, JOF_ENVCOORD|JOF_NAME|JOF_PROPINIT|JOF_DETECTING) \
     /*
      * Pushes a JS_UNINITIALIZED_LEXICAL value onto the stack, representing an
      * uninitialized lexical binding.
      *
      * This opcode is used with the JSOP_INITLEXICAL opcode.
      *
      *   Category: Literals
      *   Type: Constants
--- a/js/src/vm/TypeSet.h
+++ b/js/src/vm/TypeSet.h
@@ -184,21 +184,17 @@ enum : uint32_t {
   OBJECT_FLAG_LENGTH_OVERFLOW = 0x00040000,
 
   /* Whether any objects have been iterated over. */
   OBJECT_FLAG_ITERATED = 0x00080000,
 
   /* Whether any object this represents may have non-extensible elements. */
   OBJECT_FLAG_NON_EXTENSIBLE_ELEMENTS = 0x00100000,
 
-  /*
-   * For the function on a run-once script, whether the function has actually
-   * run multiple times.
-   */
-  OBJECT_FLAG_RUNONCE_INVALIDATED = 0x00200000,
+  // (0x00200000 is unused)
 
   /*
    * For a global object, whether any array buffers in this compartment with
    * typed object views have ever been detached.
    */
   OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER = 0x00400000,
 
   /*