Revert^2 "Compile time null checks for VarHandle intrinsics."
This reverts commit 4a889b7f1e58368f0ffd795eaa24f2f493ccab8d.
Reason for revert: relanding the original change after fixing the
baseline compiler.
Static checks for VarHandle intrinsics are now done in two places:
1) Simple static checks are done for both baseline and optimizing
compilers in `HInstructionBuilder::BuildInvokePolymorphic`.
2) More complex checks are done in instruction simplifier only for the
optimizing compiler. They can use information provided by preceding
optimization passes.
Bug: 191765508
Test: art/test.py --host -r
Change-Id: I92932f6fcf408c700e6db0101fe2fb1e8300a54a
diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc
index 2a2f245..f1dfa9e 100644
--- a/compiler/optimizing/intrinsics_arm_vixl.cc
+++ b/compiler/optimizing/intrinsics_arm_vixl.cc
@@ -3891,6 +3891,7 @@
static void GenerateVarHandleInstanceFieldChecks(HInvoke* invoke,
CodeGeneratorARMVIXL* codegen,
SlowPathCodeARMVIXL* slow_path) {
+ VarHandleOptimizations optimizations(invoke);
ArmVIXLAssembler* assembler = codegen->GetAssembler();
vixl32::Register varhandle = InputRegisterAt(invoke, 0);
vixl32::Register object = InputRegisterAt(invoke, 1);
@@ -3899,8 +3900,10 @@
const MemberOffset coordinate_type1_offset = mirror::VarHandle::CoordinateType1Offset();
// Null-check the object.
- __ Cmp(object, 0);
- __ B(eq, slow_path->GetEntryLabel());
+ if (!optimizations.GetSkipObjectNullCheck()) {
+ __ Cmp(object, 0);
+ __ B(eq, slow_path->GetEntryLabel());
+ }
// Use the first temporary register, whether it's for the declaring class or the offset.
// It is not used yet at this point.
@@ -3941,6 +3944,7 @@
static void GenerateVarHandleArrayChecks(HInvoke* invoke,
CodeGeneratorARMVIXL* codegen,
VarHandleSlowPathARMVIXL* slow_path) {
+ VarHandleOptimizations optimizations(invoke);
ArmVIXLAssembler* assembler = codegen->GetAssembler();
vixl32::Register varhandle = InputRegisterAt(invoke, 0);
vixl32::Register object = InputRegisterAt(invoke, 1);
@@ -3957,8 +3961,10 @@
const MemberOffset array_length_offset = mirror::Array::LengthOffset();
// Null-check the object.
- __ Cmp(object, 0);
- __ B(eq, slow_path->GetEntryLabel());
+ if (!optimizations.GetSkipObjectNullCheck()) {
+ __ Cmp(object, 0);
+ __ B(eq, slow_path->GetEntryLabel());
+ }
// Use the offset temporary register. It is not used yet at this point.
vixl32::Register temp = RegisterFrom(invoke->GetLocations()->GetTemp(0u));
@@ -4114,91 +4120,6 @@
}
}
-static bool HasVarHandleIntrinsicImplementation(HInvoke* invoke) {
- size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
- if (expected_coordinates_count > 2u) {
- // Invalid coordinate count. This invoke shall throw at runtime.
- return false;
- }
- if (expected_coordinates_count != 0u &&
- invoke->InputAt(1)->GetType() != DataType::Type::kReference) {
- // Except for static fields (no coordinates), the first coordinate must be a reference.
- return false;
- }
- if (expected_coordinates_count == 2u) {
- // For arrays and views, the second coordinate must be convertible to `int`.
- // In this context, `boolean` is not convertible but we have to look at the shorty
- // as compiler transformations can give the invoke a valid boolean input.
- DataType::Type index_type = GetDataTypeFromShorty(invoke, 2);
- if (index_type == DataType::Type::kBool ||
- DataType::Kind(index_type) != DataType::Type::kInt32) {
- return false;
- }
- }
-
- uint32_t number_of_arguments = invoke->GetNumberOfArguments();
- DataType::Type return_type = invoke->GetType();
- mirror::VarHandle::AccessModeTemplate access_mode_template =
- mirror::VarHandle::GetAccessModeTemplateByIntrinsic(invoke->GetIntrinsic());
- switch (access_mode_template) {
- case mirror::VarHandle::AccessModeTemplate::kGet:
- // The return type should be the same as varType, so it shouldn't be void.
- if (return_type == DataType::Type::kVoid) {
- return false;
- }
- break;
- case mirror::VarHandle::AccessModeTemplate::kSet:
- if (return_type != DataType::Type::kVoid) {
- return false;
- }
- break;
- case mirror::VarHandle::AccessModeTemplate::kCompareAndSet: {
- if (return_type != DataType::Type::kBool) {
- return false;
- }
- uint32_t expected_value_index = number_of_arguments - 2;
- uint32_t new_value_index = number_of_arguments - 1;
- DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
- DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
- if (expected_value_type != new_value_type) {
- return false;
- }
- break;
- }
- case mirror::VarHandle::AccessModeTemplate::kCompareAndExchange: {
- uint32_t expected_value_index = number_of_arguments - 2;
- uint32_t new_value_index = number_of_arguments - 1;
- DataType::Type expected_value_type = GetDataTypeFromShorty(invoke, expected_value_index);
- DataType::Type new_value_type = GetDataTypeFromShorty(invoke, new_value_index);
- if (expected_value_type != new_value_type || return_type != expected_value_type) {
- return false;
- }
- break;
- }
- case mirror::VarHandle::AccessModeTemplate::kGetAndUpdate: {
- DataType::Type value_type = GetDataTypeFromShorty(invoke, number_of_arguments - 1);
- if (IsVarHandleGetAndAdd(invoke) &&
- (value_type == DataType::Type::kReference || value_type == DataType::Type::kBool)) {
- // We should only add numerical types.
- return false;
- } else if (IsVarHandleGetAndBitwiseOp(invoke) && !DataType::IsIntegralType(value_type)) {
- // We can only apply operators to bitwise integral types.
- // Note that bitwise VarHandle operations accept a non-integral boolean type and
- // perform the appropriate logical operation. However, the result is the same as
- // using the bitwise operation on our boolean representation and this fits well
- // with DataType::IsIntegralType() treating the compiler type kBool as integral.
- return false;
- }
- if (value_type != return_type) {
- return false;
- }
- break;
- }
- }
-
- return true;
-}
-
static LocationSummary* CreateVarHandleCommonLocations(HInvoke* invoke) {
size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
DataType::Type return_type = invoke->GetType();
@@ -4251,7 +4172,8 @@
static void CreateVarHandleGetLocations(HInvoke* invoke,
CodeGeneratorARMVIXL* codegen,
bool atomic) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}
@@ -4399,7 +4321,8 @@
static void CreateVarHandleSetLocations(HInvoke* invoke,
CodeGeneratorARMVIXL* codegen,
bool atomic) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}
@@ -4561,7 +4484,8 @@
}
static void CreateVarHandleCompareAndSetOrExchangeLocations(HInvoke* invoke, bool return_success) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}
@@ -4892,7 +4816,8 @@
static void CreateVarHandleGetAndUpdateLocations(HInvoke* invoke,
GetAndUpdateOp get_and_update_op) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}