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:
Terrence Cole 2011-09-22 17:35:25 +01:00
Родитель 11bd6931dd
Коммит 28beac255b
12 изменённых файлов: 13 добавлений и 129 удалений

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

@ -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();