// 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; }
void Canonicalizer::do_LoadIndexed (LoadIndexed* x) { StableArrayConstant* array = x->array()->type()->as_StableArrayConstant(); IntConstant* index = x->index()->type()->as_IntConstant(); assert(array == NULL || FoldStableValues, "not enabled"); // Constant fold loads from stable arrays. if (!x->mismatched() && array != NULL && index != NULL) { jint idx = index->value(); if (idx < 0 || idx >= array->value()->length()) { // Leave the load as is. The range check will handle it. return; } ciConstant field_val = array->value()->element_value(idx); if (!field_val.is_null_or_zero()) { jint dimension = array->dimension(); assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info"); ValueType* value = NULL; if (dimension > 1) { // Preserve information about the dimension for the element. assert(field_val.as_object()->is_array(), "not an array"); value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1); } else { assert(dimension == 1, "sanity"); value = as_ValueType(field_val); } set_canonical(new Constant(value)); } } }
void Canonicalizer::do_Intrinsic (Intrinsic* x) { switch (x->id()) { case ciMethod::_floatToRawIntBits : { FloatConstant* c = x->argument_at(0)->type()->as_FloatConstant(); if (c != NULL) { JavaValue v; v.set_jfloat(c->value()); set_constant(v.get_jint()); } break; } case ciMethod::_intBitsToFloat : { IntConstant* c = x->argument_at(0)->type()->as_IntConstant(); if (c != NULL) { JavaValue v; v.set_jint(c->value()); set_constant(v.get_jfloat()); } break; } case ciMethod::_doubleToRawLongBits : { DoubleConstant* c = x->argument_at(0)->type()->as_DoubleConstant(); if (c != NULL) { JavaValue v; v.set_jdouble(c->value()); set_constant(v.get_jlong()); } break; } case ciMethod::_longBitsToDouble : { LongConstant* c = x->argument_at(0)->type()->as_LongConstant(); if (c != NULL) { JavaValue v; v.set_jlong(c->value()); set_constant(v.get_jdouble()); } break; } } }
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; }