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_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index d0c64c2..800e5bd 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -4045,6 +4045,7 @@
static void GenerateVarHandleInstanceFieldChecks(HInvoke* invoke,
CodeGeneratorARM64* codegen,
SlowPathCodeARM64* slow_path) {
+ VarHandleOptimizations optimizations(invoke);
MacroAssembler* masm = codegen->GetVIXLAssembler();
Register varhandle = InputRegisterAt(invoke, 0);
Register object = InputRegisterAt(invoke, 1);
@@ -4053,7 +4054,9 @@
const MemberOffset coordinate_type1_offset = mirror::VarHandle::CoordinateType1Offset();
// Null-check the object.
- __ Cbz(object, slow_path->GetEntryLabel());
+ if (!optimizations.GetSkipObjectNullCheck()) {
+ __ Cbz(object, slow_path->GetEntryLabel());
+ }
UseScratchRegisterScope temps(masm);
Register temp = temps.AcquireW();
@@ -4090,6 +4093,7 @@
static void GenerateVarHandleArrayChecks(HInvoke* invoke,
CodeGeneratorARM64* codegen,
VarHandleSlowPathARM64* slow_path) {
+ VarHandleOptimizations optimizations(invoke);
MacroAssembler* masm = codegen->GetVIXLAssembler();
Register varhandle = InputRegisterAt(invoke, 0);
Register object = InputRegisterAt(invoke, 1);
@@ -4106,7 +4110,9 @@
const MemberOffset array_length_offset = mirror::Array::LengthOffset();
// Null-check the object.
- __ Cbz(object, slow_path->GetEntryLabel());
+ if (!optimizations.GetSkipObjectNullCheck()) {
+ __ Cbz(object, slow_path->GetEntryLabel());
+ }
UseScratchRegisterScope temps(masm);
Register temp = temps.AcquireW();
@@ -4262,91 +4268,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();
@@ -4399,7 +4320,8 @@
}
static void CreateVarHandleGetLocations(HInvoke* invoke) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}
@@ -4525,7 +4447,8 @@
}
static void CreateVarHandleSetLocations(HInvoke* invoke) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}
@@ -4630,7 +4553,8 @@
}
static void CreateVarHandleCompareAndSetOrExchangeLocations(HInvoke* invoke, bool return_success) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}
@@ -4977,7 +4901,8 @@
static void CreateVarHandleGetAndUpdateLocations(HInvoke* invoke,
GetAndUpdateOp get_and_update_op) {
- if (!HasVarHandleIntrinsicImplementation(invoke)) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
return;
}