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()); } } } }
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 LoopInvariantCodeMotion::process_block(BlockBegin* block) { TRACE_VALUE_NUMBERING(tty->print_cr("processing block B%d", block->block_id())); Instruction* prev = block; Instruction* cur = block->next(); while (cur != NULL) { // determine if cur instruction is loop invariant // only selected instruction types are processed here bool cur_invariant = false; if (cur->as_Constant() != NULL) { cur_invariant = !cur->can_trap(); } else if (cur->as_ArithmeticOp() != NULL || cur->as_LogicOp() != NULL || cur->as_ShiftOp() != NULL) { assert(cur->as_Op2() != NULL, "must be Op2"); Op2* op2 = (Op2*)cur; cur_invariant = !op2->can_trap() && is_invariant(op2->x()) && is_invariant(op2->y()); } else if (cur->as_LoadField() != NULL) { LoadField* lf = (LoadField*)cur; // deoptimizes on NullPointerException cur_invariant = !lf->needs_patching() && !lf->field()->is_volatile() && !_short_loop_optimizer->has_field_store(lf->field()->type()->basic_type()) && is_invariant(lf->obj()) && _insert_is_pred; } else if (cur->as_ArrayLength() != NULL) { ArrayLength *length = cur->as_ArrayLength(); cur_invariant = is_invariant(length->array()); } else if (cur->as_LoadIndexed() != NULL) { LoadIndexed *li = (LoadIndexed *)cur->as_LoadIndexed(); cur_invariant = !_short_loop_optimizer->has_indexed_store(as_BasicType(cur->type())) && is_invariant(li->array()) && is_invariant(li->index()) && _insert_is_pred; } if (cur_invariant) { // perform value numbering and mark instruction as loop-invariant _gvn->substitute(cur); if (cur->as_Constant() == NULL) { // ensure that code for non-constant instructions is always generated cur->pin(); } // remove cur instruction from loop block and append it to block before loop Instruction* next = cur->next(); Instruction* in = _insertion_point->next(); _insertion_point = _insertion_point->set_next(cur); cur->set_next(in); // Deoptimize on exception cur->set_flag(Instruction::DeoptimizeOnException, true); // Clear exception handlers cur->set_exception_handlers(NULL); TRACE_VALUE_NUMBERING(tty->print_cr("Instruction %c%d is loop invariant", cur->type()->tchar(), cur->id())); if (cur->state_before() != NULL) { cur->set_state_before(_state->copy()); } if (cur->exception_state() != NULL) { cur->set_exception_state(_state->copy()); } cur = prev->set_next(next); } else { prev = cur; cur = cur->next(); } } }