void Canonicalizer::do_ArrayLength (ArrayLength* x) { NewArray* array = x->array()->as_NewArray(); if (array != NULL && array->length() != NULL) { Constant* length = array->length()->as_Constant(); if (length != NULL) { // do not use the Constant itself, but create a new Constant // with same value Otherwise a Constant is live over multiple // blocks without being registered in a state array. assert(length->type()->as_IntConstant() != NULL, "array length must be integer"); set_constant(length->type()->as_IntConstant()->value()); } } else { LoadField* lf = x->array()->as_LoadField(); if (lf != NULL) { ciField* field = lf->field(); if (field->is_constant() && field->is_static()) { // final static field ciObject* c = field->constant_value().as_object(); if (c->is_array()) { ciArray* array = (ciArray*) c; set_constant(array->length()); } } } } }
void Canonicalizer::do_ArrayLength (ArrayLength* x) { NewArray* na; Constant* ct; LoadField* lf; if ((na = x->array()->as_NewArray()) != NULL) { // New arrays might have the known length. // Do not use the Constant itself, but create a new Constant // with same value Otherwise a Constant is live over multiple // blocks without being registered in a state array. Constant* length; if (na->length() != NULL && (length = na->length()->as_Constant()) != NULL) { assert(length->type()->as_IntConstant() != NULL, "array length must be integer"); set_constant(length->type()->as_IntConstant()->value()); } } else if ((ct = x->array()->as_Constant()) != NULL) { // Constant arrays have constant lengths. ArrayConstant* cnst = ct->type()->as_ArrayConstant(); if (cnst != NULL) { set_constant(cnst->value()->length()); } } else if ((lf = x->array()->as_LoadField()) != NULL) { ciField* field = lf->field(); if (field->is_static_constant()) { assert(PatchALot || ScavengeRootsInCode < 2, "Constant field loads are folded during parsing"); ciObject* c = field->constant_value().as_object(); if (!c->is_null_object()) { set_constant(c->as_array()->length()); } } } }
// perform constant and interval tests on index value bool AccessIndexed::compute_needs_range_check() { Constant* clength = length()->as_Constant(); Constant* cindex = index()->as_Constant(); if (clength && cindex) { IntConstant* l = clength->type()->as_IntConstant(); IntConstant* i = cindex->type()->as_IntConstant(); if (l && i && i->value() < l->value() && i->value() >= 0) { return false; } } return true; }
static bool match_index_and_scale(Instruction* instr, Instruction** index, int* log2_scale, Instruction** instr_to_unpin) { *instr_to_unpin = NULL; // Skip conversion ops Convert* convert = instr->as_Convert(); if (convert != NULL) { instr = convert->value(); } ShiftOp* shift = instr->as_ShiftOp(); if (shift != NULL) { if (shift->is_pinned()) { *instr_to_unpin = shift; } // Constant shift value? Constant* con = shift->y()->as_Constant(); if (con == NULL) return false; // Well-known type and value? IntConstant* val = con->type()->as_IntConstant(); if (val == NULL) return false; if (shift->x()->type() != intType) return false; *index = shift->x(); int tmp_scale = val->value(); if (tmp_scale >= 0 && tmp_scale < 4) { *log2_scale = tmp_scale; return true; } else { return false; } } ArithmeticOp* arith = instr->as_ArithmeticOp(); if (arith != NULL) { if (arith->is_pinned()) { *instr_to_unpin = arith; } // Check for integer multiply if (arith->op() == Bytecodes::_imul) { // See if either arg is a known constant Constant* con = arith->x()->as_Constant(); if (con != NULL) { *index = arith->y(); } else { con = arith->y()->as_Constant(); if (con == NULL) return false; *index = arith->x(); } if ((*index)->type() != intType) return false; // Well-known type and value? IntConstant* val = con->type()->as_IntConstant(); if (val == NULL) return false; switch (val->value()) { case 1: *log2_scale = 0; return true; case 2: *log2_scale = 1; return true; case 4: *log2_scale = 2; return true; case 8: *log2_scale = 3; return true; default: return false; } } } // Unknown instruction sequence; don't touch it return false; }