mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 851109 - Add NAME IC for invoking getters on the global object. r=djvj
--HG-- extra : rebase_source : 4a4fa5be4a6ee0dc24f309ead094f90a420c6bab
This commit is contained in:
parent
34b1b23ac6
commit
d824ce1336
@ -4690,11 +4690,12 @@ CodeGenerator::visitCallsiteCloneIC(OutOfLineUpdateCache *ool, CallsiteCloneIC *
|
||||
bool
|
||||
CodeGenerator::visitGetNameCache(LGetNameCache *ins)
|
||||
{
|
||||
RegisterSet liveRegs = ins->safepoint()->liveRegs();
|
||||
Register scopeChain = ToRegister(ins->scopeObj());
|
||||
TypedOrValueRegister output(GetValueOutput(ins));
|
||||
bool isTypeOf = ins->mir()->accessKind() != MGetNameCache::NAME;
|
||||
|
||||
NameIC cache(isTypeOf, scopeChain, ins->mir()->name(), output);
|
||||
NameIC cache(liveRegs, isTypeOf, scopeChain, ins->mir()->name(), output);
|
||||
return addCache(ins, allocateCache(cache));
|
||||
}
|
||||
|
||||
|
@ -513,20 +513,12 @@ struct GetNativePropertyStub
|
||||
masm.popValue(tempVal);
|
||||
}
|
||||
|
||||
// Reserve scratch register for prototype guards.
|
||||
bool restoreScratch = false;
|
||||
Register scratchReg = Register::FromCode(0); // Quell compiler warning.
|
||||
|
||||
// If we need a scratch register, use either an output register or the object
|
||||
// register (and restore it afterwards). After this point, we cannot jump
|
||||
// directly to |stubFailure| since we may still have to pop the object register.
|
||||
Label prototypeFailures;
|
||||
JS_ASSERT(output.hasValue());
|
||||
scratchReg = output.valueReg().scratchReg();
|
||||
Register scratchReg = output.valueReg().scratchReg();
|
||||
|
||||
// Note: this may clobber the object register if it's used as scratch.
|
||||
if (obj != holder)
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object, scratchReg, &prototypeFailures);
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object, scratchReg, &stubFailure);
|
||||
|
||||
// Guard on the holder's shape.
|
||||
Register holderReg = scratchReg;
|
||||
@ -534,10 +526,7 @@ struct GetNativePropertyStub
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
&prototypeFailures);
|
||||
|
||||
if (restoreScratch)
|
||||
masm.pop(scratchReg);
|
||||
&stubFailure);
|
||||
|
||||
// Now we're good to go to invoke the native call.
|
||||
|
||||
@ -696,9 +685,6 @@ struct GetNativePropertyStub
|
||||
masm.bind(&rejoin_);
|
||||
|
||||
// Exit jump.
|
||||
masm.bind(&prototypeFailures);
|
||||
if (restoreScratch)
|
||||
masm.pop(scratchReg);
|
||||
masm.bind(&stubFailure);
|
||||
if (nonRepatchFailures)
|
||||
masm.bind(nonRepatchFailures);
|
||||
@ -1918,7 +1904,8 @@ BindNameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain)
|
||||
}
|
||||
|
||||
bool
|
||||
NameIC::attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject holder, HandleShape shape)
|
||||
NameIC::attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject holder,
|
||||
HandleShape shape)
|
||||
{
|
||||
MacroAssembler masm(cx);
|
||||
Label failures;
|
||||
@ -1958,8 +1945,9 @@ NameIC::attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObj
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCacheableName(JSContext *cx, HandleObject scopeChain, HandleObject obj, HandleObject holder,
|
||||
HandleShape shape, jsbytecode *pc, const TypedOrValueRegister &output)
|
||||
IsCacheableNameReadSlot(JSContext *cx, HandleObject scopeChain, HandleObject obj,
|
||||
HandleObject holder, HandleShape shape, jsbytecode *pc,
|
||||
const TypedOrValueRegister &output)
|
||||
{
|
||||
if (!shape)
|
||||
return false;
|
||||
@ -1996,13 +1984,51 @@ IsCacheableName(JSContext *cx, HandleObject scopeChain, HandleObject obj, Handle
|
||||
return obj == obj2;
|
||||
}
|
||||
|
||||
bool
|
||||
NameIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
HandleShape shape, const SafepointIndex *safepointIndex, void *returnAddr)
|
||||
{
|
||||
MacroAssembler masm(cx);
|
||||
RepatchLabel failures;
|
||||
|
||||
// Need to set correct framePushed on the masm so that exit frame descriptors are
|
||||
// properly constructed.
|
||||
masm.setFramePushed(ion->frameSize());
|
||||
|
||||
GetNativePropertyStub getprop;
|
||||
if (!getprop.generateCallGetter(cx, masm, obj, name(), holder, shape, liveRegs_,
|
||||
scopeChainReg(), outputReg(), returnAddr, pc, &failures))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *attachKind = "name getter";
|
||||
return linkAndAttachStub(cx, masm, ion, attachKind, getprop.rejoinOffset, &getprop.exitOffset,
|
||||
&getprop.stubCodePatchOffset);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCacheableNameCallGetter(JSObject *scopeChain, JSObject *obj, JSObject *holder, RawShape shape)
|
||||
{
|
||||
if (obj != scopeChain)
|
||||
return false;
|
||||
|
||||
if (!obj->isGlobal())
|
||||
return false;
|
||||
|
||||
return IsCacheableGetPropCallNative(obj, holder, shape) ||
|
||||
IsCacheableGetPropCallPropertyOp(obj, holder, shape);
|
||||
}
|
||||
|
||||
bool
|
||||
NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
AutoFlushCache afc ("GetNameCache");
|
||||
|
||||
IonScript *ion = GetTopIonJSScript(cx)->ionScript();
|
||||
const SafepointIndex *safepointIndex;
|
||||
void *returnAddr;
|
||||
IonScript *ion = GetTopIonJSScript(cx, &safepointIndex, &returnAddr)->ionScript();
|
||||
|
||||
NameIC &cache = ion->getCache(cacheIndex).toName();
|
||||
RootedPropertyName name(cx, cache.name());
|
||||
@ -2017,11 +2043,14 @@ NameIC::update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain,
|
||||
if (!LookupName(cx, name, scopeChain, &obj, &holder, &shape))
|
||||
return false;
|
||||
|
||||
if (cache.canAttachStub() &&
|
||||
IsCacheableName(cx, scopeChain, obj, holder, shape, pc, cache.outputReg()))
|
||||
{
|
||||
if (!cache.attach(cx, ion, scopeChain, obj, shape))
|
||||
return false;
|
||||
if (cache.canAttachStub()) {
|
||||
if (IsCacheableNameReadSlot(cx, scopeChain, obj, holder, shape, pc, cache.outputReg())) {
|
||||
if (!cache.attachReadSlot(cx, ion, scopeChain, obj, shape))
|
||||
return false;
|
||||
} else if (IsCacheableNameCallGetter(scopeChain, obj, holder, shape)) {
|
||||
if (!cache.attachCallGetter(cx, ion, obj, holder, shape, safepointIndex, returnAddr))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cache.isTypeOf()) {
|
||||
|
@ -493,16 +493,21 @@ class BindNameIC : public IonCache
|
||||
class NameIC : public IonCache
|
||||
{
|
||||
protected:
|
||||
// Registers live after the cache, excluding output registers. The initial
|
||||
// value of these registers must be preserved by the cache.
|
||||
RegisterSet liveRegs_;
|
||||
|
||||
bool typeOf_;
|
||||
Register scopeChain_;
|
||||
PropertyName *name_;
|
||||
TypedOrValueRegister output_;
|
||||
|
||||
public:
|
||||
NameIC(bool typeOf,
|
||||
NameIC(RegisterSet liveRegs, bool typeOf,
|
||||
Register scopeChain, PropertyName *name,
|
||||
TypedOrValueRegister output)
|
||||
: typeOf_(typeOf),
|
||||
: liveRegs_(liveRegs),
|
||||
typeOf_(typeOf),
|
||||
scopeChain_(scopeChain),
|
||||
name_(name),
|
||||
output_(output)
|
||||
@ -524,8 +529,11 @@ class NameIC : public IonCache
|
||||
return typeOf_;
|
||||
}
|
||||
|
||||
bool attach(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject obj,
|
||||
HandleShape shape);
|
||||
bool attachReadSlot(JSContext *cx, IonScript *ion, HandleObject scopeChain, HandleObject obj,
|
||||
HandleShape shape);
|
||||
bool attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject *holder,
|
||||
HandleShape shape, const SafepointIndex *safepointIndex,
|
||||
void *returnAddr);
|
||||
|
||||
static bool
|
||||
update(JSContext *cx, size_t cacheIndex, HandleObject scopeChain, MutableHandleValue vp);
|
||||
|
6
js/src/jit-test/tests/ion/bug851109.js
Normal file
6
js/src/jit-test/tests/ion/bug851109.js
Normal file
@ -0,0 +1,6 @@
|
||||
function f() {
|
||||
for (var i=0; i<50; i++) {
|
||||
assertEq(customNative, undefined);
|
||||
}
|
||||
}
|
||||
f();
|
@ -4780,6 +4780,12 @@ NewGlobalObject(JSContext *cx)
|
||||
its_setter, JSPROP_READONLY))
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, glob, "customNative", UndefinedValue(),
|
||||
(JSPropertyOp)its_get_customNative,
|
||||
(JSStrictPropertyOp)its_set_customNative,
|
||||
JSPROP_READONLY | JSPROP_NATIVE_ACCESSORS))
|
||||
return NULL;
|
||||
|
||||
/* Initialize FakeDOMObject. */
|
||||
static js::DOMCallbacks DOMcallbacks = {
|
||||
InstanceClassHasProtoAtDepth
|
||||
|
Loading…
Reference in New Issue
Block a user