我正在浏览SpiderMonkey引擎源,并在解释器中看到了一些引起我兴趣的代码。
window.location.href=url
(来源: https://dxr.mozilla.org/mozilla-b2g44_v2_5/source/js/src/vm/Interpreter.cpp#1579 )
将// Portable switch-based dispatch.
# define INTERPRETER_LOOP() the_switch: switch (switchOp)
# define CASE(OP) case OP:
# define DEFAULT() default:
定义为case OP:
这样的内容是否有任何非风格上的好处?
答案 0 :(得分:11)
#if (defined(__GNUC__) || \
(__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \
__SUNPRO_C >= 0x570)
// Non-standard but faster indirect-goto-based dispatch.
# define INTERPRETER_LOOP()
# define CASE(OP) label_##OP:
// ... <snip>
#else
// Portable switch-based dispatch.
# define INTERPRETER_LOOP() the_switch: switch (switchOp)
# define CASE(OP) case OP:
// ... <snip>
#endif
GCC和其他一些编译器支持"computed goto" faster than a loop-switch for an interpreter loop,但它是非标准的,因此不可移植。
如果编译器支持计算goto,则此#if
的第一个分支定义INTERPRETER_LOOP
,CASE(OP)
等以使用计算的goto;否则,#else
分支根据标准设施定义它们。
答案 1 :(得分:7)
如果你在相同的源代码中看起来更高,那么对于不同的编译器语法,这些相同的宏有不同的定义:
/*
* Define macros for an interpreter loop. Opcode dispatch may be either by a
* switch statement or by indirect goto (aka a threaded interpreter), depending
* on compiler support.
*
* Threaded interpretation appears to be well-supported by GCC 3 and higher.
* IBM's C compiler when run with the right options (e.g., -qlanglvl=extended)
* also supports threading. Ditto the SunPro C compiler.
*/
#if (defined(__GNUC__) || \
(__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \
__SUNPRO_C >= 0x570)
// Non-standard but faster indirect-goto-based dispatch.
# define INTERPRETER_LOOP()
# define CASE(OP) label_##OP:
# define DEFAULT() label_default:
# define DISPATCH_TO(OP) goto* addresses[(OP)]
//...
#else
// Portable switch-based dispatch.
# define INTERPRETER_LOOP() the_switch: switch (switchOp)
# define CASE(OP) case OP:
# define DEFAULT() default:
# define DISPATCH_TO(OP) \
JS_BEGIN_MACRO \
switchOp = (OP); \
goto the_switch; \
JS_END_MACRO
// ...
#endif
如果你在同一个源中进一步查看,你会看到实际使用这些宏:
INTERPRETER_LOOP() {
CASE(EnableInterruptsPseudoOpcode)
{
//...
DISPATCH_TO(op);
}
* Various 1-byte no-ops. */
CASE(JSOP_NOP)
CASE(JSOP_UNUSED14)
CASE(JSOP_BACKPATCH)
//...
{
//...
ADVANCE_AND_DISPATCH(1);
}
CASE(JSOP_LOOPHEAD)
END_CASE(JSOP_LOOPHEAD)
//...
DEFAULT()
{
//...
goto error;
}
} /* interpreter loop */
根据编译器的不同,该代码将编译为:
static const void* const addresses[EnableInterruptsPseudoOpcode + 1] = {
...
};
...
{
label_EnableInterruptsPseudoOpcode:
{
//...
goto* addresses[op];
}
* Various 1-byte no-ops. */
label_JSOP_NOP:
label_JSOP_UNUSED14:
label_JSOP_BACKPATCH:
//...
{
//...
REGS.pc += 1;
SANITY_CHECKS();
goto* addresses[*REGS.pc | activation.opMask()];
}
label_JSOP_LOOPHEAD:
goto* addresses[JSOP_LOOPHEAD_LENGTH];
//...
label_default:
{
//...
goto error;
}
} /* interpreter loop */
或者对此:
jsbytecode switchOp;
...
the_switch:
switch (switchOp) {
case EnableInterruptsPseudoOpcode:
{
//...
switchOp = op;
goto the_switch;
}
* Various 1-byte no-ops. */
case JSOP_NOP:
case JSOP_UNUSED14:
case JSOP_BACKPATCH:
//...
{
//...
REGS.pc += 1;
SANITY_CHECKS();
switchOp = *REGS.pc | activation.opMask;
goto the_switch;
}
case JSOP_LOOPHEAD:
REGS.pc += JSOP_LOOPHEAD_LENGTH;
SANITY_CHECKS();
switchOp = *REGS.pc | activation.opMask();
goto the_switch;
//...
default:
{
//...
goto error;
}
} /* interpreter loop */