# HG changeset patch # User David Anderson # Date 1344154535 25200 # Node ID 91071a2255bf067b2f1e3602a322c744bb1455d2 # Parent b760e8cb29a842c2158918242b4f545395d33e13 Remove OP_BOUNDS in favor of an inline check. diff -r b760e8cb29a8 -r 91071a2255bf src/BytecodeCompiler.cpp --- a/src/BytecodeCompiler.cpp Sun Aug 05 01:10:49 2012 -0700 +++ b/src/BytecodeCompiler.cpp Sun Aug 05 01:15:35 2012 -0700 @@ -249,23 +249,14 @@ IndexExpression *index = node->lvalue()->toIndexExpression(); __ note_position(index->pos()); - // Note: Eventually, watch out for a hole here. An expression like: - // - // (a[4] = (5, a = [])) - // - // Could shrink array, so we need to either bind a[i] to a Reference, - // or keep the bounds check near the set. This is just a semantic - // decision. index->left()->accept(this); index->right()->accept(this); if (node->token() != TOK_ASSIGN) __ dup2(); - if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) { - __ bounds(); + if (node->token() != TOK_ASSIGN || (type->isStruct() || type->isArray())) __ getelem(index->type()); - } } if (node->token() == TOK_ASSIGN) { @@ -302,9 +293,6 @@ __ setfield(expr->fieldIndex(), expr->type()); } else { IndexExpression *index = node->lvalue()->toIndexExpression(); - // :TODO: get rid of the BOUNDS instruction, embed it in g/setelem*? - // We can't emit it here because the stack is slightly out of position. - // __ bounds(); __ setelem(index->type()); } } @@ -382,7 +370,6 @@ index->right()->accept(this); assert(!node->type()->isArray()); - __ bounds(); __ dup2(); __ getelem(node->type()); @@ -538,7 +525,6 @@ node->left()->accept(this); node->right()->accept(this); __ note_position(node->pos()); - __ bounds(); __ getelem(node->type()); } @@ -887,7 +873,6 @@ expr->left()->accept(this); expr->right()->accept(this); __ note_position(expr->pos()); - __ bounds(); __ arrayref_lifo(); } else { // We don't know how to, or can't, build a direct reference to diff -r b760e8cb29a8 -r 91071a2255bf src/BytecodeEmitter.h --- a/src/BytecodeEmitter.h Sun Aug 05 01:10:49 2012 -0700 +++ b/src/BytecodeEmitter.h Sun Aug 05 01:15:35 2012 -0700 @@ -430,10 +430,6 @@ writeUint32(var->slot()); } - void bounds() { - singleByteOp(OP_BOUNDS); - markOop(2); - } void float_(float value) { ensure(OP_FLOAT_LENGTH); writeOp(OP_FLOAT); diff -r b760e8cb29a8 -r 91071a2255bf src/Interpreter.cpp --- a/src/Interpreter.cpp Sun Aug 05 01:10:49 2012 -0700 +++ b/src/Interpreter.cpp Sun Aug 05 01:15:35 2012 -0700 @@ -741,21 +741,16 @@ break; } -case OP_BOUNDS: +case OP_GETELEM: { - Array *array = top.sp[-2].array; + Array *array = Array::cast(top.sp[-2].obj); int index = top.sp[-1].i32; + if (index < 0 || unsigned(index) >= array->length()) { zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length()); goto error; } - break; -} -case OP_GETELEM: -{ - Array *array = Array::cast(top.sp[-2].obj); - int index = top.sp[-1].i32; GetElement(array, index, &top.sp[-2]); top.sp--; break; @@ -765,6 +760,12 @@ { Array *array = Array::cast(top.sp[-3].obj); int index = top.sp[-2].i32; + + if (index < 0 || unsigned(index) >= array->length()) { + zone->reportError(Message_ArrayIndexOutOfBounds, index, array->length()); + goto error; + } + SetElement(zone, array, index, top.sp[-1]); top.sp[-3] = top.sp[-1]; top.sp -= 2; diff -r b760e8cb29a8 -r 91071a2255bf src/Opcodes.cpp --- a/src/Opcodes.cpp Sun Aug 05 01:10:49 2012 -0700 +++ b/src/Opcodes.cpp Sun Aug 05 01:15:35 2012 -0700 @@ -162,7 +162,6 @@ case OP_POP: case OP_GETELEM: case OP_SETELEM: - case OP_BOUNDS: case OP_SHL: case OP_SHR: case OP_USHR: diff -r b760e8cb29a8 -r 91071a2255bf src/Opcodes.tbl --- a/src/Opcodes.tbl Sun Aug 05 01:10:49 2012 -0700 +++ b/src/Opcodes.tbl Sun Aug 05 01:15:35 2012 -0700 @@ -125,73 +125,65 @@ OPDEF(OP_GETELEM, 42, "getelem", 1, 2, 1) OPDEF(OP_SETELEM, 43, "setelem", 1, 3, 1) -// Performs a bounds check on an unsafe array. -// -// index = pop() -// array = pop() -// push(array) -// push(index) -OPDEF(OP_BOUNDS, 44, "bounds", 1, 2, 2) - // Pushes a 32-bit IEEE-754 floating point immediate onto the stack. -OPDEF(OP_FLOAT, 45, "float", 5, 0, 1) +OPDEF(OP_FLOAT, 44, "float", 5, 0, 1) // Converts an integer to a 32-bit IEEE-754 floating point immediate. -OPDEF(OP_CVT_I2F, 46, "cvt.i2f", 1, 1, 1) +OPDEF(OP_CVT_I2F, 45, "cvt.i2f", 1, 1, 1) // Stack transitions for these binary operators: // rhs = pop() // lhs = pop() // push(lhs OP rhs) -OPDEF(OP_ADD_F, 47, "add.f", 1, 2, 1) -OPDEF(OP_SUB_F, 48, "sub.f", 1, 2, 1) -OPDEF(OP_MUL_F, 49, "mul.f", 1, 2, 1) -OPDEF(OP_DIV_F, 50, "div.f", 1, 2, 1) +OPDEF(OP_ADD_F, 46, "add.f", 1, 2, 1) +OPDEF(OP_SUB_F, 47, "sub.f", 1, 2, 1) +OPDEF(OP_MUL_F, 48, "mul.f", 1, 2, 1) +OPDEF(OP_DIV_F, 49, "div.f", 1, 2, 1) -OPDEF(OP_LT_F, 51, "lt.f", 1, 2, 1) -OPDEF(OP_LE_F, 52, "le.f", 1, 2, 1) -OPDEF(OP_GE_F, 53, "ge.f", 1, 2, 1) -OPDEF(OP_GT_F, 54, "gt.f", 1, 2, 1) -OPDEF(OP_EQ_F, 55, "eq.f", 1, 2, 1) -OPDEF(OP_NE_F, 56, "ne.f", 1, 2, 1) +OPDEF(OP_LT_F, 50, "lt.f", 1, 2, 1) +OPDEF(OP_LE_F, 51, "le.f", 1, 2, 1) +OPDEF(OP_GE_F, 52, "ge.f", 1, 2, 1) +OPDEF(OP_GT_F, 53, "gt.f", 1, 2, 1) +OPDEF(OP_EQ_F, 54, "eq.f", 1, 2, 1) +OPDEF(OP_NE_F, 55, "ne.f", 1, 2, 1) -OPDEF(OP_NOT_F, 57, "not.f", 1, 1, 1) -OPDEF(OP_NEG_F, 58, "neg.f", 1, 1, 1) +OPDEF(OP_NOT_F, 56, "not.f", 1, 1, 1) +OPDEF(OP_NEG_F, 57, "neg.f", 1, 1, 1) // Bitwise operators. -OPDEF(OP_SHL, 59, "shl", 1, 2, 1) -OPDEF(OP_SHR, 60, "shr", 1, 2, 1) -OPDEF(OP_USHR, 61, "ushr", 1, 2, 1) -OPDEF(OP_BITAND, 62, "bitand", 1, 2, 1) -OPDEF(OP_BITOR, 63, "bitor", 1, 2, 1) -OPDEF(OP_BITXOR, 64, "bitxor", 1, 2, 1) -OPDEF(OP_BITNOT, 65, "bitnot", 1, 1, 1) +OPDEF(OP_SHL, 58, "shl", 1, 2, 1) +OPDEF(OP_SHR, 59, "shr", 1, 2, 1) +OPDEF(OP_USHR, 60, "ushr", 1, 2, 1) +OPDEF(OP_BITAND, 61, "bitand", 1, 2, 1) +OPDEF(OP_BITOR, 62, "bitor", 1, 2, 1) +OPDEF(OP_BITXOR, 63, "bitxor", 1, 2, 1) +OPDEF(OP_BITNOT, 64, "bitnot", 1, 1, 1) // Saves or restores the position of the LIFO heap to/from a local slot. -OPDEF(OP_SAVELIFO, 66, "savelifo", 5, 0, 0) -OPDEF(OP_UNWINDLIFO, 67, "unwindlifo", 5, 0, 0) +OPDEF(OP_SAVELIFO, 65, "savelifo", 5, 0, 0) +OPDEF(OP_UNWINDLIFO, 66, "unwindlifo", 5, 0, 0) // Composes a variable reference to a stack slot or argument. -OPDEF(OP_VARREF_LIFO, 68, "varref.lifo", 5, 0, 1) -OPDEF(OP_ARGREF_LIFO, 69, "argref.lifo", 5, 0, 1) -OPDEF(OP_SLOTREF_LIFO, 70, "slotref.lifo", 1, 1, 1) -OPDEF(OP_ARRAYREF_LIFO, 71, "arrayref.lifo",1, 2, 1) -OPDEF(OP_GETREF_I, 72, "getref.i", 1, 1, 1) -OPDEF(OP_SETREF_I, 73, "setref.i", 1, 2, 1) -OPDEF(OP_GETREF_F, 74, "getref.f", 1, 1, 1) -OPDEF(OP_SETREF_F, 75, "setref.f", 1, 2, 1) +OPDEF(OP_VARREF_LIFO, 67, "varref.lifo", 5, 0, 1) +OPDEF(OP_ARGREF_LIFO, 68, "argref.lifo", 5, 0, 1) +OPDEF(OP_SLOTREF_LIFO, 69, "slotref.lifo", 1, 1, 1) +OPDEF(OP_ARRAYREF_LIFO, 70, "arrayref.lifo",1, 2, 1) +OPDEF(OP_GETREF_I, 71, "getref.i", 1, 1, 1) +OPDEF(OP_SETREF_I, 72, "setref.i", 1, 2, 1) +OPDEF(OP_GETREF_F, 73, "getref.f", 1, 1, 1) +OPDEF(OP_SETREF_F, 74, "setref.f", 1, 2, 1) // Pushes an object reference onto the stack. -OPDEF(OP_OBJECT, 76, "object", 5, 0, 1) +OPDEF(OP_OBJECT, 75, "object", 5, 0, 1) // Duplicates the top item on the stack. -OPDEF(OP_DUP, 77, "dup", 1, 1, 2) +OPDEF(OP_DUP, 76, "dup", 1, 1, 2) // Duplicates the top two items on the stack. -OPDEF(OP_DUP2, 78, "dup2", 1, 2, 4) +OPDEF(OP_DUP2, 77, "dup2", 1, 2, 4) // Swaps the two items at the top of the stack. -OPDEF(OP_SWAP, 79, "swap", 1, 2, 2) +OPDEF(OP_SWAP, 78, "swap", 1, 2, 2) // Roll operation is the same as Forth. It steals a value on the stack, // shifting all stack values down, and then places the stolen value back at @@ -201,14 +193,14 @@ // sp[-3] = sp[-2] // sp[-2] = sp[-1] // sp[-1] = p -OPDEF(OP_ROLL3, 80, "roll3", 1, 3, 3) +OPDEF(OP_ROLL3, 79, "roll3", 1, 3, 3) // Pick operation is the same as Forth. It pushes a copy of a slot at a // specific depth. // // push(sp[-n]) -OPDEF(OP_PICK2, 81, "pick2", 1, 2, 3) -OPDEF(OP_PICK3, 82, "pick3", 1, 3, 4) +OPDEF(OP_PICK2, 80, "pick2", 1, 2, 3) +OPDEF(OP_PICK3, 81, "pick3", 1, 3, 4) // Calls a native function. During the course of calling a native, arguments // on the stack are re-pushed to match the cell-based native calling @@ -219,51 +211,51 @@ // // [u8 Opcode] [u32 Index] [u32 ArgCount] // -OPDEF(OP_CALLNATIVE, 83, "callnative", 9, -1, 1) +OPDEF(OP_CALLNATIVE, 82, "callnative", 9, -1, 1) // Returns from a function that does return a value. -OPDEF(OP_RETURNVOID, 84, "returnvoid", 1, 0, 0) +OPDEF(OP_RETURNVOID, 83, "returnvoid", 1, 0, 0) // Loads the module of the running function. -OPDEF(OP_MODULE, 85, "module", 1, 0, 1) +OPDEF(OP_MODULE, 84, "module", 1, 0, 1) // Loads a function from a module object. The operand is the slot number // in the module. -OPDEF(OP_GETMODULE_FN, 86, "getmodule.fn", 5, 1, 1) +OPDEF(OP_GETMODULE_FN, 85, "getmodule.fn", 5, 1, 1) // Opcodes for accessing an environment slot in the global scope. -OPDEF(OP_SETGLOBAL_I, 87, "setglobal.i", 5, 1, 1) -OPDEF(OP_SETGLOBAL_F, 88, "setglobal.f", 5, 1, 1) -OPDEF(OP_SETGLOBAL_O, 89, "setglobal.o", 5, 1, 1) -OPDEF(OP_GETGLOBAL_I, 90, "getglobal.i", 5, 0, 1) -OPDEF(OP_GETGLOBAL_F, 91, "getglobal.f", 5, 0, 1) -OPDEF(OP_GETGLOBAL_O, 92, "getglobal.o", 5, 0, 1) +OPDEF(OP_SETGLOBAL_I, 86, "setglobal.i", 5, 1, 1) +OPDEF(OP_SETGLOBAL_F, 87, "setglobal.f", 5, 1, 1) +OPDEF(OP_SETGLOBAL_O, 88, "setglobal.o", 5, 1, 1) +OPDEF(OP_GETGLOBAL_I, 89, "getglobal.i", 5, 0, 1) +OPDEF(OP_GETGLOBAL_F, 90, "getglobal.f", 5, 0, 1) +OPDEF(OP_GETGLOBAL_O, 91, "getglobal.o", 5, 0, 1) // Reinterprets a 32-bit integer as a float, or vice-versa. -OPDEF(OP_BITS_I2F, 93, "bits.i2f", 1, 1, 1) -OPDEF(OP_BITS_F2I, 94, "bits.f2i", 1, 1, 1) +OPDEF(OP_BITS_I2F, 92, "bits.i2f", 1, 1, 1) +OPDEF(OP_BITS_F2I, 93, "bits.f2i", 1, 1, 1) // Pushes a boolean value. -OPDEF(OP_TRUE, 95, "true", 1, 0, 1) -OPDEF(OP_FALSE, 96, "false", 1, 0, 1) +OPDEF(OP_TRUE, 94, "true", 1, 0, 1) +OPDEF(OP_FALSE, 95, "false", 1, 0, 1) // Allocate a struct. The HeapTenure is stored as a byte following pc. The // StructMap to use is specified as an index into the script's Map table. // // Format: // [u8 op] [u32 index] -OPDEF(OP_NEWSTRUCT, 97, "newstruct", 6, 0, 1) +OPDEF(OP_NEWSTRUCT, 96, "newstruct", 6, 0, 1) // Performs a struct-to-struct assignment. // Left = pop() // Right = pop() // copy(Left, Right) // push(Left) -OPDEF(OP_COPYSTRUCT, 98, "structcopy", 1, 2, 1) +OPDEF(OP_COPYSTRUCT, 97, "structcopy", 1, 2, 1) // Sets or gets a property in a struct. The index of the field is specified as // a 32-bit integer. Note that these opcodes follow a new style of deriving // their types at runtime. -OPDEF(OP_GETFIELD, 99, "getfield", 5, 1, 1) -OPDEF(OP_SETFIELD, 100, "setfield", 5, 2, 1) +OPDEF(OP_GETFIELD, 98, "getfield", 5, 1, 1) +OPDEF(OP_SETFIELD, 99, "setfield", 5, 2, 1)