Bug 1591209 - Add JSFunction::baseScript() accessor. r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Fri, 25 Oct 2019 13:08:09 +0000
changeset 499022 ce39fc80bb5b9060bab9a6ffe3774fbf7153f490
parent 499021 77f62942e8c9b610354549ac5e6fde6d5d101364
child 499023 6e89821525dbef7fe33fbe380aaeb6ca1d37756f
push id36734
push userncsoregi@mozilla.com
push dateSat, 26 Oct 2019 09:45:46 +0000
treeherdermozilla-central@0b9d0a86ebfd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1591209
milestone72.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 1591209 - Add JSFunction::baseScript() accessor. r=jandem Add a baseScript() accessor to use in cases where to accessor properties through a JSFunction that are defined for both lazy and non-lazy scripts. Differential Revision: https://phabricator.services.mozilla.com/D50526
js/src/frontend/FunctionEmitter.cpp
js/src/frontend/ParseContext.cpp
js/src/frontend/Parser.cpp
js/src/frontend/SharedContext.cpp
js/src/jit/MIR.h
js/src/jit/OptimizationTracking.cpp
js/src/vm/JSFunction-inl.h
js/src/vm/JSFunction.cpp
js/src/vm/JSFunction.h
js/src/vm/JSScript.h
js/src/vm/ObjectGroup.cpp
js/src/vm/Xdr.cpp
--- a/js/src/frontend/FunctionEmitter.cpp
+++ b/js/src/frontend/FunctionEmitter.cpp
@@ -31,19 +31,17 @@ using mozilla::Some;
 FunctionEmitter::FunctionEmitter(BytecodeEmitter* bce, FunctionBox* funbox,
                                  FunctionSyntaxKind syntaxKind,
                                  IsHoisted isHoisted)
     : bce_(bce),
       funbox_(funbox),
       fun_(bce_->cx, funbox_->function()),
       name_(bce_->cx, fun_->explicitName()),
       syntaxKind_(syntaxKind),
-      isHoisted_(isHoisted) {
-  MOZ_ASSERT_IF(fun_->isInterpretedLazy(), fun_->lazyScript());
-}
+      isHoisted_(isHoisted) {}
 
 bool FunctionEmitter::interpretedCommon() {
   // Mark as singletons any function which will only be executed once, or
   // which is inner to a lambda we only expect to run once. In the latter
   // case, if the lambda runs multiple times then CloneFunctionObject will
   // make a deep clone of its contents.
   bool singleton = bce_->checkRunOnceContext();
   if (!JSFunction::setTypeForScriptedFunction(bce_->cx, fun_, singleton)) {
@@ -111,17 +109,17 @@ bool FunctionEmitter::emitLazy() {
   if (!interpretedCommon()) {
     return false;
   }
 
   funbox_->setEnclosingScopeForInnerLazyFunction(bce_->innermostScope());
   if (bce_->emittingRunOnceLambda) {
     // NOTE: The 'funbox' is only partially initialized so we defer checking
     // the shouldSuppressRunOnce condition until delazification.
-    fun_->lazyScript()->setTreatAsRunOnce();
+    fun_->baseScript()->setTreatAsRunOnce();
   }
 
   if (!emitFunction()) {
     //              [stack] FUN?
     return false;
   }
 
 #ifdef DEBUG
--- a/js/src/frontend/ParseContext.cpp
+++ b/js/src/frontend/ParseContext.cpp
@@ -511,17 +511,17 @@ bool ParseContext::declareFunctionThis(c
 
   // Derived class constructors emit JSOP_CHECKRETURN, which requires
   // '.this' to be bound.
   FunctionBox* funbox = functionBox();
   HandlePropertyName dotThis = sc()->cx_->names().dotThis;
 
   bool declareThis;
   if (canSkipLazyClosedOverBindings) {
-    declareThis = funbox->function()->lazyScript()->hasThisBinding();
+    declareThis = funbox->function()->baseScript()->hasThisBinding();
   } else {
     declareThis =
         hasUsedFunctionSpecialName(usedNames, dotThis) ||
         funbox->kind() == FunctionFlags::FunctionKind::ClassConstructor;
   }
 
   if (declareThis) {
     ParseContext::Scope& funScope = functionScope();
@@ -546,17 +546,17 @@ bool ParseContext::declareFunctionArgume
   bool hasExtraBodyVarScope = &funScope != &_varScope;
 
   // Time to implement the odd semantics of 'arguments'.
   HandlePropertyName argumentsName = sc()->cx_->names().arguments;
 
   bool tryDeclareArguments;
   if (canSkipLazyClosedOverBindings) {
     tryDeclareArguments =
-        funbox->function()->lazyScript()->shouldDeclareArguments();
+        funbox->function()->baseScript()->shouldDeclareArguments();
   } else {
     tryDeclareArguments = hasUsedFunctionSpecialName(usedNames, argumentsName);
   }
 
   // ES 9.2.12 steps 19 and 20 say formal parameters, lexical bindings,
   // and body-level functions named 'arguments' shadow the arguments
   // object.
   //
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -2618,24 +2618,24 @@ bool Parser<FullParseHandler, Unit>::ski
   RootedFunction fun(cx_, handler_.nextLazyInnerFunction());
   FunctionBox* funbox = newFunctionBox(funNode, fun, toStringStart,
                                        Directives(/* strict = */ false),
                                        fun->generatorKind(), fun->asyncKind());
   if (!funbox) {
     return false;
   }
 
-  LazyScript* lazy = fun->lazyScript();
-  if (lazy->needsHomeObject()) {
+  BaseScript* base = fun->baseScript();
+  if (base->needsHomeObject()) {
     funbox->setNeedsHomeObject();
   }
 
-  PropagateTransitiveParseFlags(lazy, pc_->sc());
-
-  if (!tokenStream.advance(fun->lazyScript()->sourceEnd())) {
+  PropagateTransitiveParseFlags(base, pc_->sc());
+
+  if (!tokenStream.advance(base->sourceEnd())) {
     return false;
   }
 
   // Append possible Annex B function box only upon successfully parsing.
   if (tryAnnexB &&
       !pc_->innermostScope()->addPossibleAnnexBFunctionBox(pc_, funbox)) {
     return false;
   }
@@ -7207,21 +7207,25 @@ bool GeneralParser<ParseHandler, Unit>::
 
     if (numFields > 0) {
       // Field initialization need access to `this`.
       ctorbox->setHasThisBinding();
     }
 
     // Set the same information, but on the lazyScript.
     if (ctorbox->isInterpretedLazy()) {
-      ctorbox->function()->lazyScript()->setToStringEnd(classEndOffset);
+      ctorbox->function()->baseScript()->setToStringEnd(classEndOffset);
 
       if (numFields > 0) {
-        ctorbox->function()->lazyScript()->setHasThisBinding();
-      }
+        ctorbox->function()->baseScript()->setHasThisBinding();
+      }
+    } else {
+      // There should not be any non-lazy script yet.
+      MOZ_ASSERT_IF(ctorbox->hasObject(),
+                    ctorbox->function()->hasUncompletedScript());
     }
 
     if (numFields == 0) {
       handler_.deleteConstructorScope(cx_, classMembers);
     }
   }
 
   return true;
--- a/js/src/frontend/SharedContext.cpp
+++ b/js/src/frontend/SharedContext.cpp
@@ -198,24 +198,25 @@ FunctionBox::FunctionBox(JSContext* cx, 
                   data.get().flags.isGetter(), data.get().flags.isSetter(),
                   data.get().flags.isMethod(), data.get().flags.isInterpreted(),
                   data.get().flags.isInterpretedLazy(), data.get().flags.kind(),
                   data.get().atom) {
   functionCreationData_.emplace(data);
 }
 
 void FunctionBox::initFromLazyFunction(JSFunction* fun) {
-  if (fun->lazyScript()->isDerivedClassConstructor()) {
+  LazyScript* lazy = fun->lazyScript();
+  if (lazy->isDerivedClassConstructor()) {
     setDerivedClassConstructor();
   }
-  if (fun->lazyScript()->needsHomeObject()) {
+  if (lazy->needsHomeObject()) {
     setNeedsHomeObject();
   }
-  if (fun->lazyScript()->hasEnclosingScope()) {
-    enclosingScope_ = fun->lazyScript()->enclosingScope();
+  if (lazy->hasEnclosingScope()) {
+    enclosingScope_ = lazy->enclosingScope();
   } else {
     enclosingScope_ = nullptr;
   }
   initWithEnclosingScope(enclosingScope_, fun);
 }
 
 void FunctionBox::initStandaloneFunction(Scope* enclosingScope) {
   // Standalone functions are Function or Generator constructors and are
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -6739,18 +6739,17 @@ struct LambdaFunctionInfo {
   gc::Cell* scriptOrLazyScript;
   bool singletonType;
   bool useSingletonForClone;
 
   explicit LambdaFunctionInfo(JSFunction* fun)
       : fun_(fun),
         flags(fun->flags().toRaw()),
         nargs(fun->nargs()),
-        scriptOrLazyScript(fun->hasScript() ? (gc::Cell*)fun->nonLazyScript()
-                                            : (gc::Cell*)fun->lazyScript()),
+        scriptOrLazyScript(fun->baseScript()),
         singletonType(fun->isSingleton()),
         useSingletonForClone(ObjectGroup::useSingletonForClone(fun)) {
     // If this assert fails, make sure CodeGenerator::visitLambda does the
     // right thing. We can't assert this off-thread in CodeGenerator,
     // because fun->isAsync() accesses the script/lazyScript and can race
     // with delazification on the main thread.
     MOZ_ASSERT_IF(flags & FunctionFlags::EXTENDED,
                   fun->isArrow() || fun->allowSuperProperty() ||
--- a/js/src/jit/OptimizationTracking.cpp
+++ b/js/src/jit/OptimizationTracking.cpp
@@ -788,22 +788,19 @@ static JSFunction* MaybeConstructorFromT
   AutoSweepObjectGroup sweep(obj);
   TypeNewScript* newScript = obj->newScript(sweep);
   return newScript ? newScript->function() : nullptr;
 }
 
 static void InterpretedFunctionFilenameAndLineNumber(JSFunction* fun,
                                                      const char** filename,
                                                      Maybe<unsigned>* lineno) {
-  if (fun->hasScript()) {
-    *filename = fun->nonLazyScript()->maybeForwardedScriptSource()->filename();
-    *lineno = Some((unsigned)fun->nonLazyScript()->lineno());
-  } else if (fun->hasLazyScript()) {
-    *filename = fun->lazyScript()->maybeForwardedScriptSource()->filename();
-    *lineno = Some((unsigned)fun->lazyScript()->lineno());
+  if (fun->hasBaseScript()) {
+    *filename = fun->baseScript()->maybeForwardedScriptSource()->filename();
+    *lineno = Some((unsigned)fun->baseScript()->lineno());
   } else {
     *filename = "(self-hosted builtin)";
     *lineno = Nothing();
   }
 }
 
 static void SpewConstructor(TypeSet::Type ty, JSFunction* constructor) {
 #ifdef JS_JITSPEW
--- a/js/src/vm/JSFunction-inl.h
+++ b/js/src/vm/JSFunction-inl.h
@@ -27,32 +27,28 @@ inline const char* GetFunctionNameBytes(
   }
   return js_anonymous_str;
 }
 
 inline bool CanReuseFunctionForClone(JSContext* cx, HandleFunction fun) {
   if (!fun->isSingleton()) {
     return false;
   }
-  if (fun->isInterpretedLazy()) {
-    LazyScript* lazy = fun->lazyScript();
-    if (lazy->hasBeenCloned()) {
-      return false;
-    }
-    lazy->setHasBeenCloned();
-  } else {
-    JSScript* script = fun->nonLazyScript();
-    if (script->hasBeenCloned()) {
-      return false;
-    }
-    script->setHasBeenCloned();
-    if (LazyScript* lazy = script->maybeLazyScript()) {
+
+  if (fun->baseScript()->hasBeenCloned()) {
+    return false;
+  }
+  fun->baseScript()->setHasBeenCloned();
+
+  if (fun->hasScript()) {
+    if (LazyScript* lazy = fun->nonLazyScript()->maybeLazyScript()) {
       lazy->setHasBeenCloned();
     }
   }
+
   return true;
 }
 
 inline JSFunction* CloneFunctionObjectIfNotSingleton(
     JSContext* cx, HandleFunction fun, HandleObject parent,
     HandleObject proto = nullptr, NewObjectKind newKind = GenericObject) {
   /*
    * For attempts to clone functions at a function definition opcode,
--- a/js/src/vm/JSFunction.cpp
+++ b/js/src/vm/JSFunction.cpp
@@ -1211,32 +1211,29 @@ static const ClassSpec JSFunctionClassSp
 const JSClass JSFunction::class_ = {js_Function_str,
                                     JSCLASS_HAS_CACHED_PROTO(JSProto_Function),
                                     &JSFunctionClassOps, &JSFunctionClassSpec};
 
 const JSClass* const js::FunctionClassPtr = &JSFunction::class_;
 
 bool JSFunction::isDerivedClassConstructor() {
   bool derived;
-  if (isInterpretedLazy()) {
+  if (hasSelfHostedLazyScript()) {
     // There is only one plausible lazy self-hosted derived
     // constructor.
-    if (isSelfHostedBuiltin()) {
-      JSAtom* name = GetClonedSelfHostedFunctionName(this);
-
-      // This function is called from places without access to a
-      // JSContext. Trace some plumbing to get what we want.
-      derived = name == compartment()
-                            ->runtimeFromAnyThread()
-                            ->commonNames->DefaultDerivedClassConstructor;
-    } else {
-      derived = lazyScript()->isDerivedClassConstructor();
-    }
-  } else {
-    derived = nonLazyScript()->isDerivedClassConstructor();
+    JSAtom* name = GetClonedSelfHostedFunctionName(this);
+
+    // This function is called from places without access to a
+    // JSContext. Trace some plumbing to get what we want.
+    derived = name == compartment()
+                          ->runtimeFromAnyThread()
+                          ->commonNames->DefaultDerivedClassConstructor;
+  }
+  if (hasBaseScript()) {
+    derived = baseScript()->isDerivedClassConstructor();
   }
   MOZ_ASSERT_IF(derived, isClassConstructor());
   return derived;
 }
 
 /* static */
 bool JSFunction::getLength(JSContext* cx, HandleFunction fun,
                            uint16_t* length) {
@@ -2159,18 +2156,17 @@ bool js::CanReuseScriptForClone(JS::Real
   // script's flags appropriately.  We hit this case for JSOP_LAMBDA, for
   // example.
   if (IsSyntacticEnvironment(newParent)) {
     return true;
   }
 
   // We need to clone the script if we're not already marked as having a
   // non-syntactic scope.
-  return fun->hasScript() ? fun->nonLazyScript()->hasNonSyntacticScope()
-                          : fun->lazyScript()->hasNonSyntacticScope();
+  return fun->baseScript()->hasNonSyntacticScope();
 }
 
 static inline JSFunction* NewFunctionClone(JSContext* cx, HandleFunction fun,
                                            NewObjectKind newKind,
                                            gc::AllocKind allocKind,
                                            HandleObject proto) {
   RootedObject cloneProto(cx, proto);
   if (!proto) {
--- a/js/src/vm/JSFunction.h
+++ b/js/src/vm/JSFunction.h
@@ -465,16 +465,17 @@ class JSFunction : public js::NativeObje
   // For live JSFunctions the pointer values will always be non-null, but due
   // to partial initialization the GC (and other features that scan the heap
   // directly) may still return a null pointer.
   bool hasScript() const { return flags_.hasScript(); }
   bool hasLazyScript() const { return flags_.hasLazyScript(); }
   bool hasSelfHostedLazyScript() const {
     return flags_.hasSelfHostedLazyScript();
   }
+  bool hasBaseScript() const { return hasScript() || hasLazyScript(); }
 
   // Arrow functions store their lexical new.target in the first extended slot.
   bool isArrow() const { return flags_.isArrow(); }
   // Every class-constructor is also a method.
   bool isMethod() const { return flags_.isMethod(); }
   bool isClassConstructor() const { return flags_.isClassConstructor(); }
 
   bool isGetter() const { return flags_.isGetter(); }
@@ -509,21 +510,17 @@ class JSFunction : public js::NativeObje
   bool isNamedLambda() const { return flags_.isNamedLambda(displayAtom()); }
 
   bool hasLexicalThis() const { return isArrow(); }
 
   bool isBuiltinFunctionConstructor();
   bool needsPrototypeProperty();
 
   /* Returns the strictness of this function, which must be interpreted. */
-  bool strict() const {
-    MOZ_ASSERT(isInterpreted());
-    return isInterpretedLazy() ? lazyScript()->strict()
-                               : nonLazyScript()->strict();
-  }
+  bool strict() const { return baseScript()->strict(); }
 
   void setFlags(uint16_t flags) { flags_ = FunctionFlags(flags); }
   void setFlags(FunctionFlags flags) { flags_ = flags; }
   void setKind(FunctionFlags::FunctionKind kind) { flags_.setKind(kind); }
 
   // Make the function constructible.
   void setIsConstructor() { flags_.setIsConstructor(); }
   void setIsClassConstructor() { flags_.setIsClassConstructor(); }
@@ -762,45 +759,41 @@ class JSFunction : public js::NativeObje
     return u.scripted.s.lazy_;
   }
 
   js::SelfHostedLazyScript* selfHostedLazyScript() const {
     MOZ_ASSERT(hasSelfHostedLazyScript() && u.scripted.s.selfHostedLazy_);
     return u.scripted.s.selfHostedLazy_;
   }
 
-  js::GeneratorKind generatorKind() const {
-    if (!isInterpreted()) {
-      return js::GeneratorKind::NotGenerator;
-    }
+  // Access fields defined on both lazy and non-lazy scripts. This should
+  // optimize away the branch since the union arms are compatible.
+  js::BaseScript* baseScript() const {
     if (hasScript()) {
-      return nonLazyScript()->generatorKind();
+      return nonLazyScript();
     }
-    if (hasLazyScript()) {
-      return lazyScript()->generatorKind();
+    MOZ_ASSERT(hasLazyScript());
+    return lazyScript();
+  }
+
+  js::GeneratorKind generatorKind() const {
+    if (hasBaseScript()) {
+      return baseScript()->generatorKind();
     }
-    MOZ_ASSERT(isSelfHostedBuiltin());
     return js::GeneratorKind::NotGenerator;
   }
 
   bool isGenerator() const {
     return generatorKind() == js::GeneratorKind::Generator;
   }
 
   js::FunctionAsyncKind asyncKind() const {
-    if (!isInterpreted()) {
-      return js::FunctionAsyncKind::SyncFunction;
+    if (hasBaseScript()) {
+      return baseScript()->asyncKind();
     }
-    if (hasScript()) {
-      return nonLazyScript()->asyncKind();
-    }
-    if (hasLazyScript()) {
-      return lazyScript()->asyncKind();
-    }
-    MOZ_ASSERT(isSelfHostedBuiltin());
     return js::FunctionAsyncKind::SyncFunction;
   }
 
   bool isAsync() const {
     return asyncKind() == js::FunctionAsyncKind::AsyncFunction;
   }
 
   void setScript(JSScript* script) {
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -1651,16 +1651,22 @@ class BaseScript : public gc::TenuredCel
   }
 
   uint32_t sourceStart() const { return sourceStart_; }
   uint32_t sourceEnd() const { return sourceEnd_; }
   uint32_t sourceLength() const { return sourceEnd_ - sourceStart_; }
   uint32_t toStringStart() const { return toStringStart_; }
   uint32_t toStringEnd() const { return toStringEnd_; }
 
+  void setToStringEnd(uint32_t toStringEnd) {
+    MOZ_ASSERT(toStringStart_ <= toStringEnd);
+    MOZ_ASSERT(toStringEnd_ >= sourceEnd_);
+    toStringEnd_ = toStringEnd;
+  }
+
   uint32_t lineno() const { return lineno_; }
   uint32_t column() const { return column_; }
 
   // ImmutableFlags accessors.
   MOZ_MUST_USE bool hasFlag(ImmutableFlags flag) const {
     return immutableFlags_ & uint32_t(flag);
   }
   uint32_t immutableFlags() const { return immutableFlags_; }
@@ -3407,22 +3413,16 @@ class LazyScript : public BaseScript {
     lazyData_->fieldInitializers_ = fieldInitializers;
   }
 
   const FieldInitializers& getFieldInitializers() const {
     MOZ_ASSERT(lazyData_);
     return lazyData_->fieldInitializers_;
   }
 
-  void setToStringEnd(uint32_t toStringEnd) {
-    MOZ_ASSERT(toStringStart_ <= toStringEnd);
-    MOZ_ASSERT(toStringEnd_ >= sourceEnd_);
-    toStringEnd_ = toStringEnd;
-  }
-
   // Returns true if the enclosing script has ever been compiled.
   // Once the enclosing script is compiled, the scope chain is created.
   // This LazyScript is delazify-able as long as it has the enclosing scope,
   // even if the enclosing JSScript is GCed.
   // The enclosing JSScript can be GCed later if the enclosing scope is not
   // FunctionScope or ModuleScope.
   bool enclosingScriptHasEverBeenCompiled() const {
     return hasEnclosingScope();
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -168,30 +168,21 @@ bool ObjectGroup::useSingletonForClone(J
    *
    * Each instance of the innermost function will have a different wrapped
    * initialize method. We capture this, along with similar cases, by looking
    * for short scripts which use both .apply and arguments. For such scripts,
    * whenever creating a new instance of the function we both give that
    * instance a singleton type and clone the underlying script.
    */
 
-  uint32_t begin, end;
-  if (fun->hasScript()) {
-    if (!fun->nonLazyScript()->isLikelyConstructorWrapper()) {
-      return false;
-    }
-    begin = fun->nonLazyScript()->sourceStart();
-    end = fun->nonLazyScript()->sourceEnd();
-  } else {
-    if (!fun->lazyScript()->isLikelyConstructorWrapper()) {
-      return false;
-    }
-    begin = fun->lazyScript()->sourceStart();
-    end = fun->lazyScript()->sourceEnd();
+  if (!fun->baseScript()->isLikelyConstructorWrapper()) {
+    return false;
   }
+  uint32_t begin = fun->baseScript()->sourceStart();
+  uint32_t end = fun->baseScript()->sourceEnd();
 
   return end - begin <= 100;
 }
 
 /* static */
 bool ObjectGroup::useSingletonForNewObject(JSContext* cx, JSScript* script,
                                            jsbytecode* pc) {
   /*
--- a/js/src/vm/Xdr.cpp
+++ b/js/src/vm/Xdr.cpp
@@ -349,31 +349,22 @@ class XDRIncrementalEncoder::DepthFirstS
   const SlicesTree& tree_;
 };
 
 AutoXDRTree::Key XDRIncrementalEncoder::getTopLevelTreeKey() const {
   return AutoXDRTree::topLevel;
 }
 
 AutoXDRTree::Key XDRIncrementalEncoder::getTreeKey(JSFunction* fun) const {
-  if (fun->isInterpretedLazy()) {
-    static_assert(
-        sizeof(fun->lazyScript()->sourceStart()) == 4 ||
-            sizeof(fun->lazyScript()->sourceEnd()) == 4,
-        "AutoXDRTree key requires LazyScripts positions to be uint32");
-    return uint64_t(fun->lazyScript()->sourceStart()) << 32 |
-           fun->lazyScript()->sourceEnd();
-  }
-
-  if (fun->isInterpreted()) {
-    static_assert(sizeof(fun->nonLazyScript()->sourceStart()) == 4 ||
-                      sizeof(fun->nonLazyScript()->sourceEnd()) == 4,
-                  "AutoXDRTree key requires JSScripts positions to be uint32");
-    return uint64_t(fun->nonLazyScript()->sourceStart()) << 32 |
-           fun->nonLazyScript()->sourceEnd();
+  if (fun->hasBaseScript()) {
+    static_assert(sizeof(fun->baseScript()->sourceStart()) == 4 &&
+                      sizeof(fun->baseScript()->sourceEnd()) == 4,
+                  "AutoXDRTree key requires BaseScript positions to be uint32");
+    return uint64_t(fun->baseScript()->sourceStart()) << 32 |
+           fun->baseScript()->sourceEnd();
   }
 
   return AutoXDRTree::noKey;
 }
 
 void XDRIncrementalEncoder::createOrReplaceSubTree(AutoXDRTree* child) {
   AutoXDRTree* parent = scope_;
   child->parent_ = parent;