mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 880816 - Mark IonCode embedded pointers during MinorGC if they may be Nursery things; r=bhackett
--HG-- extra : rebase_source : 2c2e6320671e38fde041fcb350730e6bd7f86f8e
This commit is contained in:
parent
d4696b6e54
commit
ec525ea7a7
@ -399,6 +399,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
parser.sct = &sct;
|
||||
|
||||
JS_ASSERT(fun);
|
||||
JS_ASSERT(fun->isTenured());
|
||||
|
||||
fun->setArgCount(formals.length());
|
||||
|
||||
|
@ -489,6 +489,8 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu
|
||||
insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()),
|
||||
funCxFlags()
|
||||
{
|
||||
JS_ASSERT(fun->isTenured());
|
||||
|
||||
if (!outerpc) {
|
||||
inWith = false;
|
||||
|
||||
|
@ -497,6 +497,9 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason)
|
||||
{
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
|
@ -389,7 +389,8 @@ HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, Hand
|
||||
const jschar *chars = src->chars().get();
|
||||
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED,
|
||||
cx->global(), name));
|
||||
cx->global(), name, JSFunction::FinalizeKind,
|
||||
TenuredObject));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
|
@ -5188,27 +5188,6 @@ CodeGenerator::generate()
|
||||
return !masm.oom();
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
* IonScripts normally live as long as their owner JSScript; however, they can
|
||||
* occasionally get destroyed outside the context of a GC by FinishInvalidationOf.
|
||||
* Because of this case, we cannot use the normal store buffer to guard them.
|
||||
* Instead we use the generic buffer to mark the owner script, which will mark the
|
||||
* IonScript's fields, if it is still alive.
|
||||
*/
|
||||
class IonScriptRefs : public gc::BufferableRef
|
||||
{
|
||||
JSScript *script_;
|
||||
|
||||
public:
|
||||
IonScriptRefs(JSScript *script) : script_(script) {}
|
||||
virtual bool match(void *location) { return false; }
|
||||
virtual void mark(JSTracer *trc) {
|
||||
gc::MarkScriptUnbarriered(trc, &script_, "script for IonScript");
|
||||
}
|
||||
};
|
||||
#endif // JSGC_GENERATIONAL
|
||||
|
||||
bool
|
||||
CodeGenerator::link()
|
||||
{
|
||||
@ -5306,9 +5285,6 @@ CodeGenerator::link()
|
||||
ionScript->copySnapshots(&snapshots_);
|
||||
if (graph.numConstants())
|
||||
ionScript->copyConstants(graph.constantPool());
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
cx->runtime()->gcStoreBuffer.putGeneric(IonScriptRefs(script));
|
||||
#endif
|
||||
JS_ASSERT(graph.mir().numScripts() > 0);
|
||||
ionScript->copyScriptEntries(graph.mir().scripts());
|
||||
if (callTargets.length() > 0)
|
||||
|
@ -8,11 +8,34 @@
|
||||
#define jsion_compileinfo_inl_h__
|
||||
|
||||
#include "CompileInfo.h"
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace ion;
|
||||
|
||||
CompileInfo::CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
|
||||
ExecutionMode executionMode)
|
||||
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
|
||||
executionMode_(executionMode)
|
||||
{
|
||||
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
||||
|
||||
// The function here can flow in from anywhere so look up the canonical function to ensure that
|
||||
// we do not try to embed a nursery pointer in jit-code.
|
||||
if (fun_) {
|
||||
fun_ = fun_->nonLazyScript()->function();
|
||||
JS_ASSERT(fun_->isTenured());
|
||||
}
|
||||
|
||||
nimplicit_ = StartArgSlot(script, fun) /* scope chain and argument obj */
|
||||
+ (fun ? 1 : 0); /* this */
|
||||
nargs_ = fun ? fun->nargs : 0;
|
||||
nlocals_ = script->nfixed;
|
||||
nstack_ = script->nslots - script->nfixed;
|
||||
nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
|
||||
}
|
||||
|
||||
const char *
|
||||
CompileInfo::filename() const
|
||||
{
|
||||
|
@ -40,18 +40,7 @@ class CompileInfo
|
||||
{
|
||||
public:
|
||||
CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
|
||||
ExecutionMode executionMode)
|
||||
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
|
||||
executionMode_(executionMode)
|
||||
{
|
||||
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
||||
nimplicit_ = StartArgSlot(script, fun) /* scope chain and argument obj */
|
||||
+ (fun ? 1 : 0); /* this */
|
||||
nargs_ = fun ? fun->nargs : 0;
|
||||
nlocals_ = script->nfixed;
|
||||
nstack_ = script->nslots - script->nfixed;
|
||||
nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
|
||||
}
|
||||
ExecutionMode executionMode);
|
||||
|
||||
CompileInfo(unsigned nlocals, ExecutionMode executionMode)
|
||||
: script_(NULL), fun_(NULL), osrPc_(NULL), constructing_(false),
|
||||
|
@ -526,7 +526,7 @@ IonCode::writeBarrierPre(IonCode *code)
|
||||
void
|
||||
IonCode::writeBarrierPost(IonCode *code, void *addr)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// Nothing to do.
|
||||
#endif
|
||||
}
|
||||
|
@ -439,8 +439,9 @@ IsCacheableDOMProxy(JSObject *obj)
|
||||
}
|
||||
|
||||
static void
|
||||
GeneratePrototypeGuards(JSContext *cx, MacroAssembler &masm, JSObject *obj, JSObject *holder,
|
||||
Register objectReg, Register scratchReg, Label *failures)
|
||||
GeneratePrototypeGuards(JSContext *cx, IonScript *ion, MacroAssembler &masm, JSObject *obj,
|
||||
JSObject *holder, Register objectReg, Register scratchReg,
|
||||
Label *failures)
|
||||
{
|
||||
JS_ASSERT(obj != holder);
|
||||
|
||||
@ -449,7 +450,8 @@ GeneratePrototypeGuards(JSContext *cx, MacroAssembler &masm, JSObject *obj, JSOb
|
||||
// use objectReg in the rest of this function.
|
||||
masm.loadPtr(Address(objectReg, JSObject::offsetOfType()), scratchReg);
|
||||
Address proto(scratchReg, offsetof(types::TypeObject, proto));
|
||||
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->getProto()), failures);
|
||||
masm.branchPtr(Assembler::NotEqual, proto,
|
||||
ImmMaybeNurseryPtr(ion->method(), obj->getProto()), failures);
|
||||
}
|
||||
|
||||
JSObject *pobj = IsCacheableDOMProxy(obj)
|
||||
@ -460,7 +462,7 @@ GeneratePrototypeGuards(JSContext *cx, MacroAssembler &masm, JSObject *obj, JSOb
|
||||
while (pobj != holder) {
|
||||
if (pobj->hasUncacheableProto()) {
|
||||
JS_ASSERT(!pobj->hasSingletonType());
|
||||
masm.movePtr(ImmGCPtr(pobj), scratchReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), pobj), scratchReg);
|
||||
Address objType(scratchReg, JSObject::offsetOfType());
|
||||
masm.branchPtr(Assembler::NotEqual, objType, ImmGCPtr(pobj->type()), failures);
|
||||
}
|
||||
@ -699,9 +701,10 @@ GenerateDOMProxyChecks(JSContext *cx, MacroAssembler &masm, JSObject *obj,
|
||||
}
|
||||
|
||||
static void
|
||||
GenerateReadSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
JSObject *obj, PropertyName *name, JSObject *holder, Shape *shape,
|
||||
Register object, TypedOrValueRegister output, Label *failures = NULL)
|
||||
GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, PropertyName *name,
|
||||
JSObject *holder, Shape *shape, Register object, TypedOrValueRegister output,
|
||||
Label *failures = NULL)
|
||||
{
|
||||
// If there's a single jump to |failures|, we can patch the shape guard
|
||||
// jump directly. Otherwise, jump to the end of the stub, so there's a
|
||||
@ -759,13 +762,13 @@ GenerateReadSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
|
||||
Register holderReg;
|
||||
if (obj != holder) {
|
||||
// Note: this may clobber the object register if it's used as scratch.
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object, scratchReg,
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg,
|
||||
failures);
|
||||
|
||||
if (holder) {
|
||||
// Guard on the holder's shape.
|
||||
holderReg = scratchReg;
|
||||
masm.movePtr(ImmGCPtr(holder), holderReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), holder), holderReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
@ -827,10 +830,10 @@ GenerateReadSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
|
||||
}
|
||||
|
||||
static bool
|
||||
GenerateCallGetter(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
JSObject *obj, PropertyName *name, JSObject *holder, HandleShape shape,
|
||||
RegisterSet &liveRegs, Register object, TypedOrValueRegister output,
|
||||
void *returnAddr, jsbytecode *pc)
|
||||
GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, PropertyName *name,
|
||||
JSObject *holder, HandleShape shape, RegisterSet &liveRegs, Register object,
|
||||
TypedOrValueRegister output, void *returnAddr, jsbytecode *pc)
|
||||
{
|
||||
// Initial shape check.
|
||||
Label stubFailure;
|
||||
@ -845,11 +848,11 @@ GenerateCallGetter(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &
|
||||
|
||||
// Note: this may clobber the object register if it's used as scratch.
|
||||
if (obj != holder)
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object, scratchReg, &stubFailure);
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg, &stubFailure);
|
||||
|
||||
// Guard on the holder's shape.
|
||||
Register holderReg = scratchReg;
|
||||
masm.movePtr(ImmGCPtr(holder), holderReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), holder), holderReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
@ -1013,7 +1016,7 @@ GetPropertyIC::attachReadSlot(JSContext *cx, IonScript *ion, JSObject *obj, JSOb
|
||||
{
|
||||
RepatchStubAppender attacher(*this);
|
||||
MacroAssembler masm(cx);
|
||||
GenerateReadSlot(cx, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
const char *attachKind = "non idempotent reading";
|
||||
if (idempotent())
|
||||
attachKind = "idempotent reading";
|
||||
@ -1147,7 +1150,7 @@ GetPropertyIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj,
|
||||
masm.setFramePushed(ion->frameSize());
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateCallGetter(cx, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
object(), output(), returnAddr, pc))
|
||||
{
|
||||
return false;
|
||||
@ -1621,7 +1624,7 @@ ParallelGetPropertyIC::attachReadSlot(LockedJSContext &cx, IonScript *ion,
|
||||
// Ready to generate the read slot stub.
|
||||
DispatchStubPrepender attacher(*this);
|
||||
MacroAssembler masm(cx);
|
||||
GenerateReadSlot(cx, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
|
||||
const char *attachKind = "parallel non-idempotent reading";
|
||||
if (idempotent())
|
||||
@ -1794,9 +1797,9 @@ SetPropertyIC::attachSetterCall(JSContext *cx, IonScript *ion,
|
||||
|
||||
// Generate prototype/shape guards.
|
||||
if (obj != holder)
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object(), scratchReg, &protoFailure);
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object(), scratchReg, &protoFailure);
|
||||
|
||||
masm.movePtr(ImmGCPtr(holder), scratchReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), holder), scratchReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(scratchReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
@ -2185,7 +2188,7 @@ GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
masm.branchTestValue(Assembler::NotEqual, val, idval, &failures);
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateReadSlot(cx, masm, attacher, obj, name, holder, shape, object(), output(),
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, name, holder, shape, object(), output(),
|
||||
&failures);
|
||||
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "property");
|
||||
@ -2954,7 +2957,7 @@ NameIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject
|
||||
masm.setFramePushed(ion->frameSize());
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateCallGetter(cx, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
scopeChainReg(), outputReg(), returnAddr, pc))
|
||||
{
|
||||
return false;
|
||||
|
@ -121,6 +121,24 @@ struct ImmGCPtr
|
||||
explicit ImmGCPtr(const gc::Cell *ptr) : value(reinterpret_cast<uintptr_t>(ptr))
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedPtr(ptr));
|
||||
JS_ASSERT_IF(ptr, ptr->isTenured());
|
||||
}
|
||||
|
||||
protected:
|
||||
ImmGCPtr() : value(0) {}
|
||||
};
|
||||
|
||||
// Used for immediates which require relocation and may be traced during minor GC.
|
||||
struct ImmMaybeNurseryPtr : public ImmGCPtr
|
||||
{
|
||||
explicit ImmMaybeNurseryPtr(IonCode *code, gc::Cell *ptr)
|
||||
{
|
||||
this->value = reinterpret_cast<uintptr_t>(ptr);
|
||||
JS_ASSERT(!IsPoisonedPtr(ptr));
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (ptr && ptr->runtime()->gcNursery.isInside(ptr))
|
||||
ptr->runtime()->gcStoreBuffer.putWholeCell(code);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -35,8 +35,10 @@ class AssemblerX86Shared
|
||||
bool enoughMemory_;
|
||||
|
||||
void writeDataRelocation(const Value &val) {
|
||||
if (val.isMarkable())
|
||||
if (val.isMarkable()) {
|
||||
JS_ASSERT(static_cast<gc::Cell*>(val.toGCThing())->isTenured());
|
||||
dataRelocations_.writeUnsigned(masm.currentOffset());
|
||||
}
|
||||
}
|
||||
void writeDataRelocation(const ImmGCPtr &ptr) {
|
||||
if (ptr.value)
|
||||
|
30
js/src/jit-test/tests/gc/bug-880816.js
Normal file
30
js/src/jit-test/tests/gc/bug-880816.js
Normal file
@ -0,0 +1,30 @@
|
||||
var lfcode = new Array();
|
||||
lfcode.push("const baz = 'bar';");
|
||||
lfcode.push("2");
|
||||
lfcode.push("{ function foo() {} }");
|
||||
lfcode.push("evaluate('\
|
||||
var INVALIDATE_MODES = INVALIDATE_MODE_STRINGS.map(s => ({mode: s}));\
|
||||
function range(n, m) {}\
|
||||
function seq_scan(array, f) {}\
|
||||
function assertStructuralEq(e1, e2) {}\
|
||||
for (var i = 0, l = a.length; i < l; i++) {}\
|
||||
');");
|
||||
lfcode.push("for (var x of Set(Object.getOwnPropertyNames(this))) {}");
|
||||
var lfRunTypeId = -1;
|
||||
while (true) {
|
||||
var file = lfcode.shift(); if (file == undefined) { break; }
|
||||
loadFile(file)
|
||||
}
|
||||
function loadFile(lfVarx) {
|
||||
try {
|
||||
if (lfVarx.substr(-3) == ".js") {}
|
||||
if (!isNaN(lfVarx)) {
|
||||
lfRunTypeId = parseInt(lfVarx);
|
||||
} else {
|
||||
switch (lfRunTypeId) {
|
||||
case 2: new Function(lfVarx)(); break;
|
||||
default: evaluate(lfVarx); break;
|
||||
}
|
||||
}
|
||||
} catch (lfVare) {}
|
||||
}
|
@ -5499,7 +5499,8 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj, funAtom));
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj,
|
||||
funAtom, JSFunction::FinalizeKind, TenuredObject));
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
|
@ -329,7 +329,7 @@ bool
|
||||
js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
||||
MutableHandleObject objp)
|
||||
{
|
||||
/* NB: Keep this in sync with CloneInterpretedFunction. */
|
||||
/* NB: Keep this in sync with CloneFunctionAndScript. */
|
||||
RootedAtom atom(xdr->cx());
|
||||
uint32_t firstword; /* flag telling whether fun->atom is non-null,
|
||||
plus for fun->u.i.skipmin, fun->u.i.wrapper,
|
||||
@ -354,7 +354,8 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
|
||||
atom = fun->atom();
|
||||
script = fun->nonLazyScript();
|
||||
} else {
|
||||
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr());
|
||||
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr(),
|
||||
JSFunction::FinalizeKind, TenuredObject);
|
||||
if (!fun)
|
||||
return false;
|
||||
atom = NULL;
|
||||
@ -395,14 +396,13 @@ template bool
|
||||
js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, MutableHandleObject);
|
||||
|
||||
JSObject *
|
||||
js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
|
||||
{
|
||||
/* NB: Keep this in sync with XDRInterpretedFunction. */
|
||||
|
||||
RootedFunction clone(cx, NewFunction(cx, NullPtr(), NULL, 0,
|
||||
JSFunction::INTERPRETED, NullPtr(), NullPtr(),
|
||||
JSFunction::FinalizeKind, newKind));
|
||||
JSFunction::FinalizeKind, TenuredObject));
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
@ -1462,7 +1462,8 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
|
||||
*/
|
||||
RootedAtom anonymousAtom(cx, cx->names().anonymous);
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED_LAMBDA,
|
||||
global, anonymousAtom));
|
||||
global, anonymousAtom, JSFunction::FinalizeKind,
|
||||
TenuredObject));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
|
@ -443,8 +443,7 @@ XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
|
||||
HandleScript enclosingScript, MutableHandleObject objp);
|
||||
|
||||
extern JSObject *
|
||||
CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
|
||||
|
||||
/*
|
||||
* Report an error that call.thisv is not compatible with the specified class,
|
||||
|
@ -2334,8 +2334,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
||||
else
|
||||
enclosingScope = fun;
|
||||
|
||||
clone = CloneInterpretedFunction(cx, enclosingScope, innerFun,
|
||||
src->selfHosted ? TenuredObject : newKind);
|
||||
clone = CloneFunctionAndScript(cx, enclosingScope, innerFun);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -87,6 +87,7 @@ SetFrameArgumentsObject(JSContext *cx, AbstractFramePtr frame,
|
||||
inline void
|
||||
JSScript::setFunction(JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(fun->isTenured());
|
||||
function_ = fun;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user