From 288c7a8664e516d7486ab85267050e676e84cc39 Mon Sep 17 00:00:00 2001 From: Serguei Katkov Date: Mon, 16 May 2016 11:53:15 +0600 Subject: [PATCH] Revert "Revert "ART: Reference.getReferent intrinsic for x86 and x86_64"" This reverts commit 0997d24e67d78f2146ebae2888eda0d7d254789a. ART_HEAP_POISONING=true mode is fixed. Change-Id: I83f6d5c101ea6a86802753f81b3e4348a263fb21 Signed-off-by: Serguei Katkov --- compiler/optimizing/code_generator.cc | 14 +++++++ compiler/optimizing/code_generator.h | 3 ++ compiler/optimizing/code_generator_x86.cc | 19 ++++++--- compiler/optimizing/code_generator_x86.h | 1 + compiler/optimizing/code_generator_x86_64.cc | 12 ++++-- compiler/optimizing/code_generator_x86_64.h | 1 + compiler/optimizing/intrinsics_x86.cc | 60 +++++++++++++++++++++++++++- compiler/optimizing/intrinsics_x86_64.cc | 60 +++++++++++++++++++++++++++- 8 files changed, 159 insertions(+), 11 deletions(-) diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index 51fbaea51..08670a0d8 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -1305,4 +1305,18 @@ void CodeGenerator::CreateSystemArrayCopyLocationSummary(HInvoke* invoke) { locations->AddTemp(Location::RequiresRegister()); } +uint32_t CodeGenerator::GetReferenceSlowFlagOffset() const { + ScopedObjectAccess soa(Thread::Current()); + mirror::Class* klass = mirror::Reference::GetJavaLangRefReference(); + DCHECK(klass->IsInitialized()); + return klass->GetSlowPathFlagOffset().Uint32Value(); +} + +uint32_t CodeGenerator::GetReferenceDisableFlagOffset() const { + ScopedObjectAccess soa(Thread::Current()); + mirror::Class* klass = mirror::Reference::GetJavaLangRefReference(); + DCHECK(klass->IsInitialized()); + return klass->GetDisableIntrinsicFlagOffset().Uint32Value(); +} + } // namespace art diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h index 6e75e3bb2..82a54d2ed 100644 --- a/compiler/optimizing/code_generator.h +++ b/compiler/optimizing/code_generator.h @@ -469,6 +469,9 @@ class CodeGenerator : public DeletableArenaObject { virtual void GenerateNop() = 0; + uint32_t GetReferenceSlowFlagOffset() const; + uint32_t GetReferenceDisableFlagOffset() const; + protected: // Method patch info used for recording locations of required linker patches and // target methods. The target method can be used for various purposes, whether for diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc index 50892a9d4..bdbafcdf6 100644 --- a/compiler/optimizing/code_generator_x86.cc +++ b/compiler/optimizing/code_generator_x86.cc @@ -4308,16 +4308,18 @@ Register CodeGeneratorX86::GetInvokeStaticOrDirectExtraParameter(HInvokeStaticOr // save one load. However, since this is just an intrinsic slow path we prefer this // simple and more robust approach rather that trying to determine if that's the case. SlowPathCode* slow_path = GetCurrentSlowPath(); - DCHECK(slow_path != nullptr); // For intrinsified invokes the call is emitted on the slow path. - if (slow_path->IsCoreRegisterSaved(location.AsRegister())) { - int stack_offset = slow_path->GetStackOffsetOfCoreRegister(location.AsRegister()); - __ movl(temp, Address(ESP, stack_offset)); - return temp; + if (slow_path != nullptr) { + if (slow_path->IsCoreRegisterSaved(location.AsRegister())) { + int stack_offset = slow_path->GetStackOffsetOfCoreRegister(location.AsRegister()); + __ movl(temp, Address(ESP, stack_offset)); + return temp; + } } return location.AsRegister(); } -void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) { +Location CodeGeneratorX86::GenerateCalleeMethodStaticOrDirectCall(HInvokeStaticOrDirect* invoke, + Location temp) { Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp. switch (invoke->GetMethodLoadKind()) { case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: @@ -4366,6 +4368,11 @@ void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, break; } } + return callee_method; +} + +void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) { + Location callee_method = GenerateCalleeMethodStaticOrDirectCall(invoke, temp); switch (invoke->GetCodePtrLocation()) { case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf: diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h index fe7d3ed85..98dc8ca28 100644 --- a/compiler/optimizing/code_generator_x86.h +++ b/compiler/optimizing/code_generator_x86.h @@ -398,6 +398,7 @@ class CodeGeneratorX86 : public CodeGenerator { MethodReference target_method) OVERRIDE; // Generate a call to a static or direct method. + Location GenerateCalleeMethodStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp); void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; // Generate a call to a virtual method. void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc index 56c5b0694..30eca2c10 100644 --- a/compiler/optimizing/code_generator_x86_64.cc +++ b/compiler/optimizing/code_generator_x86_64.cc @@ -762,10 +762,9 @@ HInvokeStaticOrDirect::DispatchInfo CodeGeneratorX86_64::GetSupportedInvokeStati } } -void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, - Location temp) { +Location CodeGeneratorX86_64::GenerateCalleeMethodStaticOrDirectCall(HInvokeStaticOrDirect* invoke, + Location temp) { // All registers are assumed to be correctly set up. - Location callee_method = temp; // For all kinds except kRecursive, callee will be in temp. switch (invoke->GetMethodLoadKind()) { case HInvokeStaticOrDirect::MethodLoadKind::kStringInit: @@ -815,6 +814,13 @@ void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invo break; } } + return callee_method; +} + +void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, + Location temp) { + // All registers are assumed to be correctly set up. + Location callee_method = GenerateCalleeMethodStaticOrDirectCall(invoke, temp); switch (invoke->GetCodePtrLocation()) { case HInvokeStaticOrDirect::CodePtrLocation::kCallSelf: diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h index d9908bb96..7cf12459b 100644 --- a/compiler/optimizing/code_generator_x86_64.h +++ b/compiler/optimizing/code_generator_x86_64.h @@ -394,6 +394,7 @@ class CodeGeneratorX86_64 : public CodeGenerator { const HInvokeStaticOrDirect::DispatchInfo& desired_dispatch_info, MethodReference target_method) OVERRIDE; + Location GenerateCalleeMethodStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp); void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) OVERRIDE; void GenerateVirtualCall(HInvokeVirtual* invoke, Location temp) OVERRIDE; diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index d0edecae2..70c46d5f5 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -2631,8 +2631,66 @@ void IntrinsicCodeGeneratorX86::VisitLongNumberOfTrailingZeros(HInvoke* invoke) GenTrailingZeros(GetAssembler(), codegen_, invoke, /* is_long */ true); } +void IntrinsicLocationsBuilderX86::VisitReferenceGetReferent(HInvoke* invoke) { + if (kEmitCompilerReadBarrier) { + // Do not intrinsify this call with the read barrier configuration. + return; + } + LocationSummary* locations = new (arena_) LocationSummary(invoke, + LocationSummary::kCallOnSlowPath, + kIntrinsified); + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetOut(Location::SameAsFirstInput()); + locations->AddTemp(Location::RequiresRegister()); +} + +void IntrinsicCodeGeneratorX86::VisitReferenceGetReferent(HInvoke* invoke) { + DCHECK(!kEmitCompilerReadBarrier); + LocationSummary* locations = invoke->GetLocations(); + X86Assembler* assembler = GetAssembler(); + + Register obj = locations->InAt(0).AsRegister(); + Register out = locations->Out().AsRegister(); + + SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86(invoke); + codegen_->AddSlowPath(slow_path); + + // Load ArtMethod first. + HInvokeStaticOrDirect* invoke_direct = invoke->AsInvokeStaticOrDirect(); + DCHECK(invoke_direct != nullptr); + Location temp_loc = codegen_->GenerateCalleeMethodStaticOrDirectCall( + invoke_direct, locations->GetTemp(0)); + DCHECK(temp_loc.Equals(locations->GetTemp(0))); + Register temp = temp_loc.AsRegister(); + + // Now get declaring class. + __ movl(temp, Address(temp, ArtMethod::DeclaringClassOffset().Int32Value())); + + uint32_t slow_path_flag_offset = codegen_->GetReferenceSlowFlagOffset(); + uint32_t disable_flag_offset = codegen_->GetReferenceDisableFlagOffset(); + DCHECK_NE(slow_path_flag_offset, 0u); + DCHECK_NE(disable_flag_offset, 0u); + DCHECK_NE(slow_path_flag_offset, disable_flag_offset); + + // Check static flags preventing us for using intrinsic. + if (slow_path_flag_offset == disable_flag_offset + 1) { + __ cmpw(Address(temp, disable_flag_offset), Immediate(0)); + __ j(kNotEqual, slow_path->GetEntryLabel()); + } else { + __ cmpb(Address(temp, disable_flag_offset), Immediate(0)); + __ j(kNotEqual, slow_path->GetEntryLabel()); + __ cmpb(Address(temp, slow_path_flag_offset), Immediate(0)); + __ j(kNotEqual, slow_path->GetEntryLabel()); + } + + // Fast path. + __ movl(out, Address(obj, mirror::Reference::ReferentOffset().Int32Value())); + codegen_->MaybeRecordImplicitNullCheck(invoke); + __ MaybeUnpoisonHeapReference(out); + __ Bind(slow_path->GetExitLabel()); +} + UNIMPLEMENTED_INTRINSIC(X86, MathRoundDouble) -UNIMPLEMENTED_INTRINSIC(X86, ReferenceGetReferent) UNIMPLEMENTED_INTRINSIC(X86, SystemArrayCopy) UNIMPLEMENTED_INTRINSIC(X86, FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(X86, DoubleIsInfinite) diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 4ee2368ff..654c393bc 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -2719,7 +2719,65 @@ void IntrinsicCodeGeneratorX86_64::VisitLongNumberOfTrailingZeros(HInvoke* invok GenTrailingZeros(GetAssembler(), codegen_, invoke, /* is_long */ true); } -UNIMPLEMENTED_INTRINSIC(X86_64, ReferenceGetReferent) +void IntrinsicLocationsBuilderX86_64::VisitReferenceGetReferent(HInvoke* invoke) { + if (kEmitCompilerReadBarrier) { + // Do not intrinsify this call with the read barrier configuration. + return; + } + LocationSummary* locations = new (arena_) LocationSummary(invoke, + LocationSummary::kCallOnSlowPath, + kIntrinsified); + locations->SetInAt(0, Location::RequiresRegister()); + locations->SetOut(Location::SameAsFirstInput()); + locations->AddTemp(Location::RequiresRegister()); +} + +void IntrinsicCodeGeneratorX86_64::VisitReferenceGetReferent(HInvoke* invoke) { + DCHECK(!kEmitCompilerReadBarrier); + LocationSummary* locations = invoke->GetLocations(); + X86_64Assembler* assembler = GetAssembler(); + + CpuRegister obj = locations->InAt(0).AsRegister(); + CpuRegister out = locations->Out().AsRegister(); + + SlowPathCode* slow_path = new (GetAllocator()) IntrinsicSlowPathX86_64(invoke); + codegen_->AddSlowPath(slow_path); + + // Load ArtMethod first. + HInvokeStaticOrDirect* invoke_direct = invoke->AsInvokeStaticOrDirect(); + DCHECK(invoke_direct != nullptr); + Location temp_loc = codegen_->GenerateCalleeMethodStaticOrDirectCall( + invoke_direct, locations->GetTemp(0)); + DCHECK(temp_loc.Equals(locations->GetTemp(0))); + CpuRegister temp = temp_loc.AsRegister(); + + // Now get declaring class. + __ movl(temp, Address(temp, ArtMethod::DeclaringClassOffset().Int32Value())); + + uint32_t slow_path_flag_offset = codegen_->GetReferenceSlowFlagOffset(); + uint32_t disable_flag_offset = codegen_->GetReferenceDisableFlagOffset(); + DCHECK_NE(slow_path_flag_offset, 0u); + DCHECK_NE(disable_flag_offset, 0u); + DCHECK_NE(slow_path_flag_offset, disable_flag_offset); + + // Check static flags preventing us for using intrinsic. + if (slow_path_flag_offset == disable_flag_offset + 1) { + __ cmpw(Address(temp, disable_flag_offset), Immediate(0)); + __ j(kNotEqual, slow_path->GetEntryLabel()); + } else { + __ cmpb(Address(temp, disable_flag_offset), Immediate(0)); + __ j(kNotEqual, slow_path->GetEntryLabel()); + __ cmpb(Address(temp, slow_path_flag_offset), Immediate(0)); + __ j(kNotEqual, slow_path->GetEntryLabel()); + } + + // Fast path. + __ movl(out, Address(obj, mirror::Reference::ReferentOffset().Int32Value())); + codegen_->MaybeRecordImplicitNullCheck(invoke); + __ MaybeUnpoisonHeapReference(out); + __ Bind(slow_path->GetExitLabel()); +} + UNIMPLEMENTED_INTRINSIC(X86_64, FloatIsInfinite) UNIMPLEMENTED_INTRINSIC(X86_64, DoubleIsInfinite) -- 2.11.0