Remove OP_BOUNDS in favor of an inline check.
authorDavid Anderson <dvander@alliedmods.net>
Sun Aug 05 01:15:35 2012 -0700 (2012-08-05)
changeset 15891071a2255bf
parent 157 b760e8cb29a8
child 159 d515dceb12f9
Remove OP_BOUNDS in favor of an inline check.
src/BytecodeCompiler.cpp
src/BytecodeEmitter.h
src/Interpreter.cpp
src/Opcodes.cpp
src/Opcodes.tbl
     1.1 --- a/src/BytecodeCompiler.cpp	Sun Aug 05 01:10:49 2012 -0700
     1.2 +++ b/src/BytecodeCompiler.cpp	Sun Aug 05 01:15:35 2012 -0700
     1.3 @@ -249,23 +249,14 @@
     1.4          IndexExpression *index = node->lvalue()->toIndexExpression();
     1.5          __ note_position(index->pos());
     1.6  
     1.7 -        // Note: Eventually, watch out for a hole here. An expression like:
     1.8 -        //
     1.9 -        //   (a[4] = (5, a = []))
    1.10 -        //
    1.11 -        // Could shrink array, so we need to either bind a[i] to a Reference,
    1.12 -        // or keep the bounds check near the set. This is just a semantic
    1.13 -        // decision.
    1.14          index->left()->accept(this);
    1.15          index->right()->accept(this);
    1.16  
    1.17          if (node->token() != TOK_ASSIGN)
    1.18              __ dup2();
    1.19  
    1.20 -        if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) {
    1.21 -            __ bounds();
    1.22 +        if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray()))
    1.23              __ getelem(index->type());
    1.24 -        }
    1.25      }
    1.26  
    1.27      if (node->token() == TOK_ASSIGN) {
    1.28 @@ -302,9 +293,6 @@
    1.29          __ setfield(expr->fieldIndex(), expr->type());
    1.30      } else {
    1.31          IndexExpression *index = node->lvalue()->toIndexExpression();
    1.32 -        // :TODO: get rid of the BOUNDS instruction, embed it in g/setelem*?
    1.33 -        // We can't emit it here because the stack is slightly out of position.
    1.34 -        // __ bounds();
    1.35          __ setelem(index->type());
    1.36      }
    1.37  }
    1.38 @@ -382,7 +370,6 @@
    1.39          index->right()->accept(this);
    1.40  
    1.41          assert(!node->type()->isArray());
    1.42 -        __ bounds();
    1.43          __ dup2();
    1.44          __ getelem(node->type());
    1.45  
    1.46 @@ -538,7 +525,6 @@
    1.47      node->left()->accept(this);
    1.48      node->right()->accept(this);
    1.49      __ note_position(node->pos());
    1.50 -    __ bounds();
    1.51      __ getelem(node->type());
    1.52  }
    1.53  
    1.54 @@ -887,7 +873,6 @@
    1.55                  expr->left()->accept(this);
    1.56                  expr->right()->accept(this);
    1.57                  __ note_position(expr->pos());
    1.58 -                __ bounds();
    1.59                  __ arrayref_lifo();
    1.60              } else {
    1.61                  // We don't know how to, or can't, build a direct reference to
     2.1 --- a/src/BytecodeEmitter.h	Sun Aug 05 01:10:49 2012 -0700
     2.2 +++ b/src/BytecodeEmitter.h	Sun Aug 05 01:15:35 2012 -0700
     2.3 @@ -430,10 +430,6 @@
     2.4          writeUint32(var->slot());
     2.5      }
     2.6  
     2.7 -    void bounds() {
     2.8 -        singleByteOp(OP_BOUNDS);
     2.9 -        markOop(2);
    2.10 -    }
    2.11      void float_(float value) {
    2.12          ensure(OP_FLOAT_LENGTH);
    2.13          writeOp(OP_FLOAT);
     3.1 --- a/src/Interpreter.cpp	Sun Aug 05 01:10:49 2012 -0700
     3.2 +++ b/src/Interpreter.cpp	Sun Aug 05 01:15:35 2012 -0700
     3.3 @@ -741,21 +741,16 @@
     3.4      break;
     3.5  }
     3.6  
     3.7 -case OP_BOUNDS:
     3.8 +case OP_GETELEM:
     3.9  {
    3.10 -    Array *array = top.sp[-2].array;
    3.11 +    Array *array = Array::cast(top.sp[-2].obj);
    3.12      int index = top.sp[-1].i32;
    3.13 +
    3.14      if (index < 0 || unsigned(index) >= array->length()) {
    3.15          zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
    3.16          goto error;
    3.17      }
    3.18 -    break;
    3.19 -}
    3.20  
    3.21 -case OP_GETELEM:
    3.22 -{
    3.23 -    Array *array = Array::cast(top.sp[-2].obj);
    3.24 -    int index = top.sp[-1].i32;
    3.25      GetElement(array, index, &top.sp[-2]);
    3.26      top.sp--;
    3.27      break;
    3.28 @@ -765,6 +760,12 @@
    3.29  {
    3.30      Array *array = Array::cast(top.sp[-3].obj);
    3.31      int index = top.sp[-2].i32;
    3.32 +
    3.33 +    if (index < 0 || unsigned(index) >= array->length()) {
    3.34 +        zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length());
    3.35 +        goto error;
    3.36 +    }
    3.37 +
    3.38      SetElement(zone, array, index, top.sp[-1]);
    3.39      top.sp[-3] = top.sp[-1];
    3.40      top.sp -= 2;
     4.1 --- a/src/Opcodes.cpp	Sun Aug 05 01:10:49 2012 -0700
     4.2 +++ b/src/Opcodes.cpp	Sun Aug 05 01:15:35 2012 -0700
     4.3 @@ -162,7 +162,6 @@
     4.4            case OP_POP:
     4.5            case OP_GETELEM:
     4.6            case OP_SETELEM:
     4.7 -          case OP_BOUNDS:
     4.8            case OP_SHL:
     4.9            case OP_SHR:
    4.10            case OP_USHR:
     5.1 --- a/src/Opcodes.tbl	Sun Aug 05 01:10:49 2012 -0700
     5.2 +++ b/src/Opcodes.tbl	Sun Aug 05 01:15:35 2012 -0700
     5.3 @@ -125,73 +125,65 @@
     5.4  OPDEF(OP_GETELEM,       42,         "getelem",      1,      2,  1)
     5.5  OPDEF(OP_SETELEM,       43,         "setelem",      1,      3,  1)
     5.6  
     5.7 -// Performs a bounds check on an unsafe array.
     5.8 -//
     5.9 -// index = pop()
    5.10 -// array = pop()
    5.11 -// push(array)
    5.12 -// push(index)
    5.13 -OPDEF(OP_BOUNDS,        44,         "bounds",       1,      2,  2)
    5.14 -
    5.15  // Pushes a 32-bit IEEE-754 floating point immediate onto the stack.
    5.16 -OPDEF(OP_FLOAT,         45,         "float",        5,      0,  1)
    5.17 +OPDEF(OP_FLOAT,         44,         "float",        5,      0,  1)
    5.18  
    5.19  // Converts an integer to a 32-bit IEEE-754 floating point immediate.
    5.20 -OPDEF(OP_CVT_I2F,       46,         "cvt.i2f",      1,      1,  1)
    5.21 +OPDEF(OP_CVT_I2F,       45,         "cvt.i2f",      1,      1,  1)
    5.22  
    5.23  // Stack transitions for these binary operators:
    5.24  // rhs = pop()
    5.25  // lhs = pop()
    5.26  // push(lhs OP rhs)
    5.27 -OPDEF(OP_ADD_F,         47,         "add.f",        1,      2,  1)
    5.28 -OPDEF(OP_SUB_F,         48,         "sub.f",        1,      2,  1)
    5.29 -OPDEF(OP_MUL_F,         49,         "mul.f",        1,      2,  1)
    5.30 -OPDEF(OP_DIV_F,         50,         "div.f",        1,      2,  1)
    5.31 +OPDEF(OP_ADD_F,         46,         "add.f",        1,      2,  1)
    5.32 +OPDEF(OP_SUB_F,         47,         "sub.f",        1,      2,  1)
    5.33 +OPDEF(OP_MUL_F,         48,         "mul.f",        1,      2,  1)
    5.34 +OPDEF(OP_DIV_F,         49,         "div.f",        1,      2,  1)
    5.35  
    5.36 -OPDEF(OP_LT_F,          51,         "lt.f",         1,      2,  1)
    5.37 -OPDEF(OP_LE_F,          52,         "le.f",         1,      2,  1)
    5.38 -OPDEF(OP_GE_F,          53,         "ge.f",         1,      2,  1)
    5.39 -OPDEF(OP_GT_F,          54,         "gt.f",         1,      2,  1)
    5.40 -OPDEF(OP_EQ_F,          55,         "eq.f",         1,      2,  1)
    5.41 -OPDEF(OP_NE_F,          56,         "ne.f",         1,      2,  1)
    5.42 +OPDEF(OP_LT_F,          50,         "lt.f",         1,      2,  1)
    5.43 +OPDEF(OP_LE_F,          51,         "le.f",         1,      2,  1)
    5.44 +OPDEF(OP_GE_F,          52,         "ge.f",         1,      2,  1)
    5.45 +OPDEF(OP_GT_F,          53,         "gt.f",         1,      2,  1)
    5.46 +OPDEF(OP_EQ_F,          54,         "eq.f",         1,      2,  1)
    5.47 +OPDEF(OP_NE_F,          55,         "ne.f",         1,      2,  1)
    5.48  
    5.49 -OPDEF(OP_NOT_F,         57,         "not.f",        1,      1,  1)
    5.50 -OPDEF(OP_NEG_F,         58,         "neg.f",        1,      1,  1)
    5.51 +OPDEF(OP_NOT_F,         56,         "not.f",        1,      1,  1)
    5.52 +OPDEF(OP_NEG_F,         57,         "neg.f",        1,      1,  1)
    5.53  
    5.54  // Bitwise operators.
    5.55 -OPDEF(OP_SHL,           59,         "shl",          1,      2,  1)
    5.56 -OPDEF(OP_SHR,           60,         "shr",          1,      2,  1)
    5.57 -OPDEF(OP_USHR,          61,         "ushr",         1,      2,  1)
    5.58 -OPDEF(OP_BITAND,        62,         "bitand",       1,      2,  1)
    5.59 -OPDEF(OP_BITOR,         63,         "bitor",        1,      2,  1)
    5.60 -OPDEF(OP_BITXOR,        64,         "bitxor",       1,      2,  1)
    5.61 -OPDEF(OP_BITNOT,        65,         "bitnot",       1,      1,  1)
    5.62 +OPDEF(OP_SHL,           58,         "shl",          1,      2,  1)
    5.63 +OPDEF(OP_SHR,           59,         "shr",          1,      2,  1)
    5.64 +OPDEF(OP_USHR,          60,         "ushr",         1,      2,  1)
    5.65 +OPDEF(OP_BITAND,        61,         "bitand",       1,      2,  1)
    5.66 +OPDEF(OP_BITOR,         62,         "bitor",        1,      2,  1)
    5.67 +OPDEF(OP_BITXOR,        63,         "bitxor",       1,      2,  1)
    5.68 +OPDEF(OP_BITNOT,        64,         "bitnot",       1,      1,  1)
    5.69  
    5.70  // Saves or restores the position of the LIFO heap to/from a local slot.
    5.71 -OPDEF(OP_SAVELIFO,      66,         "savelifo",     5,      0,  0)
    5.72 -OPDEF(OP_UNWINDLIFO,    67,         "unwindlifo",   5,      0,  0)
    5.73 +OPDEF(OP_SAVELIFO,      65,         "savelifo",     5,      0,  0)
    5.74 +OPDEF(OP_UNWINDLIFO,    66,         "unwindlifo",   5,      0,  0)
    5.75  
    5.76  // Composes a variable reference to a stack slot or argument.
    5.77 -OPDEF(OP_VARREF_LIFO,   68,         "varref.lifo",  5,      0,  1)
    5.78 -OPDEF(OP_ARGREF_LIFO,   69,         "argref.lifo",  5,      0,  1)
    5.79 -OPDEF(OP_SLOTREF_LIFO,  70,         "slotref.lifo", 1,      1,  1)
    5.80 -OPDEF(OP_ARRAYREF_LIFO, 71,         "arrayref.lifo",1,      2,  1)
    5.81 -OPDEF(OP_GETREF_I,      72,         "getref.i",     1,      1,  1)
    5.82 -OPDEF(OP_SETREF_I,      73,         "setref.i",     1,      2,  1)
    5.83 -OPDEF(OP_GETREF_F,      74,         "getref.f",     1,      1,  1)
    5.84 -OPDEF(OP_SETREF_F,      75,         "setref.f",     1,      2,  1)
    5.85 +OPDEF(OP_VARREF_LIFO,   67,         "varref.lifo",  5,      0,  1)
    5.86 +OPDEF(OP_ARGREF_LIFO,   68,         "argref.lifo",  5,      0,  1)
    5.87 +OPDEF(OP_SLOTREF_LIFO,  69,         "slotref.lifo", 1,      1,  1)
    5.88 +OPDEF(OP_ARRAYREF_LIFO, 70,         "arrayref.lifo",1,      2,  1)
    5.89 +OPDEF(OP_GETREF_I,      71,         "getref.i",     1,      1,  1)
    5.90 +OPDEF(OP_SETREF_I,      72,         "setref.i",     1,      2,  1)
    5.91 +OPDEF(OP_GETREF_F,      73,         "getref.f",     1,      1,  1)
    5.92 +OPDEF(OP_SETREF_F,      74,         "setref.f",     1,      2,  1)
    5.93  
    5.94  // Pushes an object reference onto the stack.
    5.95 -OPDEF(OP_OBJECT,        76,         "object",       5,      0,  1)
    5.96 +OPDEF(OP_OBJECT,        75,         "object",       5,      0,  1)
    5.97  
    5.98  // Duplicates the top item on the stack.
    5.99 -OPDEF(OP_DUP,           77,         "dup",          1,      1,  2)
   5.100 +OPDEF(OP_DUP,           76,         "dup",          1,      1,  2)
   5.101  
   5.102  // Duplicates the top two items on the stack.
   5.103 -OPDEF(OP_DUP2,          78,         "dup2",         1,      2,  4)
   5.104 +OPDEF(OP_DUP2,          77,         "dup2",         1,      2,  4)
   5.105  
   5.106  // Swaps the two items at the top of the stack.
   5.107 -OPDEF(OP_SWAP,          79,         "swap",         1,      2,  2)
   5.108 +OPDEF(OP_SWAP,          78,         "swap",         1,      2,  2)
   5.109  
   5.110  // Roll operation is the same as Forth. It steals a value on the stack,
   5.111  // shifting all stack values down, and then places the stolen value back at
   5.112 @@ -201,14 +193,14 @@
   5.113  //  sp[-3] = sp[-2]
   5.114  //  sp[-2] = sp[-1]
   5.115  //  sp[-1] = p
   5.116 -OPDEF(OP_ROLL3,         80,         "roll3",        1,      3, 3)
   5.117 +OPDEF(OP_ROLL3,         79,         "roll3",        1,      3, 3)
   5.118  
   5.119  // Pick operation is the same as Forth. It pushes a copy of a slot at a
   5.120  // specific depth.
   5.121  //
   5.122  // push(sp[-n])
   5.123 -OPDEF(OP_PICK2,         81,         "pick2",        1,      2, 3)
   5.124 -OPDEF(OP_PICK3,         82,         "pick3",        1,      3, 4)
   5.125 +OPDEF(OP_PICK2,         80,         "pick2",        1,      2, 3)
   5.126 +OPDEF(OP_PICK3,         81,         "pick3",        1,      3, 4)
   5.127  
   5.128  // Calls a native function. During the course of calling a native, arguments
   5.129  // on the stack are re-pushed to match the cell-based native calling
   5.130 @@ -219,51 +211,51 @@
   5.131  //
   5.132  // [u8 Opcode] [u32 Index] [u32 ArgCount]
   5.133  //
   5.134 -OPDEF(OP_CALLNATIVE,    83,         "callnative",   9,      -1, 1)
   5.135 +OPDEF(OP_CALLNATIVE,    82,         "callnative",   9,      -1, 1)
   5.136  
   5.137  // Returns from a function that does return a value.
   5.138 -OPDEF(OP_RETURNVOID,    84,         "returnvoid",   1,      0, 0)
   5.139 +OPDEF(OP_RETURNVOID,    83,         "returnvoid",   1,      0, 0)
   5.140  
   5.141  // Loads the module of the running function.
   5.142 -OPDEF(OP_MODULE,        85,         "module",       1,      0, 1)
   5.143 +OPDEF(OP_MODULE,        84,         "module",       1,      0, 1)
   5.144  
   5.145  // Loads a function from a module object. The operand is the slot number
   5.146  // in the module.
   5.147 -OPDEF(OP_GETMODULE_FN,  86,         "getmodule.fn", 5,      1, 1)
   5.148 +OPDEF(OP_GETMODULE_FN,  85,         "getmodule.fn", 5,      1, 1)
   5.149  
   5.150  // Opcodes for accessing an environment slot in the global scope.
   5.151 -OPDEF(OP_SETGLOBAL_I,   87,         "setglobal.i",  5,      1, 1)
   5.152 -OPDEF(OP_SETGLOBAL_F,   88,         "setglobal.f",  5,      1, 1)
   5.153 -OPDEF(OP_SETGLOBAL_O,   89,         "setglobal.o",  5,      1, 1)
   5.154 -OPDEF(OP_GETGLOBAL_I,   90,         "getglobal.i",  5,      0, 1)
   5.155 -OPDEF(OP_GETGLOBAL_F,   91,         "getglobal.f",  5,      0, 1)
   5.156 -OPDEF(OP_GETGLOBAL_O,   92,         "getglobal.o",  5,      0, 1)
   5.157 +OPDEF(OP_SETGLOBAL_I,   86,         "setglobal.i",  5,      1, 1)
   5.158 +OPDEF(OP_SETGLOBAL_F,   87,         "setglobal.f",  5,      1, 1)
   5.159 +OPDEF(OP_SETGLOBAL_O,   88,         "setglobal.o",  5,      1, 1)
   5.160 +OPDEF(OP_GETGLOBAL_I,   89,         "getglobal.i",  5,      0, 1)
   5.161 +OPDEF(OP_GETGLOBAL_F,   90,         "getglobal.f",  5,      0, 1)
   5.162 +OPDEF(OP_GETGLOBAL_O,   91,         "getglobal.o",  5,      0, 1)
   5.163  
   5.164  // Reinterprets a 32-bit integer as a float, or vice-versa.
   5.165 -OPDEF(OP_BITS_I2F,      93,         "bits.i2f",     1,      1, 1)
   5.166 -OPDEF(OP_BITS_F2I,      94,         "bits.f2i",     1,      1, 1)
   5.167 +OPDEF(OP_BITS_I2F,      92,         "bits.i2f",     1,      1, 1)
   5.168 +OPDEF(OP_BITS_F2I,      93,         "bits.f2i",     1,      1, 1)
   5.169  
   5.170  // Pushes a boolean value.
   5.171 -OPDEF(OP_TRUE,          95,         "true",         1,      0, 1)
   5.172 -OPDEF(OP_FALSE,         96,         "false",        1,      0, 1)
   5.173 +OPDEF(OP_TRUE,          94,         "true",         1,      0, 1)
   5.174 +OPDEF(OP_FALSE,         95,         "false",        1,      0, 1)
   5.175  
   5.176  // Allocate a struct. The HeapTenure is stored as a byte following pc. The
   5.177  // StructMap to use is specified as an index into the script's Map table.
   5.178  //
   5.179  // Format:
   5.180  //  [u8 op] [u32 index]
   5.181 -OPDEF(OP_NEWSTRUCT,     97,         "newstruct",    6,      0, 1)
   5.182 +OPDEF(OP_NEWSTRUCT,     96,         "newstruct",    6,      0, 1)
   5.183  
   5.184  // Performs a struct-to-struct assignment.
   5.185  //   Left = pop()
   5.186  //   Right = pop()
   5.187  //   copy(Left, Right)
   5.188  //   push(Left)
   5.189 -OPDEF(OP_COPYSTRUCT,    98,         "structcopy",   1,      2, 1)
   5.190 +OPDEF(OP_COPYSTRUCT,    97,         "structcopy",   1,      2, 1)
   5.191  
   5.192  // Sets or gets a property in a struct. The index of the field is specified as
   5.193  // a 32-bit integer. Note that these opcodes follow a new style of deriving
   5.194  // their types at runtime.
   5.195 -OPDEF(OP_GETFIELD,      99,         "getfield",     5,      1, 1)
   5.196 -OPDEF(OP_SETFIELD,      100,        "setfield",     5,      2, 1)
   5.197 +OPDEF(OP_GETFIELD,      98,         "getfield",     5,      1, 1)
   5.198 +OPDEF(OP_SETFIELD,      99,         "setfield",     5,      2, 1)
   5.199