Backed out 4 changesets (bug 826148) because of test failures
authorEhsan Akhgari <ehsan@mozilla.com>
Fri, 11 Jan 2013 00:05:36 -0500
changeset 118506 6cda85d6e4f6140c196bc3e23d611edf1cc1606b
parent 118505 e520c411aed6a09e7d2fade06aa949cd018e97f3
child 118507 1830a14dd3af839a4c5f633fc334750ee3fdd956
push id24166
push userMs2ger@gmail.com
push dateFri, 11 Jan 2013 13:57:41 +0000
treeherdermozilla-central@63c4b0f66a0c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs826148
milestone21.0a1
backs oute520c411aed6a09e7d2fade06aa949cd018e97f3
1db5b4e596492d56613ce019ae3f6126e5bd6816
57bf735f3e186a1501fe2fe01b46bc1ef41d0ca2
b659dc17b1646aa6ecb3275afab6829b6080c7f1
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
Backed out 4 changesets (bug 826148) because of test failures Backed out changeset e520c411aed6 (bug 826148) Backed out changeset 1db5b4e59649 (bug 826148) Backed out changeset 57bf735f3e18 (bug 826148) Backed out changeset b659dc17b164 (bug 826148)
js/src/ion/CodeGenerator.cpp
js/src/ion/CodeGenerator.h
js/src/ion/IonBuilder.cpp
js/src/ion/IonBuilder.h
js/src/ion/IonCaches.cpp
js/src/ion/IonCaches.h
js/src/ion/LIR-Common.h
js/src/ion/LOpcodes.h
js/src/ion/Lowering.cpp
js/src/ion/Lowering.h
js/src/ion/MIR.cpp
js/src/ion/MIR.h
js/src/ion/MOpcodes.h
js/src/ion/VMFunctions.cpp
js/src/ion/VMFunctions.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsinfer.cpp
js/src/jsinterp.cpp
js/src/jsscript.cpp
js/src/jsscript.h
js/src/methodjit/Compiler.cpp
js/src/methodjit/Compiler.h
js/src/methodjit/InvokeHelpers.cpp
js/src/methodjit/MonoIC.cpp
js/src/methodjit/MonoIC.h
js/src/methodjit/StubCalls-inl.h
js/src/methodjit/StubCalls.h
--- a/js/src/ion/CodeGenerator.cpp
+++ b/js/src/ion/CodeGenerator.cpp
@@ -3839,18 +3839,16 @@ class OutOfLineCache : public OutOfLineC
             return codegen->visitOutOfLineGetElementCache(this);
           case LInstruction::LOp_SetPropertyCacheT:
           case LInstruction::LOp_SetPropertyCacheV:
             return codegen->visitOutOfLineSetPropertyCache(this);
           case LInstruction::LOp_BindNameCache:
             return codegen->visitOutOfLineBindNameCache(this);
           case LInstruction::LOp_GetNameCache:
             return codegen->visitOutOfLineGetNameCache(this);
-          case LInstruction::LOp_CallsiteCloneCache:
-            return codegen->visitOutOfLineCallsiteCloneCache(this);
           default:
             JS_NOT_REACHED("Bad instruction");
             return false;
         }
     }
 
     LInstruction *cache() {
         return ins;
@@ -3880,51 +3878,16 @@ CodeGenerator::visitCache(LInstruction *
     CodeOffsetJump jump = masm.jumpWithPatch(ool->repatchEntry());
     CodeOffsetLabel label = masm.labelForPatch();
     masm.bind(ool->rejoin());
 
     ool->setInlineJump(jump, label);
     return true;
 }
 
-typedef JSObject *(*CallsiteCloneCacheFn)(JSContext *, size_t, HandleObject);
-static const VMFunction CallsiteCloneCacheInfo =
-    FunctionInfo<CallsiteCloneCacheFn>(CallsiteCloneCache);
-
-bool
-CodeGenerator::visitOutOfLineCallsiteCloneCache(OutOfLineCache *ool)
-{
-    LCallsiteCloneCache *lir = ool->cache()->toCallsiteCloneCache();
-    const MCallsiteCloneCache *mir = lir->mir();
-    Register callee = ToRegister(lir->callee());
-    RegisterSet liveRegs = lir->safepoint()->liveRegs();
-    Register output = ToRegister(lir->output());
-
-    IonCacheCallsiteClone cache(ool->getInlineJump(), ool->getInlineLabel(),
-                                masm.labelForPatch(), liveRegs,
-                                callee, mir->block()->info().script(), mir->callPc(), output);
-
-    JS_ASSERT(!mir->resumePoint());
-
-    size_t cacheIndex = allocateCache(cache);
-
-    saveLive(lir);
-
-    pushArg(callee);
-    pushArg(Imm32(cacheIndex));
-    if (!callVM(CallsiteCloneCacheInfo, lir))
-        return false;
-
-    masm.storeCallResult(output);
-    restoreLive(lir);
-
-    masm.jump(ool->rejoin());
-    return true;
-}
-
 typedef bool (*GetNameCacheFn)(JSContext *, size_t, HandleObject, MutableHandleValue);
 static const VMFunction GetNameCacheInfo =
     FunctionInfo<GetNameCacheFn>(GetNameCache);
 
 bool
 CodeGenerator::visitOutOfLineGetNameCache(OutOfLineCache *ool)
 {
     LGetNameCache *lir = ool->cache()->toGetNameCache();
--- a/js/src/ion/CodeGenerator.h
+++ b/js/src/ion/CodeGenerator.h
@@ -196,17 +196,16 @@ class CodeGenerator : public CodeGenerat
     bool visitOutOfLineUnboxDouble(OutOfLineUnboxDouble *ool);
     bool visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool);
 
     bool visitOutOfLineCacheGetProperty(OutOfLineCache *ool);
     bool visitOutOfLineGetElementCache(OutOfLineCache *ool);
     bool visitOutOfLineSetPropertyCache(OutOfLineCache *ool);
     bool visitOutOfLineBindNameCache(OutOfLineCache *ool);
     bool visitOutOfLineGetNameCache(OutOfLineCache *ool);
-    bool visitOutOfLineCallsiteCloneCache(OutOfLineCache *ool);
 
     bool visitGetPropertyCacheV(LGetPropertyCacheV *ins) {
         return visitCache(ins);
     }
     bool visitGetPropertyCacheT(LGetPropertyCacheT *ins) {
         return visitCache(ins);
     }
     bool visitGetElementCacheV(LGetElementCacheV *ins) {
@@ -219,19 +218,16 @@ class CodeGenerator : public CodeGenerat
         return visitCache(ins);
     }
     bool visitSetPropertyCacheT(LSetPropertyCacheT *ins) {
         return visitCache(ins);
     }
     bool visitGetNameCache(LGetNameCache *ins) {
         return visitCache(ins);
     }
-    bool visitCallsiteCloneCache(LCallsiteCloneCache *ins) {
-        return visitCache(ins);
-    }
 
   private:
     bool visitCache(LInstruction *load);
     bool visitCallSetProperty(LInstruction *ins);
 
     ConstantOrRegister getSetPropertyValue(LInstruction *ins);
     bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr);
 
--- a/js/src/ion/IonBuilder.cpp
+++ b/js/src/ion/IonBuilder.cpp
@@ -3104,17 +3104,18 @@ IonBuilder::checkInlineableGetPropertyCa
 
     if (!ValidateInlineableGetPropertyCache(getPropCache, thisDefn, 1))
         return NULL;
 
     return getPropCache;
 }
 
 MPolyInlineDispatch *
-IonBuilder::makePolyInlineDispatch(JSContext *cx, int argc, MGetPropertyCache *getPropCache,
+IonBuilder::makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
+                                   MGetPropertyCache *getPropCache,
                                    types::StackTypeSet *types, types::StackTypeSet *barrier,
                                    MBasicBlock *bottom,
                                    Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns)
 {
     int funcDefnDepth = -((int) argc + 2);
     MDefinition *funcDefn = current->peek(funcDefnDepth);
 
     // If we're not optimizing away a GetPropertyCache, then this is pretty simple.
@@ -3201,18 +3202,17 @@ IonBuilder::makePolyInlineDispatch(JSCon
     // Finally create a fallbackEnd block to do the actual call.  The fallbackEnd block will
     // have the |pc| restored to the current PC.
     MBasicBlock *fallbackEndBlock = newBlock(fallbackBlock, pc, preCallResumePoint);
     if (!fallbackEndBlock)
         return NULL;
     fallbackBlock->end(MGoto::New(fallbackEndBlock));
 
     // Create Call
-    MCall *call = MCall::New(NULL, argc + 1, argc, false,
-                             oracle->getCallTarget(script(), argc, pc));
+    MCall *call = MCall::New(NULL, argc + 1, argc, false);
     if (!call)
         return NULL;
 
     // Set up the MPrepCall
     MPrepareCall *prepCall = new MPrepareCall;
     fallbackEndBlock->add(prepCall);
 
     // Grab the arguments for the call directly from the current block's stack.
@@ -3244,18 +3244,17 @@ IonBuilder::makePolyInlineDispatch(JSCon
 
     // Create a new MPolyInlineDispatch containing the getprop and the fallback block
     return MPolyInlineDispatch::New(targetObject, inlinePropTable,
                                     fallbackPrepBlock, fallbackBlock,
                                     fallbackEndBlock);
 }
 
 bool
-IonBuilder::inlineScriptedCall(AutoObjectVector &targets, AutoObjectVector &originals,
-                               uint32_t argc, bool constructing,
+IonBuilder::inlineScriptedCall(AutoObjectVector &targets, uint32_t argc, bool constructing,
                                types::StackTypeSet *types, types::StackTypeSet *barrier)
 {
 #ifdef DEBUG
     uint32_t origStackDepth = current->stackDepth();
 #endif
 
     IonSpew(IonSpew_Inlining, "Inlining %d targets", (int) targets.length());
     JS_ASSERT(targets.length() > 0);
@@ -3285,17 +3284,17 @@ IonBuilder::inlineScriptedCall(AutoObjec
         if (getPropCache) {
             InlinePropertyTable *inlinePropTable = getPropCache->inlinePropertyTable();
             // checkInlineableGetPropertyCache should have verified this.
             JS_ASSERT(inlinePropTable != NULL);
 
             int numCases = inlinePropTable->numEntries();
             IonSpew(IonSpew_Inlining, "Got inlineable property cache with %d cases", numCases);
 
-            inlinePropTable->trimToAndMaybePatchTargets(targets, originals);
+            inlinePropTable->trimToTargets(targets);
 
             // Trim the cases based on those that match the targets at this call site.
             IonSpew(IonSpew_Inlining, "%d inlineable cases left after trimming to %d targets",
                                         (int) inlinePropTable->numEntries(),
                                         (int) targets.length());
 
             if (inlinePropTable->numEntries() == 0)
                 getPropCache = NULL;
@@ -3335,28 +3334,24 @@ IonBuilder::inlineScriptedCall(AutoObjec
         // for the Inline_Exit node (mostly for the case below)
         if (instrumentedProfiling())
             bottom->add(MFunctionBoundary::New(NULL, MFunctionBoundary::Inline_Exit));
 
     } else {
         // In the polymorphic case, we end the current block with a MPolyInlineDispatch instruction.
 
         // Create a PolyInlineDispatch instruction for this call site
-        MPolyInlineDispatch *disp = makePolyInlineDispatch(cx, argc, getPropCache, types, barrier,
-                                                           bottom, retvalDefns);
+        MPolyInlineDispatch *disp = makePolyInlineDispatch(cx, targets, argc, getPropCache,
+                                                           types, barrier, bottom, retvalDefns);
         if (!disp)
             return false;
-
-        // It's guaranteed that targets.length() == originals.length()
         for (size_t i = 0; i < targets.length(); i++) {
-            // Create an MConstant for the function. Note that we guard on the
-            // original function pointer, even if we have a clone, as we only
-            // clone at the callsite, so guarding on the clone would be
-            // guaranteed to fail.
-            JSFunction *func = originals[i]->toFunction();
+            // Create an MConstant for the function
+            JSFunction *func = targets[i]->toFunction();
+            RootedFunction target(cx, func);
             MConstant *constFun = MConstant::New(ObjectValue(*func));
 
             // Create new entry block for the inlined callee graph.
             MBasicBlock *entryBlock = newBlock(current, pc);
             if (!entryBlock)
                 return false;
 
             // Add case to PolyInlineDispatch
@@ -3694,44 +3689,29 @@ IonBuilder::createThis(HandleFunction ta
     MDefinition *createThis = createThisScriptedSingleton(target, callee);
     if (createThis)
         return createThis;
 
     return createThisScripted(callee);
 }
 
 bool
-IonBuilder::anyFunctionIsCloneAtCallsite(types::StackTypeSet *funTypes)
-{
-    uint32_t count = funTypes->getObjectCount();
-    if (count < 1)
-        return false;
-
-    for (uint32_t i = 0; i < count; i++) {
-        JSObject *obj = funTypes->getSingleObject(i);
-        if (obj->isFunction() && obj->toFunction()->isCloneAtCallsite())
-            return true;
-    }
-    return false;
-}
-
-bool
 IonBuilder::jsop_funcall(uint32_t argc)
 {
     // Stack for JSOP_FUNCALL:
     // 1:      MPassArg(arg0)
     // ...
     // argc:   MPassArg(argN)
     // argc+1: MPassArg(JSFunction *), the 'f' in |f.call()|, in |this| position.
     // argc+2: The native 'call' function.
 
     // If |Function.prototype.call| may be overridden, don't optimize callsite.
     RootedFunction native(cx, getSingleCallTarget(argc, pc));
     if (!native || !native->isNative() || native->native() != &js_fun_call)
-        return makeCall(native, argc, false, false);
+        return makeCall(native, argc, false);
 
     // Extract call target.
     types::StackTypeSet *funTypes = oracle->getCallArg(script(), argc, 0, pc);
     RootedObject funobj(cx, (funTypes) ? funTypes->getSingleton() : NULL);
     RootedFunction target(cx, (funobj && funobj->isFunction()) ? funobj->toFunction() : NULL);
 
     // Unwrap the (JSFunction *) parameter.
     int funcDepth = -((int)argc + 1);
@@ -3754,36 +3734,36 @@ IonBuilder::jsop_funcall(uint32_t argc)
         current->add(pass);
         current->push(pass);
     } else {
         // |this| becomes implicit in the call.
         argc -= 1; 
     }
 
     // Call without inlining.
-    return makeCall(target, argc, false, false);
+    return makeCall(target, argc, false);
 }
 
 bool
 IonBuilder::jsop_funapply(uint32_t argc)
 {
     RootedFunction native(cx, getSingleCallTarget(argc, pc));
     if (argc != 2)
-        return makeCall(native, argc, false, false);
+        return makeCall(native, argc, false);
 
     // Disable compilation if the second argument to |apply| cannot be guaranteed
     // to be either definitely |arguments| or definitely not |arguments|.
     types::StackTypeSet *argObjTypes = oracle->getCallArg(script(), argc, 2, pc);
     LazyArgumentsType isArgObj = oracle->isArgumentObject(argObjTypes);
     if (isArgObj == MaybeArguments)
         return abort("fun.apply with MaybeArguments");
 
     // Fallback to regular call if arg 2 is not definitely |arguments|.
     if (isArgObj != DefinitelyArguments)
-        return makeCall(native, argc, false, false);
+        return makeCall(native, argc, false);
 
     if (!native ||
         !native->isNative() ||
         native->native() != js_fun_apply)
     {
         return abort("fun.apply speculation failed");
     }
 
@@ -3862,92 +3842,54 @@ IonBuilder::jsop_funapplyarguments(uint3
     MPassArg *passFunc = current->pop()->toPassArg();
     MDefinition *argFunc = passFunc->getArgument();
     passFunc->replaceAllUsesWith(argFunc);
     passFunc->block()->discard(passFunc);
 
     // Pop apply function.
     current->pop();
 
-    return makeCall(target, false, false, argFunc, thisArg, args);
+    return makeCall(target, false, argFunc, thisArg, args);
 }
 
 bool
 IonBuilder::jsop_call(uint32_t argc, bool constructing)
 {
     AssertCanGC();
 
     // Acquire known call target if existent.
-    AutoObjectVector originals(cx);
-    uint32_t numTargets = getPolyCallTargets(argc, pc, originals, 4);
+    AutoObjectVector targets(cx);
+    uint32_t numTargets = getPolyCallTargets(argc, pc, targets, 4);
     types::StackTypeSet *barrier;
     types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
 
-    // If any call targets need to be cloned, clone them. Keep track of the
-    // originals as we need to case on them for poly inline.
-    bool hasClones = false;
-    AutoObjectVector targets(cx);
-    RootedFunction fun(cx);
-    RootedScript scriptRoot(cx, script());
-    for (uint32_t i = 0; i < numTargets; i++) {
-        fun = originals[i]->toFunction();
-        if (fun->isCloneAtCallsite()) {
-            fun = CloneFunctionAtCallsite(cx, fun, scriptRoot, pc);
-            if (!fun)
-                return false;
-            hasClones = true;
-        }
-        if (!targets.append(fun))
-            return false;
-    }
-
     // Attempt to inline native and scripted functions.
     if (inliningEnabled()) {
         // Inline a single native call if possible.
         if (numTargets == 1 && targets[0]->toFunction()->isNative()) {
             RootedFunction target(cx, targets[0]->toFunction());
             switch (inlineNativeCall(target->native(), argc, constructing)) {
               case InliningStatus_Inlined:
                 return true;
               case InliningStatus_Error:
                 return false;
               case InliningStatus_NotInlined:
                 break;
             }
         }
 
         if (numTargets > 0 && makeInliningDecision(targets, argc))
-            return inlineScriptedCall(targets, originals, argc, constructing, types, barrier);
+            return inlineScriptedCall(targets, argc, constructing, types, barrier);
     }
 
     RootedFunction target(cx, NULL);
     if (numTargets == 1)
         target = targets[0]->toFunction();
 
-    return makeCallBarrier(target, argc, constructing, hasClones, types, barrier);
-}
-
-MDefinition *
-IonBuilder::makeCallsiteClone(HandleFunction target, MDefinition *fun)
-{
-    // Bake in the clone eagerly if we have a known target. We have arrived here
-    // because TI told us that the known target is a should-clone-at-callsite
-    // function, which means that target already is the clone.
-    if (target) {
-        MConstant *constant = MConstant::New(ObjectValue(*target));
-        current->add(constant);
-        return constant;
-    }
-
-    // Add a callsite clone IC if we have multiple targets. Note that we
-    // should have checked already that at least some targets are marked as
-    // should-clone-at-callsite.
-    MCallsiteCloneCache *clone = MCallsiteCloneCache::New(fun, pc);
-    current->add(clone);
-    return clone;
+    return makeCallBarrier(target, argc, constructing, types, barrier);
 }
 
 static bool
 TestShouldDOMCall(JSContext *cx, types::TypeSet *inTypes, HandleFunction func,
                   JSJitInfo::OpType opType)
 {
     if (!func->isNative() || !func->jitInfo())
         return false;
@@ -4055,44 +3997,42 @@ IonBuilder::popFormals(uint32_t argc, MD
     for (int32_t i = argc; i > 0; i--)
         current->pop();
 
     *thisArg = current->pop()->toPassArg();
     *fun = current->pop();
 }
 
 MCall *
-IonBuilder::makeCallHelper(HandleFunction target, uint32_t argc, bool constructing,
-                           bool cloneAtCallsite)
+IonBuilder::makeCallHelper(HandleFunction target, uint32_t argc, bool constructing)
 {
     Vector<MPassArg *> args(cx);
     MPassArg *thisArg;
     MDefinition *fun;
 
     popFormals(argc, &fun, &thisArg, &args);
-    return makeCallHelper(target, constructing, cloneAtCallsite, fun, thisArg, args);
+    return makeCallHelper(target, constructing, fun, thisArg, args);
 }
 
 MCall *
-IonBuilder::makeCallHelper(HandleFunction target, bool constructing, bool cloneAtCallsite,
+IonBuilder::makeCallHelper(HandleFunction target, bool constructing,
                            MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args)
 {
     // This function may be called with mutated stack.
     // Querying TI for popped types is invalid.
 
     uint32_t argc = args.length();
     uint32_t targetArgs = argc;
 
     // Collect number of missing arguments provided that the target is
     // scripted. Native functions are passed an explicit 'argc' parameter.
     if (target && !target->isNative())
         targetArgs = Max<uint32_t>(target->nargs, argc);
 
-    MCall *call = MCall::New(target, targetArgs + 1, argc, constructing,
-                             target ? NULL : oracle->getCallTarget(script(), argc, pc));
+    MCall *call = MCall::New(target, targetArgs + 1, argc, constructing);
     if (!call)
         return NULL;
 
     // Explicitly pad any missing arguments with |undefined|.
     // This permits skipping the argumentsRectifier.
     for (int i = targetArgs; i > (int)argc; i--) {
         JS_ASSERT_IF(target, !target->isNative());
         MConstant *undef = MConstant::New(UndefinedValue());
@@ -4126,35 +4066,29 @@ IonBuilder::makeCallHelper(HandleFunctio
         thisArg->block()->discard(thisArg);
         current->add(newThis);
         thisArg = newThis;
     }
 
     // Pass |this| and function.
     call->addArg(0, thisArg);
 
-    // Add a callsite clone IC for multiple targets which all should be
-    // callsite cloned, or bake in the clone for a single target.
-    if (cloneAtCallsite)
-        fun = makeCallsiteClone(target, fun);
-
     if (target && JSOp(*pc) == JSOP_CALL) {
         // We know we have a single call target.  Check whether the "this" types
         // are DOM types and our function a DOM function, and if so flag the
         // MCall accordingly.
         types::StackTypeSet *thisTypes = oracle->getCallArg(script(), argc, 0, pc);
         if (thisTypes &&
             TestAreKnownDOMTypes(cx, thisTypes) &&
             TestShouldDOMCall(cx, thisTypes, target, JSJitInfo::Method))
         {
             FreezeDOMTypes(cx, thisTypes);
             call->setDOMFunction();
         }
     }
-
     call->initFunction(fun);
 
     current->add(call);
     return call;
 }
 
 static types::StackTypeSet*
 AdjustTypeBarrierForDOMCall(const JSJitInfo* jitinfo, types::StackTypeSet *types,
@@ -4174,37 +4108,36 @@ AdjustTypeBarrierForDOMCall(const JSJitI
         return barrier;
     
     // No need for a barrier if we're already expecting the type we'll produce.
     return NULL;
 }
 
 bool
 IonBuilder::makeCallBarrier(HandleFunction target, uint32_t argc,
-                            bool constructing, bool cloneAtCallsite,
+                            bool constructing,
                             types::StackTypeSet *types,
                             types::StackTypeSet *barrier)
 {
     Vector<MPassArg *> args(cx);
     MPassArg *thisArg;
     MDefinition *fun;
 
     popFormals(argc, &fun, &thisArg, &args);
-    return makeCallBarrier(target, constructing, cloneAtCallsite,
-                           fun, thisArg, args, types, barrier);
+    return makeCallBarrier(target, constructing, fun, thisArg, args, types, barrier);
 }
 
 bool
-IonBuilder::makeCallBarrier(HandleFunction target, bool constructing, bool cloneAtCallsite,
+IonBuilder::makeCallBarrier(HandleFunction target, bool constructing,
                             MDefinition *fun, MPassArg *thisArg,
                             Vector<MPassArg *> &args,
                             types::StackTypeSet *types,
                             types::StackTypeSet *barrier)
 {
-    MCall *call = makeCallHelper(target, constructing, cloneAtCallsite, fun, thisArg, args);
+    MCall *call = makeCallHelper(target, constructing, fun, thisArg, args);
     if (!call)
         return false;
 
     current->push(call);
     if (!resumeAfter(call))
         return false;
 
     if (call->isDOMFunction()) {
@@ -4212,35 +4145,34 @@ IonBuilder::makeCallBarrier(HandleFuncti
         JS_ASSERT(target && target->isNative() && target->jitInfo());
         barrier = AdjustTypeBarrierForDOMCall(target->jitInfo(), types, barrier);
     }
 
     return pushTypeBarrier(call, types, barrier);
 }
 
 bool
-IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing, bool cloneAtCallsite)
+IonBuilder::makeCall(HandleFunction target, uint32_t argc, bool constructing)
 {
     Vector<MPassArg *> args(cx);
     MPassArg *thisArg;
     MDefinition *fun;
 
     popFormals(argc, &fun, &thisArg, &args);
-    return makeCall(target, constructing, cloneAtCallsite, fun, thisArg, args);
+    return makeCall(target, constructing, fun, thisArg, args);
 }
 
 bool
-IonBuilder::makeCall(HandleFunction target, bool constructing, bool cloneAtCallsite,
+IonBuilder::makeCall(HandleFunction target, bool constructing,
                      MDefinition *fun, MPassArg *thisArg,
                      Vector<MPassArg*> &args)
 {
     types::StackTypeSet *barrier;
     types::StackTypeSet *types = oracle->returnTypeSet(script(), pc, &barrier);
-    return makeCallBarrier(target, constructing, cloneAtCallsite,
-                           fun, thisArg, args, types, barrier);
+    return makeCallBarrier(target, constructing, fun, thisArg, args, types, barrier);
 }
 
 bool
 IonBuilder::jsop_compare(JSOp op)
 {
     MDefinition *right = current->pop();
     MDefinition *left = current->pop();
 
@@ -6347,17 +6279,17 @@ IonBuilder::getPropTryCommonGetter(bool 
 
     // Spoof stack to expected state for call.
     pushConstant(ObjectValue(*commonGetter));
 
     MPassArg *wrapper = MPassArg::New(obj);
     current->add(wrapper);
     current->push(wrapper);
 
-    if (!makeCallBarrier(getter, 0, false, false, types, barrier))
+    if (!makeCallBarrier(getter, 0, false, types, barrier))
         return false;
 
     *emitted = true;
     return true;
 }
 
 bool
 IonBuilder::getPropTryMonomorphic(bool *emitted, HandleId id, types::StackTypeSet *barrier,
@@ -6513,17 +6445,17 @@ IonBuilder::jsop_setprop(HandlePropertyN
         current->add(wrapper);
 
         MPassArg *arg = MPassArg::New(value);
         current->push(arg);
         current->add(arg);
 
         // Call the setter. Note that we have to push the original value, not
         // the setter's return value.
-        MCall *call = makeCallHelper(setter, 1, false, false);
+        MCall *call = makeCallHelper(setter, 1, false);
         if (!call)
             return false;
 
         current->push(value);
         return resumeAfter(call);
     }
 
     oracle->binaryOp(script(), pc);
--- a/js/src/ion/IonBuilder.h
+++ b/js/src/ion/IonBuilder.h
@@ -414,51 +414,46 @@ class IonBuilder : public MIRGenerator
     // RegExp natives.
     InliningStatus inlineRegExpTest(uint32_t argc, bool constructing);
 
     InliningStatus inlineNativeCall(JSNative native, uint32_t argc, bool constructing);
 
     bool jsop_call_inline(HandleFunction callee, uint32_t argc, bool constructing,
                           MConstant *constFun, MBasicBlock *bottom,
                           Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns);
-    bool inlineScriptedCall(AutoObjectVector &targets, AutoObjectVector &originals,
-                            uint32_t argc, bool constructing,
+    bool inlineScriptedCall(AutoObjectVector &targets, uint32_t argc, bool constructing,
                             types::StackTypeSet *types, types::StackTypeSet *barrier);
     bool makeInliningDecision(AutoObjectVector &targets, uint32_t argc);
 
-    bool anyFunctionIsCloneAtCallsite(types::StackTypeSet *funTypes);
-    MDefinition *makeCallsiteClone(HandleFunction target, MDefinition *fun);
     void popFormals(uint32_t argc, MDefinition **fun, MPassArg **thisArg,
                     Vector<MPassArg *> *args);
-    MCall *makeCallHelper(HandleFunction target, bool constructing, bool cloneAtCallsite,
+    MCall *makeCallHelper(HandleFunction target, bool constructing,
                           MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args);
-    MCall *makeCallHelper(HandleFunction target, uint32_t argc, bool constructing,
-                          bool cloneAtCallsite);
+    MCall *makeCallHelper(HandleFunction target, uint32_t argc, bool constructing);
     bool makeCallBarrier(HandleFunction target, uint32_t argc, bool constructing,
-                         bool cloneAtCallsite, types::StackTypeSet *types,
-                         types::StackTypeSet *barrier);
-    bool makeCallBarrier(HandleFunction target, bool constructing, bool cloneAtCallsite,
+                         types::StackTypeSet *types, types::StackTypeSet *barrier);
+    bool makeCallBarrier(HandleFunction target, bool constructing,
                          MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args,
                          types::StackTypeSet *types, types::StackTypeSet *barrier);
-    bool makeCall(HandleFunction target, uint32_t argc, bool constructing, bool cloneAtCallsite);
-    bool makeCall(HandleFunction target, bool constructing, bool cloneAtCallsite,
+    bool makeCall(HandleFunction target, uint32_t argc, bool constructing);
+    bool makeCall(HandleFunction target, bool constructing,
                   MDefinition *fun, MPassArg *thisArg, Vector<MPassArg *> &args);
 
     inline bool TestCommonPropFunc(JSContext *cx, types::StackTypeSet *types,
                                    HandleId id, JSFunction **funcp,
                                    bool isGetter, bool *isDOM,
                                    MDefinition **guardOut);
 
     bool annotateGetPropertyCache(JSContext *cx, MDefinition *obj, MGetPropertyCache *getPropCache,
                                   types::StackTypeSet *objTypes, types::StackTypeSet *pushedTypes);
 
     MGetPropertyCache *checkInlineableGetPropertyCache(uint32_t argc);
 
     MPolyInlineDispatch *
-    makePolyInlineDispatch(JSContext *cx, int argc,
+    makePolyInlineDispatch(JSContext *cx, AutoObjectVector &targets, int argc,
                            MGetPropertyCache *getPropCache,
                            types::StackTypeSet *types, types::StackTypeSet *barrier,
                            MBasicBlock *bottom,
                            Vector<MDefinition *, 8, IonAllocPolicy> &retvalDefns);
 
     const types::StackTypeSet *cloneTypeSet(const types::StackTypeSet *types);
 
     // A builder is inextricably tied to a particular script.
--- a/js/src/ion/IonCaches.cpp
+++ b/js/src/ion/IonCaches.cpp
@@ -2085,77 +2085,8 @@ js::ion::GetNameCache(JSContext *cx, siz
             return false;
     }
 
     // Monitor changes to cache entry.
     types::TypeScript::Monitor(cx, script, pc, vp);
 
     return true;
 }
-
-bool
-IonCacheCallsiteClone::attach(JSContext *cx, IonScript *ion, HandleFunction original,
-                              HandleFunction clone)
-{
-    MacroAssembler masm;
-
-    // Guard against object identity on the original.
-    RepatchLabel exit;
-    CodeOffsetJump exitOffset = masm.branchPtrWithPatch(Assembler::NotEqual, calleeReg(),
-                                                        ImmWord(uintptr_t(original.get())), &exit);
-    masm.bind(&exit);
-
-    // Load the clone.
-    masm.movePtr(ImmWord(uintptr_t(clone.get())), outputReg());
-
-    RepatchLabel rejoin;
-    CodeOffsetJump rejoinOffset = masm.jumpWithPatch(&rejoin);
-    masm.bind(&rejoin);
-
-    Linker linker(masm);
-    IonCode *code = linker.newCode(cx);
-    if (!code)
-        return false;
-
-    rejoinOffset.fixup(&masm);
-    exitOffset.fixup(&masm);
-
-    if (ion->invalidated())
-        return true;
-
-    CodeLocationJump rejoinJump(code, rejoinOffset);
-    CodeLocationJump exitJump(code, exitOffset);
-    CodeLocationJump lastJump_ = lastJump();
-    PatchJump(lastJump_, CodeLocationLabel(code));
-    PatchJump(rejoinJump, rejoinLabel());
-    PatchJump(exitJump, cacheLabel());
-    updateLastJump(exitJump);
-
-    IonSpew(IonSpew_InlineCaches, "Generated CALL callee clone stub at %p", code->raw());
-    return true;
-}
-
-JSObject *
-js::ion::CallsiteCloneCache(JSContext *cx, size_t cacheIndex, HandleObject callee)
-{
-    AutoFlushCache afc ("CallsiteCloneCache");
-
-    // Act as the identity for functions that are not clone-at-callsite, as we
-    // generate this cache as long as some callees are clone-at-callsite.
-    RootedFunction fun(cx, callee->toFunction());
-    if (!fun->isCloneAtCallsite())
-        return fun;
-
-    IonScript *ion = GetTopIonJSScript(cx)->ionScript();
-    IonCacheCallsiteClone &cache = ion->getCache(cacheIndex).toCallsiteClone();
-
-    RootedFunction clone(cx, CloneFunctionAtCallsite(cx, fun, cache.callScript(), cache.callPc()));
-    if (!clone)
-        return NULL;
-
-    if (cache.stubCount() < MAX_STUBS) {
-        if (!cache.attach(cx, ion, fun, clone))
-            return NULL;
-        cache.incrementStubCount();
-    }
-
-    return clone;
-}
--- a/js/src/ion/IonCaches.h
+++ b/js/src/ion/IonCaches.h
@@ -18,17 +18,16 @@ class JSScript;
 namespace js {
 namespace ion {
 
 class IonCacheGetProperty;
 class IonCacheSetProperty;
 class IonCacheGetElement;
 class IonCacheBindName;
 class IonCacheName;
-class IonCacheCallsiteClone;
 
 // Common structure encoding the state of a polymorphic inline cache contained
 // in the code for an IonScript. IonCaches are used for polymorphic operations
 // where multiple implementations may be required.
 //
 // The cache is initially compiled as a patchable jump to an out of line
 // fragment which invokes a cache function to perform the operation. The cache
 // function may generate a stub to perform the operation in certain cases
@@ -83,18 +82,17 @@ class IonCache
   public:
     enum Kind {
         Invalid = 0,
         GetProperty,
         SetProperty,
         GetElement,
         BindName,
         Name,
-        NameTypeOf,
-        CallsiteClone
+        NameTypeOf
     };
 
   protected:
     Kind kind_ : 8;
     bool pure_ : 1;
     bool idempotent_ : 1;
     size_t stubCount_ : 6;
 
@@ -135,22 +133,16 @@ class IonCache
             PropertyName *name;
             Register output;
         } bindname;
         struct {
             Register scopeChain;
             PropertyName *name;
             TypedOrValueRegisterSpace output;
         } name;
-        struct {
-            Register callee;
-            Register output;
-            JSScript *callScript;
-            jsbytecode *callPc;
-        } callsiteclone;
     } u;
 
     // Registers live after the cache, excluding output registers. The initial
     // value of these registers must be preserved by the cache.
     RegisterSet liveRegs;
 
     // Location of this operation, NULL for idempotent caches.
     JSScript *script;
@@ -232,20 +224,16 @@ class IonCache
     IonCacheBindName &toBindName() {
         JS_ASSERT(kind_ == BindName);
         return *(IonCacheBindName *)this;
     }
     IonCacheName &toName() {
         JS_ASSERT(kind_ == Name || kind_ == NameTypeOf);
         return *(IonCacheName *)this;
     }
-    IonCacheCallsiteClone &toCallsiteClone() {
-        JS_ASSERT(kind_ == CallsiteClone);
-        return *(IonCacheCallsiteClone *)this;
-    }
 
     void setScriptedLocation(UnrootedScript script, jsbytecode *pc) {
         JS_ASSERT(!idempotent_);
         this->script = script;
         this->pc = pc;
     }
 
     void getScriptedLocation(MutableHandleScript pscript, jsbytecode **ppc) {
@@ -430,49 +418,16 @@ class IonCacheName : public IonCache
     bool isTypeOf() const {
         return kind_ == NameTypeOf;
     }
 
     bool attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject obj,
                 HandleShape shape);
 };
 
-class IonCacheCallsiteClone : public IonCache
-{
-  public:
-    IonCacheCallsiteClone(CodeOffsetJump initialJump,
-                          CodeOffsetLabel rejoinLabel,
-                          CodeOffsetLabel cacheLabel,
-                          RegisterSet liveRegs,
-                          Register callee, JSScript *callScript, jsbytecode *callPc,
-                          Register output)
-    {
-        init(CallsiteClone, liveRegs, initialJump, rejoinLabel, cacheLabel);
-        u.callsiteclone.callee = callee;
-        u.callsiteclone.callScript = callScript;
-        u.callsiteclone.callPc = callPc;
-        u.callsiteclone.output = output;
-    }
-
-    Register calleeReg() const {
-        return u.callsiteclone.callee;
-    }
-    HandleScript callScript() const {
-        return HandleScript::fromMarkedLocation(&u.callsiteclone.callScript);
-    }
-    jsbytecode *callPc() const {
-        return u.callsiteclone.callPc;
-    }
-    Register outputReg() const {
-        return u.callsiteclone.output;
-    }
-
-    bool attach(JSContext *cx, IonScript *ion, HandleFunction original, HandleFunction clone);
-};
-
 bool
 GetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, MutableHandleValue vp);
 
 bool
 SetPropertyCache(JSContext *cx, size_t cacheIndex, HandleObject obj, HandleValue value,
                  bool isSetName);
 
 bool
@@ -480,15 +435,12 @@ GetElementCache(JSContext *cx, size_t ca
                 MutableHandleValue vp);
 
 JSObject *
 BindNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain);
 
 bool
 GetNameCache(JSContext *cx, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp);
 
-JSObject *
-CallsiteCloneCache(JSContext *cx, size_t cacheIndex, HandleObject callee);
-
 } // namespace ion
 } // namespace js
 
 #endif // jsion_caches_h__
--- a/js/src/ion/LIR-Common.h
+++ b/js/src/ion/LIR-Common.h
@@ -2806,32 +2806,16 @@ class LCallGetIntrinsicValue : public LC
     LIR_HEADER(CallGetIntrinsicValue)
     BOX_OUTPUT_ACCESSORS()
 
     const MCallGetIntrinsicValue *mir() const {
         return mir_->toCallGetIntrinsicValue();
     }
 };
 
-class LCallsiteCloneCache : public LInstructionHelper<1, 1, 0>
-{
-  public:
-    LIR_HEADER(CallsiteCloneCache);
-
-    LCallsiteCloneCache(const LAllocation &callee) {
-        setOperand(0, callee);
-    }
-    const LAllocation *callee() {
-        return getOperand(0);
-    }
-    const MCallsiteCloneCache *mir() const {
-        return mir_->toCallsiteCloneCache();
-    }
-};
-
 // Patchable jump to stubs generated for a GetProperty cache, which loads a
 // boxed value.
 class LGetPropertyCacheV : public LInstructionHelper<BOX_PIECES, 1, 0>
 {
   public:
     LIR_HEADER(GetPropertyCacheV)
     BOX_OUTPUT_ACCESSORS()
 
--- a/js/src/ion/LOpcodes.h
+++ b/js/src/ion/LOpcodes.h
@@ -149,17 +149,16 @@
     _(FunctionEnvironment)          \
     _(GetPropertyCacheV)            \
     _(GetPropertyCacheT)            \
     _(GetElementCacheV)             \
     _(BindNameCache)                \
     _(CallGetProperty)              \
     _(GetNameCache)                 \
     _(CallGetIntrinsicValue)        \
-    _(CallsiteCloneCache)           \
     _(CallGetElement)               \
     _(CallSetElement)               \
     _(CallSetProperty)              \
     _(CallDeleteProperty)           \
     _(SetPropertyCacheV)            \
     _(SetPropertyCacheT)            \
     _(CallIteratorStart)            \
     _(IteratorStart)                \
--- a/js/src/ion/Lowering.cpp
+++ b/js/src/ion/Lowering.cpp
@@ -1880,27 +1880,16 @@ LIRGenerator::visitCallGetIntrinsicValue
 {
     LCallGetIntrinsicValue *lir = new LCallGetIntrinsicValue();
     if (!defineReturn(lir, ins))
         return false;
     return assignSafepoint(lir, ins);
 }
 
 bool
-LIRGenerator::visitCallsiteCloneCache(MCallsiteCloneCache *ins)
-{
-    JS_ASSERT(ins->callee()->type() == MIRType_Object);
-
-    LCallsiteCloneCache *lir = new LCallsiteCloneCache(useRegister(ins->callee()));
-    if (!define(lir, ins))
-        return false;
-    return assignSafepoint(lir, ins);
-}
-
-bool
 LIRGenerator::visitGetPropertyCache(MGetPropertyCache *ins)
 {
     JS_ASSERT(ins->object()->type() == MIRType_Object);
     if (ins->type() == MIRType_Value) {
         LGetPropertyCacheV *lir = new LGetPropertyCacheV(useRegister(ins->object()));
         if (!defineBox(lir, ins))
             return false;
         return assignSafepoint(lir, ins);
--- a/js/src/ion/Lowering.h
+++ b/js/src/ion/Lowering.h
@@ -170,17 +170,16 @@ class LIRGenerator : public LIRGenerator
     bool visitBindNameCache(MBindNameCache *ins);
     bool visitGuardClass(MGuardClass *ins);
     bool visitGuardObject(MGuardObject *ins);
     bool visitGuardString(MGuardString *ins);
     bool visitCallGetProperty(MCallGetProperty *ins);
     bool visitDeleteProperty(MDeleteProperty *ins);
     bool visitGetNameCache(MGetNameCache *ins);
     bool visitCallGetIntrinsicValue(MCallGetIntrinsicValue *ins);
-    bool visitCallsiteCloneCache(MCallsiteCloneCache *ins);
     bool visitCallGetElement(MCallGetElement *ins);
     bool visitCallSetElement(MCallSetElement *ins);
     bool visitSetPropertyCache(MSetPropertyCache *ins);
     bool visitCallSetProperty(MCallSetProperty *ins);
     bool visitIteratorStart(MIteratorStart *ins);
     bool visitIteratorNext(MIteratorNext *ins);
     bool visitIteratorMore(MIteratorMore *ins);
     bool visitIteratorEnd(MIteratorEnd *ins);
--- a/js/src/ion/MIR.cpp
+++ b/js/src/ion/MIR.cpp
@@ -390,21 +390,20 @@ MParameter::congruentTo(MDefinition * co
 {
     if (!ins->isParameter())
         return false;
 
     return ins->toParameter()->index() == index_;
 }
 
 MCall *
-MCall::New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct,
-           types::StackTypeSet *calleeTypes)
+MCall::New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct)
 {
     JS_ASSERT(maxArgc >= numActualArgs);
-    MCall *ins = new MCall(target, numActualArgs, construct, calleeTypes);
+    MCall *ins = new MCall(target, numActualArgs, construct);
     if (!ins->init(maxArgc + NumNonArgumentOperands))
         return NULL;
     return ins;
 }
 
 MApplyArgs *
 MApplyArgs::New(JSFunction *target, MDefinition *fun, MDefinition *argc, MDefinition *self)
 {
--- a/js/src/ion/MIR.h
+++ b/js/src/ion/MIR.h
@@ -1166,33 +1166,28 @@ class MCall
 
   protected:
     // True if the call is for JSOP_NEW.
     bool construct_;
     // Monomorphic cache of single target from TI, or NULL.
     CompilerRootFunction target_;
     // Original value of argc from the bytecode.
     uint32_t numActualArgs_;
-    // The typeset of the callee, could be NULL.
-    types::StackTypeSet *calleeTypes_;
-
-    MCall(JSFunction *target, uint32_t numActualArgs, bool construct,
-          types::StackTypeSet *calleeTypes)
+
+    MCall(JSFunction *target, uint32_t numActualArgs, bool construct)
       : construct_(construct),
         target_(target),
-        numActualArgs_(numActualArgs),
-        calleeTypes_(calleeTypes)
+        numActualArgs_(numActualArgs)
     {
         setResultType(MIRType_Value);
     }
 
   public:
     INSTRUCTION_HEADER(Call)
-    static MCall *New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct,
-                      types::StackTypeSet *calleeTypes);
+    static MCall *New(JSFunction *target, size_t maxArgc, size_t numActualArgs, bool construct);
 
     void initPrepareCall(MDefinition *start) {
         JS_ASSERT(start->isPrepareCall());
         return initOperand(PrepareCallOperandIndex, start);
     }
     void initFunction(MDefinition *func) {
         JS_ASSERT(!func->isPassArg());
         return initOperand(FunctionOperandIndex, func);
@@ -1214,19 +1209,16 @@ class MCall
     // For TI-informed monomorphic callsites.
     JSFunction *getSingleTarget() const {
         return target_;
     }
 
     bool isConstructing() const {
         return construct_;
     }
-    types::StackTypeSet *calleeTypes() const {
-        return calleeTypes_;
-    }
 
     // The number of stack arguments is the max between the number of formal
     // arguments and the number of actual arguments. The number of stack
     // argument includes the |undefined| padding added in case of underflow.
     // Includes |this|.
     uint32_t numStackArgs() const {
         return numOperands() - NumNonArgumentOperands;
     }
@@ -4346,26 +4338,22 @@ class InlinePropertyTable : public TempO
         return entries_[i]->typeObj;
     }
 
     JSFunction *getFunction(size_t i) const {
         JS_ASSERT(i < numEntries());
         return entries_[i]->func;
     }
 
-    void trimToAndMaybePatchTargets(AutoObjectVector &targets, AutoObjectVector &originals) {
+    void trimToTargets(AutoObjectVector &targets) {
         size_t i = 0;
         while (i < numEntries()) {
             bool foundFunc = false;
-            // Compare using originals, but if we find a matching function,
-            // patch it to the target, which might be a clone.
-            for (size_t j = 0; j < originals.length(); j++) {
-                if (entries_[i]->func == originals[j]) {
-                    if (entries_[i]->func != targets[j])
-                        entries_[i] = new Entry(entries_[i]->typeObj, targets[j]->toFunction());
+            for (size_t j = 0; j < targets.length(); j++) {
+                if (entries_[i]->func == targets[j]) {
                     foundFunc = true;
                     break;
                 }
             }
             if (!foundFunc)
                 entries_.erase(&(entries_[i]));
             else
                 i++;
@@ -4983,51 +4971,16 @@ class MCallGetIntrinsicValue : public MN
     static MCallGetIntrinsicValue *New(HandlePropertyName name) {
         return new MCallGetIntrinsicValue(name);
     }
     PropertyName *name() const {
         return name_;
     }
 };
 
-class MCallsiteCloneCache
-  : public MUnaryInstruction,
-    public SingleObjectPolicy
-{
-    jsbytecode *callPc_;
-
-    MCallsiteCloneCache(MDefinition *callee, jsbytecode *callPc)
-      : MUnaryInstruction(callee),
-        callPc_(callPc)
-    {
-        setResultType(MIRType_Object);
-    }
-
-  public:
-    INSTRUCTION_HEADER(CallsiteCloneCache);
-
-    static MCallsiteCloneCache *New(MDefinition *callee, jsbytecode *callPc) {
-        return new MCallsiteCloneCache(callee, callPc);
-    }
-    TypePolicy *typePolicy() {
-        return this;
-    }
-    MDefinition *callee() const {
-        return getOperand(0);
-    }
-    jsbytecode *callPc() const {
-        return callPc_;
-    }
-
-    // Callsite cloning is idempotent.
-    AliasSet getAliasSet() const {
-        return AliasSet::None();
-    }
-};
-
 class MSetPropertyInstruction : public MBinaryInstruction
 {
     CompilerRootPropertyName name_;
     bool strict_;
     bool needsBarrier_;
 
   protected:
     MSetPropertyInstruction(MDefinition *obj, MDefinition *value, HandlePropertyName name,
--- a/js/src/ion/MOpcodes.h
+++ b/js/src/ion/MOpcodes.h
@@ -118,17 +118,16 @@ namespace ion {
     _(LoadTypedArrayElementHole)                                            \
     _(StoreTypedArrayElement)                                               \
     _(ClampToUint8)                                                         \
     _(LoadFixedSlot)                                                        \
     _(StoreFixedSlot)                                                       \
     _(CallGetProperty)                                                      \
     _(GetNameCache)                                                         \
     _(CallGetIntrinsicValue)                                                \
-    _(CallsiteCloneCache)                                                   \
     _(CallGetElement)                                                       \
     _(CallSetElement)                                                       \
     _(CallSetProperty)                                                      \
     _(DeleteProperty)                                                       \
     _(SetPropertyCache)                                                     \
     _(IteratorStart)                                                        \
     _(IteratorNext)                                                         \
     _(IteratorMore)                                                         \
--- a/js/src/ion/VMFunctions.cpp
+++ b/js/src/ion/VMFunctions.cpp
@@ -42,37 +42,25 @@ static inline bool
 ShouldMonitorReturnType(JSFunction *fun)
 {
     return fun->isInterpreted() &&
            (!fun->nonLazyScript()->hasAnalysis() ||
             !fun->nonLazyScript()->analysis()->ranInference());
 }
 
 bool
-InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, Value *rval)
+InvokeFunction(JSContext *cx, HandleFunction fun, uint32_t argc, Value *argv, Value *rval)
 {
     AssertCanGC();
 
-    RootedFunction fun(cx, fun0);
-
     // In order to prevent massive bouncing between Ion and JM, see if we keep
     // hitting functions that are uncompilable.
     if (fun->isInterpreted()) {
         if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
             return false;
-
-        if (fun->isCloneAtCallsite()) {
-            RootedScript script(cx);
-            jsbytecode *pc;
-            types::TypeScript::GetPcScript(cx, &script, &pc);
-            fun = CloneFunctionAtCallsite(cx, fun0, script, pc);
-            if (!fun)
-                return false;
-        }
-
         if (!fun->nonLazyScript()->canIonCompile()) {
             UnrootedScript script = GetTopIonJSScript(cx);
             if (script->hasIonScript() &&
                 ++script->ion->slowCallCount >= js_IonOptions.slowCallLimit)
             {
                 AutoFlushCache afc("InvokeFunction");
 
                 // Poison the script so we don't try to run it again. This will
--- a/js/src/ion/VMFunctions.h
+++ b/js/src/ion/VMFunctions.h
@@ -405,17 +405,17 @@ class AutoDetectInvalidation
     }
 
     ~AutoDetectInvalidation() {
         if (!disabled_ && ionScript_->invalidated())
             cx_->runtime->setIonReturnOverride(*rval_);
     }
 };
 
-bool InvokeFunction(JSContext *cx, HandleFunction fun0, uint32_t argc, Value *argv, Value *rval);
+bool InvokeFunction(JSContext *cx, HandleFunction fun, uint32_t argc, Value *argv, Value *rval);
 JSObject *NewGCThing(JSContext *cx, gc::AllocKind allocKind, size_t thingSize);
 
 bool CheckOverRecursed(JSContext *cx);
 
 bool DefVarOrConst(JSContext *cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
 bool InitProp(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValue value);
 
 template<bool Equal>
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -237,68 +237,16 @@ JSRuntime::createJaegerRuntime(JSContext
         return NULL;
     }
 
     jaegerRuntime_ = jr;
     return jaegerRuntime_;
 }
 #endif
 
-void
-JSCompartment::sweepCallsiteClones()
-{
-    if (callsiteClones.initialized()) {
-        for (CallsiteCloneTable::Enum e(callsiteClones); !e.empty(); e.popFront()) {
-            CallsiteCloneKey key = e.front().key;
-            JSFunction *fun = e.front().value;
-            if (!key.script->isMarked() || !fun->isMarked())
-                e.removeFront();
-        }
-    }
-}
-
-RawFunction
-js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
-{
-    JS_ASSERT(cx->typeInferenceEnabled());
-    JS_ASSERT(fun->isCloneAtCallsite());
-    JS_ASSERT(types::UseNewTypeForClone(fun));
-    JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
-
-    typedef CallsiteCloneKey Key;
-    typedef CallsiteCloneTable Table;
-
-    Table &table = cx->compartment->callsiteClones;
-    if (!table.initialized() && !table.init())
-        return NULL;
-
-    Key key;
-    key.script = script;
-    key.offset = pc - script->code;
-    key.original = fun;
-
-    Table::AddPtr p = table.lookupForAdd(key);
-    if (p)
-        return p->value;
-
-    RootedObject parent(cx, fun->environment());
-    RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent,
-                                                 JSFunction::ExtendedFinalizeKind));
-    if (!clone)
-        return NULL;
-
-    // Store a link back to the original for function.caller.
-    clone->setExtendedSlot(0, ObjectValue(*fun));
-
-    if (!table.add(p, key, clone.get()))
-        return NULL;
-
-    return clone;
-}
-
 JSContext *
 js::NewContext(JSRuntime *rt, size_t stackChunkSize)
 {
     JS_AbortIfWrongThread(rt);
 
     JSContext *cx = js_new<JSContext>(rt);
     if (!cx)
         return NULL;
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -53,49 +53,16 @@ js_ReportOutOfMemory(JSContext *cx);
 
 extern void
 js_ReportAllocationOverflow(JSContext *cx);
 
 namespace js {
 
 typedef HashSet<JSObject *> ObjectSet;
 
-struct CallsiteCloneKey {
-    /* The original function that we are cloning. */
-    JSFunction *original;
-
-    /* The script of the call. */
-    JSScript *script;
-
-    /* The offset of the call. */
-    uint32_t offset;
-
-    CallsiteCloneKey() { PodZero(this); }
-
-    typedef CallsiteCloneKey Lookup;
-
-    static inline uint32_t hash(CallsiteCloneKey key) {
-        return uint32_t(size_t(key.script->code + key.offset) ^ size_t(key.original));
-    }
-
-    static inline bool match(const CallsiteCloneKey &a, const CallsiteCloneKey &b) {
-        return a.script == b.script && a.offset == b.offset && a.original == b.original;
-    }
-};
-
-typedef HashMap<CallsiteCloneKey,
-                ReadBarriered<JSFunction>,
-                CallsiteCloneKey,
-                SystemAllocPolicy> CallsiteCloneTable;
-
-RawFunction CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun,
-                                    HandleScript script, jsbytecode *pc);
-
-typedef HashSet<JSObject *> ObjectSet;
-
 /* Detects cycles when traversing an object graph. */
 class AutoCycleDetector
 {
     JSContext *cx;
     JSObject *obj;
     bool cyclic;
     uint32_t hashsetGenerationAtInit;
     ObjectSet::AddPtr hashsetAddPointer;
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -645,17 +645,16 @@ JSCompartment::sweep(FreeOp *fop, bool r
 
         /* Remove dead references held weakly by the compartment. */
 
         sweepBaseShapeTable();
         sweepInitialShapeTable();
         sweepNewTypeObjectTable(newTypeObjects);
         sweepNewTypeObjectTable(lazyTypeObjects);
         sweepBreakpoints(fop);
-        sweepCallsiteClones();
 
         if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet()))
             global_ = NULL;
 
 #ifdef JS_ION
         if (ionCompartment_)
             ionCompartment_->sweep(fop);
 #endif
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -345,24 +345,16 @@ struct JSCompartment : private JS::shado
     void sweepNewTypeObjectTable(js::types::TypeObjectSet &table);
 
     js::types::TypeObject *getNewType(JSContext *cx, js::TaggedProto proto,
                                       JSFunction *fun = NULL, bool isDOM = false);
 
     js::types::TypeObject *getLazyType(JSContext *cx, js::Handle<js::TaggedProto> proto);
 
     /*
-     * Hash table of all manually call site-cloned functions from within
-     * self-hosted code. Cloning according to call site provides extra
-     * sensitivity for type specialization and inlining.
-     */
-    js::CallsiteCloneTable callsiteClones;
-    void sweepCallsiteClones();
-
-    /*
      * Keeps track of the total number of malloc bytes connected to a
      * compartment's GC things. This counter should be used in preference to
      * gcMallocBytes. These counters affect collection in the same way as
      * gcBytes and gcTriggerBytes.
      */
     size_t                       gcMallocAndFreeBytes;
     size_t                       gcTriggerMallocAndFreeBytes;
 
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -80,23 +80,16 @@ fun_getProperty(JSContext *cx, HandleObj
         if (!JSObject::getProto(cx, obj, &obj))
             return false;
         if (!obj)
             return true;
     }
     RootedFunction fun(cx, obj->toFunction());
 
     /*
-     * Callsite clones should never escape to script, so get the original
-     * function.
-     */
-    if (fun->isCallsiteClone())
-        fun = fun->getExtendedSlot(0).toObject().toFunction();
-
-    /*
      * Mark the function's script as uninlineable, to expand any of its
      * frames on the stack before we go looking for them. This allows the
      * below walk to only check each explicit frame rather than needing to
      * check any calls that were inlined.
      */
     if (fun->isInterpreted()) {
         JSFunction::getOrCreateScript(cx, fun)->uninlineable = true;
         MarkTypeObjectFlags(cx, fun, OBJECT_FLAG_UNINLINEABLE);
@@ -1516,18 +1509,39 @@ js_CloneFunctionObject(JSContext *cx, Ha
             return NULL;
 
         /*
          * Across compartments we have to clone the script for interpreted
          * functions. Cross-compartment cloning only happens via JSAPI
          * (JS_CloneFunctionObject) which dynamically ensures that 'script' has
          * no enclosing lexical scope (only the global scope).
          */
-        if (clone->isInterpreted() && !CloneFunctionScript(cx, fun, clone))
-            return NULL;
+        if (clone->isInterpreted()) {
+            RootedScript script(cx, clone->nonLazyScript());
+            JS_ASSERT(script->compartment() == fun->compartment());
+            JS_ASSERT_IF(script->compartment() != cx->compartment,
+                         !script->enclosingStaticScope());
+
+            RootedObject scope(cx, script->enclosingStaticScope());
+
+            clone->mutableScript().init(NULL);
+
+            RootedScript cscript(cx, CloneScript(cx, scope, clone, script));
+            if (!cscript)
+                return NULL;
+
+            clone->setScript(cscript);
+            cscript->setFunction(clone);
+
+            GlobalObject *global = script->compileAndGo ? &script->global() : NULL;
+
+            script = clone->nonLazyScript();
+            CallNewScriptHook(cx, script, clone);
+            Debugger::onNewScript(cx, script, global);
+        }
     }
     return clone;
 }
 
 JSFunction *
 js_DefineFunction(JSContext *cx, HandleObject obj, HandleId id, Native native,
                   unsigned nargs, unsigned flags, AllocKind kind)
 {
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -39,23 +39,16 @@ class JSFunction : public JSObject
         SELF_HOSTED      = 0x0100,  /* function is self-hosted builtin and must not be
                                        decompilable nor constructible. */
         SELF_HOSTED_CTOR = 0x0200,  /* function is self-hosted builtin constructor and
                                        must be constructible but not decompilable. */
         HAS_REST         = 0x0400,  /* function has a rest (...) parameter */
         HAS_DEFAULTS     = 0x0800,  /* function has at least one default parameter */
         INTERPRETED_LAZY = 0x1000,  /* function is interpreted but doesn't have a script yet */
 
-        /*
-         * Function is cloned anew at each callsite. This is temporarily
-         * needed for ParallelArray selfhosted code until type information can
-         * be made context sensitive. See discussion in bug 826148.
-         */
-        CALLSITE_CLONE   = 0x2000,
-
         /* Derived Flags values for convenience: */
         NATIVE_FUN = 0,
         INTERPRETED_LAMBDA = INTERPRETED | LAMBDA
     };
 
     static void staticAsserts() {
         JS_STATIC_ASSERT(INTERPRETED == JS_FUNCTION_INTERPRETED_BIT);
         MOZ_STATIC_ASSERT(sizeof(JSFunction) == sizeof(js::shadow::Function),
@@ -102,21 +95,16 @@ class JSFunction : public JSObject
     bool isExprClosure()            const { return flags & EXPR_CLOSURE; }
     bool hasGuessedAtom()           const { return flags & HAS_GUESSED_ATOM; }
     bool isLambda()                 const { return flags & LAMBDA; }
     bool isSelfHostedBuiltin()      const { return flags & SELF_HOSTED; }
     bool isSelfHostedConstructor()  const { return flags & SELF_HOSTED_CTOR; }
     bool hasRest()                  const { return flags & HAS_REST; }
     bool hasDefaults()              const { return flags & HAS_DEFAULTS; }
 
-    /* Original functions that should be cloned are not extended. */
-    bool isCloneAtCallsite()        const { return (flags & CALLSITE_CLONE) && !isExtended(); }
-    /* Cloned functions keep a backlink to the original in extended slot 0. */
-    bool isCallsiteClone()          const { return (flags & CALLSITE_CLONE) && isExtended(); }
-
     /* Compound attributes: */
     bool isBuiltin() const {
         return isNative() || isSelfHostedBuiltin();
     }
     bool isInterpretedConstructor() const {
         return isInterpreted() && !isFunctionPrototype() &&
                (!isSelfHostedBuiltin() || isSelfHostedConstructor());
     }
@@ -148,20 +136,16 @@ class JSFunction : public JSObject
         flags |= SELF_HOSTED;
     }
 
     void setIsSelfHostedConstructor() {
         JS_ASSERT(!isSelfHostedConstructor());
         flags |= SELF_HOSTED_CTOR;
     }
 
-    void setIsCloneAtCallsite() {
-        flags |= CALLSITE_CLONE;
-    }
-
     void setIsFunctionPrototype() {
         JS_ASSERT(!isFunctionPrototype());
         flags |= IS_FUN_PROTO;
     }
 
     void setIsHeavyweight() {
         flags |= HEAVYWEIGHT;
     }
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -684,17 +684,16 @@ class TypeConstraintCall : public TypeCo
 
     TypeConstraintCall(TypeCallsite *callsite)
         : callsite(callsite)
     {}
 
     const char *kind() { return "call"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
-    bool newCallee(JSContext *cx, HandleFunction callee, HandleScript script);
 };
 
 void
 StackTypeSet::addCall(JSContext *cx, TypeCallsite *site)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintCall>(site));
 }
 
@@ -768,17 +767,16 @@ class TypeConstraintPropagateThis : publ
 
     TypeConstraintPropagateThis(UnrootedScript script, jsbytecode *callpc, Type type, StackTypeSet *types)
         : script_(script), callpc(callpc), type(type), types(types)
     {}
 
     const char *kind() { return "propagatethis"; }
 
     void newType(JSContext *cx, TypeSet *source, Type type);
-    bool newCallee(JSContext *cx, HandleFunction callee);
 };
 
 void
 StackTypeSet::addPropagateThis(JSContext *cx, HandleScript script, jsbytecode *pc,
                                Type type, StackTypeSet *types)
 {
     add(cx, cx->analysisLifoAlloc().new_<TypeConstraintPropagateThis>(script, pc, type, types));
 }
@@ -1253,33 +1251,16 @@ TypeConstraintSetElement::newType(JSCont
     RootedScript script(cx, script_);
     if (type.isUnknown() ||
         type.isPrimitive(JSVAL_TYPE_INT32) ||
         type.isPrimitive(JSVAL_TYPE_DOUBLE)) {
         objectTypes->addSetProperty(cx, script, pc, valueTypes, JSID_VOID);
     }
 }
 
-static inline RawFunction
-CloneCallee(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
-{
-    /*
-     * Clone called functions at appropriate callsites to match interpreter
-     * behavior.
-     */
-    RawFunction callee = CloneFunctionAtCallsite(cx, fun, script, pc);
-    if (!callee)
-        return NULL;
-
-    InferSpew(ISpewOps, "callsiteCloneType: #%u:%05u: %s",
-              script->id(), pc - script->code, TypeString(Type::ObjectType(callee)));
-
-    return callee;
-}
-
 void
 TypeConstraintCall::newType(JSContext *cx, TypeSet *source, Type type)
 {
     AssertCanGC();
     RootedScript script(cx, callsite->script);
     jsbytecode *pc = callsite->pc;
 
     JS_ASSERT_IF(script->hasAnalysis(),
@@ -1362,48 +1343,29 @@ TypeConstraintCall::newType(JSContext *c
         callee = type.typeObject()->interpretedFunction;
         if (!callee)
             return;
     } else {
         /* Calls on non-objects are dynamically monitored. */
         return;
     }
 
-    if (callee->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, callee))
+    RootedScript calleeScript(cx, JSFunction::getOrCreateScript(cx, callee));
+    if (!calleeScript)
         return;
-
-    /*
-     * As callsite cloning is a hint, we must propagate to both the original
-     * and the clone.
-     */
-    if (callee->isCloneAtCallsite()) {
-        RootedFunction clone(cx, CloneCallee(cx, callee, script, pc));
-        if (!clone)
-            return;
-        if (!newCallee(cx, clone, script))
-            return;
-    }
-
-    newCallee(cx, callee, script);
-}
-
-bool
-TypeConstraintCall::newCallee(JSContext *cx, HandleFunction callee, HandleScript script)
-{
-    RootedScript calleeScript(cx, callee->nonLazyScript());
     if (!calleeScript->ensureHasTypes(cx))
-        return false;
+        return;
 
     unsigned nargs = callee->nargs;
 
     /* Add bindings for the arguments of the call. */
     for (unsigned i = 0; i < callsite->argumentCount && i < nargs; i++) {
         StackTypeSet *argTypes = callsite->argumentTypes[i];
         StackTypeSet *types = TypeScript::ArgTypes(calleeScript, i);
-        argTypes->addSubsetBarrier(cx, script, callsite->pc, types);
+        argTypes->addSubsetBarrier(cx, script, pc, types);
     }
 
     /* Add void type for any formals in the callee not supplied at the call site. */
     for (unsigned i = callsite->argumentCount; i < nargs; i++) {
         TypeSet *types = TypeScript::ArgTypes(calleeScript, i);
         types->addType(cx, Type::UndefinedType());
     }
 
@@ -1425,33 +1387,31 @@ TypeConstraintCall::newCallee(JSContext 
          * binding for the receiver object, as this is done with PropagateThis
          * constraints added by the original JSOP_CALL* op. The type sets we
          * manipulate here have lost any correlations between particular types
          * in the 'this' and 'callee' sets, which we want to maintain for
          * polymorphic JSOP_CALLPROP invocations.
          */
         returnTypes->addSubset(cx, callsite->returnTypes);
     }
-
-    return true;
 }
 
 void
 TypeConstraintPropagateThis::newType(JSContext *cx, TypeSet *source, Type type)
 {
     AssertCanGC();
 
-    RootedScript script(cx, script_);
     if (type.isUnknown() || type.isAnyObject()) {
         /*
          * The callee is unknown, make sure the call is monitored so we pick up
          * possible this/callee correlations. This only comes into play for
          * CALLPROP, for other calls we are past the type barrier and a
          * TypeConstraintCall will also monitor the call.
          */
+        RootedScript script(cx, script_);
         cx->compartment->types.monitorBytecode(cx, script, callpc - script->code);
         return;
     }
 
     /* Ignore calls to natives, these will be handled by TypeConstraintCall. */
     RootedFunction callee(cx);
 
     if (type.isSingleObject()) {
@@ -1464,47 +1424,24 @@ TypeConstraintPropagateThis::newType(JSC
         if (!object->interpretedFunction)
             return;
         callee = object->interpretedFunction;
     } else {
         /* Ignore calls to primitives, these will go through a stub. */
         return;
     }
 
-    if (callee->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, callee))
+    if (!(JSFunction::getOrCreateScript(cx, callee) && callee->nonLazyScript()->ensureHasTypes(cx)))
         return;
 
-    /*
-     * As callsite cloning is a hint, we must propagate to both the original
-     * and the clone.
-     */
-    if (callee->isCloneAtCallsite()) {
-        RootedFunction clone(cx, CloneCallee(cx, callee, script, callpc));
-        if (!clone)
-            return;
-        if (!newCallee(cx, clone))
-            return;
-    }
-
-    newCallee(cx, callee);
-}
-
-bool
-TypeConstraintPropagateThis::newCallee(JSContext *cx, HandleFunction callee)
-{
-    if (!callee->nonLazyScript()->ensureHasTypes(cx))
-        return false;
-
     TypeSet *thisTypes = TypeScript::ThisTypes(callee->nonLazyScript());
     if (this->types)
         this->types->addSubset(cx, thisTypes);
     else
         thisTypes->addType(cx, this->type);
-
-    return true;
 }
 
 void
 TypeConstraintArith::newType(JSContext *cx, TypeSet *source, Type type)
 {
     /*
      * We only model a subset of the arithmetic behavior that is actually
      * possible. The following need to be watched for at runtime:
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2354,35 +2354,18 @@ BEGIN_CASE(JSOP_FUNCALL)
     if (regs.fp()->hasPushedSPSFrame())
         cx->runtime->spsProfiler.updatePC(script, regs.pc);
     JS_ASSERT(regs.stackDepth() >= 2 + GET_ARGC(regs.pc));
     CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
 
     bool construct = (*regs.pc == JSOP_NEW);
 
     RootedFunction &fun = rootFunction0;
-    bool isFunction = IsFunctionObject(args.calleev(), fun.address());
-
-    /*
-     * Some builtins are marked as clone-at-callsite to increase precision of
-     * TI and JITs.
-     */
-    if (isFunction) {
-        if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
-            goto error;
-        if (cx->typeInferenceEnabled() && fun->isCloneAtCallsite()) {
-            fun = CloneFunctionAtCallsite(cx, fun, script, regs.pc);
-            if (!fun)
-                goto error;
-            args.setCallee(ObjectValue(*fun));
-        }
-    }
-
     /* Don't bother trying to fast-path calls to scripted non-constructors. */
-    if (!isFunction || !fun->isInterpretedConstructor()) {
+    if (!IsFunctionObject(args.calleev(), fun.address()) || !fun->isInterpretedConstructor()) {
         if (construct) {
             if (!InvokeConstructorKernel(cx, args))
                 goto error;
         } else {
             if (!InvokeKernel(cx, args))
                 goto error;
         }
         Value *newsp = args.spAfterCall();
@@ -2392,17 +2375,19 @@ BEGIN_CASE(JSOP_FUNCALL)
         DO_NEXT_OP(len);
     }
 
     if (!TypeMonitorCall(cx, args, construct))
         goto error;
 
     InitialFrameFlags initial = construct ? INITIAL_CONSTRUCT : INITIAL_NONE;
     bool newType = cx->typeInferenceEnabled() && UseNewType(cx, script, regs.pc);
-    RootedScript funScript(cx, fun->nonLazyScript());
+    RootedScript funScript(cx, JSFunction::getOrCreateScript(cx, fun));
+    if (!funScript)
+        goto error;
     if (!cx->stack.pushInlineFrame(cx, regs, args, *fun, funScript, initial))
         goto error;
 
     SET_SCRIPT(regs.fp()->script());
 #ifdef JS_METHODJIT
     script->resetLoopCount();
 #endif
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -2338,47 +2338,16 @@ js::CloneScript(JSContext *cx, HandleObj
             vector[i].init(regexps[i]);
     }
     if (ntrynotes != 0)
         dst->trynotes()->vector = Rebase<JSTryNote>(dst, src, src->trynotes()->vector);
 
     return dst;
 }
 
-bool
-js::CloneFunctionScript(JSContext *cx, HandleFunction original, HandleFunction clone)
-{
-    JS_ASSERT(clone->isInterpreted());
-
-    RootedScript script(cx, clone->nonLazyScript());
-    JS_ASSERT(script);
-    JS_ASSERT(script->compartment() == original->compartment());
-    JS_ASSERT_IF(script->compartment() != cx->compartment,
-                 !script->enclosingStaticScope());
-
-    RootedObject scope(cx, script->enclosingStaticScope());
-
-    clone->mutableScript().init(NULL);
-
-    RawScript cscript = CloneScript(cx, scope, clone, script);
-    if (!cscript)
-        return false;
-
-    clone->setScript(cscript);
-    cscript->setFunction(clone);
-
-    GlobalObject *global = script->compileAndGo ? &script->global() : NULL;
-
-    script = clone->nonLazyScript();
-    CallNewScriptHook(cx, script, clone);
-    Debugger::onNewScript(cx, script, global);
-
-    return true;
-}
-
 DebugScript *
 JSScript::debugScript()
 {
     JS_ASSERT(hasDebugScript);
     DebugScriptMap *map = compartment()->debugScriptMap;
     JS_ASSERT(map);
     DebugScriptMap::Ptr p = map->lookup(this);
     JS_ASSERT(p);
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -1295,19 +1295,16 @@ enum LineOption {
 };
 
 inline void
 CurrentScriptFileLineOrigin(JSContext *cx, unsigned *linenop, LineOption = NOT_CALLED_FROM_JSOP_EVAL);
 
 extern UnrootedScript
 CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun, HandleScript script);
 
-bool
-CloneFunctionScript(JSContext *cx, HandleFunction original, HandleFunction clone);
-
 /*
  * NB: after a successful XDR_DECODE, XDRScript callers must do any required
  * subsequent set-up of owning function or script object and then call
  * js_CallNewScriptHook.
  */
 template<XDRMode mode>
 bool
 XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -1632,17 +1632,16 @@ mjit::Compiler::finishThisUp()
 
         stubCode.patch(from.addrLabel, &to);
     }
 
     ic::CallICInfo *jitCallICs = (ic::CallICInfo *)cursor;
     chunk->nCallICs = callICs.length();
     cursor += sizeof(ic::CallICInfo) * chunk->nCallICs;
     for (size_t i = 0; i < chunk->nCallICs; i++) {
-        jitCallICs[i].funGuardLabel = fullCode.locationOf(callICs[i].funGuardLabel);
         jitCallICs[i].funGuard = fullCode.locationOf(callICs[i].funGuard);
         jitCallICs[i].funJump = fullCode.locationOf(callICs[i].funJump);
         jitCallICs[i].slowPathStart = stubCode.locationOf(callICs[i].slowPathStart);
         jitCallICs[i].typeMonitored = callICs[i].typeMonitored;
 
         /* Compute the hot call offset. */
         uint32_t offset = fullCode.locationOf(callICs[i].hotJump) -
                         fullCode.locationOf(callICs[i].funGuard);
@@ -4426,17 +4425,16 @@ mjit::Compiler::inlineCallHelper(uint32_
     /* Reserve space just before initialization of funGuard. */
     RESERVE_IC_SPACE(masm);
 
     /*
      * Guard on the callee identity. This misses on the first run. If the
      * callee is scripted, compiled/compilable, and argc == nargs, then this
      * guard is patched, and the compiled code address is baked in.
      */
-    callIC.funGuardLabel = masm.label();
     Jump j = masm.branchPtrWithPatch(Assembler::NotEqual, icCalleeData, callIC.funGuard);
     callIC.funJump = j;
 
     /* Reserve space just before initialization of slowPathStart. */
     RESERVE_OOL_SPACE(stubcc.masm);
 
     Jump rejoin1, rejoin2;
     {
@@ -4626,21 +4624,16 @@ mjit::Compiler::inlineScriptedFunction(u
     JS_ASSERT(inlining());
 
     /* We already know which frames we are inlining at each PC, so scan the list of inline frames. */
     bool calleeMultipleReturns = false;
     Vector<JSScript *> inlineCallees(CompilerAllocPolicy(cx, *this));
     for (unsigned i = 0; i < ssa.numFrames(); i++) {
         if (ssa.iterFrame(i).parent == a->inlineIndex && ssa.iterFrame(i).parentpc == PC) {
             JSScript *script_ = ssa.iterFrame(i).script;
-
-            /* Don't inline if any of the callees should be cloned at callsite. */
-            if (script_->function()->isCloneAtCallsite())
-                return Compile_InlineAbort;
-
             inlineCallees.append(script_);
             if (script_->analysis()->numReturnSites() > 1)
                 calleeMultipleReturns = true;
         }
     }
 
     if (inlineCallees.empty())
         return Compile_InlineAbort;
--- a/js/src/methodjit/Compiler.h
+++ b/js/src/methodjit/Compiler.h
@@ -115,17 +115,16 @@ class Compiler : public BaseCompiler
     /* InlineFrameAssembler wants to see this. */
   public:
     struct CallGenInfo {
         /*
          * These members map to members in CallICInfo. See that structure for
          * more comments.
          */
         uint32_t     callIndex;
-        Label        funGuardLabel;
         DataLabelPtr funGuard;
         Jump         funJump;
         Jump         hotJump;
         Call         oolCall;
         Label        joinPoint;
         Label        slowJoinPoint;
         Label        slowPathStart;
         Label        hotPathLabel;
--- a/js/src/methodjit/InvokeHelpers.cpp
+++ b/js/src/methodjit/InvokeHelpers.cpp
@@ -125,60 +125,38 @@ FindExceptionHandler(JSContext *cx)
 
     return NULL;
 }
 
 /*
  * Clean up a frame and return.
  */
 
-static inline bool
-MaybeCloneAndPatchCallee(JSContext *cx, CallArgs args, HandleScript script, jsbytecode *pc)
-{
-    if (cx->typeInferenceEnabled() &&
-        args.callee().isFunction() && args.callee().toFunction()->isCloneAtCallsite())
-    {
-        RootedFunction fun(cx, args.callee().toFunction());
-        fun = CloneFunctionAtCallsite(cx, fun, script, pc);
-        if (!fun)
-            return false;
-        args.setCallee(ObjectValue(*fun));
-    }
-
-    return true;
-}
-
 void JS_FASTCALL
 stubs::SlowCall(VMFrame &f, uint32_t argc)
 {
     if (*f.regs.pc == JSOP_FUNAPPLY && !GuardFunApplyArgumentsOptimization(f.cx))
         THROW();
 
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
-    RootedScript fscript(f.cx, f.script());
-
-    if (!MaybeCloneAndPatchCallee(f.cx, args, fscript, f.pc()))
-        THROW();
     if (!InvokeKernel(f.cx, args))
         THROW();
 
+    RootedScript fscript(f.cx, f.script());
     types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
 }
 
 void JS_FASTCALL
 stubs::SlowNew(VMFrame &f, uint32_t argc)
 {
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
-    RootedScript fscript(f.cx, f.script());
-
-    if (!MaybeCloneAndPatchCallee(f.cx, args, fscript, f.pc()))
-        THROW();
     if (!InvokeConstructorKernel(f.cx, args))
         THROW();
 
+    RootedScript fscript(f.cx, f.script());
     types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
 }
 
 static inline bool
 CheckStackQuota(VMFrame &f)
 {
     JS_ASSERT(f.regs.stackDepth() == 0);
 
@@ -227,20 +205,16 @@ stubs::FixupArity(VMFrame &f, uint32_t n
     RootedScript script(cx, fun->nonLazyScript());
     void *ncode = oldfp->nativeReturnAddress();
 
     /* Pop the inline frame. */
     f.regs.popPartialFrame((Value *)oldfp);
 
     /* Reserve enough space for a callee frame. */
     CallArgs args = CallArgsFromSp(nactual, f.regs.sp);
-    if (fun->isCallsiteClone()) {
-        JS_ASSERT(args.callee().toFunction() == fun->getExtendedSlot(0).toObject().toFunction());
-        args.setCallee(ObjectValue(*fun));
-    }
     StackFrame *fp = cx->stack.getFixupFrame(cx, DONT_REPORT_ERROR, args, fun,
                                              script, ncode, initial, &f.stackLimit);
 
     if (!fp) {
         f.regs.updateForNcode(f.jit(), ncode);
         js_ReportOverRecursed(cx);
         THROWV(NULL);
     }
@@ -308,17 +282,17 @@ static inline bool
 UncachedInlineCall(VMFrame &f, InitialFrameFlags initial,
                    void **pret, bool *unjittable, uint32_t argc)
 {
     AssertCanGC();
     JSContext *cx = f.cx;
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
     RootedFunction newfun(cx, args.callee().toFunction());
 
-    RootedScript newscript(cx, newfun->nonLazyScript());
+    RootedScript newscript(cx, JSFunction::getOrCreateScript(cx, newfun));
     if (!newscript)
         return false;
 
     bool construct = InitialFrameFlagsAreConstructing(initial);
 
     RootedScript fscript(cx, f.script());
     bool newType = construct && cx->typeInferenceEnabled() &&
         types::UseNewType(cx, fscript, f.pc());
@@ -416,28 +390,25 @@ stubs::UncachedNew(VMFrame &f, uint32_t 
 }
 
 void
 stubs::UncachedNewHelper(VMFrame &f, uint32_t argc, UncachedCallResult &ucr)
 {
     ucr.init();
     JSContext *cx = f.cx;
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
-    RootedScript fscript(cx, f.script());
-
-    if (!ucr.setFunction(cx, args, fscript, f.pc()))
-        THROW();
 
     /* Try to do a fast inline call before the general Invoke path. */
-    if (ucr.fun && ucr.fun->isInterpretedConstructor()) {
+    if (IsFunctionObject(args.calleev(), ucr.fun.address()) && ucr.fun->isInterpretedConstructor()) {
         if (!UncachedInlineCall(f, INITIAL_CONSTRUCT, &ucr.codeAddr, &ucr.unjittable, argc))
             THROW();
     } else {
         if (!InvokeConstructorKernel(cx, args))
             THROW();
+        RootedScript fscript(cx, f.script());
         types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
     }
 }
 
 void * JS_FASTCALL
 stubs::UncachedCall(VMFrame &f, uint32_t argc)
 {
     UncachedCallResult ucr(f.cx);
@@ -477,22 +448,18 @@ stubs::Eval(VMFrame &f, uint32_t argc)
 
 void
 stubs::UncachedCallHelper(VMFrame &f, uint32_t argc, bool lowered, UncachedCallResult &ucr)
 {
     ucr.init();
 
     JSContext *cx = f.cx;
     CallArgs args = CallArgsFromSp(argc, f.regs.sp);
-    RootedScript fscript(cx, f.script());
 
-    if (!ucr.setFunction(cx, args, fscript, f.pc()))
-        THROW();
-
-    if (ucr.fun) {
+    if (IsFunctionObject(args.calleev(), ucr.fun.address())) {
         if (ucr.fun->isInterpreted()) {
             InitialFrameFlags initial = lowered ? INITIAL_LOWERED : INITIAL_NONE;
             if (!UncachedInlineCall(f, initial, &ucr.codeAddr, &ucr.unjittable, argc))
                 THROW();
             return;
         }
 
         if (ucr.fun->isNative()) {
@@ -502,16 +469,17 @@ stubs::UncachedCallHelper(VMFrame &f, ui
             types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
             return;
         }
     }
 
     if (!InvokeKernel(f.cx, args))
         THROW();
 
+    RootedScript fscript(cx, f.script());
     types::TypeScript::Monitor(f.cx, fscript, f.pc(), args.rval());
     return;
 }
 
 static void
 RemoveOrphanedNative(JSContext *cx, StackFrame *fp)
 {
     /*
--- a/js/src/methodjit/MonoIC.cpp
+++ b/js/src/methodjit/MonoIC.cpp
@@ -1024,23 +1024,23 @@ class CallCompiler : public BaseCompiler
         if (!linker.verifyRange(f.chunk())) {
             disable();
             return true;
         }
 
         linker.link(claspGuard, ic.slowPathStart);
         linker.link(funGuard, ic.slowPathStart);
         linker.link(done, ic.funGuard.labelAtOffset(ic.hotPathOffset));
-        ic.funJumpTarget = linker.finalize(f);
+        JSC::CodeLocationLabel cs = linker.finalize(f);
 
         JaegerSpew(JSpew_PICs, "generated CALL closure stub %p (%lu bytes)\n",
-                   ic.funJumpTarget.executableAddress(), (unsigned long) masm.size());
+                   cs.executableAddress(), (unsigned long) masm.size());
 
         Repatcher repatch(f.chunk());
-        repatch.relink(ic.funJump, ic.funJumpTarget);
+        repatch.relink(ic.funJump, cs);
 
         return true;
     }
 
     bool generateNativeStub()
     {
         /* Snapshot the frameDepth before SplatApplyArgs modifies it. */
         unsigned initialFrameDepth = f.regs.sp - f.fp()->slots();
@@ -1204,77 +1204,20 @@ class CallCompiler : public BaseCompiler
             return true;
         }
 
         linker.patchJump(ic.nativeRejoin());
 
         ic.fastGuardedNative = fun;
 
         linker.link(funGuard, ic.slowPathStart);
-        ic.funJumpTarget = linker.finalize(f);
+        JSC::CodeLocationLabel start = linker.finalize(f);
 
         JaegerSpew(JSpew_PICs, "generated native CALL stub %p (%lu bytes)\n",
-                   ic.funJumpTarget.executableAddress(), (unsigned long) masm.size());
-
-        Repatcher repatch(f.chunk());
-        repatch.relink(ic.funJump, ic.funJumpTarget);
-
-        return true;
-    }
-
-    bool generateCallsiteCloneStub(HandleFunction original, HandleFunction fun)
-    {
-        AutoAssertNoGC nogc;
-
-        Assembler masm;
-
-        // If we have a callsite clone, we do the folowing hack:
-        //
-        //  1) Patch funJump to a stub which guards on the identity of the
-        //     original function. If this guard fails, we jump to the original
-        //     funJump target.
-        //  2) Load the clone into the callee register.
-        //  3) Jump *back* to funGuard.
-        //
-        // For the inline path, hopefully we will succeed upon jumping back to
-        // funGuard after loading the clone.
-        //
-        // This hack is not ideal, as we can actually fail the first funGuard
-        // twice: we fail the first funGuard, pass the second funGuard, load
-        // the clone, and jump back to the first funGuard. We fail the first
-        // funGuard again, and this time we also fail the second funGuard,
-        // since a function's clone is never equal to itself. Finally, we jump
-        // to the original funJump target.
-
-        // Guard on the original function's identity.
-        Jump originalGuard = masm.branchPtr(Assembler::NotEqual, ic.funObjReg, ImmPtr(original));
-
-        // Load the clone.
-        masm.move(ImmPtr(fun), ic.funObjReg);
-
-        // Jump back to the first fun guard.
-        Jump done = masm.jump();
-
-        LinkerHelper linker(masm, JSC::JAEGER_CODE);
-        JSC::ExecutablePool *ep = linker.init(f.cx);
-        if (!ep)
-            return false;
-
-        if (!linker.verifyRange(f.chunk())) {
-            disable();
-            return true;
-        }
-
-        linker.link(originalGuard, !!ic.funJumpTarget ? ic.funJumpTarget : ic.slowPathStart);
-        linker.link(done, ic.funGuardLabel);
-        JSC::CodeLocationLabel start = linker.finalize(f);
-
-        JaegerSpew(JSpew_PICs, "generated CALL clone stub %p (%lu bytes)\n",
                    start.executableAddress(), (unsigned long) masm.size());
-        JaegerSpew(JSpew_PICs, "guarding %p with clone %p\n", original.get(), fun.get());
 
         Repatcher repatch(f.chunk());
         repatch.relink(ic.funJump, start);
 
         return true;
     }
 
     void *update()
@@ -1355,19 +1298,16 @@ class CallCompiler : public BaseCompiler
                 if (!generateStubForClosures(fun))
                     THROWV(NULL);
             } else {
                 if (!generateFullCallStub(script, flags))
                     THROWV(NULL);
             }
         }
 
-        if (ucr.original && !generateCallsiteCloneStub(ucr.original, ucr.fun))
-            THROWV(NULL);
-
         return ucr.codeAddr;
     }
 };
 
 } // namespace mjit
 } // namespace js
 
 void * JS_FASTCALL
--- a/js/src/methodjit/MonoIC.h
+++ b/js/src/methodjit/MonoIC.h
@@ -160,35 +160,26 @@ struct CallICInfo {
     JSObject *fastGuardedObject;
     JSObject *fastGuardedNative;
 
     /* Return site for scripted calls at this site, with PC and inlining state. */
     CallSite *call;
 
     FrameSize frameSize;
 
-    /* Label to the function object identity guard. */
-    JSC::CodeLocationLabel funGuardLabel;
-
     /* Function object identity guard. */
     JSC::CodeLocationDataLabelPtr funGuard;
 
     /* Starting point for all slow call paths. */
     JSC::CodeLocationLabel slowPathStart;
 
     /* Inline to OOL jump, redirected by stubs. */
     JSC::CodeLocationJump funJump;
 
     /*
-     * Target of the above jump, remembered so that if we need to generate a
-     * callsite clone stub we can redirect to the original funJump target.
-     */
-    JSC::CodeLocationLabel funJumpTarget;
-
-    /*
      * If an Ion stub has been generated, its guard may be linked to another
      * stub. The guard location is stored in this label.
      */
     bool hasIonStub_;
     JSC::JITCode lastOolCode_;
     JSC::CodeLocationJump lastOolJump_;
 
     /* Offset to inline scripted call, from funGuard. */
--- a/js/src/methodjit/StubCalls-inl.h
+++ b/js/src/methodjit/StubCalls-inl.h
@@ -24,34 +24,13 @@ ThrowException(VMFrame &f)
 static inline void
 ReportAtomNotDefined(JSContext *cx, JSAtom *atom)
 {
     JSAutoByteString printable;
     if (js_AtomToPrintableString(cx, atom, &printable))
         js_ReportIsNotDefined(cx, printable.ptr());
 }
 
-inline bool
-stubs::UncachedCallResult::setFunction(JSContext *cx, CallArgs &args,
-                                       HandleScript callScript, jsbytecode *callPc)
-{
-    if (!IsFunctionObject(args.calleev(), fun.address()))
-        return true;
-
-    if (fun->isInterpretedLazy() && !JSFunction::getOrCreateScript(cx, fun))
-        return false;
-
-    if (cx->typeInferenceEnabled() && fun->isCloneAtCallsite()) {
-        original = fun;
-        fun = CloneFunctionAtCallsite(cx, original, callScript, callPc);
-        if (!fun)
-            return false;
-        args.setCallee(ObjectValue(*fun));
-    }
-
-    return true;
-}
-
 } /* namespace mjit */
 } /* namespace js */
 
 #endif /* jslogic_h__ */
 
--- a/js/src/methodjit/StubCalls.h
+++ b/js/src/methodjit/StubCalls.h
@@ -3,17 +3,16 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #if !defined jslogic_h__ && defined JS_METHODJIT
 #define jslogic_h__
 
-#include "jsfuninlines.h"
 #include "MethodJIT.h"
 
 namespace js {
 namespace mjit {
 namespace stubs {
 
 typedef enum JSTrapType {
     JSTRAP_NONE = 0,
@@ -54,31 +53,26 @@ void JS_FASTCALL ScriptProbeOnlyEpilogue
  *   (1) The function was executed in the interpreter. Then all fields
  *       are NULL except unjittable.
  *
  *   (2) The function was not executed, and the function has been compiled
  *       to JM native code. Then all fields are non-NULL.
  */
 struct UncachedCallResult {
     RootedFunction fun;        // callee function
-    RootedFunction original;   // NULL if fun is not a callsite clone, else
-                               // points to the original function.
     void           *codeAddr;  // code address of compiled callee function
     bool           unjittable; // did we try to JIT and fail?
 
-    UncachedCallResult(JSContext *cx) : fun(cx), original(cx) {}
+    UncachedCallResult(JSContext *cx) : fun(cx) {}
 
     void init() {
         fun = NULL;
-        original = NULL;
         codeAddr = NULL;
         unjittable = false;
     }
-    inline bool setFunction(JSContext *cx, CallArgs &args,
-                            HandleScript callScript, jsbytecode *callPc);
 };
 
 /*
  * Helper functions for stubs and IC functions for calling functions.
  * These functions either execute the function, return a native code
  * pointer that can be used to call the function, or throw.
  */
 void UncachedCallHelper(VMFrame &f, uint32_t argc, bool lowered, UncachedCallResult &ucr);