зеркало из https://github.com/mozilla/gecko-dev.git
Bug 685315 - Remove the GETGLOBAL opcode; r=dvander
This was a nice and simple way to get a perf boost in the interpreter and JM, but JSOP_GETGNAME has the same information and more. TI doesn't need it, JM technically doesn't, and IM won't either. We can just do a normal property lookup during compilation.
This commit is contained in:
Родитель
11bd6931dd
Коммит
28beac255b
|
@ -2268,10 +2268,9 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
* by a local variable, and not mutating the variable, try and
|
||||
* optimize to a fast, unguarded global access.
|
||||
*/
|
||||
if (!BindKnownGlobal(cx, cg, dn, pn, atom))
|
||||
return JS_FALSE;
|
||||
if (!pn->pn_cookie.isFree()) {
|
||||
pn->setOp(JSOP_GETGLOBAL);
|
||||
pn->setOp(JSOP_GETGNAME);
|
||||
pn->pn_dflags |= PND_BOUND;
|
||||
return JS_TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -2279,7 +2278,7 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
/*
|
||||
* The locally stored cookie here should really come from |pn|, not
|
||||
* |dn|. For example, we could have a SETGNAME op's lexdef be a
|
||||
* GETGLOBAL op, and their cookies have very different meanings. As
|
||||
* GETGNAME op, and their cookies have very different meanings. As
|
||||
* a workaround, just make the cookie free.
|
||||
*/
|
||||
cookie.makeFree();
|
||||
|
@ -2772,9 +2771,6 @@ EmitNameOp(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn,
|
|||
case JSOP_GETGNAME:
|
||||
op = JSOP_CALLGNAME;
|
||||
break;
|
||||
case JSOP_GETGLOBAL:
|
||||
op = JSOP_CALLGLOBAL;
|
||||
break;
|
||||
case JSOP_GETARG:
|
||||
op = JSOP_CALLARG;
|
||||
break;
|
||||
|
@ -4659,10 +4655,7 @@ EmitAssignment(JSContext *cx, JSCodeGenerator *cg, JSParseNode *lhs, JSOp op, JS
|
|||
} else if (lhs->isOp(JSOP_SETGNAME)) {
|
||||
if (!BindGlobal(cx, cg, lhs, lhs->pn_atom))
|
||||
return false;
|
||||
if (lhs->pn_cookie.isFree())
|
||||
EmitAtomOp(cx, lhs, JSOP_GETGNAME, cg);
|
||||
else
|
||||
EMIT_UINT16_IMM_OP(JSOP_GETGLOBAL, lhs->pn_cookie.asInteger());
|
||||
EmitAtomOp(cx, lhs, JSOP_GETGNAME, cg);
|
||||
} else {
|
||||
EMIT_UINT16_IMM_OP(lhs->isOp(JSOP_SETARG) ? JSOP_GETARG : JSOP_GETLOCAL, atomIndex);
|
||||
}
|
||||
|
|
|
@ -1974,13 +1974,6 @@ GetAtomId(JSContext *cx, JSScript *script, const jsbytecode *pc, unsigned offset
|
|||
return MakeTypeId(cx, ATOM_TO_JSID(script->getAtom(index)));
|
||||
}
|
||||
|
||||
static inline jsid
|
||||
GetGlobalId(JSContext *cx, JSScript *script, const jsbytecode *pc)
|
||||
{
|
||||
unsigned index = GET_SLOTNO(pc);
|
||||
return MakeTypeId(cx, ATOM_TO_JSID(script->getGlobalAtom(index)));
|
||||
}
|
||||
|
||||
static inline JSObject *
|
||||
GetScriptObject(JSContext *cx, JSScript *script, const jsbytecode *pc, unsigned offset)
|
||||
{
|
||||
|
@ -3463,15 +3456,9 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
break;
|
||||
}
|
||||
|
||||
case JSOP_GETGLOBAL:
|
||||
case JSOP_CALLGLOBAL:
|
||||
case JSOP_GETGNAME:
|
||||
case JSOP_CALLGNAME: {
|
||||
jsid id;
|
||||
if (op == JSOP_GETGLOBAL || op == JSOP_CALLGLOBAL)
|
||||
id = GetGlobalId(cx, script, pc);
|
||||
else
|
||||
id = GetAtomId(cx, script, pc, 0);
|
||||
jsid id = GetAtomId(cx, script, pc, 0);
|
||||
|
||||
TypeSet *seen = bytecodeTypes(pc);
|
||||
seen->addSubset(cx, &pushed[0]);
|
||||
|
@ -3491,7 +3478,7 @@ ScriptAnalysis::analyzeTypesBytecode(JSContext *cx, unsigned offset,
|
|||
/* Handle as a property access. */
|
||||
PropertyAccess(cx, script, pc, script->global()->getType(cx), false, seen, id);
|
||||
|
||||
if (op == JSOP_CALLGLOBAL || op == JSOP_CALLGNAME) {
|
||||
if (op == JSOP_CALLGNAME) {
|
||||
pushed[1].addType(cx, Type::UnknownType());
|
||||
pushed[0].addPropagateThis(cx, script, pc, Type::UnknownType());
|
||||
}
|
||||
|
|
|
@ -4579,19 +4579,8 @@ BEGIN_CASE(JSOP_CALLFCSLOT)
|
|||
}
|
||||
END_CASE(JSOP_GETFCSLOT)
|
||||
|
||||
BEGIN_CASE(JSOP_GETGLOBAL)
|
||||
BEGIN_CASE(JSOP_CALLGLOBAL)
|
||||
{
|
||||
uint32 slot = GET_SLOTNO(regs.pc);
|
||||
slot = script->getGlobalSlot(slot);
|
||||
JSObject *obj = regs.fp()->scopeChain().getGlobal();
|
||||
JS_ASSERT(obj->containsSlot(slot));
|
||||
PUSH_COPY(obj->getSlot(slot));
|
||||
TypeScript::Monitor(cx, script, regs.pc, regs.sp[-1]);
|
||||
if (op == JSOP_CALLGLOBAL)
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
END_CASE(JSOP_GETGLOBAL)
|
||||
BEGIN_CASE(JSOP_UNUSED0)
|
||||
BEGIN_CASE(JSOP_UNUSED1)
|
||||
|
||||
BEGIN_CASE(JSOP_DEFCONST)
|
||||
BEGIN_CASE(JSOP_DEFVAR)
|
||||
|
|
|
@ -545,17 +545,6 @@ js_Disassemble1(JSContext *cx, JSScript *script, jsbytecode *pc,
|
|||
}
|
||||
break;
|
||||
|
||||
case JOF_GLOBAL:
|
||||
atom = script->getGlobalAtom(GET_SLOTNO(pc));
|
||||
v = STRING_TO_JSVAL(atom);
|
||||
{
|
||||
JSAutoByteString bytes;
|
||||
if (!ToDisassemblySource(cx, v, &bytes))
|
||||
return 0;
|
||||
Sprint(sp, " %s", bytes.ptr());
|
||||
}
|
||||
break;
|
||||
|
||||
case JOF_UINT16PAIR:
|
||||
i = (jsint)GET_UINT16(pc);
|
||||
Sprint(sp, " %d", i);
|
||||
|
@ -4016,11 +4005,6 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
#endif
|
||||
goto do_name;
|
||||
|
||||
case JSOP_CALLGLOBAL:
|
||||
case JSOP_GETGLOBAL:
|
||||
atom = jp->script->getGlobalAtom(GET_SLOTNO(pc));
|
||||
goto do_name;
|
||||
|
||||
case JSOP_CALLNAME:
|
||||
case JSOP_NAME:
|
||||
case JSOP_GETGNAME:
|
||||
|
|
|
@ -96,7 +96,6 @@ typedef enum JSOp {
|
|||
#define JOF_INT8 18 /* int8 immediate operand */
|
||||
#define JOF_ATOMOBJECT 19 /* uint16 constant index + object index */
|
||||
#define JOF_UINT16PAIR 20 /* pair of uint16 immediates */
|
||||
#define JOF_GLOBAL 21 /* uint16 global array index */
|
||||
#define JOF_TYPEMASK 0x001f /* mask for above immediate types */
|
||||
|
||||
#define JOF_NAME (1U<<5) /* name operation */
|
||||
|
|
|
@ -275,8 +275,8 @@ OPDEF(JSOP_LOCALDEC, 104,"localdec", NULL, 3, 0, 1, 15, JOF_LOCAL|
|
|||
OPDEF(JSOP_IMACOP, 105,"imacop", NULL, 1, 0, 0, 0, JOF_BYTE)
|
||||
|
||||
/* Static binding for globals. */
|
||||
OPDEF(JSOP_GETGLOBAL, 106,"getglobal", NULL, 3, 0, 1, 19, JOF_GLOBAL|JOF_NAME|JOF_TYPESET)
|
||||
OPDEF(JSOP_CALLGLOBAL,107,"callglobal", NULL, 3, 0, 2, 19, JOF_GLOBAL|JOF_NAME|JOF_TYPESET|JOF_CALLOP)
|
||||
OPDEF(JSOP_UNUSED0, 106,"unused0", NULL, 3, 0, 1, 19, JOF_BYTE)
|
||||
OPDEF(JSOP_UNUSED1, 107,"unused1", NULL, 3, 0, 2, 19, JOF_BYTE)
|
||||
|
||||
/* Like JSOP_FUNAPPLY but for f.call instead of f.apply. */
|
||||
OPDEF(JSOP_FUNCALL, 108,"funcall", NULL, 3, -1, 1, 18, JOF_UINT16|JOF_INVOKE|JOF_TYPESET)
|
||||
|
|
|
@ -747,18 +747,6 @@ struct JSScript : public js::gc::Cell {
|
|||
return arr->vector[index];
|
||||
}
|
||||
|
||||
uint32 getGlobalSlot(size_t index) {
|
||||
js::GlobalSlotArray *arr = globals();
|
||||
JS_ASSERT(index < arr->length);
|
||||
return arr->vector[index].slot;
|
||||
}
|
||||
|
||||
JSAtom *getGlobalAtom(size_t index) {
|
||||
js::GlobalSlotArray *arr = globals();
|
||||
JS_ASSERT(index < arr->length);
|
||||
return getAtom(arr->vector[index].atomIndex);
|
||||
}
|
||||
|
||||
JSVersion getVersion() const {
|
||||
return JSVersion(version);
|
||||
}
|
||||
|
|
|
@ -16361,26 +16361,12 @@ TraceRecorder::record_JSOP_SHARPINIT()
|
|||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_GETGLOBAL()
|
||||
{
|
||||
uint32 slot = cx->fp()->script()->getGlobalSlot(GET_SLOTNO(cx->regs().pc));
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
RETURN_STOP_A("lazy import of global slot failed");
|
||||
|
||||
stack(0, get(&globalObj->getSlotRef(slot)));
|
||||
TraceRecorder::record_JSOP_UNUSED0() {
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
JS_REQUIRES_STACK AbortableRecordingStatus
|
||||
TraceRecorder::record_JSOP_CALLGLOBAL()
|
||||
{
|
||||
uint32 slot = cx->fp()->script()->getGlobalSlot(GET_SLOTNO(cx->regs().pc));
|
||||
if (!lazilyImportGlobalSlot(slot))
|
||||
RETURN_STOP_A("lazy import of global slot failed");
|
||||
|
||||
const Value &v = globalObj->getSlot(slot);
|
||||
stack(0, get(&v));
|
||||
stack(1, w.immiUndefined());
|
||||
TraceRecorder::record_JSOP_UNUSED1() {
|
||||
return ARECORD_CONTINUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -222,7 +222,7 @@ JS_XDRFindClassById(JSXDRState *xdr, uint32 id);
|
|||
* before deserialization of bytecode. If the saved version does not match
|
||||
* the current version, abort deserialization and invalidate the file.
|
||||
*/
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 94)
|
||||
#define JSXDR_BYTECODE_VERSION (0xb973c0de - 95)
|
||||
|
||||
/*
|
||||
* Library-private functions.
|
||||
|
|
|
@ -2758,13 +2758,6 @@ mjit::Compiler::generateMethod()
|
|||
INLINE_STUBCALL(stubs::UnbrandThis, REJOIN_FALLTHROUGH);
|
||||
END_CASE(JSOP_UNBRANDTHIS)
|
||||
|
||||
BEGIN_CASE(JSOP_GETGLOBAL)
|
||||
BEGIN_CASE(JSOP_CALLGLOBAL)
|
||||
jsop_getglobal(GET_SLOTNO(PC));
|
||||
if (op == JSOP_CALLGLOBAL)
|
||||
frame.push(UndefinedValue());
|
||||
END_CASE(JSOP_GETGLOBAL)
|
||||
|
||||
default:
|
||||
/* Sorry, this opcode isn't implemented yet. */
|
||||
#ifdef JS_METHODJIT_SPEW
|
||||
|
@ -2897,38 +2890,6 @@ mjit::Compiler::jumpInScript(Jump j, jsbytecode *pc)
|
|||
return branchPatches.append(BranchPatch(j, pc, a->inlineIndex));
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::jsop_getglobal(uint32 index)
|
||||
{
|
||||
JS_ASSERT(globalObj);
|
||||
uint32 slot = script->getGlobalSlot(index);
|
||||
|
||||
JSObject *singleton = pushedSingleton(0);
|
||||
if (singleton && !hasTypeBarriers(PC) && !globalObj->getSlot(slot).isUndefined()) {
|
||||
frame.push(ObjectValue(*singleton));
|
||||
return;
|
||||
}
|
||||
|
||||
if (cx->typeInferenceEnabled() && globalObj->isGlobal() &&
|
||||
!globalObj->getType(cx)->unknownProperties()) {
|
||||
Value *value = &globalObj->getSlotRef(slot);
|
||||
if (!value->isUndefined()) {
|
||||
watchGlobalReallocation();
|
||||
RegisterID reg = frame.allocReg();
|
||||
masm.move(ImmPtr(value), reg);
|
||||
|
||||
BarrierState barrier = pushAddressMaybeBarrier(Address(reg), knownPushedType(0), true);
|
||||
finishBarrier(barrier, REJOIN_GETTER, 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterID reg = frame.allocReg();
|
||||
Address address = masm.objSlotRef(globalObj, reg, slot);
|
||||
BarrierState barrier = pushAddressMaybeBarrier(address, knownPushedType(0), true);
|
||||
finishBarrier(barrier, REJOIN_GETTER, 0);
|
||||
}
|
||||
|
||||
void
|
||||
mjit::Compiler::emitFinalReturn(Assembler &masm)
|
||||
{
|
||||
|
|
|
@ -615,7 +615,6 @@ class Compiler : public BaseCompiler
|
|||
bool finishLoop(jsbytecode *head);
|
||||
void jsop_bindname(JSAtom *atom, bool usePropCache);
|
||||
void jsop_setglobal(uint32 index);
|
||||
void jsop_getglobal(uint32 index);
|
||||
void jsop_getprop_slow(JSAtom *atom, bool usePropCache = true);
|
||||
void jsop_getarg(uint32 slot);
|
||||
void jsop_setarg(uint32 slot, bool popped);
|
||||
|
|
|
@ -1475,7 +1475,6 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
|||
switch (op) {
|
||||
case JSOP_NAME:
|
||||
case JSOP_GETGNAME:
|
||||
case JSOP_GETGLOBAL:
|
||||
case JSOP_GETFCSLOT:
|
||||
case JSOP_GETPROP:
|
||||
case JSOP_GETXPROP:
|
||||
|
@ -1491,7 +1490,6 @@ js_InternalInterpret(void *returnData, void *returnType, void *returnReg, js::VM
|
|||
f.regs.pc = nextpc;
|
||||
break;
|
||||
|
||||
case JSOP_CALLGLOBAL:
|
||||
case JSOP_CALLFCSLOT:
|
||||
/* |this| is always undefined for CALLGLOBAL/CALLFCSLOT. */
|
||||
nextsp[-1].setUndefined();
|
||||
|
|
Загрузка…
Ссылка в новой задаче