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_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index d11bfa2..bed9ebe 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -3291,81 +3291,20 @@
__ Bind(slow_path->GetExitLabel());
}
-static bool IsValidFieldVarHandleExpected(HInvoke* invoke) {
+static bool HasVarHandleIntrinsicImplementation(HInvoke* invoke) {
+ VarHandleOptimizations optimizations(invoke);
+ if (optimizations.GetDoNotIntrinsify()) {
+ return false;
+ }
+
size_t expected_coordinates_count = GetExpectedVarHandleCoordinatesCount(invoke);
+ DCHECK_LE(expected_coordinates_count, 2u); // Filtered by the `DoNotIntrinsify` flag above.
if (expected_coordinates_count > 1u) {
// Only static and instance fields VarHandle are supported now.
+ // TODO: add support for arrays and views.
return false;
}
- if (expected_coordinates_count == 1u &&
- invoke->InputAt(1)->GetType() != DataType::Type::kReference) {
- // For instance fields, the source object must be a reference
- 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::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;
- }
- 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;
- }
- }
-
return true;
}
@@ -3426,11 +3365,15 @@
__ Bind(&type_matched);
}
-static void GenerateVarHandleInstanceFieldObjectCheck(Register varhandle_object,
- Register object,
- Register temp,
- SlowPathCode* slow_path,
- X86Assembler* assembler) {
+static void GenerateVarHandleInstanceFieldChecks(HInvoke* invoke,
+ Register temp,
+ SlowPathCode* slow_path,
+ X86Assembler* assembler) {
+ VarHandleOptimizations optimizations(invoke);
+ LocationSummary* locations = invoke->GetLocations();
+ Register varhandle_object = locations->InAt(0).AsRegister<Register>();
+ Register object = locations->InAt(1).AsRegister<Register>();
+
const uint32_t coordtype0_offset = mirror::VarHandle::CoordinateType0Offset().Uint32Value();
const uint32_t coordtype1_offset = mirror::VarHandle::CoordinateType1Offset().Uint32Value();
@@ -3441,8 +3384,10 @@
__ j(kNotEqual, slow_path->GetEntryLabel());
// Check if the object is null
- __ testl(object, object);
- __ j(kZero, slow_path->GetEntryLabel());
+ if (!optimizations.GetSkipObjectNullCheck()) {
+ __ testl(object, object);
+ __ j(kZero, slow_path->GetEntryLabel());
+ }
// Check the object's class against coordinateType0.
GenerateSubTypeObjectCheck(object,
@@ -3490,8 +3435,7 @@
GenerateVarHandleStaticFieldCheck(vh_object, slow_path, assembler);
break;
case 1u: {
- Register object = locations->InAt(1).AsRegister<Register>();
- GenerateVarHandleInstanceFieldObjectCheck(vh_object, object, temp, slow_path, assembler);
+ GenerateVarHandleInstanceFieldChecks(invoke, temp, slow_path, assembler);
break;
}
default:
@@ -3603,7 +3547,7 @@
return;
}
- if (!IsValidFieldVarHandleExpected(invoke)) {
+ if (!HasVarHandleIntrinsicImplementation(invoke)) {
return;
}
@@ -3726,7 +3670,7 @@
return;
}
- if (!IsValidFieldVarHandleExpected(invoke)) {
+ if (!HasVarHandleIntrinsicImplementation(invoke)) {
return;
}
@@ -3896,7 +3840,7 @@
return;
}
- if (!IsValidFieldVarHandleExpected(invoke)) {
+ if (!HasVarHandleIntrinsicImplementation(invoke)) {
return;
}
@@ -4067,7 +4011,7 @@
return;
}
- if (!IsValidFieldVarHandleExpected(invoke)) {
+ if (!HasVarHandleIntrinsicImplementation(invoke)) {
return;
}
@@ -4250,7 +4194,7 @@
return;
}
- if (!IsValidFieldVarHandleExpected(invoke)) {
+ if (!HasVarHandleIntrinsicImplementation(invoke)) {
return;
}
@@ -4400,7 +4344,7 @@
return;
}
- if (!IsValidFieldVarHandleExpected(invoke)) {
+ if (!HasVarHandleIntrinsicImplementation(invoke)) {
return;
}