size_t insns_size = accessor.InsnsSizeInCodeUnits(); if (insns_size >= 4u) { if (!is_recognizable_constructor) { return nullptr;
} // We can recognize a constructor with 6 or 4 code units. if (insns_size != 4u && insns_size != 6u) { return nullptr;
}
}
// Recognize: // iget-{object,wide,boolean} vX, v0, field // return-{object} vX // Or: // iput-{object,wide,boolean} v1, v0, field // return-void // Or: // sget-object vX, field // return-object vX // Or: // iput-{object,wide,boolean} v1, v0, field // invoke-direct v0, j.l.Object.<init> // return-void // Or: // invoke-direct v0, j.l.Object.<init> // iput-{object,wide,boolean} v1, v0, field // return-void if (insns_size == 3u || insns_size == 6u) {
DCHECK_IMPLIES(insns_size == 6u, is_recognizable_constructor);
uint16_t number_of_vregs = accessor.RegistersSize();
uint16_t number_of_parameters = accessor.InsSize();
uint16_t obj_reg = number_of_vregs - number_of_parameters;
uint16_t first_param_reg = number_of_vregs - number_of_parameters + 1;
uint16_t dest_reg = -1;
uint32_t offset = -1; bool is_object = false; bool is_put = false; bool is_static = false; bool is_final = false;
Primitive::Type field_type; for (DexInstructionPcPair pair : accessor) { const Instruction& instruction = pair.Inst(); switch (pair->Opcode()) { case Instruction::INVOKE_DIRECT: if (!is_recognizable_constructor || !is_object_init_invoke(instruction)) { return nullptr;
} break; case Instruction::SGET_OBJECT:
is_static = true;
FALLTHROUGH_INTENDED; case Instruction::IPUT_OBJECT: case Instruction::IGET_OBJECT:
is_object = true;
FALLTHROUGH_INTENDED; case Instruction::IPUT: case Instruction::IGET: case Instruction::IGET_BOOLEAN: case Instruction::IPUT_BOOLEAN: case Instruction::IGET_WIDE: case Instruction::IPUT_WIDE: {
is_put = (pair->Opcode() == Instruction::IPUT ||
pair->Opcode() == Instruction::IPUT_OBJECT ||
pair->Opcode() == Instruction::IPUT_BOOLEAN ||
pair->Opcode() == Instruction::IPUT_WIDE); if (!is_static && obj_reg != instruction.VRegB_22c()) { // The field access is not on the first parameter. return nullptr;
} if (!is_static && method->IsStatic()) { // Getting/setting an instance field on an object that can be null. // Our stubs cannot handle implicit null checks. return nullptr;
} if (is_put) { if (first_param_reg != instruction.VRegA_22c()) { // The value being stored is not the first parameter after 'this'. return nullptr;
}
} else {
dest_reg = is_static ? instruction.VRegA_21c() : instruction.VRegA_22c();
}
uint16_t field_index = is_static ? instruction.VRegB_21c() : instruction.VRegC_22c();
Thread* self = Thread::Current();
ArtField* field =
ResolveFieldWithAccessChecks(Thread::Current(),
class_linker,
field_index,
method,
is_static,
is_put, /* resolve_field_type= */ is_put && is_object); if (field == nullptr) {
self->ClearException(); return nullptr;
} if (field->IsVolatile()) { return nullptr;
} if (is_static && field->GetDeclaringClass() != method->GetDeclaringClass()) { return nullptr;
}
offset = field->GetOffset().Int32Value(); if (is_static) { // We subtract the start of reference fields to share more stubs.
MemberOffset first_field_offset =
field->GetDeclaringClass()->GetFirstReferenceStaticFieldOffset(kRuntimePointerSize);
offset = offset - first_field_offset.Int32Value();
} else {
offset = offset - sizeof(mirror::Object);
} if (offset > 64) { return nullptr;
}
field_type = field->GetTypeAsPrimitiveType();
is_final = field->IsFinal(); break;
} case Instruction::RETURN_OBJECT: case Instruction::RETURN_WIDE: case Instruction::RETURN: { if (is_put || dest_reg != instruction.VRegA_11x()) { // The returned value is not the fetched field. return nullptr;
} if (is_static) {
DO_SWITCH(offset, ReturnStaticFieldObjectAt, ReturnStaticFieldAt, field_type);
} else {
DO_SWITCH(offset, ReturnFieldObjectAt, ReturnFieldAt, field_type);
}
} case Instruction::RETURN_VOID: { if (!is_put) { return nullptr;
} if (is_final) {
DCHECK(is_recognizable_constructor);
DO_SWITCH(offset, ConstructorSetFieldObjectAt, ConstructorSetFieldAt, field_type);
} else {
DO_SWITCH(offset, SetFieldObjectAt, SetFieldAt, field_type);
}
} default: return nullptr;
}
}
}
return nullptr;
}
} // namespace jit
} // namespace art
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.19Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.