src/BytecodeCompiler.cpp
changeset 172 48cffae8c9e0
parent 169 0456a16c2a63
child 173 bbf9f3809d55
     1.1 --- a/src/BytecodeCompiler.cpp	Sun Aug 12 13:22:56 2012 -0700
     1.2 +++ b/src/BytecodeCompiler.cpp	Sun Aug 12 20:48:49 2012 -0700
     1.3 @@ -971,6 +971,115 @@
     1.4      __ bind(&join);
     1.5  }
     1.6  
     1.7 +bool
     1.8 +BytecodeCompiler::tableswitch(SwitchStatement *node)
     1.9 +{
    1.10 +    CaseValueList *values = node->caseValueList();
    1.11 +
    1.12 +    if (values->length() < 3)
    1.13 +        return false;
    1.14 +
    1.15 +    // Find the delta between the largest and smallest value.
    1.16 +    int hi = values->at(values->length() - 1).box.toInt();
    1.17 +    int lo = values->at(0).box.toInt();
    1.18 +    assert(hi > lo);
    1.19 +
    1.20 +    unsigned tablesize = TableSwitchEntries(lo, hi);
    1.21 +    if (tablesize > MAX_TABLESWITCH_ENTRIES)
    1.22 +        return false;
    1.23 +
    1.24 +    Label def, join;
    1.25 +
    1.26 +    // Create the list of labels that each statement will bind to.
    1.27 +    Label *labels = new Label[node->cases()->length()];
    1.28 +
    1.29 +    // Create the table of labels we'll use for each case.
    1.30 +    Label **table = new Label *[tablesize];
    1.31 +
    1.32 +    // Link all cases, by default, to the default label.
    1.33 +    for (size_t i = 0; i < tablesize; i++)
    1.34 +        table[i] = &def;
    1.35 +
    1.36 +    // Now patch actual cases to their correct labels.
    1.37 +    for (size_t i = 0; i < values->length(); i++) {
    1.38 +        CaseValue &v = values->at(i);
    1.39 +        assert(v.statement < node->cases()->length());
    1.40 +
    1.41 +        unsigned index = unsigned(v.box.toInt() - lo);
    1.42 +        assert(index < tablesize);
    1.43 +
    1.44 +        table[index] = &labels[v.statement];
    1.45 +    }
    1.46 +
    1.47 +    // Emit the tableswitch opcode and the jump table.
    1.48 +    __ tableswitch(lo, hi, &def, table);
    1.49 +
    1.50 +    // We're done with the jump table now.
    1.51 +    delete [] table;
    1.52 +
    1.53 +    // Emit each statement.
    1.54 +    for (size_t i = 0; i < node->cases()->length(); i++) {
    1.55 +        Statement *stmt = node->cases()->at(i)->statement();
    1.56 +
    1.57 +        __ bind(&labels[i]);
    1.58 +        stmt->accept(this);
    1.59 +        __ jump(&join);
    1.60 +    }
    1.61 +
    1.62 +    // We're done with the statement labels.
    1.63 +    delete [] labels;
    1.64 +
    1.65 +    // Emit the default case.
    1.66 +    __ bind(&def);
    1.67 +    if (node->defaultCase())
    1.68 +        node->defaultCase()->accept(this);
    1.69 +
    1.70 +    __ bind(&join);
    1.71 +
    1.72 +    return true;
    1.73 +}
    1.74 +
    1.75 +void
    1.76 +BytecodeCompiler::visit(SwitchStatement *node)
    1.77 +{
    1.78 +    node->expression()->accept(this);
    1.79 +
    1.80 +    if (tableswitch(node))
    1.81 +        return;
    1.82 +
    1.83 +    Label join;
    1.84 +
    1.85 +    for (size_t i = 0; i < node->cases()->length(); i++) {
    1.86 +        Case *c = node->cases()->at(i);
    1.87 +
    1.88 +        Label success, fail;
    1.89 +        if (c->others()) {
    1.90 +            for (size_t j = 0; j < c->others()->length(); j++) {
    1.91 +                Expression *expr = c->others()->at(j);
    1.92 +
    1.93 +                __ dup();
    1.94 +                expr->accept(this);
    1.95 +                __ j(OP_JEQ, &success);
    1.96 +            }
    1.97 +        }
    1.98 +
    1.99 +        // The final test.
   1.100 +        __ dup();
   1.101 +        c->expression()->accept(this);
   1.102 +        __ j(OP_JNE, &fail);
   1.103 +        __ bind(&success);
   1.104 +        c->statement()->accept(this);
   1.105 +        __ jump(&join);
   1.106 +        __ bind(&fail);
   1.107 +    }
   1.108 +
   1.109 +    if (node->defaultCase())
   1.110 +        node->defaultCase()->accept(this);
   1.111 +
   1.112 +    __ drop(1);
   1.113 +    __ bind(&join);
   1.114 +}
   1.115 +
   1.116  void
   1.117  BytecodeCompiler::visit(FunctionStatement *node)
   1.118  {