Ignore:
Timestamp:
Jul 23, 2008, 5:49:46 PM (17 years ago)
Author:
[email protected]
Message:

Improve switch performance.

Reviewed by Geoff Garen and Sam Weinig.

Improve switch performance by converting to a hashmap based jump
table to avoid the sequence of dispatches that would otherwise be
needed. This results in a 9-19x performance win for string switches
based on ad hoc testing, and a 6x improvement for integer switch
statements. SunSpider reports a 1.2% progression.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/VM/CodeBlock.cpp

    r35291 r35309  
    198198        } while (i < exceptionHandlers.size());
    199199    }
    200        
     200   
     201    if (immediateSwitchJumpTables.size()) {
     202        printf("immediate switch jump tables:\n");
     203        unsigned i = 0;
     204        do {
     205            printf("\t{\n");
     206            int entry = 0;
     207            Vector<int32_t>::const_iterator end = immediateSwitchJumpTables[i].branchOffsets.end();
     208            for (Vector<int32_t>::const_iterator iter = immediateSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry)
     209                if (*iter)
     210                    printf("\t\t%4d => %04d\n", entry + immediateSwitchJumpTables[i].min, *iter);
     211            printf("\t}\n");
     212            ++i;
     213        } while (i < immediateSwitchJumpTables.size());
     214    }
     215   
     216    if (characterSwitchJumpTables.size()) {
     217        printf("\ncharacter switch jump tables:\n");
     218        unsigned i = 0;
     219        do {
     220            printf("\t{\n");
     221            int entry = 0;
     222            Vector<int32_t>::const_iterator end = characterSwitchJumpTables[i].branchOffsets.end();
     223            for (Vector<int32_t>::const_iterator iter = characterSwitchJumpTables[i].branchOffsets.begin(); iter != end; ++iter, ++entry) {
     224                ASSERT(!((i + characterSwitchJumpTables[i].min) & ~0xFFFF));
     225                UChar ch = static_cast<UChar>(i + characterSwitchJumpTables[i].min);
     226                printf("\t\t\"%s\" => %04d\n", UString(&ch, 1).ascii(), *iter);
     227            }
     228            printf("\t}\n");
     229            ++i;
     230        } while (i < characterSwitchJumpTables.size());
     231    }
     232   
     233    if (stringSwitchJumpTables.size()) {
     234        printf("\nstring switch jump tables:\n");
     235        unsigned i = 0;
     236        do {
     237            printf("\t{\n");
     238            StringJumpTable::const_iterator end = stringSwitchJumpTables[i].end();
     239            for (StringJumpTable::const_iterator iter = stringSwitchJumpTables[i].begin(); iter != end; ++iter)
     240                printf("\t\t\"%s\" => %04d\n", UString(iter->first).ascii(), iter->second);
     241            printf("\t}\n");
     242            ++i;
     243        } while (i < stringSwitchJumpTables.size());
     244    }
     245
    201246    printf("\n");
    202247}
     
    501546            int offset = (++it)->u.operand;
    502547            printf("[%4d] loop_if_less %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, jumpTarget(begin, it, offset));
     548            break;
     549        }
     550        case op_switch_imm: {
     551            int tableIndex = (++it)->u.operand;
     552            int defaultTarget = (++it)->u.operand;
     553            int scrutineeRegister = (++it)->u.operand;
     554            printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, jumpTarget(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
     555            break;
     556        }
     557        case op_switch_char: {
     558            int tableIndex = (++it)->u.operand;
     559            int defaultTarget = (++it)->u.operand;
     560            int scrutineeRegister = (++it)->u.operand;
     561            printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, jumpTarget(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
     562            break;
     563        }
     564        case op_switch_string: {
     565            int tableIndex = (++it)->u.operand;
     566            int defaultTarget = (++it)->u.operand;
     567            int scrutineeRegister = (++it)->u.operand;
     568            printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, jumpTarget(begin, it, defaultTarget), registerName(scrutineeRegister).c_str());
    503569            break;
    504570        }
     
    711777}
    712778
     779int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset)
     780{
     781    if (value >= min && static_cast<uint32_t>(value - min) < branchOffsets.size()) {
     782        int32_t offset = branchOffsets[value - min];
     783        if (offset)
     784            return offset;
     785    }
     786    return defaultOffset;       
     787}
     788
    713789} // namespace KJS
Note: See TracChangeset for help on using the changeset viewer.