static bool match(UnsafeRawOp* x, Instruction** base, Instruction** index, int* log2_scale) { Instruction* instr_to_unpin = NULL; ArithmeticOp* root = x->base()->as_ArithmeticOp(); if (root == NULL) return false; // Limit ourselves to addition for now if (root->op() != Bytecodes::_ladd) return false; // Try to find shift or scale op if (match_index_and_scale(root->y(), index, log2_scale, &instr_to_unpin)) { *base = root->x(); } else if (match_index_and_scale(root->x(), index, log2_scale, &instr_to_unpin)) { *base = root->y(); } else if (root->y()->as_Convert() != NULL) { Convert* convert = root->y()->as_Convert(); if (convert->op() == Bytecodes::_i2l && convert->value()->type() == intType) { // pick base and index, setting scale at 1 *base = root->x(); *index = convert->value(); *log2_scale = 0; } else { return false; } } else { // doesn't match any expected sequences return false; } // Typically the addition is pinned, as it is the result of an // inlined routine. We want to unpin it so as to avoid the long // addition, but in order to do so we must still ensure that the // operands are pinned, as they may be computed arbitrarily before // the Unsafe op completes (even if the Unsafe op is pinned). At // this point we do not really need to pin Unsafe raw or object // gets. if (root->is_pinned()) { if (root->pin_state() == Instruction::PinInlineReturnValue) { assert(x->is_pinned(), "All unsafe raw ops should be pinned"); root->unpin(Instruction::PinInlineReturnValue); (*base)->pin(); (*index)->pin(); } else { // can't safely unpin this instruction return false; } } if (PrintUnsafeOptimization && instr_to_unpin != NULL) { tty->print_cr("pin_state = 0x%x", instr_to_unpin->pin_state()); instr_to_unpin->print(); } return true; }