Bug 589199 - Support global lexicals in Baseline. (r=jandem)

This commit is contained in:
Shu-yu Guo 2015-10-06 14:00:29 -07:00
Родитель 78aa3b8277
Коммит 934bb0bb13
12 изменённых файлов: 363 добавлений и 155 удалений

Просмотреть файл

@ -2115,6 +2115,7 @@ BaselineCompiler::emit_JSOP_GETGNAME()
RootedPropertyName name(cx, script->getName(pc));
// These names are non-configurable on the global and cannot be shadowed.
if (name == cx->names().undefined) {
frame.push(UndefinedValue());
return true;
@ -2130,7 +2131,7 @@ BaselineCompiler::emit_JSOP_GETGNAME()
frame.syncStack(0);
masm.movePtr(ImmGCPtr(&script->global()), R0.scratchReg());
masm.movePtr(ImmGCPtr(&script->global().lexicalScope()), R0.scratchReg());
// Call IC.
ICGetName_Fallback::Compiler stubCompiler(cx);
@ -2146,8 +2147,27 @@ bool
BaselineCompiler::emit_JSOP_BINDGNAME()
{
if (!script->hasNonSyntacticScope()) {
frame.push(ObjectValue(script->global()));
return true;
// We can bind name to the global lexical scope if the binding already
// exists and is initialized at compile time.
RootedPropertyName name(cx, script->getName(pc));
Rooted<ClonedBlockObject*> globalLexical(cx, &script->global().lexicalScope());
if (Shape* shape = globalLexical->lookup(cx, name)) {
if (!globalLexical->getSlot(shape->slot()).isMagic(JS_UNINITIALIZED_LEXICAL)) {
frame.push(ObjectValue(*globalLexical));
return true;
}
}
// We can bind name to the global object if the property exists on the
// global and is non-configurable, as then it cannot be shadowed.
if (Shape* shape = script->global().lookup(cx, name)) {
if (!shape->configurable()) {
frame.push(ObjectValue(script->global()));
return true;
}
}
// Otherwise we have to use the dynamic scope chain.
}
return emit_JSOP_BINDNAME();
@ -2437,8 +2457,8 @@ BaselineCompiler::emit_JSOP_GETINTRINSIC()
return true;
}
typedef bool (*DefVarOrConstFn)(JSContext*, HandlePropertyName, unsigned, HandleObject);
static const VMFunction DefVarOrConstInfo = FunctionInfo<DefVarOrConstFn>(DefVarOrConst);
typedef bool (*DefVarFn)(JSContext*, HandlePropertyName, unsigned, HandleObject);
static const VMFunction DefVarInfo = FunctionInfo<DefVarFn>(DefVar);
bool
BaselineCompiler::emit_JSOP_DEFVAR()
@ -2446,9 +2466,7 @@ BaselineCompiler::emit_JSOP_DEFVAR()
frame.syncStack(0);
unsigned attrs = JSPROP_ENUMERATE;
if (JSOp(*pc) == JSOP_DEFCONST)
attrs |= JSPROP_READONLY;
else if (!script->isForEval())
if (!script->isForEval())
attrs |= JSPROP_PERMANENT;
MOZ_ASSERT(attrs <= UINT32_MAX);
@ -2460,34 +2478,34 @@ BaselineCompiler::emit_JSOP_DEFVAR()
pushArg(Imm32(attrs));
pushArg(ImmGCPtr(script->getName(pc)));
return callVM(DefVarOrConstInfo);
return callVM(DefVarInfo);
}
typedef bool (*DefLexicalFn)(JSContext*, HandlePropertyName, unsigned);
static const VMFunction DefLexicalInfo = FunctionInfo<DefLexicalFn>(DefLexicalOperation);
bool
BaselineCompiler::emit_JSOP_DEFCONST()
{
return emit_JSOP_DEFVAR();
return emit_JSOP_DEFLET();
}
typedef bool (*SetConstFn)(JSContext*, HandlePropertyName, HandleObject, HandleValue);
static const VMFunction SetConstInfo = FunctionInfo<SetConstFn>(SetConst);
bool
BaselineCompiler::emit_JSOP_SETCONST()
BaselineCompiler::emit_JSOP_DEFLET()
{
frame.popRegsAndSync(1);
frame.push(R0);
frame.syncStack(0);
masm.loadPtr(frame.addressOfScopeChain(), R1.scratchReg());
unsigned attrs = JSPROP_ENUMERATE | JSPROP_PERMANENT;
if (*pc == JSOP_DEFCONST)
attrs |= JSPROP_READONLY;
MOZ_ASSERT(attrs <= UINT32_MAX);
prepareVMCall();
pushArg(R0);
pushArg(R1.scratchReg());
pushArg(Imm32(attrs));
pushArg(ImmGCPtr(script->getName(pc)));
return callVM(SetConstInfo);
return callVM(DefLexicalInfo);
}
typedef bool (*DefFunOperationFn)(JSContext*, HandleScript, HandleObject, HandleFunction);
@ -2818,6 +2836,15 @@ BaselineCompiler::emit_JSOP_INITLEXICAL()
return emit_JSOP_SETLOCAL();
}
bool
BaselineCompiler::emit_JSOP_INITGLEXICAL()
{
frame.popRegsAndSync(1);
frame.push(ObjectValue(script->global().lexicalScope()));
frame.push(R0);
return emit_JSOP_SETPROP();
}
bool
BaselineCompiler::emit_JSOP_CHECKALIASEDLEXICAL()
{

Просмотреть файл

@ -141,7 +141,7 @@ namespace jit {
_(JSOP_GETINTRINSIC) \
_(JSOP_DEFVAR) \
_(JSOP_DEFCONST) \
_(JSOP_SETCONST) \
_(JSOP_DEFLET) \
_(JSOP_DEFFUN) \
_(JSOP_GETLOCAL) \
_(JSOP_SETLOCAL) \
@ -149,6 +149,7 @@ namespace jit {
_(JSOP_SETARG) \
_(JSOP_CHECKLEXICAL) \
_(JSOP_INITLEXICAL) \
_(JSOP_INITGLEXICAL) \
_(JSOP_CHECKALIASEDLEXICAL) \
_(JSOP_INITALIASEDLEXICAL) \
_(JSOP_UNINITIALIZED) \

Просмотреть файл

@ -696,6 +696,7 @@ RecompileBaselineScriptForDebugMode(JSContext* cx, JSScript* script,
_(GetElem_NativePrototypeCallScriptedSymbol) \
_(GetProp_CallScripted) \
_(GetProp_CallNative) \
_(GetProp_CallNativeGlobal) \
_(GetProp_CallDOMProxyNative) \
_(GetProp_CallDOMProxyWithGenerationNative) \
_(GetProp_DOMProxyShadowed) \
@ -708,7 +709,8 @@ RecompileBaselineScriptForDebugMode(JSContext* cx, JSScript* script,
_(GetElem_Dense) \
_(GetElem_Arguments) \
_(GetProp_NativePrototype) \
_(GetProp_Native)
_(GetProp_Native) \
_(GetName_Global)
#endif
static bool

Просмотреть файл

@ -16,8 +16,11 @@ using namespace js::jit;
bool
FrameInfo::init(TempAllocator& alloc)
{
// One slot is always needed for this/arguments type checks.
size_t nstack = Max(script->nslots() - script->nfixed(), size_t(1));
// The minimum stack size is two. One slot is always needed for
// this/arguments type checks. Two slots are needed because INITGLEXICAL
// (stack depth 1) is compiled as a SETPROP (stack depth 2) on the global
// lexical scope.
size_t nstack = Max(script->nslots() - script->nfixed(), size_t(2));
if (!stack.init(alloc, nstack))
return false;

Просмотреть файл

@ -4893,25 +4893,29 @@ UpdateExistingSetPropCallStubs(ICSetProp_Fallback* fallbackStub,
// Attach an optimized stub for a GETGNAME/CALLGNAME slot-read op.
static bool
TryAttachGlobalNameValueStub(JSContext* cx, HandleScript script, jsbytecode* pc,
ICGetName_Fallback* stub, Handle<GlobalObject*> global,
ICGetName_Fallback* stub, Handle<ClonedBlockObject*> globalLexical,
HandlePropertyName name, bool* attached)
{
MOZ_ASSERT(global->is<GlobalObject>());
MOZ_ASSERT(globalLexical->isGlobal());
MOZ_ASSERT(!*attached);
RootedId id(cx, NameToId(name));
// The property must be found, and it must be found as a normal data property.
RootedShape shape(cx);
RootedNativeObject current(cx, global);
RootedShape shape(cx, globalLexical->lookup(cx, id));
RootedNativeObject current(cx, globalLexical);
while (true) {
shape = current->lookup(cx, id);
if (shape)
break;
JSObject* proto = current->getProto();
if (!proto || !proto->is<NativeObject>())
return true;
current = &proto->as<NativeObject>();
if (current == globalLexical) {
current = &globalLexical->global();
} else {
JSObject* proto = current->getProto();
if (!proto || !proto->is<NativeObject>())
return true;
current = &proto->as<NativeObject>();
}
}
// Instantiate this global property, for use during Ion compilation.
@ -4924,23 +4928,28 @@ TryAttachGlobalNameValueStub(JSContext* cx, HandleScript script, jsbytecode* pc,
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
ICStub* newStub;
if (current == global) {
if (current == globalLexical) {
MOZ_ASSERT(shape->slot() >= current->numFixedSlots());
uint32_t slot = shape->slot() - current->numFixedSlots();
JitSpew(JitSpew_BaselineIC, " Generating GetName(GlobalName) stub");
ICGetName_Global::Compiler compiler(cx, monitorStub, current->lastProperty(), slot);
JitSpew(JitSpew_BaselineIC, " Generating GetName(GlobalName lexical) stub");
ICGetName_GlobalLexical::Compiler compiler(cx, monitorStub, slot);
newStub = compiler.getStub(compiler.getStubSpace(script));
} else {
bool isFixedSlot;
uint32_t offset;
GetFixedOrDynamicSlotOffset(shape, &isFixedSlot, &offset);
if (!IsCacheableGetPropReadSlot(global, current, shape))
// Check the prototype chain from the global to the current
// prototype. Ignore the global lexical scope as it doesn' figure
// into the prototype chain. We guard on the global lexical
// scope's shape independently.
if (!IsCacheableGetPropReadSlot(&globalLexical->global(), current, shape))
return true;
JitSpew(JitSpew_BaselineIC, " Generating GetName(GlobalName prototype) stub");
ICGetPropNativeCompiler compiler(cx, ICStub::GetProp_NativePrototype, false, monitorStub,
global, current, name, isFixedSlot, offset,
JitSpew(JitSpew_BaselineIC, " Generating GetName(GlobalName non-lexical) stub");
ICGetPropNativeCompiler compiler(cx, ICStub::GetName_Global, false, monitorStub,
globalLexical, current, name, isFixedSlot, offset,
/* inputDefinitelyObject = */ true);
newStub = compiler.getStub(compiler.getStubSpace(script));
}
@ -4956,14 +4965,19 @@ TryAttachGlobalNameValueStub(JSContext* cx, HandleScript script, jsbytecode* pc,
// Attach an optimized stub for a GETGNAME/CALLGNAME getter op.
static bool
TryAttachGlobalNameAccessorStub(JSContext* cx, HandleScript script, jsbytecode* pc,
ICGetName_Fallback* stub, Handle<GlobalObject*> global,
ICGetName_Fallback* stub, Handle<ClonedBlockObject*> globalLexical,
HandlePropertyName name, bool* attached,
bool* isTemporarilyUnoptimizable)
{
MOZ_ASSERT(global->is<GlobalObject>());
MOZ_ASSERT(globalLexical->isGlobal());
RootedId id(cx, NameToId(name));
// There must not be a shadowing binding on the global lexical scope.
if (globalLexical->lookup(cx, id))
return true;
RootedGlobalObject global(cx, &globalLexical->global());
// The property must be found, and it must be found as a normal data property.
RootedShape shape(cx);
RootedNativeObject current(cx, global);
@ -4998,10 +5012,11 @@ TryAttachGlobalNameAccessorStub(JSContext* cx, HandleScript script, jsbytecode*
*attached = true;
return true;
}
ICGetProp_CallNative::Compiler compiler(cx, monitorStub, global, current,
getter, script->pcToOffset(pc),
/* outerClass = */ nullptr,
/* inputDefinitelyObject = */ true);
ICGetPropCallNativeCompiler compiler(cx, ICStub::GetProp_CallNativeGlobal,
monitorStub, globalLexical, current,
getter, script->pcToOffset(pc),
/* outerClass = */ nullptr,
/* inputDefinitelyObject = */ true);
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
if (!newStub)
@ -5142,8 +5157,9 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
}
if (!attached && IsGlobalOp(JSOp(*pc)) && !script->hasNonSyntacticScope()) {
if (!TryAttachGlobalNameAccessorStub(cx, script, pc, stub, scopeChain.as<GlobalObject>(),
name, &attached, &isTemporarilyUnoptimizable))
if (!TryAttachGlobalNameAccessorStub(cx, script, pc, stub,
scopeChain.as<ClonedBlockObject>(),
name, &attached, &isTemporarilyUnoptimizable))
{
return false;
}
@ -5172,8 +5188,8 @@ DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_
return true;
if (IsGlobalOp(JSOp(*pc)) && !script->hasNonSyntacticScope()) {
Handle<GlobalObject*> global = scopeChain.as<GlobalObject>();
if (!TryAttachGlobalNameValueStub(cx, script, pc, stub, global, name, &attached))
Handle<ClonedBlockObject*> globalLexical = scopeChain.as<ClonedBlockObject>();
if (!TryAttachGlobalNameValueStub(cx, script, pc, stub, globalLexical, name, &attached))
return false;
} else {
if (!TryAttachScopeNameStub(cx, script, stub, scopeChain, name, &attached))
@ -5205,7 +5221,7 @@ ICGetName_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
}
bool
ICGetName_Global::Compiler::generateStubCode(MacroAssembler& masm)
ICGetName_GlobalLexical::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
@ -5213,13 +5229,12 @@ ICGetName_Global::Compiler::generateStubCode(MacroAssembler& masm)
Register obj = R0.scratchReg();
Register scratch = R1.scratchReg();
// Shape guard.
masm.loadPtr(Address(ICStubReg, ICGetName_Global::offsetOfShape()), scratch);
masm.branchTestObjShape(Assembler::NotEqual, obj, scratch, &failure);
// There's no need to guard on the shape. Lexical bindings are
// non-configurable, and this stub cannot be shared across globals.
// Load dynamic slot.
masm.loadPtr(Address(obj, NativeObject::offsetOfSlots()), obj);
masm.load32(Address(ICStubReg, ICGetName_Global::offsetOfSlot()), scratch);
masm.load32(Address(ICStubReg, ICGetName_GlobalLexical::offsetOfSlot()), scratch);
masm.loadValue(BaseIndex(obj, scratch, TimesEight), R0);
// Enter type monitor IC to type-check result.
@ -5789,8 +5804,9 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecod
return true;
}
ICGetProp_CallNative::Compiler compiler(cx, monitorStub, obj, holder, callee,
script->pcToOffset(pc), outerClass);
ICGetPropCallNativeCompiler compiler(cx, ICStub::GetProp_CallNative,
monitorStub, obj, holder, callee,
script->pcToOffset(pc), outerClass);
newStub = compiler.getStub(compiler.getStubSpace(script));
}
if (!newStub)
@ -6361,11 +6377,31 @@ ICGetPropNativeCompiler::getStub(ICStubSpace* space)
offset_, holder_, holderShape);
}
case ICStub::GetName_Global: {
MOZ_ASSERT(obj_ != holder_);
Shape* holderShape = holder_->as<NativeObject>().lastProperty();
Shape* globalShape = obj_->as<ClonedBlockObject>().global().lastProperty();
return newStub<ICGetName_Global>(space, getStubCode(), firstMonitorStub_, guard,
offset_, holder_, holderShape, globalShape);
}
default:
MOZ_CRASH("Bad stub kind");
}
}
static void
GuardGlobalObject(MacroAssembler& masm, HandleObject holder, Register globalLexicalReg,
Register holderReg, Register scratch, size_t globalShapeOffset, Label* failure)
{
if (holder->is<GlobalObject>())
return;
masm.extractObject(Address(globalLexicalReg, ScopeObject::offsetOfEnclosingScope()),
holderReg);
masm.loadPtr(Address(ICStubReg, globalShapeOffset), scratch);
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, failure);
}
bool
ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
{
@ -6393,6 +6429,7 @@ ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
Register holderReg;
if (obj_ == holder_) {
MOZ_ASSERT(kind != ICStub::GetName_Global);
if (obj_->is<UnboxedPlainObject>()) {
// We are loading off the expando object, so use that for the holder.
holderReg = regs.takeAny();
@ -6401,8 +6438,17 @@ ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
holderReg = objReg;
}
} else {
// Shape guard holder.
holderReg = regs.takeAny();
// If we are generating a non-lexical GETGNAME stub, we must also
// guard on the shape of the GlobalObject.
if (kind == ICStub::GetName_Global) {
MOZ_ASSERT(obj_->is<ClonedBlockObject>() && obj_->as<ClonedBlockObject>().isGlobal());
GuardGlobalObject(masm, holder_, objReg, holderReg, scratch,
ICGetName_Global::offsetOfGlobalShape(), &failure);
}
// Shape guard holder.
masm.loadPtr(Address(ICStubReg, ICGetProp_NativePrototype::offsetOfHolder()),
holderReg);
masm.loadPtr(Address(ICStubReg, ICGetProp_NativePrototype::offsetOfHolderShape()),
@ -6657,7 +6703,7 @@ ICGetProp_CallScripted::Compiler::generateStubCode(MacroAssembler& masm)
}
bool
ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm)
ICGetPropCallNativeCompiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
@ -6689,12 +6735,22 @@ ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm)
// Shape guard.
GuardReceiverObject(masm, ReceiverGuard(receiver_), objReg, scratch,
ICGetProp_CallNative::offsetOfReceiverGuard(), &failure);
ICGetPropCallGetter::offsetOfReceiverGuard(), &failure);
if (receiver_ != holder_ ) {
if (receiver_ != holder_) {
Register holderReg = regs.takeAny();
masm.loadPtr(Address(ICStubReg, ICGetProp_CallNative::offsetOfHolder()), holderReg);
masm.loadPtr(Address(ICStubReg, ICGetProp_CallNative::offsetOfHolderShape()), scratch);
// If we are generating a non-lexical GETGNAME stub, we must also
// guard on the shape of the GlobalObject.
if (kind == ICStub::GetProp_CallNativeGlobal) {
MOZ_ASSERT(receiver_->is<ClonedBlockObject>() &&
receiver_->as<ClonedBlockObject>().isGlobal());
GuardGlobalObject(masm, holder_, objReg, holderReg, scratch,
ICGetProp_CallNativeGlobal::offsetOfGlobalShape(), &failure);
}
masm.loadPtr(Address(ICStubReg, ICGetPropCallGetter::offsetOfHolder()), holderReg);
masm.loadPtr(Address(ICStubReg, ICGetPropCallGetter::offsetOfHolderShape()), scratch);
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failure);
regs.add(holderReg);
}
@ -6711,7 +6767,12 @@ ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm)
// Load callee function.
Register callee = regs.takeAny();
masm.loadPtr(Address(ICStubReg, ICGetProp_CallNative::offsetOfGetter()), callee);
masm.loadPtr(Address(ICStubReg, ICGetPropCallGetter::offsetOfGetter()), callee);
// If we're calling a getter on the global, inline the logic for the
// 'this' hook on the global lexical scope and manually push the global.
if (kind == ICStub::GetProp_CallNativeGlobal)
masm.extractObject(Address(objReg, ScopeObject::offsetOfEnclosingScope()), objReg);
// Push args for vm call.
masm.push(objReg);
@ -6734,6 +6795,30 @@ ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm)
return true;
}
ICStub*
ICGetPropCallNativeCompiler::getStub(ICStubSpace* space)
{
ReceiverGuard guard(receiver_);
Shape* holderShape = holder_->as<NativeObject>().lastProperty();
switch (kind) {
case ICStub::GetProp_CallNative:
return newStub<ICGetProp_CallNative>(space, getStubCode(), firstMonitorStub_,
guard, holder_, holderShape,
getter_, pcOffset_);
case ICStub::GetProp_CallNativeGlobal: {
Shape* globalShape = receiver_->as<ClonedBlockObject>().global().lastProperty();
return newStub<ICGetProp_CallNativeGlobal>(space, getStubCode(), firstMonitorStub_,
guard, holder_, holderShape, globalShape,
getter_, pcOffset_);
}
default:
MOZ_CRASH("Bad stub kind");
}
}
bool
ICGetPropCallDOMProxyNativeCompiler::generateStubCode(MacroAssembler& masm,
Address* expandoAndGenerationAddr,
@ -7476,7 +7561,8 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
op == JSOP_INITLOCKEDPROP ||
op == JSOP_INITHIDDENPROP ||
op == JSOP_SETALIASEDVAR ||
op == JSOP_INITALIASEDLEXICAL);
op == JSOP_INITALIASEDLEXICAL ||
op == JSOP_INITGLEXICAL);
RootedPropertyName name(cx);
if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL)
@ -7529,6 +7615,9 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
return false;
} else if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
obj->as<ScopeObject>().setAliasedVar(cx, ScopeCoordinate(pc), name, rhs);
} else if (op == JSOP_INITGLEXICAL) {
RootedValue v(cx, rhs);
InitGlobalLexicalOperation(cx, script, pc, v);
} else {
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
@ -11268,10 +11357,9 @@ ICIn_Dense::ICIn_Dense(JitCode* stubCode, HandleShape shape)
shape_(shape)
{ }
ICGetName_Global::ICGetName_Global(JitCode* stubCode, ICStub* firstMonitorStub, Shape* shape,
uint32_t slot)
: ICMonitoredStub(GetName_Global, stubCode, firstMonitorStub),
shape_(shape),
ICGetName_GlobalLexical::ICGetName_GlobalLexical(JitCode* stubCode, ICStub* firstMonitorStub,
uint32_t slot)
: ICMonitoredStub(GetName_GlobalLexical, stubCode, firstMonitorStub),
slot_(slot)
{ }
@ -11322,10 +11410,11 @@ ICGetProp_Native::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorS
other.receiverGuard(), other.offset());
}
ICGetProp_NativePrototype::ICGetProp_NativePrototype(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, uint32_t offset,
JSObject* holder, Shape* holderShape)
: ICGetPropNativeStub(GetProp_NativePrototype, stubCode, firstMonitorStub, guard, offset),
ICGetPropNativePrototypeStub::ICGetPropNativePrototypeStub(ICStub::Kind kind, JitCode* stubCode,
ICStub* firstMonitorStub,
ReceiverGuard guard, uint32_t offset,
JSObject* holder, Shape* holderShape)
: ICGetPropNativeStub(kind, stubCode, firstMonitorStub, guard, offset),
holder_(holder),
holderShape_(holderShape)
{ }
@ -11336,7 +11425,24 @@ ICGetProp_NativePrototype::Clone(JSContext* cx, ICStubSpace* space, ICStub* firs
{
return New<ICGetProp_NativePrototype>(cx, space, other.jitCode(), firstMonitorStub,
other.receiverGuard(), other.offset(),
other.holder_, other.holderShape_);
other.holder(), other.holderShape());
}
ICGetName_Global::ICGetName_Global(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, uint32_t offset,
JSObject* holder, Shape* holderShape, Shape* globalShape)
: ICGetPropNativePrototypeStub(GetName_Global, stubCode, firstMonitorStub, guard, offset,
holder, holderShape),
globalShape_(globalShape)
{ }
/* static */ ICGetName_Global*
ICGetName_Global::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetName_Global& other)
{
return New<ICGetName_Global>(cx, space, other.jitCode(), firstMonitorStub,
other.receiverGuard(), other.offset(),
other.holder(), other.holderShape(), other.globalShape());
}
ICGetProp_NativeDoesNotExist::ICGetProp_NativeDoesNotExist(
@ -11394,6 +11500,7 @@ ICGetPropCallGetter::ICGetPropCallGetter(Kind kind, JitCode* stubCode, ICStub* f
{
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted ||
kind == ICStub::GetProp_CallNative ||
kind == ICStub::GetProp_CallNativeGlobal ||
kind == ICStub::GetProp_CallDOMProxyNative ||
kind == ICStub::GetProp_CallDOMProxyWithGenerationNative);
}
@ -11425,6 +11532,16 @@ ICGetProp_CallNative::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMoni
other.holderShape_, other.getter_, other.pcOffset_);
}
/* static */ ICGetProp_CallNativeGlobal*
ICGetProp_CallNativeGlobal::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetProp_CallNativeGlobal& other)
{
return New<ICGetProp_CallNativeGlobal>(cx, space, other.jitCode(), firstMonitorStub,
other.receiverGuard(), other.holder_,
other.holderShape_, other.globalShape_,
other.getter_, other.pcOffset_);
}
ICSetProp_Native::ICSetProp_Native(JitCode* stubCode, ObjectGroup* group, Shape* shape,
uint32_t offset)
: ICUpdatedStub(SetProp_Native, stubCode),

Просмотреть файл

@ -2100,47 +2100,37 @@ class ICGetName_Fallback : public ICMonitoredFallbackStub
};
};
// Optimized GETGNAME/CALLGNAME stub.
class ICGetName_Global : public ICMonitoredStub
// Optimized lexical GETGNAME stub.
class ICGetName_GlobalLexical : public ICMonitoredStub
{
friend class ICStubSpace;
protected: // Protected to silence Clang warning.
HeapPtrShape shape_;
uint32_t slot_;
ICGetName_Global(JitCode* stubCode, ICStub* firstMonitorStub, Shape* shape, uint32_t slot);
ICGetName_GlobalLexical(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t slot);
public:
HeapPtrShape& shape() {
return shape_;
}
static size_t offsetOfShape() {
return offsetof(ICGetName_Global, shape_);
}
static size_t offsetOfSlot() {
return offsetof(ICGetName_Global, slot_);
return offsetof(ICGetName_GlobalLexical, slot_);
}
class Compiler : public ICStubCompiler {
ICStub* firstMonitorStub_;
RootedShape shape_;
uint32_t slot_;
protected:
bool generateStubCode(MacroAssembler& masm);
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, Shape* shape, uint32_t slot)
: ICStubCompiler(cx, ICStub::GetName_Global, Engine::Baseline),
Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t slot)
: ICStubCompiler(cx, ICStub::GetName_GlobalLexical, Engine::Baseline),
firstMonitorStub_(firstMonitorStub),
shape_(cx, shape),
slot_(slot)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICGetName_Global>(space, getStubCode(), firstMonitorStub_, shape_,
slot_);
return newStub<ICGetName_GlobalLexical>(space, getStubCode(), firstMonitorStub_, slot_);
}
};
};
@ -2577,27 +2567,16 @@ class ICGetProp_Native : public ICGetPropNativeStub
ICGetProp_Native& other);
};
// Stub for accessing a property on the native prototype of a native or unboxed
// object. Note that due to the shape teleporting optimization, we only have to
// guard on the object's shape/group and the holder's shape.
class ICGetProp_NativePrototype : public ICGetPropNativeStub
class ICGetPropNativePrototypeStub : public ICGetPropNativeStub
{
friend class ICStubSpace;
protected:
// Holder and its shape.
HeapPtrObject holder_;
HeapPtrShape holderShape_;
ICGetProp_NativePrototype(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard,
uint32_t offset, JSObject* holder, Shape* holderShape);
public:
static ICGetProp_NativePrototype* Clone(JSContext* cx,
ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetProp_NativePrototype& other);
protected:
ICGetPropNativePrototypeStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard guard, uint32_t offset, JSObject* holder,
Shape* holderShape);
public:
HeapPtrObject& holder() {
@ -2607,10 +2586,59 @@ class ICGetProp_NativePrototype : public ICGetPropNativeStub
return holderShape_;
}
static size_t offsetOfHolder() {
return offsetof(ICGetProp_NativePrototype, holder_);
return offsetof(ICGetPropNativePrototypeStub, holder_);
}
static size_t offsetOfHolderShape() {
return offsetof(ICGetProp_NativePrototype, holderShape_);
return offsetof(ICGetPropNativePrototypeStub, holderShape_);
}
};
// Stub for accessing a property on the native prototype of a native or unboxed
// object. Note that due to the shape teleporting optimization, we only have to
// guard on the object's shape/group and the holder's shape.
class ICGetProp_NativePrototype : public ICGetPropNativePrototypeStub
{
friend class ICStubSpace;
protected:
ICGetProp_NativePrototype(JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
uint32_t offset, JSObject* holder, Shape* holderShape)
: ICGetPropNativePrototypeStub(GetProp_NativePrototype, stubCode, firstMonitorStub, guard,
offset, holder, holderShape)
{ }
public:
static ICGetProp_NativePrototype* Clone(JSContext* cx,
ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetProp_NativePrototype& other);
};
// Stub for accessing a non-lexical global name. Semantically, it is really a
// getprop: the name is either on the GlobalObject or its prototype chain. We
// teleport to the object that has the name, but we also need to guard on the
// shape of the global object.
//
// The receiver object is the global lexical scope.
class ICGetName_Global : public ICGetPropNativePrototypeStub
{
friend class ICStubSpace;
protected:
HeapPtrShape globalShape_;
ICGetName_Global(JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
uint32_t slot, JSObject* holder, Shape* holderShape, Shape* globalShape);
public:
static ICGetName_Global* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetName_Global& other);
HeapPtrShape& globalShape() {
return globalShape_;
}
static size_t offsetOfGlobalShape() {
return offsetof(ICGetName_Global, globalShape_);
}
};
@ -2955,7 +2983,7 @@ class ICGetPropCallGetter : public ICMonitoredStub
const Class* outerClass_;
virtual int32_t getKey() const {
// ICGetProp_CallNative::Compiler::getKey adds more bits to our
// ICGetPropCallNativeCompiler::getKey adds more bits to our
// return value, so be careful when making changes here.
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
@ -2977,7 +3005,8 @@ class ICGetPropCallGetter : public ICMonitoredStub
outerClass_(outerClass)
{
MOZ_ASSERT(kind == ICStub::GetProp_CallScripted ||
kind == ICStub::GetProp_CallNative);
kind == ICStub::GetProp_CallNative ||
kind == ICStub::GetProp_CallNativeGlobal);
}
};
};
@ -3042,36 +3071,61 @@ class ICGetProp_CallNative : public ICGetPropCallGetter
static ICGetProp_CallNative* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetProp_CallNative& other);
class Compiler : public ICGetPropCallGetter::Compiler
{
bool inputDefinitelyObject_;
protected:
bool generateStubCode(MacroAssembler& masm);
};
virtual int32_t getKey() const {
int32_t baseKey = ICGetPropCallGetter::Compiler::getKey();
MOZ_ASSERT((baseKey >> 21) == 0);
return baseKey | (static_cast<int32_t>(inputDefinitelyObject_) << 21);
}
// Stub for calling a native getter on the GlobalObject.
class ICGetProp_CallNativeGlobal : public ICGetPropCallGetter
{
friend class ICStubSpace;
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, HandleObject receiver,
HandleObject holder, HandleFunction getter, uint32_t pcOffset,
const Class* outerClass, bool inputDefinitelyObject = false)
: ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative,
firstMonitorStub, receiver, holder,
getter, pcOffset, outerClass),
inputDefinitelyObject_(inputDefinitelyObject)
{}
protected:
HeapPtrShape globalShape_;
ICStub* getStub(ICStubSpace* space) {
ReceiverGuard guard(receiver_);
Shape* holderShape = holder_->as<NativeObject>().lastProperty();
return newStub<ICGetProp_CallNative>(space, getStubCode(), firstMonitorStub_,
guard, holder_, holderShape,
getter_, pcOffset_);
}
};
ICGetProp_CallNativeGlobal(JitCode* stubCode, ICStub* firstMonitorStub,
ReceiverGuard receiverGuard,
JSObject* holder, Shape* holderShape, Shape* globalShape,
JSFunction* getter, uint32_t pcOffset)
: ICGetPropCallGetter(GetProp_CallNativeGlobal, stubCode, firstMonitorStub,
receiverGuard, holder, holderShape, getter, pcOffset),
globalShape_(globalShape)
{ }
public:
static ICGetProp_CallNativeGlobal* Clone(JSContext* cx, ICStubSpace* space,
ICStub* firstMonitorStub,
ICGetProp_CallNativeGlobal& other);
HeapPtrShape& globalShape() {
return globalShape_;
}
static size_t offsetOfGlobalShape() {
return offsetof(ICGetProp_CallNativeGlobal, globalShape_);
}
};
class ICGetPropCallNativeCompiler : public ICGetPropCallGetter::Compiler
{
bool inputDefinitelyObject_;
protected:
bool generateStubCode(MacroAssembler& masm);
virtual int32_t getKey() const {
int32_t baseKey = ICGetPropCallGetter::Compiler::getKey();
MOZ_ASSERT((baseKey >> 21) == 0);
return baseKey | (static_cast<int32_t>(inputDefinitelyObject_) << 21);
}
public:
ICGetPropCallNativeCompiler(JSContext* cx, ICStub::Kind kind, ICStub* firstMonitorStub,
HandleObject receiver, HandleObject holder, HandleFunction getter,
uint32_t pcOffset, const Class* outerClass,
bool inputDefinitelyObject = false)
: ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, receiver, holder,
getter, pcOffset, outerClass),
inputDefinitelyObject_(inputDefinitelyObject)
{}
ICStub* getStub(ICStubSpace* space);
};
class ICGetPropCallDOMProxyNativeStub : public ICGetPropCallGetter

Просмотреть файл

@ -78,6 +78,7 @@ namespace jit {
_(In_Dense) \
\
_(GetName_Fallback) \
_(GetName_GlobalLexical) \
_(GetName_Global) \
_(GetName_Scope0) \
_(GetName_Scope1) \
@ -104,6 +105,7 @@ namespace jit {
_(GetProp_TypedObject) \
_(GetProp_CallScripted) \
_(GetProp_CallNative) \
_(GetProp_CallNativeGlobal) \
_(GetProp_CallDOMProxyNative) \
_(GetProp_CallDOMProxyWithGenerationNative) \
_(GetProp_DOMProxyShadowed) \

Просмотреть файл

@ -2552,7 +2552,7 @@ InlineFrameIterator::computeScopeChain(Value scopeChainValue, MaybeReadFallback&
// the global on their scope chain.
MOZ_ASSERT(!script()->isForEval());
MOZ_ASSERT(!script()->hasNonSyntacticScope());
return &script()->global();
return &script()->global().lexicalScope();
}
bool

Просмотреть файл

@ -366,7 +366,10 @@ ICStub::trace(JSTracer* trc)
}
case ICStub::GetName_Global: {
ICGetName_Global* globalStub = toGetName_Global();
TraceEdge(trc, &globalStub->shape(), "baseline-global-stub-shape");
globalStub->receiverGuard().trace(trc);
TraceEdge(trc, &globalStub->holder(), "baseline-global-stub-holder");
TraceEdge(trc, &globalStub->holderShape(), "baseline-global-stub-holdershape");
TraceEdge(trc, &globalStub->globalShape(), "baseline-global-stub-globalshape");
break;
}
case ICStub::GetName_Scope0:
@ -479,6 +482,15 @@ ICStub::trace(JSTracer* trc)
TraceEdge(trc, &callStub->getter(), "baseline-getpropcallnative-stub-getter");
break;
}
case ICStub::GetProp_CallNativeGlobal: {
ICGetProp_CallNativeGlobal* callStub = toGetProp_CallNativeGlobal();
callStub->receiverGuard().trace(trc);
TraceEdge(trc, &callStub->holder(), "baseline-getpropcallnativeglobal-stub-holder");
TraceEdge(trc, &callStub->holderShape(), "baseline-getpropcallnativeglobal-stub-holdershape");
TraceEdge(trc, &callStub->globalShape(), "baseline-getpropcallnativeglobal-stub-globalshape");
TraceEdge(trc, &callStub->getter(), "baseline-getpropcallnativeglobal-stub-getter");
break;
}
case ICStub::SetProp_Native: {
ICSetProp_Native* propStub = toSetProp_Native();
TraceEdge(trc, &propStub->shape(), "baseline-setpropnative-stub-shape");

Просмотреть файл

@ -720,6 +720,7 @@ class ICStub
case GetElem_UnboxedPropertyName:
case GetProp_CallScripted:
case GetProp_CallNative:
case GetProp_CallNativeGlobal:
case GetProp_CallDOMProxyNative:
case GetProp_CallDOMProxyWithGenerationNative:
case GetProp_DOMProxyShadowed:
@ -737,6 +738,7 @@ class ICStub
case GetElem_Arguments:
case GetProp_NativePrototype:
case GetProp_Native:
case GetName_Global:
#endif
return true;
default:

Просмотреть файл

@ -167,25 +167,14 @@ CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
}
bool
DefVarOrConst(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain)
DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain)
{
// Given the ScopeChain, extract the VarObj.
RootedObject obj(cx, scopeChain);
while (!obj->isQualifiedVarObj())
obj = obj->enclosingScope();
return DefVarOrConstOperation(cx, obj, dn, attrs);
}
bool
SetConst(JSContext* cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval)
{
// Given the ScopeChain, extract the VarObj.
RootedObject obj(cx, scopeChain);
while (!obj->isQualifiedVarObj())
obj = obj->enclosingScope();
return SetConstOperation(cx, obj, name, rval);
return DefVarOperation(cx, obj, dn, attrs);
}
bool

Просмотреть файл

@ -588,8 +588,7 @@ bool CheckOverRecursed(JSContext* cx);
bool CheckOverRecursedWithExtra(JSContext* cx, BaselineFrame* frame,
uint32_t extra, uint32_t earlyCheck);
bool DefVarOrConst(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
bool SetConst(JSContext* cx, HandlePropertyName name, HandleObject scopeChain, HandleValue rval);
bool DefVar(JSContext* cx, HandlePropertyName dn, unsigned attrs, HandleObject scopeChain);
bool MutatePrototype(JSContext* cx, HandlePlainObject obj, HandleValue value);
bool InitProp(JSContext* cx, HandleObject obj, HandlePropertyName name, HandleValue value,
jsbytecode* pc);