Merge "Support for inlining virtual and interface calls."
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 11743f3..32bde8e 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -718,6 +718,9 @@
// contains data only valid during a real run.
dex_cache->SetFieldObject<false>(mirror::DexCache::DexOffset(), nullptr);
}
+
+ // Drop the array class cache in the ClassLinker, as these are roots holding those classes live.
+ class_linker->DropFindArrayClassCache();
}
bool ImageWriter::NonImageClassesVisitor(Class* klass, void* arg) {
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index f98029d..dbda63b 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -763,6 +763,11 @@
}
DCHECK_EQ(argument_index, number_of_arguments);
+ if (invoke->IsInvokeStaticOrDirect()) {
+ invoke->SetArgumentAt(argument_index, graph_->GetCurrentMethod());
+ argument_index++;
+ }
+
if (clinit_check_requirement == HInvokeStaticOrDirect::ClinitCheckRequirement::kExplicit) {
// Add the class initialization check as last input of `invoke`.
DCHECK(clinit_check != nullptr);
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc
index 08c0351..049b3e3 100644
--- a/compiler/optimizing/code_generator.cc
+++ b/compiler/optimizing/code_generator.cc
@@ -292,7 +292,6 @@
HInvoke* invoke, InvokeDexCallingConventionVisitor* visitor) {
ArenaAllocator* allocator = invoke->GetBlock()->GetGraph()->GetArena();
LocationSummary* locations = new (allocator) LocationSummary(invoke, LocationSummary::kCall);
- locations->AddTemp(visitor->GetMethodLocation());
for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) {
HInstruction* input = invoke->InputAt(i);
@@ -300,6 +299,20 @@
}
locations->SetOut(visitor->GetReturnLocation(invoke->GetType()));
+
+ if (invoke->IsInvokeStaticOrDirect()) {
+ HInvokeStaticOrDirect* call = invoke->AsInvokeStaticOrDirect();
+ if (call->IsStringInit()) {
+ locations->AddTemp(visitor->GetMethodLocation());
+ } else if (call->IsRecursive()) {
+ locations->SetInAt(call->GetCurrentMethodInputIndex(), visitor->GetMethodLocation());
+ } else {
+ locations->AddTemp(visitor->GetMethodLocation());
+ locations->SetInAt(call->GetCurrentMethodInputIndex(), Location::RequiresRegister());
+ }
+ } else {
+ locations->AddTemp(visitor->GetMethodLocation());
+ }
}
void CodeGenerator::BlockIfInRegister(Location location, bool is_out) const {
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index 04952be..f4544ea 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -1254,6 +1254,10 @@
IntrinsicLocationsBuilderARM intrinsic(GetGraph()->GetArena(),
codegen_->GetInstructionSetFeatures());
if (intrinsic.TryDispatch(invoke)) {
+ LocationSummary* locations = invoke->GetLocations();
+ if (locations->CanCall()) {
+ locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
+ }
return;
}
@@ -1283,9 +1287,9 @@
return;
}
- Register temp = invoke->GetLocations()->GetTemp(0).AsRegister<Register>();
-
- codegen_->GenerateStaticOrDirectCall(invoke, temp);
+ LocationSummary* locations = invoke->GetLocations();
+ codegen_->GenerateStaticOrDirectCall(
+ invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -1316,12 +1320,8 @@
Location receiver = locations->InAt(0);
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
// temp = object->GetClass();
- if (receiver.IsStackSlot()) {
- __ LoadFromOffset(kLoadWord, temp, SP, receiver.GetStackIndex());
- __ LoadFromOffset(kLoadWord, temp, temp, class_offset);
- } else {
- __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
- }
+ DCHECK(receiver.IsRegister());
+ __ LoadFromOffset(kLoadWord, temp, receiver.AsRegister<Register>(), class_offset);
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
uint32_t entry_point = ArtMethod::EntryPointFromQuickCompiledCodeOffset(
@@ -1638,8 +1638,7 @@
// Processing a Dex `long-to-double' instruction.
locations->SetInAt(0, Location::RequiresRegister());
locations->SetOut(Location::RequiresFpuRegister());
- locations->AddTemp(Location::RequiresRegister());
- locations->AddTemp(Location::RequiresRegister());
+ locations->AddTemp(Location::RequiresFpuRegister());
locations->AddTemp(Location::RequiresFpuRegister());
break;
@@ -1857,29 +1856,21 @@
Register high = in.AsRegisterPairHigh<Register>();
SRegister out_s = out.AsFpuRegisterPairLow<SRegister>();
DRegister out_d = FromLowSToD(out_s);
- Register constant_low = locations->GetTemp(0).AsRegister<Register>();
- Register constant_high = locations->GetTemp(1).AsRegister<Register>();
- SRegister temp_s = locations->GetTemp(2).AsFpuRegisterPairLow<SRegister>();
+ SRegister temp_s = locations->GetTemp(0).AsFpuRegisterPairLow<SRegister>();
DRegister temp_d = FromLowSToD(temp_s);
+ SRegister constant_s = locations->GetTemp(1).AsFpuRegisterPairLow<SRegister>();
+ DRegister constant_d = FromLowSToD(constant_s);
- // out_d = int-to-double(high)
- __ vmovsr(out_s, high);
- __ vcvtdi(out_d, out_s);
- // Using vmovd to load the `k2Pow32EncodingForDouble` constant
- // as an immediate value into `temp_d` does not work, as
- // this instruction only transfers 8 significant bits of its
- // immediate operand. Instead, use two 32-bit core
- // registers to load `k2Pow32EncodingForDouble` into `temp_d`.
- __ LoadImmediate(constant_low, Low32Bits(k2Pow32EncodingForDouble));
- __ LoadImmediate(constant_high, High32Bits(k2Pow32EncodingForDouble));
- __ vmovdrr(temp_d, constant_low, constant_high);
- // out_d = out_d * 2^32
- __ vmuld(out_d, out_d, temp_d);
- // temp_d = unsigned-to-double(low)
- __ vmovsr(temp_s, low);
- __ vcvtdu(temp_d, temp_s);
- // out_d = out_d + temp_d
- __ vaddd(out_d, out_d, temp_d);
+ // temp_d = int-to-double(high)
+ __ vmovsr(temp_s, high);
+ __ vcvtdi(temp_d, temp_s);
+ // constant_d = k2Pow32EncodingForDouble
+ __ LoadDImmediate(constant_d, bit_cast<double, int64_t>(k2Pow32EncodingForDouble));
+ // out_d = unsigned-to-double(low)
+ __ vmovsr(out_s, low);
+ __ vcvtdu(out_d, out_s);
+ // out_d += temp_d * constant_d
+ __ vmlad(out_d, temp_d, constant_d);
break;
}
@@ -2910,22 +2901,22 @@
void InstructionCodeGeneratorARM::GenerateMemoryBarrier(MemBarrierKind kind) {
// TODO (ported from quick): revisit Arm barrier kinds
- DmbOptions flavour = DmbOptions::ISH; // quiet c++ warnings
+ DmbOptions flavor = DmbOptions::ISH; // quiet c++ warnings
switch (kind) {
case MemBarrierKind::kAnyStore:
case MemBarrierKind::kLoadAny:
case MemBarrierKind::kAnyAny: {
- flavour = DmbOptions::ISH;
+ flavor = DmbOptions::ISH;
break;
}
case MemBarrierKind::kStoreStore: {
- flavour = DmbOptions::ISHST;
+ flavor = DmbOptions::ISHST;
break;
}
default:
LOG(FATAL) << "Unexpected memory barrier " << kind;
}
- __ dmb(flavour);
+ __ dmb(flavor);
}
void InstructionCodeGeneratorARM::GenerateWideAtomicLoad(Register addr,
@@ -4215,9 +4206,7 @@
}
}
-void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp) {
- DCHECK_EQ(temp, kArtMethodRegister);
-
+void CodeGeneratorARM::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
// TODO: Implement all kinds of calls:
// 1) boot -> boot
// 2) app -> boot
@@ -4226,32 +4215,32 @@
// Currently we implement the app -> app logic, which looks up in the resolve cache.
if (invoke->IsStringInit()) {
+ Register reg = temp.AsRegister<Register>();
// temp = thread->string_init_entrypoint
- __ LoadFromOffset(kLoadWord, temp, TR, invoke->GetStringInitOffset());
+ __ LoadFromOffset(kLoadWord, reg, TR, invoke->GetStringInitOffset());
// LR = temp[offset_of_quick_compiled_code]
- __ LoadFromOffset(kLoadWord, LR, temp,
+ __ LoadFromOffset(kLoadWord, LR, reg,
ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kArmWordSize).Int32Value());
// LR()
__ blx(LR);
+ } else if (invoke->IsRecursive()) {
+ __ bl(GetFrameEntryLabel());
} else {
- // temp = method;
- LoadCurrentMethod(temp);
- if (!invoke->IsRecursive()) {
- // temp = temp->dex_cache_resolved_methods_;
- __ LoadFromOffset(
- kLoadWord, temp, temp, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
- // temp = temp[index_in_cache]
- __ LoadFromOffset(
- kLoadWord, temp, temp, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex()));
- // LR = temp[offset_of_quick_compiled_code]
- __ LoadFromOffset(kLoadWord, LR, temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kArmWordSize).Int32Value());
- // LR()
- __ blx(LR);
- } else {
- __ bl(GetFrameEntryLabel());
- }
+ Register current_method =
+ invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<Register>();
+ Register reg = temp.AsRegister<Register>();
+ // reg = current_method->dex_cache_resolved_methods_;
+ __ LoadFromOffset(
+ kLoadWord, reg, current_method, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value());
+ // reg = reg[index_in_cache]
+ __ LoadFromOffset(
+ kLoadWord, reg, reg, CodeGenerator::GetCacheOffset(invoke->GetDexMethodIndex()));
+ // LR = reg[offset_of_quick_compiled_code]
+ __ LoadFromOffset(kLoadWord, LR, reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kArmWordSize).Int32Value());
+ // LR()
+ __ blx(LR);
}
DCHECK(!IsLeafMethod());
diff --git a/compiler/optimizing/code_generator_arm.h b/compiler/optimizing/code_generator_arm.h
index d84f2d3..b871acd 100644
--- a/compiler/optimizing/code_generator_arm.h
+++ b/compiler/optimizing/code_generator_arm.h
@@ -301,7 +301,7 @@
Label* GetFrameEntryLabel() { return &frame_entry_label_; }
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
private:
// Labels for each block that will be compiled.
diff --git a/compiler/optimizing/code_generator_arm64.cc b/compiler/optimizing/code_generator_arm64.cc
index 2f607f7..ac99d56 100644
--- a/compiler/optimizing/code_generator_arm64.cc
+++ b/compiler/optimizing/code_generator_arm64.cc
@@ -484,7 +484,7 @@
}
Location InvokeDexCallingConventionVisitorARM64::GetMethodLocation() const {
- return LocationFrom(x0);
+ return LocationFrom(kArtMethodRegister);
}
CodeGeneratorARM64::CodeGeneratorARM64(HGraph* graph,
@@ -2227,6 +2227,10 @@
IntrinsicLocationsBuilderARM64 intrinsic(GetGraph()->GetArena());
if (intrinsic.TryDispatch(invoke)) {
+ LocationSummary* locations = invoke->GetLocations();
+ if (locations->CanCall()) {
+ locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
+ }
return;
}
@@ -2242,9 +2246,8 @@
return false;
}
-void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp) {
+void CodeGeneratorARM64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp) {
// Make sure that ArtMethod* is passed in kArtMethodRegister as per the calling convention.
- DCHECK(temp.Is(kArtMethodRegister));
size_t index_in_cache = GetCachePointerOffset(invoke->GetDexMethodIndex());
// TODO: Implement all kinds of calls:
@@ -2255,30 +2258,30 @@
// Currently we implement the app -> app logic, which looks up in the resolve cache.
if (invoke->IsStringInit()) {
+ Register reg = XRegisterFrom(temp);
// temp = thread->string_init_entrypoint
- __ Ldr(temp.X(), MemOperand(tr, invoke->GetStringInitOffset()));
+ __ Ldr(reg.X(), MemOperand(tr, invoke->GetStringInitOffset()));
// LR = temp->entry_point_from_quick_compiled_code_;
__ Ldr(lr, MemOperand(
- temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize).Int32Value()));
+ reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kArm64WordSize).Int32Value()));
// lr()
__ Blr(lr);
+ } else if (invoke->IsRecursive()) {
+ __ Bl(&frame_entry_label_);
} else {
- // temp = method;
- LoadCurrentMethod(temp.X());
- if (!invoke->IsRecursive()) {
- // temp = temp->dex_cache_resolved_methods_;
- __ Ldr(temp.W(), MemOperand(temp.X(),
- ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
- // temp = temp[index_in_cache];
- __ Ldr(temp.X(), MemOperand(temp, index_in_cache));
- // lr = temp->entry_point_from_quick_compiled_code_;
- __ Ldr(lr, MemOperand(temp.X(), ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kArm64WordSize).Int32Value()));
- // lr();
- __ Blr(lr);
- } else {
- __ Bl(&frame_entry_label_);
- }
+ Register current_method =
+ XRegisterFrom(invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()));
+ Register reg = XRegisterFrom(temp);
+ // temp = current_method->dex_cache_resolved_methods_;
+ __ Ldr(reg.W(), MemOperand(current_method.X(),
+ ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
+ // temp = temp[index_in_cache];
+ __ Ldr(reg.X(), MemOperand(reg, index_in_cache));
+ // lr = temp->entry_point_from_quick_compiled_code_;
+ __ Ldr(lr, MemOperand(reg.X(), ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kArm64WordSize).Int32Value()));
+ // lr();
+ __ Blr(lr);
}
DCHECK(!IsLeafMethod());
@@ -2294,8 +2297,9 @@
}
BlockPoolsScope block_pools(GetVIXLAssembler());
- Register temp = XRegisterFrom(invoke->GetLocations()->GetTemp(0));
- codegen_->GenerateStaticOrDirectCall(invoke, temp);
+ LocationSummary* locations = invoke->GetLocations();
+ codegen_->GenerateStaticOrDirectCall(
+ invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -2314,14 +2318,8 @@
BlockPoolsScope block_pools(GetVIXLAssembler());
- // temp = object->GetClass();
- if (receiver.IsStackSlot()) {
- __ Ldr(temp.W(), MemOperand(sp, receiver.GetStackIndex()));
- __ Ldr(temp.W(), HeapOperand(temp.W(), class_offset));
- } else {
- DCHECK(receiver.IsRegister());
- __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
- }
+ DCHECK(receiver.IsRegister());
+ __ Ldr(temp.W(), HeapOperandFrom(receiver, class_offset));
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
__ Ldr(temp, MemOperand(temp, method_offset));
@@ -2674,7 +2672,7 @@
void LocationsBuilderARM64::VisitCurrentMethod(HCurrentMethod* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kNoCall);
- locations->SetOut(LocationFrom(x0));
+ locations->SetOut(LocationFrom(kArtMethodRegister));
}
void InstructionCodeGeneratorARM64::VisitCurrentMethod(
diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h
index c62ba95..3246648 100644
--- a/compiler/optimizing/code_generator_arm64.h
+++ b/compiler/optimizing/code_generator_arm64.h
@@ -344,7 +344,7 @@
return false;
}
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, vixl::Register temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
private:
// Labels for each block that will be compiled.
diff --git a/compiler/optimizing/code_generator_x86.cc b/compiler/optimizing/code_generator_x86.cc
index 8a7b52e..4065c44 100644
--- a/compiler/optimizing/code_generator_x86.cc
+++ b/compiler/optimizing/code_generator_x86.cc
@@ -1231,6 +1231,10 @@
IntrinsicLocationsBuilderX86 intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
+ LocationSummary* locations = invoke->GetLocations();
+ if (locations->CanCall()) {
+ locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
+ }
return;
}
@@ -1255,8 +1259,9 @@
return;
}
+ LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
- invoke, invoke->GetLocations()->GetTemp(0).AsRegister<Register>());
+ invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -1276,13 +1281,8 @@
LocationSummary* locations = invoke->GetLocations();
Location receiver = locations->InAt(0);
uint32_t class_offset = mirror::Object::ClassOffset().Int32Value();
- // temp = object->GetClass();
- if (receiver.IsStackSlot()) {
- __ movl(temp, Address(ESP, receiver.GetStackIndex()));
- __ movl(temp, Address(temp, class_offset));
- } else {
- __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
- }
+ DCHECK(receiver.IsRegister());
+ __ movl(temp, Address(receiver.AsRegister<Register>(), class_offset));
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
__ movl(temp, Address(temp, method_offset));
@@ -3201,7 +3201,7 @@
void CodeGeneratorX86::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
- Register temp) {
+ Location temp) {
// TODO: Implement all kinds of calls:
// 1) boot -> boot
// 2) app -> boot
@@ -3211,25 +3211,26 @@
if (invoke->IsStringInit()) {
// temp = thread->string_init_entrypoint
- __ fs()->movl(temp, Address::Absolute(invoke->GetStringInitOffset()));
+ Register reg = temp.AsRegister<Register>();
+ __ fs()->movl(reg, Address::Absolute(invoke->GetStringInitOffset()));
// (temp + offset_of_quick_compiled_code)()
__ call(Address(
- temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+ reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
+ } else if (invoke->IsRecursive()) {
+ __ call(GetFrameEntryLabel());
} else {
- // temp = method;
- LoadCurrentMethod(temp);
- if (!invoke->IsRecursive()) {
- // temp = temp->dex_cache_resolved_methods_;
- __ movl(temp, Address(temp, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
- // temp = temp[index_in_cache]
- __ movl(temp, Address(temp,
- CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
- // (temp + offset_of_quick_compiled_code)()
- __ call(Address(temp,
- ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
- } else {
- __ call(GetFrameEntryLabel());
- }
+ Register current_method =
+ invoke->GetLocations()->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<Register>();
+ Register reg = temp.AsRegister<Register>();
+ // temp = temp->dex_cache_resolved_methods_;
+ __ movl(reg, Address(
+ current_method, ArtMethod::DexCacheResolvedMethodsOffset().Int32Value()));
+ // temp = temp[index_in_cache]
+ __ movl(reg, Address(reg,
+ CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
+ // (temp + offset_of_quick_compiled_code)()
+ __ call(Address(reg,
+ ArtMethod::EntryPointFromQuickCompiledCodeOffset(kX86WordSize).Int32Value()));
}
DCHECK(!IsLeafMethod());
diff --git a/compiler/optimizing/code_generator_x86.h b/compiler/optimizing/code_generator_x86.h
index 61827a4..b8553d2 100644
--- a/compiler/optimizing/code_generator_x86.h
+++ b/compiler/optimizing/code_generator_x86.h
@@ -263,7 +263,7 @@
void Move64(Location destination, Location source);
// Generate a call to a static or direct method.
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Register temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
// Emit a write barrier.
void MarkGCCard(Register temp,
diff --git a/compiler/optimizing/code_generator_x86_64.cc b/compiler/optimizing/code_generator_x86_64.cc
index a2a3cf5..c9fe813 100644
--- a/compiler/optimizing/code_generator_x86_64.cc
+++ b/compiler/optimizing/code_generator_x86_64.cc
@@ -360,7 +360,7 @@
}
void CodeGeneratorX86_64::GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke,
- CpuRegister temp) {
+ Location temp) {
// All registers are assumed to be correctly set up.
// TODO: Implement all kinds of calls:
@@ -371,26 +371,28 @@
// Currently we implement the app -> app logic, which looks up in the resolve cache.
if (invoke->IsStringInit()) {
+ CpuRegister reg = temp.AsRegister<CpuRegister>();
// temp = thread->string_init_entrypoint
- __ gs()->movl(temp, Address::Absolute(invoke->GetStringInitOffset()));
+ __ gs()->movl(reg, Address::Absolute(invoke->GetStringInitOffset()));
// (temp + offset_of_quick_compiled_code)()
- __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ __ call(Address(reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
kX86_64WordSize).SizeValue()));
+ } else if (invoke->IsRecursive()) {
+ __ call(&frame_entry_label_);
} else {
- // temp = method;
- LoadCurrentMethod(temp);
- if (!invoke->IsRecursive()) {
- // temp = temp->dex_cache_resolved_methods_;
- __ movl(temp, Address(temp, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
- // temp = temp[index_in_cache]
- __ movq(temp, Address(
- temp, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
- // (temp + offset_of_quick_compiled_code)()
- __ call(Address(temp, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
- kX86_64WordSize).SizeValue()));
- } else {
- __ call(&frame_entry_label_);
- }
+ LocationSummary* locations = invoke->GetLocations();
+ CpuRegister reg = temp.AsRegister<CpuRegister>();
+ CpuRegister current_method =
+ locations->InAt(invoke->GetCurrentMethodInputIndex()).AsRegister<CpuRegister>();
+ // temp = temp->dex_cache_resolved_methods_;
+ __ movl(reg, Address(
+ current_method, ArtMethod::DexCacheResolvedMethodsOffset().SizeValue()));
+ // temp = temp[index_in_cache]
+ __ movq(reg, Address(
+ reg, CodeGenerator::GetCachePointerOffset(invoke->GetDexMethodIndex())));
+ // (temp + offset_of_quick_compiled_code)()
+ __ call(Address(reg, ArtMethod::EntryPointFromQuickCompiledCodeOffset(
+ kX86_64WordSize).SizeValue()));
}
DCHECK(!IsLeafMethod());
@@ -1334,6 +1336,10 @@
IntrinsicLocationsBuilderX86_64 intrinsic(codegen_);
if (intrinsic.TryDispatch(invoke)) {
+ LocationSummary* locations = invoke->GetLocations();
+ if (locations->CanCall()) {
+ locations->SetInAt(invoke->GetCurrentMethodInputIndex(), Location::RequiresRegister());
+ }
return;
}
@@ -1358,9 +1364,9 @@
return;
}
+ LocationSummary* locations = invoke->GetLocations();
codegen_->GenerateStaticOrDirectCall(
- invoke,
- invoke->GetLocations()->GetTemp(0).AsRegister<CpuRegister>());
+ invoke, locations->HasTemps() ? locations->GetTemp(0) : Location::NoLocation());
codegen_->RecordPcInfo(invoke, invoke->GetDexPc());
}
@@ -1390,12 +1396,8 @@
Location receiver = locations->InAt(0);
size_t class_offset = mirror::Object::ClassOffset().SizeValue();
// temp = object->GetClass();
- if (receiver.IsStackSlot()) {
- __ movl(temp, Address(CpuRegister(RSP), receiver.GetStackIndex()));
- __ movl(temp, Address(temp, class_offset));
- } else {
- __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
- }
+ DCHECK(receiver.IsRegister());
+ __ movl(temp, Address(receiver.AsRegister<CpuRegister>(), class_offset));
codegen_->MaybeRecordImplicitNullCheck(invoke);
// temp = temp->GetMethodAt(method_offset);
__ movq(temp, Address(temp, method_offset));
diff --git a/compiler/optimizing/code_generator_x86_64.h b/compiler/optimizing/code_generator_x86_64.h
index c19e686..61f863c 100644
--- a/compiler/optimizing/code_generator_x86_64.h
+++ b/compiler/optimizing/code_generator_x86_64.h
@@ -277,7 +277,7 @@
return false;
}
- void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, CpuRegister temp);
+ void GenerateStaticOrDirectCall(HInvokeStaticOrDirect* invoke, Location temp);
const X86_64InstructionSetFeatures& GetInstructionSetFeatures() const {
return isa_features_;
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index b26afd1..ea613b2 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -70,6 +70,13 @@
bool should_inline = callee_name.find("$inline$") != std::string::npos;
CHECK(!should_inline) << "Could not inline " << callee_name;
}
+ } else {
+ if (kIsDebugBuild) {
+ std::string callee_name =
+ PrettyMethod(call->GetDexMethodIndex(), *outer_compilation_unit_.GetDexFile());
+ bool must_not_inline = callee_name.find("$noinline$") != std::string::npos;
+ CHECK(!must_not_inline) << "Should not have inlined " << callee_name;
+ }
}
}
instruction = next;
diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc
index 5436ec2..749bedf 100644
--- a/compiler/optimizing/intrinsics_arm.cc
+++ b/compiler/optimizing/intrinsics_arm.cc
@@ -101,7 +101,8 @@
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), kArtMethodRegister);
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
+ Location::RegisterLocation(kArtMethodRegister));
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc
index d1dc5b3..c108ad5 100644
--- a/compiler/optimizing/intrinsics_arm64.cc
+++ b/compiler/optimizing/intrinsics_arm64.cc
@@ -110,7 +110,8 @@
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), kArtMethodRegister);
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
+ LocationFrom(kArtMethodRegister));
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index 5bbbc72..424ac7c 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -138,7 +138,8 @@
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), EAX);
+ codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(),
+ Location::RegisterLocation(EAX));
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
@@ -732,7 +733,8 @@
MoveArguments(invoke, codegen);
DCHECK(invoke->IsInvokeStaticOrDirect());
- codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(), EAX);
+ codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(),
+ Location::RegisterLocation(EAX));
codegen->RecordPcInfo(invoke, invoke->GetDexPc());
// Copy the result back to the expected output.
diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc
index d6c90ff..8915314 100644
--- a/compiler/optimizing/intrinsics_x86_64.cc
+++ b/compiler/optimizing/intrinsics_x86_64.cc
@@ -129,7 +129,8 @@
MoveArguments(invoke_, codegen);
if (invoke_->IsInvokeStaticOrDirect()) {
- codegen->GenerateStaticOrDirectCall(invoke_->AsInvokeStaticOrDirect(), CpuRegister(RDI));
+ codegen->GenerateStaticOrDirectCall(
+ invoke_->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
RecordPcInfo(codegen, invoke_, invoke_->GetDexPc());
} else {
UNIMPLEMENTED(FATAL) << "Non-direct intrinsic slow-path not yet implemented";
@@ -609,7 +610,8 @@
MoveArguments(invoke, codegen);
DCHECK(invoke->IsInvokeStaticOrDirect());
- codegen->GenerateStaticOrDirectCall(invoke->AsInvokeStaticOrDirect(), CpuRegister(RDI));
+ codegen->GenerateStaticOrDirectCall(
+ invoke->AsInvokeStaticOrDirect(), Location::RegisterLocation(RDI));
codegen->RecordPcInfo(invoke, invoke->GetDexPc());
// Copy the result back to the expected output.
diff --git a/compiler/optimizing/locations.h b/compiler/optimizing/locations.h
index 09bbb33..66c5fb1 100644
--- a/compiler/optimizing/locations.h
+++ b/compiler/optimizing/locations.h
@@ -525,6 +525,8 @@
return temps_.Size();
}
+ bool HasTemps() const { return !temps_.IsEmpty(); }
+
Location Out() const { return output_; }
bool CanCall() const { return call_kind_ != kNoCall; }
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 4792734..d914363 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -2528,7 +2528,9 @@
ClinitCheckRequirement clinit_check_requirement)
: HInvoke(arena,
number_of_arguments,
- clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 1u : 0u,
+ // There is one extra argument for the HCurrentMethod node, and
+ // potentially one other if the clinit check is explicit.
+ clinit_check_requirement == ClinitCheckRequirement::kExplicit ? 2u : 1u,
return_type,
dex_pc,
dex_method_index,
@@ -2550,6 +2552,7 @@
bool NeedsDexCache() const OVERRIDE { return !IsRecursive(); }
bool IsStringInit() const { return string_init_offset_ != 0; }
int32_t GetStringInitOffset() const { return string_init_offset_; }
+ uint32_t GetCurrentMethodInputIndex() const { return GetNumberOfArguments(); }
// Is this instruction a call to a static method?
bool IsStatic() const {
diff --git a/compiler/optimizing/register_allocator.cc b/compiler/optimizing/register_allocator.cc
index a381315..e38e49c 100644
--- a/compiler/optimizing/register_allocator.cc
+++ b/compiler/optimizing/register_allocator.cc
@@ -714,13 +714,15 @@
if (defined_by != nullptr && !current->IsSplit()) {
LocationSummary* locations = defined_by->GetLocations();
if (!locations->OutputCanOverlapWithInputs() && locations->Out().IsUnallocated()) {
- for (HInputIterator it(defined_by); !it.Done(); it.Advance()) {
+ for (size_t i = 0, e = defined_by->InputCount(); i < e; ++i) {
// Take the last interval of the input. It is the location of that interval
// that will be used at `defined_by`.
- LiveInterval* interval = it.Current()->GetLiveInterval()->GetLastSibling();
+ LiveInterval* interval = defined_by->InputAt(i)->GetLiveInterval()->GetLastSibling();
// Note that interval may have not been processed yet.
// TODO: Handle non-split intervals last in the work list.
- if (interval->HasRegister() && interval->SameRegisterKind(*current)) {
+ if (locations->InAt(i).IsValid()
+ && interval->HasRegister()
+ && interval->SameRegisterKind(*current)) {
// The input must be live until the end of `defined_by`, to comply to
// the linear scan algorithm. So we use `defined_by`'s end lifetime
// position to check whether the input is dead or is inactive after
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index d5f977f..701dbb0 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -242,7 +242,7 @@
HInstruction* input = current->InputAt(i);
// Some instructions 'inline' their inputs, that is they do not need
// to be materialized.
- if (input->HasSsaIndex()) {
+ if (input->HasSsaIndex() && current->GetLocations()->InAt(i).IsValid()) {
live_in->SetBit(input->GetSsaIndex());
input->GetLiveInterval()->AddUse(current, /* environment */ nullptr, i);
}
diff --git a/compiler/optimizing/ssa_liveness_analysis.h b/compiler/optimizing/ssa_liveness_analysis.h
index 4667825..220ee6a 100644
--- a/compiler/optimizing/ssa_liveness_analysis.h
+++ b/compiler/optimizing/ssa_liveness_analysis.h
@@ -394,7 +394,7 @@
first_range_->start_ = from;
} else {
// Instruction without uses.
- DCHECK(!defined_by_->HasNonEnvironmentUses());
+ DCHECK(first_use_ == nullptr);
DCHECK(from == defined_by_->GetLifetimePosition());
first_range_ = last_range_ = range_search_start_ =
new (allocator_) LiveRange(from, from + 2, nullptr);
diff --git a/runtime/asm_support.h b/runtime/asm_support.h
index d7efe1c..10ed0f4 100644
--- a/runtime/asm_support.h
+++ b/runtime/asm_support.h
@@ -104,11 +104,11 @@
art::Thread::TopOfManagedStackOffset<__SIZEOF_POINTER__>().Int32Value())
// Offset of field Thread::tlsPtr_.managed_stack.top_quick_frame_.
-#define THREAD_SELF_OFFSET (THREAD_CARD_TABLE_OFFSET + (8 * __SIZEOF_POINTER__))
+#define THREAD_SELF_OFFSET (THREAD_CARD_TABLE_OFFSET + (9 * __SIZEOF_POINTER__))
ADD_TEST_EQ(THREAD_SELF_OFFSET,
art::Thread::SelfOffset<__SIZEOF_POINTER__>().Int32Value())
-#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 146 * __SIZEOF_POINTER__)
+#define THREAD_LOCAL_POS_OFFSET (THREAD_CARD_TABLE_OFFSET + 147 * __SIZEOF_POINTER__)
ADD_TEST_EQ(THREAD_LOCAL_POS_OFFSET,
art::Thread::ThreadLocalPosOffset<__SIZEOF_POINTER__>().Int32Value())
#define THREAD_LOCAL_END_OFFSET (THREAD_LOCAL_POS_OFFSET + __SIZEOF_POINTER__)
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 431ef27..31140a8 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -277,9 +277,9 @@
quick_to_interpreter_bridge_trampoline_(nullptr),
image_pointer_size_(sizeof(void*)) {
CHECK(intern_table_ != nullptr);
- for (auto& root : find_array_class_cache_) {
- root = GcRoot<mirror::Class>(nullptr);
- }
+ static_assert(kFindArrayCacheSize == arraysize(find_array_class_cache_),
+ "Array cache size wrong.");
+ std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot<mirror::Class>(nullptr));
}
void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path) {
@@ -5886,4 +5886,9 @@
return method;
}
+void ClassLinker::DropFindArrayClassCache() {
+ std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot<mirror::Class>(nullptr));
+ find_array_class_cache_next_victim_ = 0;
+}
+
} // namespace art
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index fa8b2e7..d9935cb 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -480,6 +480,10 @@
ArtMethod* CreateRuntimeMethod();
+ // Clear the ArrayClass cache. This is necessary when cleaning up for the image, as the cache
+ // entries are roots, but potentially not image classes.
+ void DropFindArrayClassCache() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
private:
const OatFile::OatMethod FindOatMethodFor(ArtMethod* method, bool* found)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/entrypoints_order_test.cc b/runtime/entrypoints_order_test.cc
index 482f656..963dd02 100644
--- a/runtime/entrypoints_order_test.cc
+++ b/runtime/entrypoints_order_test.cc
@@ -88,7 +88,8 @@
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, stack_end, managed_stack, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, managed_stack, suspend_trigger, sizeof(ManagedStack));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, suspend_trigger, jni_env, sizeof(void*));
- EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, jni_env, self, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, jni_env, tmp_jni_env, sizeof(void*));
+ EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, tmp_jni_env, self, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, self, opeer, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, opeer, jpeer, sizeof(void*));
EXPECT_OFFSET_DIFFP(Thread, tlsPtr_, jpeer, stack_begin, sizeof(void*));
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 59d0259..20e791d 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -2253,6 +2253,7 @@
// to large objects.
mod_union_table->SetCards();
AddModUnionTable(mod_union_table);
+ large_object_space_->SetAllLargeObjectsAsZygoteObjects(self);
if (collector::SemiSpace::kUseRememberedSet) {
// Add a new remembered set for the post-zygote non-moving space.
accounting::RememberedSet* post_zygote_non_moving_space_rem_set =
diff --git a/runtime/gc/space/large_object_space.cc b/runtime/gc/space/large_object_space.cc
index da4a930..52192e2 100644
--- a/runtime/gc/space/large_object_space.cc
+++ b/runtime/gc/space/large_object_space.cc
@@ -41,13 +41,13 @@
// Keep valgrind happy if there is any large objects such as dex cache arrays which aren't
// freed since they are held live by the class linker.
MutexLock mu(Thread::Current(), lock_);
- for (auto& m : mem_maps_) {
- delete m.second;
+ for (auto& m : large_objects_) {
+ delete m.second.mem_map;
}
}
- virtual mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
- size_t* usable_size, size_t* bytes_tl_bulk_allocated)
+ mirror::Object* Alloc(Thread* self, size_t num_bytes, size_t* bytes_allocated,
+ size_t* usable_size, size_t* bytes_tl_bulk_allocated)
OVERRIDE {
mirror::Object* obj =
LargeObjectMapSpace::Alloc(self, num_bytes + kValgrindRedZoneBytes * 2, bytes_allocated,
@@ -63,26 +63,35 @@
return object_without_rdz;
}
- virtual size_t AllocationSize(mirror::Object* obj, size_t* usable_size) OVERRIDE {
- mirror::Object* object_with_rdz = reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
- return LargeObjectMapSpace::AllocationSize(object_with_rdz, usable_size);
+ size_t AllocationSize(mirror::Object* obj, size_t* usable_size) OVERRIDE {
+ return LargeObjectMapSpace::AllocationSize(ObjectWithRedzone(obj), usable_size);
}
- virtual size_t Free(Thread* self, mirror::Object* obj) OVERRIDE {
- mirror::Object* object_with_rdz = reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
+ bool IsZygoteLargeObject(Thread* self, mirror::Object* obj) const OVERRIDE {
+ return LargeObjectMapSpace::IsZygoteLargeObject(self, ObjectWithRedzone(obj));
+ }
+
+ size_t Free(Thread* self, mirror::Object* obj) OVERRIDE {
+ mirror::Object* object_with_rdz = ObjectWithRedzone(obj);
VALGRIND_MAKE_MEM_UNDEFINED(object_with_rdz, AllocationSize(obj, nullptr));
return LargeObjectMapSpace::Free(self, object_with_rdz);
}
bool Contains(const mirror::Object* obj) const OVERRIDE {
- mirror::Object* object_with_rdz = reinterpret_cast<mirror::Object*>(
- reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
- return LargeObjectMapSpace::Contains(object_with_rdz);
+ return LargeObjectMapSpace::Contains(ObjectWithRedzone(obj));
}
private:
+ static const mirror::Object* ObjectWithRedzone(const mirror::Object* obj) {
+ return reinterpret_cast<const mirror::Object*>(
+ reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
+ }
+
+ static mirror::Object* ObjectWithRedzone(mirror::Object* obj) {
+ return reinterpret_cast<mirror::Object*>(
+ reinterpret_cast<uintptr_t>(obj) - kValgrindRedZoneBytes);
+ }
+
static constexpr size_t kValgrindRedZoneBytes = kPageSize;
};
@@ -139,8 +148,7 @@
CHECK(space_bitmap == nullptr) << obj_end << " overlaps with bitmap " << *space_bitmap;
}
MutexLock mu(self, lock_);
- large_objects_.push_back(obj);
- mem_maps_.Put(obj, mem_map);
+ large_objects_.Put(obj, LargeObject {mem_map, false /* not zygote */});
const size_t allocation_size = mem_map->BaseSize();
DCHECK(bytes_allocated != nullptr);
begin_ = std::min(begin_, reinterpret_cast<uint8_t*>(obj));
@@ -161,28 +169,43 @@
return obj;
}
+bool LargeObjectMapSpace::IsZygoteLargeObject(Thread* self, mirror::Object* obj) const {
+ MutexLock mu(self, lock_);
+ auto it = large_objects_.find(obj);
+ CHECK(it != large_objects_.end());
+ return it->second.is_zygote;
+}
+
+void LargeObjectMapSpace::SetAllLargeObjectsAsZygoteObjects(Thread* self) {
+ MutexLock mu(self, lock_);
+ for (auto& pair : large_objects_) {
+ pair.second.is_zygote = true;
+ }
+}
+
size_t LargeObjectMapSpace::Free(Thread* self, mirror::Object* ptr) {
MutexLock mu(self, lock_);
- MemMaps::iterator found = mem_maps_.find(ptr);
- if (UNLIKELY(found == mem_maps_.end())) {
- Runtime::Current()->GetHeap()->DumpSpaces(LOG(ERROR));
+ auto it = large_objects_.find(ptr);
+ if (UNLIKELY(it == large_objects_.end())) {
+ Runtime::Current()->GetHeap()->DumpSpaces(LOG(INTERNAL_FATAL));
LOG(FATAL) << "Attempted to free large object " << ptr << " which was not live";
}
- const size_t map_size = found->second->BaseSize();
+ MemMap* mem_map = it->second.mem_map;
+ const size_t map_size = mem_map->BaseSize();
DCHECK_GE(num_bytes_allocated_, map_size);
size_t allocation_size = map_size;
num_bytes_allocated_ -= allocation_size;
--num_objects_allocated_;
- delete found->second;
- mem_maps_.erase(found);
+ delete mem_map;
+ large_objects_.erase(it);
return allocation_size;
}
size_t LargeObjectMapSpace::AllocationSize(mirror::Object* obj, size_t* usable_size) {
MutexLock mu(Thread::Current(), lock_);
- auto found = mem_maps_.find(obj);
- CHECK(found != mem_maps_.end()) << "Attempted to get size of a large object which is not live";
- size_t alloc_size = found->second->BaseSize();
+ auto it = large_objects_.find(obj);
+ CHECK(it != large_objects_.end()) << "Attempted to get size of a large object which is not live";
+ size_t alloc_size = it->second.mem_map->BaseSize();
if (usable_size != nullptr) {
*usable_size = alloc_size;
}
@@ -202,8 +225,8 @@
void LargeObjectMapSpace::Walk(DlMallocSpace::WalkCallback callback, void* arg) {
MutexLock mu(Thread::Current(), lock_);
- for (auto it = mem_maps_.begin(); it != mem_maps_.end(); ++it) {
- MemMap* mem_map = it->second;
+ for (auto& pair : large_objects_) {
+ MemMap* mem_map = pair.second.mem_map;
callback(mem_map->Begin(), mem_map->End(), mem_map->Size(), arg);
callback(nullptr, nullptr, 0, arg);
}
@@ -213,22 +236,25 @@
Thread* self = Thread::Current();
if (lock_.IsExclusiveHeld(self)) {
// We hold lock_ so do the check.
- return mem_maps_.find(const_cast<mirror::Object*>(obj)) != mem_maps_.end();
+ return large_objects_.find(const_cast<mirror::Object*>(obj)) != large_objects_.end();
} else {
MutexLock mu(self, lock_);
- return mem_maps_.find(const_cast<mirror::Object*>(obj)) != mem_maps_.end();
+ return large_objects_.find(const_cast<mirror::Object*>(obj)) != large_objects_.end();
}
}
// Keeps track of allocation sizes + whether or not the previous allocation is free.
-// Used to coalesce free blocks and find the best fit block for an allocation.
+// Used to coalesce free blocks and find the best fit block for an allocation for best fit object
+// allocation. Each allocation has an AllocationInfo which contains the size of the previous free
+// block preceding it. Implemented in such a way that we can also find the iterator for any
+// allocation info pointer.
class AllocationInfo {
public:
AllocationInfo() : prev_free_(0), alloc_size_(0) {
}
// Return the number of pages that the allocation info covers.
size_t AlignSize() const {
- return alloc_size_ & ~kFlagFree;
+ return alloc_size_ & kFlagsMask;
}
// Returns the allocation size in bytes.
size_t ByteSize() const {
@@ -236,12 +262,23 @@
}
// Updates the allocation size and whether or not it is free.
void SetByteSize(size_t size, bool free) {
+ DCHECK_EQ(size & ~kFlagsMask, 0u);
DCHECK_ALIGNED(size, FreeListSpace::kAlignment);
- alloc_size_ = (size / FreeListSpace::kAlignment) | (free ? kFlagFree : 0U);
+ alloc_size_ = (size / FreeListSpace::kAlignment) | (free ? kFlagFree : 0u);
}
+ // Returns true if the block is free.
bool IsFree() const {
return (alloc_size_ & kFlagFree) != 0;
}
+ // Return true if the large object is a zygote object.
+ bool IsZygoteObject() const {
+ return (alloc_size_ & kFlagZygote) != 0;
+ }
+ // Change the object to be a zygote object.
+ void SetZygoteObject() {
+ alloc_size_ |= kFlagZygote;
+ }
+ // Return true if this is a zygote large object.
// Finds and returns the next non free allocation info after ourself.
AllocationInfo* GetNextInfo() {
return this + AlignSize();
@@ -275,10 +312,9 @@
}
private:
- // Used to implement best fit object allocation. Each allocation has an AllocationInfo which
- // contains the size of the previous free block preceding it. Implemented in such a way that we
- // can also find the iterator for any allocation info pointer.
- static constexpr uint32_t kFlagFree = 0x8000000;
+ static constexpr uint32_t kFlagFree = 0x80000000; // If block is free.
+ static constexpr uint32_t kFlagZygote = 0x40000000; // If the large object is a zygote object.
+ static constexpr uint32_t kFlagsMask = ~(kFlagFree | kFlagZygote); // Combined flags for masking.
// Contains the size of the previous free block with kAlignment as the unit. If 0 then the
// allocation before us is not free.
// These variables are undefined in the middle of allocations / free blocks.
@@ -493,7 +529,7 @@
}
void FreeListSpace::Dump(std::ostream& os) const {
- MutexLock mu(Thread::Current(), const_cast<Mutex&>(lock_));
+ MutexLock mu(Thread::Current(), lock_);
os << GetName() << " -"
<< " begin: " << reinterpret_cast<void*>(Begin())
<< " end: " << reinterpret_cast<void*>(End()) << "\n";
@@ -519,6 +555,24 @@
}
}
+bool FreeListSpace::IsZygoteLargeObject(Thread* self ATTRIBUTE_UNUSED, mirror::Object* obj) const {
+ const AllocationInfo* info = GetAllocationInfoForAddress(reinterpret_cast<uintptr_t>(obj));
+ DCHECK(info != nullptr);
+ return info->IsZygoteObject();
+}
+
+void FreeListSpace::SetAllLargeObjectsAsZygoteObjects(Thread* self) {
+ MutexLock mu(self, lock_);
+ uintptr_t free_end_start = reinterpret_cast<uintptr_t>(end_) - free_end_;
+ for (AllocationInfo* cur_info = GetAllocationInfoForAddress(reinterpret_cast<uintptr_t>(Begin())),
+ *end_info = GetAllocationInfoForAddress(free_end_start); cur_info < end_info;
+ cur_info = cur_info->GetNextInfo()) {
+ if (!cur_info->IsFree()) {
+ cur_info->SetZygoteObject();
+ }
+ }
+}
+
void LargeObjectSpace::SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg) {
SweepCallbackContext* context = static_cast<SweepCallbackContext*>(arg);
space::LargeObjectSpace* space = context->space->AsLargeObjectSpace();
diff --git a/runtime/gc/space/large_object_space.h b/runtime/gc/space/large_object_space.h
index d1f9386..45ed0cd 100644
--- a/runtime/gc/space/large_object_space.h
+++ b/runtime/gc/space/large_object_space.h
@@ -98,6 +98,12 @@
void LogFragmentationAllocFailure(std::ostream& os, size_t failed_alloc_bytes) OVERRIDE
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // Return true if the large object is a zygote large object. Potentially slow.
+ virtual bool IsZygoteLargeObject(Thread* self, mirror::Object* obj) const = 0;
+ // Called when we create the zygote space, mark all existing large objects as zygote large
+ // objects.
+ virtual void SetAllLargeObjectsAsZygoteObjects(Thread* self) = 0;
+
protected:
explicit LargeObjectSpace(const std::string& name, uint8_t* begin, uint8_t* end);
static void SweepCallback(size_t num_ptrs, mirror::Object** ptrs, void* arg);
@@ -133,16 +139,20 @@
bool Contains(const mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS;
protected:
+ struct LargeObject {
+ MemMap* mem_map;
+ bool is_zygote;
+ };
explicit LargeObjectMapSpace(const std::string& name);
virtual ~LargeObjectMapSpace() {}
+ bool IsZygoteLargeObject(Thread* self, mirror::Object* obj) const OVERRIDE LOCKS_EXCLUDED(lock_);
+ void SetAllLargeObjectsAsZygoteObjects(Thread* self) OVERRIDE LOCKS_EXCLUDED(lock_);
+
// Used to ensure mutual exclusion when the allocation spaces data structures are being modified.
mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
- std::vector<mirror::Object*, TrackingAllocator<mirror::Object*, kAllocatorTagLOS>> large_objects_
+ AllocationTrackingSafeMap<mirror::Object*, LargeObject, kAllocatorTagLOSMaps> large_objects_
GUARDED_BY(lock_);
- typedef SafeMap<mirror::Object*, MemMap*, std::less<mirror::Object*>,
- TrackingAllocator<std::pair<mirror::Object*, MemMap*>, kAllocatorTagLOSMaps>> MemMaps;
- MemMaps mem_maps_ GUARDED_BY(lock_);
};
// A continuous large object space with a free-list to handle holes.
@@ -177,6 +187,8 @@
}
// Removes header from the free blocks set by finding the corresponding iterator and erasing it.
void RemoveFreePrev(AllocationInfo* info) EXCLUSIVE_LOCKS_REQUIRED(lock_);
+ bool IsZygoteLargeObject(Thread* self, mirror::Object* obj) const OVERRIDE;
+ void SetAllLargeObjectsAsZygoteObjects(Thread* self) OVERRIDE;
class SortByPrevFree {
public:
@@ -192,7 +204,7 @@
std::unique_ptr<MemMap> allocation_info_map_;
AllocationInfo* allocation_info_;
- Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+ mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
// Free bytes at the end of the space.
size_t free_end_ GUARDED_BY(lock_);
FreeBlocks free_blocks_ GUARDED_BY(lock_);
diff --git a/runtime/gc/space/large_object_space_test.cc b/runtime/gc/space/large_object_space_test.cc
index f04a7ca..05b484a 100644
--- a/runtime/gc/space/large_object_space_test.cc
+++ b/runtime/gc/space/large_object_space_test.cc
@@ -34,6 +34,7 @@
void LargeObjectSpaceTest::LargeObjectTest() {
size_t rand_seed = 0;
+ Thread* const self = Thread::Current();
for (size_t i = 0; i < 2; ++i) {
LargeObjectSpace* los = nullptr;
if (i == 0) {
@@ -51,8 +52,8 @@
size_t request_size = test_rand(&rand_seed) % max_allocation_size;
size_t allocation_size = 0;
size_t bytes_tl_bulk_allocated;
- mirror::Object* obj = los->Alloc(Thread::Current(), request_size, &allocation_size,
- nullptr, &bytes_tl_bulk_allocated);
+ mirror::Object* obj = los->Alloc(self, request_size, &allocation_size, nullptr,
+ &bytes_tl_bulk_allocated);
ASSERT_TRUE(obj != nullptr);
ASSERT_EQ(allocation_size, los->AllocationSize(obj, nullptr));
ASSERT_GE(allocation_size, request_size);
@@ -70,8 +71,21 @@
}
}
+ // Check the zygote flag for the first phase.
+ if (phase == 0) {
+ for (const auto& pair : requests) {
+ mirror::Object* obj = pair.first;
+ ASSERT_FALSE(los->IsZygoteLargeObject(self, obj));
+ }
+ los->SetAllLargeObjectsAsZygoteObjects(self);
+ for (const auto& pair : requests) {
+ mirror::Object* obj = pair.first;
+ ASSERT_TRUE(los->IsZygoteLargeObject(self, obj));
+ }
+ }
+
// Free 1 / 2 the allocations the first phase, and all the second phase.
- size_t limit = !phase ? requests.size() / 2 : 0;
+ size_t limit = phase == 0 ? requests.size() / 2 : 0;
while (requests.size() > limit) {
mirror::Object* obj = requests.back().first;
size_t request_size = requests.back().second;
@@ -88,7 +102,7 @@
size_t bytes_allocated = 0, bytes_tl_bulk_allocated;
// Checks that the coalescing works.
- mirror::Object* obj = los->Alloc(Thread::Current(), 100 * MB, &bytes_allocated, nullptr,
+ mirror::Object* obj = los->Alloc(self, 100 * MB, &bytes_allocated, nullptr,
&bytes_tl_bulk_allocated);
EXPECT_TRUE(obj != nullptr);
los->Free(Thread::Current(), obj);
diff --git a/runtime/hprof/hprof.cc b/runtime/hprof/hprof.cc
index 917fe43..6e0e56e 100644
--- a/runtime/hprof/hprof.cc
+++ b/runtime/hprof/hprof.cc
@@ -891,8 +891,8 @@
return;
}
- gc::space::ContinuousSpace* space =
- Runtime::Current()->GetHeap()->FindContinuousSpaceFromObject(obj, true);
+ gc::Heap* const heap = Runtime::Current()->GetHeap();
+ const gc::space::ContinuousSpace* const space = heap->FindContinuousSpaceFromObject(obj, true);
HprofHeapId heap_type = HPROF_HEAP_APP;
if (space != nullptr) {
if (space->IsZygoteSpace()) {
@@ -900,6 +900,11 @@
} else if (space->IsImageSpace()) {
heap_type = HPROF_HEAP_IMAGE;
}
+ } else {
+ const auto* los = heap->GetLargeObjectsSpace();
+ if (los->Contains(obj) && los->IsZygoteLargeObject(Thread::Current(), obj)) {
+ heap_type = HPROF_HEAP_ZYGOTE;
+ }
}
CheckHeapSegmentConstraints();
@@ -1040,7 +1045,7 @@
}
// Instance fields for this class (no superclass fields)
- int iFieldCount = klass->IsObjectClass() ? 0 : klass->NumInstanceFields();
+ int iFieldCount = klass->NumInstanceFields();
if (klass->IsStringClass()) {
__ AddU2((uint16_t)iFieldCount + 1);
} else {
@@ -1114,7 +1119,7 @@
// Write the instance data; fields for this class, followed by super class fields,
// and so on. Don't write the klass or monitor fields of Object.class.
mirror::Class* orig_klass = klass;
- while (!klass->IsObjectClass()) {
+ do {
int ifieldCount = klass->NumInstanceFields();
for (int i = 0; i < ifieldCount; ++i) {
ArtField* f = klass->GetInstanceField(i);
@@ -1146,7 +1151,7 @@
}
klass = klass->GetSuperClass();
- }
+ } while (klass != nullptr);
// Output native value character array for strings.
if (orig_klass->IsStringClass()) {
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index cf4233c..d8c1ec1 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -221,7 +221,7 @@
// We call this here so that we can try and generate a full error
// message with the overlapping mapping. There's no guarantee that
// that there will be an overlap though, since
- // - The kernel is not *required* to honour expected_ptr unless MAP_FIXED is
+ // - The kernel is not *required* to honor expected_ptr unless MAP_FIXED is
// true, even if there is no overlap
// - There might have been an overlap at the point of mmap, but the
// overlapping region has since been unmapped.
diff --git a/runtime/native/java_lang_VMClassLoader.cc b/runtime/native/java_lang_VMClassLoader.cc
index 0c39f2b..1515630 100644
--- a/runtime/native/java_lang_VMClassLoader.cc
+++ b/runtime/native/java_lang_VMClassLoader.cc
@@ -55,60 +55,29 @@
return nullptr;
}
-static jint VMClassLoader_getBootClassPathSize(JNIEnv*, jclass) {
- return Runtime::Current()->GetClassLinker()->GetBootClassPath().size();
-}
-
/*
- * Returns a string URL for a resource with the specified 'javaName' in
- * entry 'index' of the boot class path.
- *
- * We return a newly-allocated String in the following form:
- *
- * jar:file://path!/name
- *
- * Where "path" is the bootstrap class path entry and "name" is the string
- * passed into this method. "path" needs to be an absolute path (starting
- * with '/'); if it's not we'd need to make it absolute as part of forming
- * the URL string.
+ * Returns an array of entries from the boot classpath that could contain resources.
*/
-static jstring VMClassLoader_getBootClassPathResource(JNIEnv* env, jclass, jstring javaName,
- jint index) {
- ScopedUtfChars name(env, javaName);
- if (name.c_str() == nullptr) {
- return nullptr;
- }
-
+static jobjectArray VMClassLoader_getBootClassPathEntries(JNIEnv* env, jclass) {
const std::vector<const DexFile*>& path =
Runtime::Current()->GetClassLinker()->GetBootClassPath();
- if (index < 0 || size_t(index) >= path.size()) {
- return nullptr;
- }
- const DexFile* dex_file = path[index];
+ jclass stringClass = env->FindClass("java/lang/String");
+ jobjectArray array = env->NewObjectArray(path.size(), stringClass, nullptr);
+ for (size_t i = 0; i < path.size(); ++i) {
+ const DexFile* dex_file = path[i];
- // For multidex locations, e.g., x.jar:classes2.dex, we want to look into x.jar.
- const std::string& location(dex_file->GetBaseLocation());
+ // For multidex locations, e.g., x.jar:classes2.dex, we want to look into x.jar.
+ const std::string& location(dex_file->GetBaseLocation());
- std::string error_msg;
- std::unique_ptr<ZipArchive> zip_archive(ZipArchive::Open(location.c_str(), &error_msg));
- if (zip_archive.get() == nullptr) {
- LOG(WARNING) << "Failed to open zip archive '" << location << "': " << error_msg;
- return nullptr;
+ jstring javaPath = env->NewStringUTF(location.c_str());
+ env->SetObjectArrayElement(array, i, javaPath);
}
- std::unique_ptr<ZipEntry> zip_entry(zip_archive->Find(name.c_str(), &error_msg));
- if (zip_entry.get() == nullptr) {
- return nullptr;
- }
-
- std::string url;
- StringAppendF(&url, "jar:file://%s!/%s", location.c_str(), name.c_str());
- return env->NewStringUTF(url.c_str());
+ return array;
}
static JNINativeMethod gMethods[] = {
NATIVE_METHOD(VMClassLoader, findLoadedClass, "!(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;"),
- NATIVE_METHOD(VMClassLoader, getBootClassPathResource, "(Ljava/lang/String;I)Ljava/lang/String;"),
- NATIVE_METHOD(VMClassLoader, getBootClassPathSize, "!()I"),
+ NATIVE_METHOD(VMClassLoader, getBootClassPathEntries, "()[Ljava/lang/String;"),
};
void register_java_lang_VMClassLoader(JNIEnv* env) {
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 65999f7..67f611e 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -196,7 +196,12 @@
// Check that if we got here we cannot be shutting down (as shutdown should never have started
// while threads are being born).
CHECK(!runtime->IsShuttingDownLocked());
- CHECK(self->Init(runtime->GetThreadList(), runtime->GetJavaVM()));
+ // Note: given that the JNIEnv is created in the parent thread, the only failure point here is
+ // a mess in InitStackHwm. We do not have a reasonable way to recover from that, so abort
+ // the runtime in such a case. In case this ever changes, we need to make sure here to
+ // delete the tmp_jni_env, as we own it at this point.
+ CHECK(self->Init(runtime->GetThreadList(), runtime->GetJavaVM(), self->tlsPtr_.tmp_jni_env));
+ self->tlsPtr_.tmp_jni_env = nullptr;
Runtime::Current()->EndThreadBirth();
}
{
@@ -358,37 +363,59 @@
env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer,
reinterpret_cast<jlong>(child_thread));
- pthread_t new_pthread;
- pthread_attr_t attr;
- CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread");
- CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED), "PTHREAD_CREATE_DETACHED");
- CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);
- int pthread_create_result = pthread_create(&new_pthread, &attr, Thread::CreateCallback, child_thread);
- CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");
+ // Try to allocate a JNIEnvExt for the thread. We do this here as we might be out of memory and
+ // do not have a good way to report this on the child's side.
+ std::unique_ptr<JNIEnvExt> child_jni_env_ext(
+ JNIEnvExt::Create(child_thread, Runtime::Current()->GetJavaVM()));
- if (pthread_create_result != 0) {
- // pthread_create(3) failed, so clean up.
- {
- MutexLock mu(self, *Locks::runtime_shutdown_lock_);
- runtime->EndThreadBirth();
+ int pthread_create_result = 0;
+ if (child_jni_env_ext.get() != nullptr) {
+ pthread_t new_pthread;
+ pthread_attr_t attr;
+ child_thread->tlsPtr_.tmp_jni_env = child_jni_env_ext.get();
+ CHECK_PTHREAD_CALL(pthread_attr_init, (&attr), "new thread");
+ CHECK_PTHREAD_CALL(pthread_attr_setdetachstate, (&attr, PTHREAD_CREATE_DETACHED),
+ "PTHREAD_CREATE_DETACHED");
+ CHECK_PTHREAD_CALL(pthread_attr_setstacksize, (&attr, stack_size), stack_size);
+ pthread_create_result = pthread_create(&new_pthread,
+ &attr,
+ Thread::CreateCallback,
+ child_thread);
+ CHECK_PTHREAD_CALL(pthread_attr_destroy, (&attr), "new thread");
+
+ if (pthread_create_result == 0) {
+ // pthread_create started the new thread. The child is now responsible for managing the
+ // JNIEnvExt we created.
+ // Note: we can't check for tmp_jni_env == nullptr, as that would require synchronization
+ // between the threads.
+ child_jni_env_ext.release();
+ return;
}
- // Manually delete the global reference since Thread::Init will not have been run.
- env->DeleteGlobalRef(child_thread->tlsPtr_.jpeer);
- child_thread->tlsPtr_.jpeer = nullptr;
- delete child_thread;
- child_thread = nullptr;
- // TODO: remove from thread group?
- env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
- {
- std::string msg(StringPrintf("pthread_create (%s stack) failed: %s",
- PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
- ScopedObjectAccess soa(env);
- soa.Self()->ThrowOutOfMemoryError(msg.c_str());
- }
+ }
+
+ // Either JNIEnvExt::Create or pthread_create(3) failed, so clean up.
+ {
+ MutexLock mu(self, *Locks::runtime_shutdown_lock_);
+ runtime->EndThreadBirth();
+ }
+ // Manually delete the global reference since Thread::Init will not have been run.
+ env->DeleteGlobalRef(child_thread->tlsPtr_.jpeer);
+ child_thread->tlsPtr_.jpeer = nullptr;
+ delete child_thread;
+ child_thread = nullptr;
+ // TODO: remove from thread group?
+ env->SetLongField(java_peer, WellKnownClasses::java_lang_Thread_nativePeer, 0);
+ {
+ std::string msg(child_jni_env_ext.get() == nullptr ?
+ "Could not allocate JNI Env" :
+ StringPrintf("pthread_create (%s stack) failed: %s",
+ PrettySize(stack_size).c_str(), strerror(pthread_create_result)));
+ ScopedObjectAccess soa(env);
+ soa.Self()->ThrowOutOfMemoryError(msg.c_str());
}
}
-bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm) {
+bool Thread::Init(ThreadList* thread_list, JavaVMExt* java_vm, JNIEnvExt* jni_env_ext) {
// This function does all the initialization that must be run by the native thread it applies to.
// (When we create a new thread from managed code, we allocate the Thread* in Thread::Create so
// we can handshake with the corresponding native thread when it's ready.) Check this native
@@ -415,9 +442,15 @@
tls32_.thin_lock_thread_id = thread_list->AllocThreadId(this);
- tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm);
- if (tlsPtr_.jni_env == nullptr) {
- return false;
+ if (jni_env_ext != nullptr) {
+ DCHECK_EQ(jni_env_ext->vm, java_vm);
+ DCHECK_EQ(jni_env_ext->self, this);
+ tlsPtr_.jni_env = jni_env_ext;
+ } else {
+ tlsPtr_.jni_env = JNIEnvExt::Create(this, java_vm);
+ if (tlsPtr_.jni_env == nullptr) {
+ return false;
+ }
}
thread_list->Register(this);
diff --git a/runtime/thread.h b/runtime/thread.h
index 8c2e215..3f0d0a5 100644
--- a/runtime/thread.h
+++ b/runtime/thread.h
@@ -975,7 +975,15 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
void RemoveFromThreadGroup(ScopedObjectAccess& soa) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- bool Init(ThreadList*, JavaVMExt*) EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
+ // Initialize a thread.
+ //
+ // The third parameter is not mandatory. If given, the thread will use this JNIEnvExt. In case
+ // Init succeeds, this means the thread takes ownership of it. If Init fails, it is the caller's
+ // responsibility to destroy the given JNIEnvExt. If the parameter is null, Init will try to
+ // create a JNIEnvExt on its own (and potentially fail at that stage, indicated by a return value
+ // of false).
+ bool Init(ThreadList*, JavaVMExt*, JNIEnvExt* jni_env_ext = nullptr)
+ EXCLUSIVE_LOCKS_REQUIRED(Locks::runtime_shutdown_lock_);
void InitCardTable();
void InitCpu();
void CleanupCpu();
@@ -1111,8 +1119,8 @@
struct PACKED(4) tls_ptr_sized_values {
tls_ptr_sized_values() : card_table(nullptr), exception(nullptr), stack_end(nullptr),
- managed_stack(), suspend_trigger(nullptr), jni_env(nullptr), self(nullptr), opeer(nullptr),
- jpeer(nullptr), stack_begin(nullptr), stack_size(0),
+ managed_stack(), suspend_trigger(nullptr), jni_env(nullptr), tmp_jni_env(nullptr),
+ self(nullptr), opeer(nullptr), jpeer(nullptr), stack_begin(nullptr), stack_size(0),
stack_trace_sample(nullptr), wait_next(nullptr), monitor_enter_object(nullptr),
top_handle_scope(nullptr), class_loader_override(nullptr), long_jump_context(nullptr),
instrumentation_stack(nullptr), debug_invoke_req(nullptr), single_step_control(nullptr),
@@ -1144,6 +1152,10 @@
// Every thread may have an associated JNI environment
JNIEnvExt* jni_env;
+ // Temporary storage to transfer a pre-allocated JNIEnvExt from the creating thread to the
+ // created thread.
+ JNIEnvExt* tmp_jni_env;
+
// Initialized to "this". On certain architectures (such as x86) reading off of Thread::Current
// is easy but getting the address of Thread::Current is hard. This field can be read off of
// Thread::Current to give the address.
diff --git a/test/004-StackWalk/src/Main.java b/test/004-StackWalk/src/Main.java
index 782f51d..9a1d0ab 100644
--- a/test/004-StackWalk/src/Main.java
+++ b/test/004-StackWalk/src/Main.java
@@ -2,7 +2,7 @@
public Main() {
}
- int f() throws Exception {
+ int $noinline$f() throws Exception {
g(1);
g(2);
@@ -93,6 +93,6 @@
public static void main(String[] args) throws Exception {
Main st = new Main();
- st.f();
+ st.$noinline$f();
}
}
diff --git a/test/067-preemptive-unpark/src/Main.java b/test/067-preemptive-unpark/src/Main.java
index 2c099b9..beb3262 100644
--- a/test/067-preemptive-unpark/src/Main.java
+++ b/test/067-preemptive-unpark/src/Main.java
@@ -40,22 +40,24 @@
/**
* Set up {@link #UNSAFE}.
*/
- public static void setUp() {
+ public static void setUp() throws Exception{
/*
* Subvert the access check to get the unique Unsafe instance.
* We can do this because there's no security manager
* installed when running the test.
*/
+ Field field = null;
try {
- Field field = Unsafe.class.getDeclaredField("THE_ONE");
- field.setAccessible(true);
-
- UNSAFE = (Unsafe) field.get(null);
- } catch (NoSuchFieldException ex) {
- throw new RuntimeException(ex);
- } catch (IllegalAccessException ex) {
- throw new RuntimeException(ex);
+ field = Unsafe.class.getDeclaredField("THE_ONE");
+ } catch (NoSuchFieldException e1) {
+ try {
+ field = Unsafe.class.getDeclaredField("theUnsafe");
+ } catch (NoSuchFieldException e2) {
+ throw new RuntimeException("Failed to find THE_ONE or theUnsafe");
+ }
}
+ field.setAccessible(true);
+ UNSAFE = (Unsafe) field.get(null);
}
/**
diff --git a/test/133-static-invoke-super/src/Main.java b/test/133-static-invoke-super/src/Main.java
index 7cfd099..e694998 100644
--- a/test/133-static-invoke-super/src/Main.java
+++ b/test/133-static-invoke-super/src/Main.java
@@ -26,14 +26,14 @@
run(timing);
}
- static int testBasis(int interations) {
- (new SubClass()).testDirect(interations);
- return interations;
+ static int testBasis(int iterations) {
+ (new SubClass()).testDirect(iterations);
+ return iterations;
}
- static int testStatic(int interations) {
- (new SubClass()).testStatic(interations);
- return interations;
+ static int testStatic(int iterations) {
+ (new SubClass()).testStatic(iterations);
+ return iterations;
}
static public void run(boolean timing) {
diff --git a/test/422-type-conversion/src/Main.java b/test/422-type-conversion/src/Main.java
index 447b9b8..9f8f417 100644
--- a/test/422-type-conversion/src/Main.java
+++ b/test/422-type-conversion/src/Main.java
@@ -138,554 +138,554 @@
}
private static void byteToLong() {
- assertLongEquals(1L, $opt$ByteToLong((byte)1));
- assertLongEquals(0L, $opt$ByteToLong((byte)0));
- assertLongEquals(-1L, $opt$ByteToLong((byte)-1));
- assertLongEquals(51L, $opt$ByteToLong((byte)51));
- assertLongEquals(-51L, $opt$ByteToLong((byte)-51));
- assertLongEquals(127L, $opt$ByteToLong((byte)127)); // 2^7 - 1
- assertLongEquals(-127L, $opt$ByteToLong((byte)-127)); // -(2^7 - 1)
- assertLongEquals(-128L, $opt$ByteToLong((byte)-128)); // -(2^7)
+ assertLongEquals(1L, $opt$noinline$ByteToLong((byte)1));
+ assertLongEquals(0L, $opt$noinline$ByteToLong((byte)0));
+ assertLongEquals(-1L, $opt$noinline$ByteToLong((byte)-1));
+ assertLongEquals(51L, $opt$noinline$ByteToLong((byte)51));
+ assertLongEquals(-51L, $opt$noinline$ByteToLong((byte)-51));
+ assertLongEquals(127L, $opt$noinline$ByteToLong((byte)127)); // 2^7 - 1
+ assertLongEquals(-127L, $opt$noinline$ByteToLong((byte)-127)); // -(2^7 - 1)
+ assertLongEquals(-128L, $opt$noinline$ByteToLong((byte)-128)); // -(2^7)
}
private static void shortToLong() {
- assertLongEquals(1L, $opt$ShortToLong((short)1));
- assertLongEquals(0L, $opt$ShortToLong((short)0));
- assertLongEquals(-1L, $opt$ShortToLong((short)-1));
- assertLongEquals(51L, $opt$ShortToLong((short)51));
- assertLongEquals(-51L, $opt$ShortToLong((short)-51));
- assertLongEquals(32767L, $opt$ShortToLong((short)32767)); // 2^15 - 1
- assertLongEquals(-32767L, $opt$ShortToLong((short)-32767)); // -(2^15 - 1)
- assertLongEquals(-32768L, $opt$ShortToLong((short)-32768)); // -(2^15)
+ assertLongEquals(1L, $opt$noinline$ShortToLong((short)1));
+ assertLongEquals(0L, $opt$noinline$ShortToLong((short)0));
+ assertLongEquals(-1L, $opt$noinline$ShortToLong((short)-1));
+ assertLongEquals(51L, $opt$noinline$ShortToLong((short)51));
+ assertLongEquals(-51L, $opt$noinline$ShortToLong((short)-51));
+ assertLongEquals(32767L, $opt$noinline$ShortToLong((short)32767)); // 2^15 - 1
+ assertLongEquals(-32767L, $opt$noinline$ShortToLong((short)-32767)); // -(2^15 - 1)
+ assertLongEquals(-32768L, $opt$noinline$ShortToLong((short)-32768)); // -(2^15)
}
private static void intToLong() {
- assertLongEquals(1L, $opt$IntToLong(1));
- assertLongEquals(0L, $opt$IntToLong(0));
- assertLongEquals(-1L, $opt$IntToLong(-1));
- assertLongEquals(51L, $opt$IntToLong(51));
- assertLongEquals(-51L, $opt$IntToLong(-51));
- assertLongEquals(2147483647L, $opt$IntToLong(2147483647)); // 2^31 - 1
- assertLongEquals(-2147483647L, $opt$IntToLong(-2147483647)); // -(2^31 - 1)
- assertLongEquals(-2147483648L, $opt$IntToLong(-2147483648)); // -(2^31)
+ assertLongEquals(1L, $opt$noinline$IntToLong(1));
+ assertLongEquals(0L, $opt$noinline$IntToLong(0));
+ assertLongEquals(-1L, $opt$noinline$IntToLong(-1));
+ assertLongEquals(51L, $opt$noinline$IntToLong(51));
+ assertLongEquals(-51L, $opt$noinline$IntToLong(-51));
+ assertLongEquals(2147483647L, $opt$noinline$IntToLong(2147483647)); // 2^31 - 1
+ assertLongEquals(-2147483647L, $opt$noinline$IntToLong(-2147483647)); // -(2^31 - 1)
+ assertLongEquals(-2147483648L, $opt$noinline$IntToLong(-2147483648)); // -(2^31)
}
private static void charToLong() {
- assertLongEquals(1L, $opt$CharToLong((char)1));
- assertLongEquals(0L, $opt$CharToLong((char)0));
- assertLongEquals(51L, $opt$CharToLong((char)51));
- assertLongEquals(32767L, $opt$CharToLong((char)32767)); // 2^15 - 1
- assertLongEquals(65535L, $opt$CharToLong((char)65535)); // 2^16 - 1
- assertLongEquals(65535L, $opt$CharToLong((char)-1));
- assertLongEquals(65485L, $opt$CharToLong((char)-51));
- assertLongEquals(32769L, $opt$CharToLong((char)-32767)); // -(2^15 - 1)
- assertLongEquals(32768L, $opt$CharToLong((char)-32768)); // -(2^15)
+ assertLongEquals(1L, $opt$noinline$CharToLong((char)1));
+ assertLongEquals(0L, $opt$noinline$CharToLong((char)0));
+ assertLongEquals(51L, $opt$noinline$CharToLong((char)51));
+ assertLongEquals(32767L, $opt$noinline$CharToLong((char)32767)); // 2^15 - 1
+ assertLongEquals(65535L, $opt$noinline$CharToLong((char)65535)); // 2^16 - 1
+ assertLongEquals(65535L, $opt$noinline$CharToLong((char)-1));
+ assertLongEquals(65485L, $opt$noinline$CharToLong((char)-51));
+ assertLongEquals(32769L, $opt$noinline$CharToLong((char)-32767)); // -(2^15 - 1)
+ assertLongEquals(32768L, $opt$noinline$CharToLong((char)-32768)); // -(2^15)
}
private static void byteToFloat() {
- assertFloatEquals(1F, $opt$ByteToFloat((byte)1));
- assertFloatEquals(0F, $opt$ByteToFloat((byte)0));
- assertFloatEquals(-1F, $opt$ByteToFloat((byte)-1));
- assertFloatEquals(51F, $opt$ByteToFloat((byte)51));
- assertFloatEquals(-51F, $opt$ByteToFloat((byte)-51));
- assertFloatEquals(127F, $opt$ByteToFloat((byte)127)); // 2^7 - 1
- assertFloatEquals(-127F, $opt$ByteToFloat((byte)-127)); // -(2^7 - 1)
- assertFloatEquals(-128F, $opt$ByteToFloat((byte)-128)); // -(2^7)
+ assertFloatEquals(1F, $opt$noinline$ByteToFloat((byte)1));
+ assertFloatEquals(0F, $opt$noinline$ByteToFloat((byte)0));
+ assertFloatEquals(-1F, $opt$noinline$ByteToFloat((byte)-1));
+ assertFloatEquals(51F, $opt$noinline$ByteToFloat((byte)51));
+ assertFloatEquals(-51F, $opt$noinline$ByteToFloat((byte)-51));
+ assertFloatEquals(127F, $opt$noinline$ByteToFloat((byte)127)); // 2^7 - 1
+ assertFloatEquals(-127F, $opt$noinline$ByteToFloat((byte)-127)); // -(2^7 - 1)
+ assertFloatEquals(-128F, $opt$noinline$ByteToFloat((byte)-128)); // -(2^7)
}
private static void shortToFloat() {
- assertFloatEquals(1F, $opt$ShortToFloat((short)1));
- assertFloatEquals(0F, $opt$ShortToFloat((short)0));
- assertFloatEquals(-1F, $opt$ShortToFloat((short)-1));
- assertFloatEquals(51F, $opt$ShortToFloat((short)51));
- assertFloatEquals(-51F, $opt$ShortToFloat((short)-51));
- assertFloatEquals(32767F, $opt$ShortToFloat((short)32767)); // 2^15 - 1
- assertFloatEquals(-32767F, $opt$ShortToFloat((short)-32767)); // -(2^15 - 1)
- assertFloatEquals(-32768F, $opt$ShortToFloat((short)-32768)); // -(2^15)
+ assertFloatEquals(1F, $opt$noinline$ShortToFloat((short)1));
+ assertFloatEquals(0F, $opt$noinline$ShortToFloat((short)0));
+ assertFloatEquals(-1F, $opt$noinline$ShortToFloat((short)-1));
+ assertFloatEquals(51F, $opt$noinline$ShortToFloat((short)51));
+ assertFloatEquals(-51F, $opt$noinline$ShortToFloat((short)-51));
+ assertFloatEquals(32767F, $opt$noinline$ShortToFloat((short)32767)); // 2^15 - 1
+ assertFloatEquals(-32767F, $opt$noinline$ShortToFloat((short)-32767)); // -(2^15 - 1)
+ assertFloatEquals(-32768F, $opt$noinline$ShortToFloat((short)-32768)); // -(2^15)
}
private static void intToFloat() {
- assertFloatEquals(1F, $opt$IntToFloat(1));
- assertFloatEquals(0F, $opt$IntToFloat(0));
- assertFloatEquals(-1F, $opt$IntToFloat(-1));
- assertFloatEquals(51F, $opt$IntToFloat(51));
- assertFloatEquals(-51F, $opt$IntToFloat(-51));
- assertFloatEquals(16777215F, $opt$IntToFloat(16777215)); // 2^24 - 1
- assertFloatEquals(-16777215F, $opt$IntToFloat(-16777215)); // -(2^24 - 1)
- assertFloatEquals(16777216F, $opt$IntToFloat(16777216)); // 2^24
- assertFloatEquals(-16777216F, $opt$IntToFloat(-16777216)); // -(2^24)
- assertFloatEquals(2147483647F, $opt$IntToFloat(2147483647)); // 2^31 - 1
- assertFloatEquals(-2147483648F, $opt$IntToFloat(-2147483648)); // -(2^31)
+ assertFloatEquals(1F, $opt$noinline$IntToFloat(1));
+ assertFloatEquals(0F, $opt$noinline$IntToFloat(0));
+ assertFloatEquals(-1F, $opt$noinline$IntToFloat(-1));
+ assertFloatEquals(51F, $opt$noinline$IntToFloat(51));
+ assertFloatEquals(-51F, $opt$noinline$IntToFloat(-51));
+ assertFloatEquals(16777215F, $opt$noinline$IntToFloat(16777215)); // 2^24 - 1
+ assertFloatEquals(-16777215F, $opt$noinline$IntToFloat(-16777215)); // -(2^24 - 1)
+ assertFloatEquals(16777216F, $opt$noinline$IntToFloat(16777216)); // 2^24
+ assertFloatEquals(-16777216F, $opt$noinline$IntToFloat(-16777216)); // -(2^24)
+ assertFloatEquals(2147483647F, $opt$noinline$IntToFloat(2147483647)); // 2^31 - 1
+ assertFloatEquals(-2147483648F, $opt$noinline$IntToFloat(-2147483648)); // -(2^31)
}
private static void charToFloat() {
- assertFloatEquals(1F, $opt$CharToFloat((char)1));
- assertFloatEquals(0F, $opt$CharToFloat((char)0));
- assertFloatEquals(51F, $opt$CharToFloat((char)51));
- assertFloatEquals(32767F, $opt$CharToFloat((char)32767)); // 2^15 - 1
- assertFloatEquals(65535F, $opt$CharToFloat((char)65535)); // 2^16 - 1
- assertFloatEquals(65535F, $opt$CharToFloat((char)-1));
- assertFloatEquals(65485F, $opt$CharToFloat((char)-51));
- assertFloatEquals(32769F, $opt$CharToFloat((char)-32767)); // -(2^15 - 1)
- assertFloatEquals(32768F, $opt$CharToFloat((char)-32768)); // -(2^15)
+ assertFloatEquals(1F, $opt$noinline$CharToFloat((char)1));
+ assertFloatEquals(0F, $opt$noinline$CharToFloat((char)0));
+ assertFloatEquals(51F, $opt$noinline$CharToFloat((char)51));
+ assertFloatEquals(32767F, $opt$noinline$CharToFloat((char)32767)); // 2^15 - 1
+ assertFloatEquals(65535F, $opt$noinline$CharToFloat((char)65535)); // 2^16 - 1
+ assertFloatEquals(65535F, $opt$noinline$CharToFloat((char)-1));
+ assertFloatEquals(65485F, $opt$noinline$CharToFloat((char)-51));
+ assertFloatEquals(32769F, $opt$noinline$CharToFloat((char)-32767)); // -(2^15 - 1)
+ assertFloatEquals(32768F, $opt$noinline$CharToFloat((char)-32768)); // -(2^15)
}
private static void byteToDouble() {
- assertDoubleEquals(1D, $opt$ByteToDouble((byte)1));
- assertDoubleEquals(0D, $opt$ByteToDouble((byte)0));
- assertDoubleEquals(-1D, $opt$ByteToDouble((byte)-1));
- assertDoubleEquals(51D, $opt$ByteToDouble((byte)51));
- assertDoubleEquals(-51D, $opt$ByteToDouble((byte)-51));
- assertDoubleEquals(127D, $opt$ByteToDouble((byte)127)); // 2^7 - 1
- assertDoubleEquals(-127D, $opt$ByteToDouble((byte)-127)); // -(2^7 - 1)
- assertDoubleEquals(-128D, $opt$ByteToDouble((byte)-128)); // -(2^7)
+ assertDoubleEquals(1D, $opt$noinline$ByteToDouble((byte)1));
+ assertDoubleEquals(0D, $opt$noinline$ByteToDouble((byte)0));
+ assertDoubleEquals(-1D, $opt$noinline$ByteToDouble((byte)-1));
+ assertDoubleEquals(51D, $opt$noinline$ByteToDouble((byte)51));
+ assertDoubleEquals(-51D, $opt$noinline$ByteToDouble((byte)-51));
+ assertDoubleEquals(127D, $opt$noinline$ByteToDouble((byte)127)); // 2^7 - 1
+ assertDoubleEquals(-127D, $opt$noinline$ByteToDouble((byte)-127)); // -(2^7 - 1)
+ assertDoubleEquals(-128D, $opt$noinline$ByteToDouble((byte)-128)); // -(2^7)
}
private static void shortToDouble() {
- assertDoubleEquals(1D, $opt$ShortToDouble((short)1));
- assertDoubleEquals(0D, $opt$ShortToDouble((short)0));
- assertDoubleEquals(-1D, $opt$ShortToDouble((short)-1));
- assertDoubleEquals(51D, $opt$ShortToDouble((short)51));
- assertDoubleEquals(-51D, $opt$ShortToDouble((short)-51));
- assertDoubleEquals(32767D, $opt$ShortToDouble((short)32767)); // 2^15 - 1
- assertDoubleEquals(-32767D, $opt$ShortToDouble((short)-32767)); // -(2^15 - 1)
- assertDoubleEquals(-32768D, $opt$ShortToDouble((short)-32768)); // -(2^15)
+ assertDoubleEquals(1D, $opt$noinline$ShortToDouble((short)1));
+ assertDoubleEquals(0D, $opt$noinline$ShortToDouble((short)0));
+ assertDoubleEquals(-1D, $opt$noinline$ShortToDouble((short)-1));
+ assertDoubleEquals(51D, $opt$noinline$ShortToDouble((short)51));
+ assertDoubleEquals(-51D, $opt$noinline$ShortToDouble((short)-51));
+ assertDoubleEquals(32767D, $opt$noinline$ShortToDouble((short)32767)); // 2^15 - 1
+ assertDoubleEquals(-32767D, $opt$noinline$ShortToDouble((short)-32767)); // -(2^15 - 1)
+ assertDoubleEquals(-32768D, $opt$noinline$ShortToDouble((short)-32768)); // -(2^15)
}
private static void intToDouble() {
- assertDoubleEquals(1D, $opt$IntToDouble(1));
- assertDoubleEquals(0D, $opt$IntToDouble(0));
- assertDoubleEquals(-1D, $opt$IntToDouble(-1));
- assertDoubleEquals(51D, $opt$IntToDouble(51));
- assertDoubleEquals(-51D, $opt$IntToDouble(-51));
- assertDoubleEquals(16777216D, $opt$IntToDouble(16777216)); // 2^24
- assertDoubleEquals(-16777216D, $opt$IntToDouble(-16777216)); // -(2^24)
- assertDoubleEquals(2147483647D, $opt$IntToDouble(2147483647)); // 2^31 - 1
- assertDoubleEquals(-2147483648D, $opt$IntToDouble(-2147483648)); // -(2^31)
+ assertDoubleEquals(1D, $opt$noinline$IntToDouble(1));
+ assertDoubleEquals(0D, $opt$noinline$IntToDouble(0));
+ assertDoubleEquals(-1D, $opt$noinline$IntToDouble(-1));
+ assertDoubleEquals(51D, $opt$noinline$IntToDouble(51));
+ assertDoubleEquals(-51D, $opt$noinline$IntToDouble(-51));
+ assertDoubleEquals(16777216D, $opt$noinline$IntToDouble(16777216)); // 2^24
+ assertDoubleEquals(-16777216D, $opt$noinline$IntToDouble(-16777216)); // -(2^24)
+ assertDoubleEquals(2147483647D, $opt$noinline$IntToDouble(2147483647)); // 2^31 - 1
+ assertDoubleEquals(-2147483648D, $opt$noinline$IntToDouble(-2147483648)); // -(2^31)
}
private static void charToDouble() {
- assertDoubleEquals(1D, $opt$CharToDouble((char)1));
- assertDoubleEquals(0D, $opt$CharToDouble((char)0));
- assertDoubleEquals(51D, $opt$CharToDouble((char)51));
- assertDoubleEquals(32767D, $opt$CharToDouble((char)32767)); // 2^15 - 1
- assertDoubleEquals(65535D, $opt$CharToDouble((char)65535)); // 2^16 - 1
- assertDoubleEquals(65535D, $opt$CharToDouble((char)-1));
- assertDoubleEquals(65485D, $opt$CharToDouble((char)-51));
- assertDoubleEquals(32769D, $opt$CharToDouble((char)-32767)); // -(2^15 - 1)
- assertDoubleEquals(32768D, $opt$CharToDouble((char)-32768)); // -(2^15)
+ assertDoubleEquals(1D, $opt$noinline$CharToDouble((char)1));
+ assertDoubleEquals(0D, $opt$noinline$CharToDouble((char)0));
+ assertDoubleEquals(51D, $opt$noinline$CharToDouble((char)51));
+ assertDoubleEquals(32767D, $opt$noinline$CharToDouble((char)32767)); // 2^15 - 1
+ assertDoubleEquals(65535D, $opt$noinline$CharToDouble((char)65535)); // 2^16 - 1
+ assertDoubleEquals(65535D, $opt$noinline$CharToDouble((char)-1));
+ assertDoubleEquals(65485D, $opt$noinline$CharToDouble((char)-51));
+ assertDoubleEquals(32769D, $opt$noinline$CharToDouble((char)-32767)); // -(2^15 - 1)
+ assertDoubleEquals(32768D, $opt$noinline$CharToDouble((char)-32768)); // -(2^15)
}
private static void longToInt() {
- assertIntEquals(1, $opt$LongToInt(1L));
- assertIntEquals(0, $opt$LongToInt(0L));
- assertIntEquals(-1, $opt$LongToInt(-1L));
- assertIntEquals(51, $opt$LongToInt(51L));
- assertIntEquals(-51, $opt$LongToInt(-51L));
- assertIntEquals(2147483647, $opt$LongToInt(2147483647L)); // 2^31 - 1
- assertIntEquals(-2147483647, $opt$LongToInt(-2147483647L)); // -(2^31 - 1)
- assertIntEquals(-2147483648, $opt$LongToInt(-2147483648L)); // -(2^31)
- assertIntEquals(-2147483648, $opt$LongToInt(2147483648L)); // (2^31)
- assertIntEquals(2147483647, $opt$LongToInt(-2147483649L)); // -(2^31 + 1)
- assertIntEquals(-1, $opt$LongToInt(9223372036854775807L)); // 2^63 - 1
- assertIntEquals(1, $opt$LongToInt(-9223372036854775807L)); // -(2^63 - 1)
- assertIntEquals(0, $opt$LongToInt(-9223372036854775808L)); // -(2^63)
+ assertIntEquals(1, $opt$noinline$LongToInt(1L));
+ assertIntEquals(0, $opt$noinline$LongToInt(0L));
+ assertIntEquals(-1, $opt$noinline$LongToInt(-1L));
+ assertIntEquals(51, $opt$noinline$LongToInt(51L));
+ assertIntEquals(-51, $opt$noinline$LongToInt(-51L));
+ assertIntEquals(2147483647, $opt$noinline$LongToInt(2147483647L)); // 2^31 - 1
+ assertIntEquals(-2147483647, $opt$noinline$LongToInt(-2147483647L)); // -(2^31 - 1)
+ assertIntEquals(-2147483648, $opt$noinline$LongToInt(-2147483648L)); // -(2^31)
+ assertIntEquals(-2147483648, $opt$noinline$LongToInt(2147483648L)); // (2^31)
+ assertIntEquals(2147483647, $opt$noinline$LongToInt(-2147483649L)); // -(2^31 + 1)
+ assertIntEquals(-1, $opt$noinline$LongToInt(9223372036854775807L)); // 2^63 - 1
+ assertIntEquals(1, $opt$noinline$LongToInt(-9223372036854775807L)); // -(2^63 - 1)
+ assertIntEquals(0, $opt$noinline$LongToInt(-9223372036854775808L)); // -(2^63)
- assertIntEquals(42, $opt$LongLiteralToInt());
+ assertIntEquals(42, $opt$noinline$LongLiteralToInt());
// Ensure long-to-int conversions truncates values as expected.
- assertLongEquals(1L, $opt$IntToLong($opt$LongToInt(4294967297L))); // 2^32 + 1
- assertLongEquals(0L, $opt$IntToLong($opt$LongToInt(4294967296L))); // 2^32
- assertLongEquals(-1L, $opt$IntToLong($opt$LongToInt(4294967295L))); // 2^32 - 1
- assertLongEquals(0L, $opt$IntToLong($opt$LongToInt(0L)));
- assertLongEquals(1L, $opt$IntToLong($opt$LongToInt(-4294967295L))); // -(2^32 - 1)
- assertLongEquals(0L, $opt$IntToLong($opt$LongToInt(-4294967296L))); // -(2^32)
- assertLongEquals(-1, $opt$IntToLong($opt$LongToInt(-4294967297L))); // -(2^32 + 1)
+ assertLongEquals(1L, $opt$noinline$IntToLong($opt$noinline$LongToInt(4294967297L))); // 2^32 + 1
+ assertLongEquals(0L, $opt$noinline$IntToLong($opt$noinline$LongToInt(4294967296L))); // 2^32
+ assertLongEquals(-1L, $opt$noinline$IntToLong($opt$noinline$LongToInt(4294967295L))); // 2^32 - 1
+ assertLongEquals(0L, $opt$noinline$IntToLong($opt$noinline$LongToInt(0L)));
+ assertLongEquals(1L, $opt$noinline$IntToLong($opt$noinline$LongToInt(-4294967295L))); // -(2^32 - 1)
+ assertLongEquals(0L, $opt$noinline$IntToLong($opt$noinline$LongToInt(-4294967296L))); // -(2^32)
+ assertLongEquals(-1, $opt$noinline$IntToLong($opt$noinline$LongToInt(-4294967297L))); // -(2^32 + 1)
}
private static void longToFloat() {
- assertFloatEquals(1F, $opt$LongToFloat(1L));
- assertFloatEquals(0F, $opt$LongToFloat(0L));
- assertFloatEquals(-1F, $opt$LongToFloat(-1L));
- assertFloatEquals(51F, $opt$LongToFloat(51L));
- assertFloatEquals(-51F, $opt$LongToFloat(-51L));
- assertFloatEquals(2147483647F, $opt$LongToFloat(2147483647L)); // 2^31 - 1
- assertFloatEquals(-2147483647F, $opt$LongToFloat(-2147483647L)); // -(2^31 - 1)
- assertFloatEquals(-2147483648F, $opt$LongToFloat(-2147483648L)); // -(2^31)
- assertFloatEquals(2147483648F, $opt$LongToFloat(2147483648L)); // (2^31)
- assertFloatEquals(-2147483649F, $opt$LongToFloat(-2147483649L)); // -(2^31 + 1)
- assertFloatEquals(4294967296F, $opt$LongToFloat(4294967296L)); // (2^32)
- assertFloatEquals(-4294967296F, $opt$LongToFloat(-4294967296L)); // -(2^32)
- assertFloatEquals(140739635871745F, $opt$LongToFloat(140739635871745L)); // 1 + 2^15 + 2^31 + 2^47
- assertFloatEquals(-140739635871745F, $opt$LongToFloat(-140739635871745L)); // -(1 + 2^15 + 2^31 + 2^47)
- assertFloatEquals(9223372036854775807F, $opt$LongToFloat(9223372036854775807L)); // 2^63 - 1
- assertFloatEquals(-9223372036854775807F, $opt$LongToFloat(-9223372036854775807L)); // -(2^63 - 1)
- assertFloatEquals(-9223372036854775808F, $opt$LongToFloat(-9223372036854775808L)); // -(2^63)
+ assertFloatEquals(1F, $opt$noinline$LongToFloat(1L));
+ assertFloatEquals(0F, $opt$noinline$LongToFloat(0L));
+ assertFloatEquals(-1F, $opt$noinline$LongToFloat(-1L));
+ assertFloatEquals(51F, $opt$noinline$LongToFloat(51L));
+ assertFloatEquals(-51F, $opt$noinline$LongToFloat(-51L));
+ assertFloatEquals(2147483647F, $opt$noinline$LongToFloat(2147483647L)); // 2^31 - 1
+ assertFloatEquals(-2147483647F, $opt$noinline$LongToFloat(-2147483647L)); // -(2^31 - 1)
+ assertFloatEquals(-2147483648F, $opt$noinline$LongToFloat(-2147483648L)); // -(2^31)
+ assertFloatEquals(2147483648F, $opt$noinline$LongToFloat(2147483648L)); // (2^31)
+ assertFloatEquals(-2147483649F, $opt$noinline$LongToFloat(-2147483649L)); // -(2^31 + 1)
+ assertFloatEquals(4294967296F, $opt$noinline$LongToFloat(4294967296L)); // (2^32)
+ assertFloatEquals(-4294967296F, $opt$noinline$LongToFloat(-4294967296L)); // -(2^32)
+ assertFloatEquals(140739635871745F, $opt$noinline$LongToFloat(140739635871745L)); // 1 + 2^15 + 2^31 + 2^47
+ assertFloatEquals(-140739635871745F, $opt$noinline$LongToFloat(-140739635871745L)); // -(1 + 2^15 + 2^31 + 2^47)
+ assertFloatEquals(9223372036854775807F, $opt$noinline$LongToFloat(9223372036854775807L)); // 2^63 - 1
+ assertFloatEquals(-9223372036854775807F, $opt$noinline$LongToFloat(-9223372036854775807L)); // -(2^63 - 1)
+ assertFloatEquals(-9223372036854775808F, $opt$noinline$LongToFloat(-9223372036854775808L)); // -(2^63)
}
private static void longToDouble() {
- assertDoubleEquals(1D, $opt$LongToDouble(1L));
- assertDoubleEquals(0D, $opt$LongToDouble(0L));
- assertDoubleEquals(-1D, $opt$LongToDouble(-1L));
- assertDoubleEquals(51D, $opt$LongToDouble(51L));
- assertDoubleEquals(-51D, $opt$LongToDouble(-51L));
- assertDoubleEquals(2147483647D, $opt$LongToDouble(2147483647L)); // 2^31 - 1
- assertDoubleEquals(-2147483647D, $opt$LongToDouble(-2147483647L)); // -(2^31 - 1)
- assertDoubleEquals(-2147483648D, $opt$LongToDouble(-2147483648L)); // -(2^31)
- assertDoubleEquals(2147483648D, $opt$LongToDouble(2147483648L)); // (2^31)
- assertDoubleEquals(-2147483649D, $opt$LongToDouble(-2147483649L)); // -(2^31 + 1)
- assertDoubleEquals(4294967296D, $opt$LongToDouble(4294967296L)); // (2^32)
- assertDoubleEquals(-4294967296D, $opt$LongToDouble(-4294967296L)); // -(2^32)
- assertDoubleEquals(140739635871745D, $opt$LongToDouble(140739635871745L)); // 1 + 2^15 + 2^31 + 2^47
- assertDoubleEquals(-140739635871745D, $opt$LongToDouble(-140739635871745L)); // -(1 + 2^15 + 2^31 + 2^47)
- assertDoubleEquals(9223372036854775807D, $opt$LongToDouble(9223372036854775807L)); // 2^63 - 1
- assertDoubleEquals(-9223372036854775807D, $opt$LongToDouble(-9223372036854775807L)); // -(2^63 - 1)
- assertDoubleEquals(-9223372036854775808D, $opt$LongToDouble(-9223372036854775808L)); // -(2^63)
+ assertDoubleEquals(1D, $opt$noinline$LongToDouble(1L));
+ assertDoubleEquals(0D, $opt$noinline$LongToDouble(0L));
+ assertDoubleEquals(-1D, $opt$noinline$LongToDouble(-1L));
+ assertDoubleEquals(51D, $opt$noinline$LongToDouble(51L));
+ assertDoubleEquals(-51D, $opt$noinline$LongToDouble(-51L));
+ assertDoubleEquals(2147483647D, $opt$noinline$LongToDouble(2147483647L)); // 2^31 - 1
+ assertDoubleEquals(-2147483647D, $opt$noinline$LongToDouble(-2147483647L)); // -(2^31 - 1)
+ assertDoubleEquals(-2147483648D, $opt$noinline$LongToDouble(-2147483648L)); // -(2^31)
+ assertDoubleEquals(2147483648D, $opt$noinline$LongToDouble(2147483648L)); // (2^31)
+ assertDoubleEquals(-2147483649D, $opt$noinline$LongToDouble(-2147483649L)); // -(2^31 + 1)
+ assertDoubleEquals(4294967296D, $opt$noinline$LongToDouble(4294967296L)); // (2^32)
+ assertDoubleEquals(-4294967296D, $opt$noinline$LongToDouble(-4294967296L)); // -(2^32)
+ assertDoubleEquals(140739635871745D, $opt$noinline$LongToDouble(140739635871745L)); // 1 + 2^15 + 2^31 + 2^47
+ assertDoubleEquals(-140739635871745D, $opt$noinline$LongToDouble(-140739635871745L)); // -(1 + 2^15 + 2^31 + 2^47)
+ assertDoubleEquals(9223372036854775807D, $opt$noinline$LongToDouble(9223372036854775807L)); // 2^63 - 1
+ assertDoubleEquals(-9223372036854775807D, $opt$noinline$LongToDouble(-9223372036854775807L)); // -(2^63 - 1)
+ assertDoubleEquals(-9223372036854775808D, $opt$noinline$LongToDouble(-9223372036854775808L)); // -(2^63)
}
private static void floatToInt() {
- assertIntEquals(1, $opt$FloatToInt(1F));
- assertIntEquals(0, $opt$FloatToInt(0F));
- assertIntEquals(0, $opt$FloatToInt(-0F));
- assertIntEquals(-1, $opt$FloatToInt(-1F));
- assertIntEquals(51, $opt$FloatToInt(51F));
- assertIntEquals(-51, $opt$FloatToInt(-51F));
- assertIntEquals(0, $opt$FloatToInt(0.5F));
- assertIntEquals(0, $opt$FloatToInt(0.4999999F));
- assertIntEquals(0, $opt$FloatToInt(-0.4999999F));
- assertIntEquals(0, $opt$FloatToInt(-0.5F));
- assertIntEquals(42, $opt$FloatToInt(42.199F));
- assertIntEquals(-42, $opt$FloatToInt(-42.199F));
- assertIntEquals(2147483647, $opt$FloatToInt(2147483647F)); // 2^31 - 1
- assertIntEquals(-2147483648, $opt$FloatToInt(-2147483647F)); // -(2^31 - 1)
- assertIntEquals(-2147483648, $opt$FloatToInt(-2147483648F)); // -(2^31)
- assertIntEquals(2147483647, $opt$FloatToInt(2147483648F)); // (2^31)
- assertIntEquals(-2147483648, $opt$FloatToInt(-2147483649F)); // -(2^31 + 1)
- assertIntEquals(2147483647, $opt$FloatToInt(9223372036854775807F)); // 2^63 - 1
- assertIntEquals(-2147483648, $opt$FloatToInt(-9223372036854775807F)); // -(2^63 - 1)
- assertIntEquals(-2147483648, $opt$FloatToInt(-9223372036854775808F)); // -(2^63)
- assertIntEquals(0, $opt$FloatToInt(Float.NaN));
- assertIntEquals(2147483647, $opt$FloatToInt(Float.POSITIVE_INFINITY));
- assertIntEquals(-2147483648, $opt$FloatToInt(Float.NEGATIVE_INFINITY));
+ assertIntEquals(1, $opt$noinline$FloatToInt(1F));
+ assertIntEquals(0, $opt$noinline$FloatToInt(0F));
+ assertIntEquals(0, $opt$noinline$FloatToInt(-0F));
+ assertIntEquals(-1, $opt$noinline$FloatToInt(-1F));
+ assertIntEquals(51, $opt$noinline$FloatToInt(51F));
+ assertIntEquals(-51, $opt$noinline$FloatToInt(-51F));
+ assertIntEquals(0, $opt$noinline$FloatToInt(0.5F));
+ assertIntEquals(0, $opt$noinline$FloatToInt(0.4999999F));
+ assertIntEquals(0, $opt$noinline$FloatToInt(-0.4999999F));
+ assertIntEquals(0, $opt$noinline$FloatToInt(-0.5F));
+ assertIntEquals(42, $opt$noinline$FloatToInt(42.199F));
+ assertIntEquals(-42, $opt$noinline$FloatToInt(-42.199F));
+ assertIntEquals(2147483647, $opt$noinline$FloatToInt(2147483647F)); // 2^31 - 1
+ assertIntEquals(-2147483648, $opt$noinline$FloatToInt(-2147483647F)); // -(2^31 - 1)
+ assertIntEquals(-2147483648, $opt$noinline$FloatToInt(-2147483648F)); // -(2^31)
+ assertIntEquals(2147483647, $opt$noinline$FloatToInt(2147483648F)); // (2^31)
+ assertIntEquals(-2147483648, $opt$noinline$FloatToInt(-2147483649F)); // -(2^31 + 1)
+ assertIntEquals(2147483647, $opt$noinline$FloatToInt(9223372036854775807F)); // 2^63 - 1
+ assertIntEquals(-2147483648, $opt$noinline$FloatToInt(-9223372036854775807F)); // -(2^63 - 1)
+ assertIntEquals(-2147483648, $opt$noinline$FloatToInt(-9223372036854775808F)); // -(2^63)
+ assertIntEquals(0, $opt$noinline$FloatToInt(Float.NaN));
+ assertIntEquals(2147483647, $opt$noinline$FloatToInt(Float.POSITIVE_INFINITY));
+ assertIntEquals(-2147483648, $opt$noinline$FloatToInt(Float.NEGATIVE_INFINITY));
}
private static void floatToLong() {
- assertLongEquals(1L, $opt$FloatToLong(1F));
- assertLongEquals(0L, $opt$FloatToLong(0F));
- assertLongEquals(0L, $opt$FloatToLong(-0F));
- assertLongEquals(-1L, $opt$FloatToLong(-1F));
- assertLongEquals(51L, $opt$FloatToLong(51F));
- assertLongEquals(-51L, $opt$FloatToLong(-51F));
- assertLongEquals(0L, $opt$FloatToLong(0.5F));
- assertLongEquals(0L, $opt$FloatToLong(0.4999999F));
- assertLongEquals(0L, $opt$FloatToLong(-0.4999999F));
- assertLongEquals(0L, $opt$FloatToLong(-0.5F));
- assertLongEquals(42L, $opt$FloatToLong(42.199F));
- assertLongEquals(-42L, $opt$FloatToLong(-42.199F));
- assertLongEquals(2147483648L, $opt$FloatToLong(2147483647F)); // 2^31 - 1
- assertLongEquals(-2147483648L, $opt$FloatToLong(-2147483647F)); // -(2^31 - 1)
- assertLongEquals(-2147483648L, $opt$FloatToLong(-2147483648F)); // -(2^31)
- assertLongEquals(2147483648L, $opt$FloatToLong(2147483648F)); // (2^31)
- assertLongEquals(-2147483648L, $opt$FloatToLong(-2147483649F)); // -(2^31 + 1)
- assertLongEquals(9223372036854775807L, $opt$FloatToLong(9223372036854775807F)); // 2^63 - 1
- assertLongEquals(-9223372036854775808L, $opt$FloatToLong(-9223372036854775807F)); // -(2^63 - 1)
- assertLongEquals(-9223372036854775808L, $opt$FloatToLong(-9223372036854775808F)); // -(2^63)
- assertLongEquals(0L, $opt$FloatToLong(Float.NaN));
- assertLongEquals(9223372036854775807L, $opt$FloatToLong(Float.POSITIVE_INFINITY));
- assertLongEquals(-9223372036854775808L, $opt$FloatToLong(Float.NEGATIVE_INFINITY));
+ assertLongEquals(1L, $opt$noinline$FloatToLong(1F));
+ assertLongEquals(0L, $opt$noinline$FloatToLong(0F));
+ assertLongEquals(0L, $opt$noinline$FloatToLong(-0F));
+ assertLongEquals(-1L, $opt$noinline$FloatToLong(-1F));
+ assertLongEquals(51L, $opt$noinline$FloatToLong(51F));
+ assertLongEquals(-51L, $opt$noinline$FloatToLong(-51F));
+ assertLongEquals(0L, $opt$noinline$FloatToLong(0.5F));
+ assertLongEquals(0L, $opt$noinline$FloatToLong(0.4999999F));
+ assertLongEquals(0L, $opt$noinline$FloatToLong(-0.4999999F));
+ assertLongEquals(0L, $opt$noinline$FloatToLong(-0.5F));
+ assertLongEquals(42L, $opt$noinline$FloatToLong(42.199F));
+ assertLongEquals(-42L, $opt$noinline$FloatToLong(-42.199F));
+ assertLongEquals(2147483648L, $opt$noinline$FloatToLong(2147483647F)); // 2^31 - 1
+ assertLongEquals(-2147483648L, $opt$noinline$FloatToLong(-2147483647F)); // -(2^31 - 1)
+ assertLongEquals(-2147483648L, $opt$noinline$FloatToLong(-2147483648F)); // -(2^31)
+ assertLongEquals(2147483648L, $opt$noinline$FloatToLong(2147483648F)); // (2^31)
+ assertLongEquals(-2147483648L, $opt$noinline$FloatToLong(-2147483649F)); // -(2^31 + 1)
+ assertLongEquals(9223372036854775807L, $opt$noinline$FloatToLong(9223372036854775807F)); // 2^63 - 1
+ assertLongEquals(-9223372036854775808L, $opt$noinline$FloatToLong(-9223372036854775807F)); // -(2^63 - 1)
+ assertLongEquals(-9223372036854775808L, $opt$noinline$FloatToLong(-9223372036854775808F)); // -(2^63)
+ assertLongEquals(0L, $opt$noinline$FloatToLong(Float.NaN));
+ assertLongEquals(9223372036854775807L, $opt$noinline$FloatToLong(Float.POSITIVE_INFINITY));
+ assertLongEquals(-9223372036854775808L, $opt$noinline$FloatToLong(Float.NEGATIVE_INFINITY));
}
private static void floatToDouble() {
- assertDoubleEquals(1D, $opt$FloatToDouble(1F));
- assertDoubleEquals(0D, $opt$FloatToDouble(0F));
- assertDoubleEquals(0D, $opt$FloatToDouble(-0F));
- assertDoubleEquals(-1D, $opt$FloatToDouble(-1F));
- assertDoubleEquals(51D, $opt$FloatToDouble(51F));
- assertDoubleEquals(-51D, $opt$FloatToDouble(-51F));
- assertDoubleEquals(0.5D, $opt$FloatToDouble(0.5F));
- assertDoubleEquals(0.49999991059303284D, $opt$FloatToDouble(0.4999999F));
- assertDoubleEquals(-0.49999991059303284D, $opt$FloatToDouble(-0.4999999F));
- assertDoubleEquals(-0.5D, $opt$FloatToDouble(-0.5F));
- assertDoubleEquals(42.19900131225586D, $opt$FloatToDouble(42.199F));
- assertDoubleEquals(-42.19900131225586D, $opt$FloatToDouble(-42.199F));
- assertDoubleEquals(2147483648D, $opt$FloatToDouble(2147483647F)); // 2^31 - 1
- assertDoubleEquals(-2147483648D, $opt$FloatToDouble(-2147483647F)); // -(2^31 - 1)
- assertDoubleEquals(-2147483648D, $opt$FloatToDouble(-2147483648F)); // -(2^31)
- assertDoubleEquals(2147483648D, $opt$FloatToDouble(2147483648F)); // (2^31)
- assertDoubleEquals(-2147483648D, $opt$FloatToDouble(-2147483649F)); // -(2^31 + 1)
- assertDoubleEquals(9223372036854775807D, $opt$FloatToDouble(9223372036854775807F)); // 2^63 - 1
- assertDoubleEquals(-9223372036854775807D, $opt$FloatToDouble(-9223372036854775807F)); // -(2^63 - 1)
- assertDoubleEquals(-9223372036854775808D, $opt$FloatToDouble(-9223372036854775808F)); // -(2^63)
- assertDoubleIsNaN($opt$FloatToDouble(Float.NaN));
- assertDoubleEquals(Double.POSITIVE_INFINITY, $opt$FloatToDouble(Float.POSITIVE_INFINITY));
- assertDoubleEquals(Double.NEGATIVE_INFINITY, $opt$FloatToDouble(Float.NEGATIVE_INFINITY));
+ assertDoubleEquals(1D, $opt$noinline$FloatToDouble(1F));
+ assertDoubleEquals(0D, $opt$noinline$FloatToDouble(0F));
+ assertDoubleEquals(0D, $opt$noinline$FloatToDouble(-0F));
+ assertDoubleEquals(-1D, $opt$noinline$FloatToDouble(-1F));
+ assertDoubleEquals(51D, $opt$noinline$FloatToDouble(51F));
+ assertDoubleEquals(-51D, $opt$noinline$FloatToDouble(-51F));
+ assertDoubleEquals(0.5D, $opt$noinline$FloatToDouble(0.5F));
+ assertDoubleEquals(0.49999991059303284D, $opt$noinline$FloatToDouble(0.4999999F));
+ assertDoubleEquals(-0.49999991059303284D, $opt$noinline$FloatToDouble(-0.4999999F));
+ assertDoubleEquals(-0.5D, $opt$noinline$FloatToDouble(-0.5F));
+ assertDoubleEquals(42.19900131225586D, $opt$noinline$FloatToDouble(42.199F));
+ assertDoubleEquals(-42.19900131225586D, $opt$noinline$FloatToDouble(-42.199F));
+ assertDoubleEquals(2147483648D, $opt$noinline$FloatToDouble(2147483647F)); // 2^31 - 1
+ assertDoubleEquals(-2147483648D, $opt$noinline$FloatToDouble(-2147483647F)); // -(2^31 - 1)
+ assertDoubleEquals(-2147483648D, $opt$noinline$FloatToDouble(-2147483648F)); // -(2^31)
+ assertDoubleEquals(2147483648D, $opt$noinline$FloatToDouble(2147483648F)); // (2^31)
+ assertDoubleEquals(-2147483648D, $opt$noinline$FloatToDouble(-2147483649F)); // -(2^31 + 1)
+ assertDoubleEquals(9223372036854775807D, $opt$noinline$FloatToDouble(9223372036854775807F)); // 2^63 - 1
+ assertDoubleEquals(-9223372036854775807D, $opt$noinline$FloatToDouble(-9223372036854775807F)); // -(2^63 - 1)
+ assertDoubleEquals(-9223372036854775808D, $opt$noinline$FloatToDouble(-9223372036854775808F)); // -(2^63)
+ assertDoubleIsNaN($opt$noinline$FloatToDouble(Float.NaN));
+ assertDoubleEquals(Double.POSITIVE_INFINITY, $opt$noinline$FloatToDouble(Float.POSITIVE_INFINITY));
+ assertDoubleEquals(Double.NEGATIVE_INFINITY, $opt$noinline$FloatToDouble(Float.NEGATIVE_INFINITY));
}
private static void doubleToInt() {
- assertIntEquals(1, $opt$DoubleToInt(1D));
- assertIntEquals(0, $opt$DoubleToInt(0D));
- assertIntEquals(0, $opt$DoubleToInt(-0D));
- assertIntEquals(-1, $opt$DoubleToInt(-1D));
- assertIntEquals(51, $opt$DoubleToInt(51D));
- assertIntEquals(-51, $opt$DoubleToInt(-51D));
- assertIntEquals(0, $opt$DoubleToInt(0.5D));
- assertIntEquals(0, $opt$DoubleToInt(0.4999999D));
- assertIntEquals(0, $opt$DoubleToInt(-0.4999999D));
- assertIntEquals(0, $opt$DoubleToInt(-0.5D));
- assertIntEquals(42, $opt$DoubleToInt(42.199D));
- assertIntEquals(-42, $opt$DoubleToInt(-42.199D));
- assertIntEquals(2147483647, $opt$DoubleToInt(2147483647D)); // 2^31 - 1
- assertIntEquals(-2147483647, $opt$DoubleToInt(-2147483647D)); // -(2^31 - 1)
- assertIntEquals(-2147483648, $opt$DoubleToInt(-2147483648D)); // -(2^31)
- assertIntEquals(2147483647, $opt$DoubleToInt(2147483648D)); // (2^31)
- assertIntEquals(-2147483648, $opt$DoubleToInt(-2147483649D)); // -(2^31 + 1)
- assertIntEquals(2147483647, $opt$DoubleToInt(9223372036854775807D)); // 2^63 - 1
- assertIntEquals(-2147483648, $opt$DoubleToInt(-9223372036854775807D)); // -(2^63 - 1)
- assertIntEquals(-2147483648, $opt$DoubleToInt(-9223372036854775808D)); // -(2^63)
- assertIntEquals(0, $opt$DoubleToInt(Double.NaN));
- assertIntEquals(2147483647, $opt$DoubleToInt(Double.POSITIVE_INFINITY));
- assertIntEquals(-2147483648, $opt$DoubleToInt(Double.NEGATIVE_INFINITY));
+ assertIntEquals(1, $opt$noinline$DoubleToInt(1D));
+ assertIntEquals(0, $opt$noinline$DoubleToInt(0D));
+ assertIntEquals(0, $opt$noinline$DoubleToInt(-0D));
+ assertIntEquals(-1, $opt$noinline$DoubleToInt(-1D));
+ assertIntEquals(51, $opt$noinline$DoubleToInt(51D));
+ assertIntEquals(-51, $opt$noinline$DoubleToInt(-51D));
+ assertIntEquals(0, $opt$noinline$DoubleToInt(0.5D));
+ assertIntEquals(0, $opt$noinline$DoubleToInt(0.4999999D));
+ assertIntEquals(0, $opt$noinline$DoubleToInt(-0.4999999D));
+ assertIntEquals(0, $opt$noinline$DoubleToInt(-0.5D));
+ assertIntEquals(42, $opt$noinline$DoubleToInt(42.199D));
+ assertIntEquals(-42, $opt$noinline$DoubleToInt(-42.199D));
+ assertIntEquals(2147483647, $opt$noinline$DoubleToInt(2147483647D)); // 2^31 - 1
+ assertIntEquals(-2147483647, $opt$noinline$DoubleToInt(-2147483647D)); // -(2^31 - 1)
+ assertIntEquals(-2147483648, $opt$noinline$DoubleToInt(-2147483648D)); // -(2^31)
+ assertIntEquals(2147483647, $opt$noinline$DoubleToInt(2147483648D)); // (2^31)
+ assertIntEquals(-2147483648, $opt$noinline$DoubleToInt(-2147483649D)); // -(2^31 + 1)
+ assertIntEquals(2147483647, $opt$noinline$DoubleToInt(9223372036854775807D)); // 2^63 - 1
+ assertIntEquals(-2147483648, $opt$noinline$DoubleToInt(-9223372036854775807D)); // -(2^63 - 1)
+ assertIntEquals(-2147483648, $opt$noinline$DoubleToInt(-9223372036854775808D)); // -(2^63)
+ assertIntEquals(0, $opt$noinline$DoubleToInt(Double.NaN));
+ assertIntEquals(2147483647, $opt$noinline$DoubleToInt(Double.POSITIVE_INFINITY));
+ assertIntEquals(-2147483648, $opt$noinline$DoubleToInt(Double.NEGATIVE_INFINITY));
}
private static void doubleToLong() {
- assertLongEquals(1L, $opt$DoubleToLong(1D));
- assertLongEquals(0L, $opt$DoubleToLong(0D));
- assertLongEquals(0L, $opt$DoubleToLong(-0D));
- assertLongEquals(-1L, $opt$DoubleToLong(-1D));
- assertLongEquals(51L, $opt$DoubleToLong(51D));
- assertLongEquals(-51L, $opt$DoubleToLong(-51D));
- assertLongEquals(0L, $opt$DoubleToLong(0.5D));
- assertLongEquals(0L, $opt$DoubleToLong(0.4999999D));
- assertLongEquals(0L, $opt$DoubleToLong(-0.4999999D));
- assertLongEquals(0L, $opt$DoubleToLong(-0.5D));
- assertLongEquals(42L, $opt$DoubleToLong(42.199D));
- assertLongEquals(-42L, $opt$DoubleToLong(-42.199D));
- assertLongEquals(2147483647L, $opt$DoubleToLong(2147483647D)); // 2^31 - 1
- assertLongEquals(-2147483647L, $opt$DoubleToLong(-2147483647D)); // -(2^31 - 1)
- assertLongEquals(-2147483648L, $opt$DoubleToLong(-2147483648D)); // -(2^31)
- assertLongEquals(2147483648L, $opt$DoubleToLong(2147483648D)); // (2^31)
- assertLongEquals(-2147483649L, $opt$DoubleToLong(-2147483649D)); // -(2^31 + 1)
- assertLongEquals(9223372036854775807L, $opt$DoubleToLong(9223372036854775807D)); // 2^63 - 1
- assertLongEquals(-9223372036854775808L, $opt$DoubleToLong(-9223372036854775807D)); // -(2^63 - 1)
- assertLongEquals(-9223372036854775808L, $opt$DoubleToLong(-9223372036854775808D)); // -(2^63)
- assertLongEquals(0L, $opt$DoubleToLong(Double.NaN));
- assertLongEquals(9223372036854775807L, $opt$DoubleToLong(Double.POSITIVE_INFINITY));
- assertLongEquals(-9223372036854775808L, $opt$DoubleToLong(Double.NEGATIVE_INFINITY));
+ assertLongEquals(1L, $opt$noinline$DoubleToLong(1D));
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(0D));
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(-0D));
+ assertLongEquals(-1L, $opt$noinline$DoubleToLong(-1D));
+ assertLongEquals(51L, $opt$noinline$DoubleToLong(51D));
+ assertLongEquals(-51L, $opt$noinline$DoubleToLong(-51D));
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(0.5D));
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(0.4999999D));
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(-0.4999999D));
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(-0.5D));
+ assertLongEquals(42L, $opt$noinline$DoubleToLong(42.199D));
+ assertLongEquals(-42L, $opt$noinline$DoubleToLong(-42.199D));
+ assertLongEquals(2147483647L, $opt$noinline$DoubleToLong(2147483647D)); // 2^31 - 1
+ assertLongEquals(-2147483647L, $opt$noinline$DoubleToLong(-2147483647D)); // -(2^31 - 1)
+ assertLongEquals(-2147483648L, $opt$noinline$DoubleToLong(-2147483648D)); // -(2^31)
+ assertLongEquals(2147483648L, $opt$noinline$DoubleToLong(2147483648D)); // (2^31)
+ assertLongEquals(-2147483649L, $opt$noinline$DoubleToLong(-2147483649D)); // -(2^31 + 1)
+ assertLongEquals(9223372036854775807L, $opt$noinline$DoubleToLong(9223372036854775807D)); // 2^63 - 1
+ assertLongEquals(-9223372036854775808L, $opt$noinline$DoubleToLong(-9223372036854775807D)); // -(2^63 - 1)
+ assertLongEquals(-9223372036854775808L, $opt$noinline$DoubleToLong(-9223372036854775808D)); // -(2^63)
+ assertLongEquals(0L, $opt$noinline$DoubleToLong(Double.NaN));
+ assertLongEquals(9223372036854775807L, $opt$noinline$DoubleToLong(Double.POSITIVE_INFINITY));
+ assertLongEquals(-9223372036854775808L, $opt$noinline$DoubleToLong(Double.NEGATIVE_INFINITY));
}
private static void doubleToFloat() {
- assertFloatEquals(1F, $opt$DoubleToFloat(1D));
- assertFloatEquals(0F, $opt$DoubleToFloat(0D));
- assertFloatEquals(0F, $opt$DoubleToFloat(-0D));
- assertFloatEquals(-1F, $opt$DoubleToFloat(-1D));
- assertFloatEquals(51F, $opt$DoubleToFloat(51D));
- assertFloatEquals(-51F, $opt$DoubleToFloat(-51D));
- assertFloatEquals(0.5F, $opt$DoubleToFloat(0.5D));
- assertFloatEquals(0.4999999F, $opt$DoubleToFloat(0.4999999D));
- assertFloatEquals(-0.4999999F, $opt$DoubleToFloat(-0.4999999D));
- assertFloatEquals(-0.5F, $opt$DoubleToFloat(-0.5D));
- assertFloatEquals(42.199F, $opt$DoubleToFloat(42.199D));
- assertFloatEquals(-42.199F, $opt$DoubleToFloat(-42.199D));
- assertFloatEquals(2147483648F, $opt$DoubleToFloat(2147483647D)); // 2^31 - 1
- assertFloatEquals(-2147483648F, $opt$DoubleToFloat(-2147483647D)); // -(2^31 - 1)
- assertFloatEquals(-2147483648F, $opt$DoubleToFloat(-2147483648D)); // -(2^31)
- assertFloatEquals(2147483648F, $opt$DoubleToFloat(2147483648D)); // (2^31)
- assertFloatEquals(-2147483648F, $opt$DoubleToFloat(-2147483649D)); // -(2^31 + 1)
- assertFloatEquals(9223372036854775807F, $opt$DoubleToFloat(9223372036854775807D)); // 2^63 - 1
- assertFloatEquals(-9223372036854775807F, $opt$DoubleToFloat(-9223372036854775807D)); // -(2^63 - 1)
- assertFloatEquals(-9223372036854775808F, $opt$DoubleToFloat(-9223372036854775808D)); // -(2^63)
- assertFloatIsNaN($opt$DoubleToFloat(Float.NaN));
- assertFloatEquals(Float.POSITIVE_INFINITY, $opt$DoubleToFloat(Double.POSITIVE_INFINITY));
- assertFloatEquals(Float.NEGATIVE_INFINITY, $opt$DoubleToFloat(Double.NEGATIVE_INFINITY));
+ assertFloatEquals(1F, $opt$noinline$DoubleToFloat(1D));
+ assertFloatEquals(0F, $opt$noinline$DoubleToFloat(0D));
+ assertFloatEquals(0F, $opt$noinline$DoubleToFloat(-0D));
+ assertFloatEquals(-1F, $opt$noinline$DoubleToFloat(-1D));
+ assertFloatEquals(51F, $opt$noinline$DoubleToFloat(51D));
+ assertFloatEquals(-51F, $opt$noinline$DoubleToFloat(-51D));
+ assertFloatEquals(0.5F, $opt$noinline$DoubleToFloat(0.5D));
+ assertFloatEquals(0.4999999F, $opt$noinline$DoubleToFloat(0.4999999D));
+ assertFloatEquals(-0.4999999F, $opt$noinline$DoubleToFloat(-0.4999999D));
+ assertFloatEquals(-0.5F, $opt$noinline$DoubleToFloat(-0.5D));
+ assertFloatEquals(42.199F, $opt$noinline$DoubleToFloat(42.199D));
+ assertFloatEquals(-42.199F, $opt$noinline$DoubleToFloat(-42.199D));
+ assertFloatEquals(2147483648F, $opt$noinline$DoubleToFloat(2147483647D)); // 2^31 - 1
+ assertFloatEquals(-2147483648F, $opt$noinline$DoubleToFloat(-2147483647D)); // -(2^31 - 1)
+ assertFloatEquals(-2147483648F, $opt$noinline$DoubleToFloat(-2147483648D)); // -(2^31)
+ assertFloatEquals(2147483648F, $opt$noinline$DoubleToFloat(2147483648D)); // (2^31)
+ assertFloatEquals(-2147483648F, $opt$noinline$DoubleToFloat(-2147483649D)); // -(2^31 + 1)
+ assertFloatEquals(9223372036854775807F, $opt$noinline$DoubleToFloat(9223372036854775807D)); // 2^63 - 1
+ assertFloatEquals(-9223372036854775807F, $opt$noinline$DoubleToFloat(-9223372036854775807D)); // -(2^63 - 1)
+ assertFloatEquals(-9223372036854775808F, $opt$noinline$DoubleToFloat(-9223372036854775808D)); // -(2^63)
+ assertFloatIsNaN($opt$noinline$DoubleToFloat(Float.NaN));
+ assertFloatEquals(Float.POSITIVE_INFINITY, $opt$noinline$DoubleToFloat(Double.POSITIVE_INFINITY));
+ assertFloatEquals(Float.NEGATIVE_INFINITY, $opt$noinline$DoubleToFloat(Double.NEGATIVE_INFINITY));
}
private static void shortToByte() {
- assertByteEquals((byte)1, $opt$ShortToByte((short)1));
- assertByteEquals((byte)0, $opt$ShortToByte((short)0));
- assertByteEquals((byte)-1, $opt$ShortToByte((short)-1));
- assertByteEquals((byte)51, $opt$ShortToByte((short)51));
- assertByteEquals((byte)-51, $opt$ShortToByte((short)-51));
- assertByteEquals((byte)127, $opt$ShortToByte((short)127)); // 2^7 - 1
- assertByteEquals((byte)-127, $opt$ShortToByte((short)-127)); // -(2^7 - 1)
- assertByteEquals((byte)-128, $opt$ShortToByte((short)-128)); // -(2^7)
- assertByteEquals((byte)-128, $opt$ShortToByte((short)128)); // 2^7
- assertByteEquals((byte)127, $opt$ShortToByte((short)-129)); // -(2^7 + 1)
- assertByteEquals((byte)-1, $opt$ShortToByte((short)32767)); // 2^15 - 1
- assertByteEquals((byte)0, $opt$ShortToByte((short)-32768)); // -(2^15)
+ assertByteEquals((byte)1, $opt$noinline$ShortToByte((short)1));
+ assertByteEquals((byte)0, $opt$noinline$ShortToByte((short)0));
+ assertByteEquals((byte)-1, $opt$noinline$ShortToByte((short)-1));
+ assertByteEquals((byte)51, $opt$noinline$ShortToByte((short)51));
+ assertByteEquals((byte)-51, $opt$noinline$ShortToByte((short)-51));
+ assertByteEquals((byte)127, $opt$noinline$ShortToByte((short)127)); // 2^7 - 1
+ assertByteEquals((byte)-127, $opt$noinline$ShortToByte((short)-127)); // -(2^7 - 1)
+ assertByteEquals((byte)-128, $opt$noinline$ShortToByte((short)-128)); // -(2^7)
+ assertByteEquals((byte)-128, $opt$noinline$ShortToByte((short)128)); // 2^7
+ assertByteEquals((byte)127, $opt$noinline$ShortToByte((short)-129)); // -(2^7 + 1)
+ assertByteEquals((byte)-1, $opt$noinline$ShortToByte((short)32767)); // 2^15 - 1
+ assertByteEquals((byte)0, $opt$noinline$ShortToByte((short)-32768)); // -(2^15)
}
private static void intToByte() {
- assertByteEquals((byte)1, $opt$IntToByte(1));
- assertByteEquals((byte)0, $opt$IntToByte(0));
- assertByteEquals((byte)-1, $opt$IntToByte(-1));
- assertByteEquals((byte)51, $opt$IntToByte(51));
- assertByteEquals((byte)-51, $opt$IntToByte(-51));
- assertByteEquals((byte)127, $opt$IntToByte(127)); // 2^7 - 1
- assertByteEquals((byte)-127, $opt$IntToByte(-127)); // -(2^7 - 1)
- assertByteEquals((byte)-128, $opt$IntToByte(-128)); // -(2^7)
- assertByteEquals((byte)-128, $opt$IntToByte(128)); // 2^7
- assertByteEquals((byte)127, $opt$IntToByte(-129)); // -(2^7 + 1)
- assertByteEquals((byte)-1, $opt$IntToByte(2147483647)); // 2^31 - 1
- assertByteEquals((byte)0, $opt$IntToByte(-2147483648)); // -(2^31)
+ assertByteEquals((byte)1, $opt$noinline$IntToByte(1));
+ assertByteEquals((byte)0, $opt$noinline$IntToByte(0));
+ assertByteEquals((byte)-1, $opt$noinline$IntToByte(-1));
+ assertByteEquals((byte)51, $opt$noinline$IntToByte(51));
+ assertByteEquals((byte)-51, $opt$noinline$IntToByte(-51));
+ assertByteEquals((byte)127, $opt$noinline$IntToByte(127)); // 2^7 - 1
+ assertByteEquals((byte)-127, $opt$noinline$IntToByte(-127)); // -(2^7 - 1)
+ assertByteEquals((byte)-128, $opt$noinline$IntToByte(-128)); // -(2^7)
+ assertByteEquals((byte)-128, $opt$noinline$IntToByte(128)); // 2^7
+ assertByteEquals((byte)127, $opt$noinline$IntToByte(-129)); // -(2^7 + 1)
+ assertByteEquals((byte)-1, $opt$noinline$IntToByte(2147483647)); // 2^31 - 1
+ assertByteEquals((byte)0, $opt$noinline$IntToByte(-2147483648)); // -(2^31)
}
private static void charToByte() {
- assertByteEquals((byte)1, $opt$CharToByte((char)1));
- assertByteEquals((byte)0, $opt$CharToByte((char)0));
- assertByteEquals((byte)51, $opt$CharToByte((char)51));
- assertByteEquals((byte)127, $opt$CharToByte((char)127)); // 2^7 - 1
- assertByteEquals((byte)-128, $opt$CharToByte((char)128)); // 2^7
- assertByteEquals((byte)-1, $opt$CharToByte((char)32767)); // 2^15 - 1
- assertByteEquals((byte)-1, $opt$CharToByte((char)65535)); // 2^16 - 1
- assertByteEquals((byte)-1, $opt$CharToByte((char)-1));
- assertByteEquals((byte)-51, $opt$CharToByte((char)-51));
- assertByteEquals((byte)-127, $opt$CharToByte((char)-127)); // -(2^7 - 1)
- assertByteEquals((byte)-128, $opt$CharToByte((char)-128)); // -(2^7)
- assertByteEquals((byte)127, $opt$CharToByte((char)-129)); // -(2^7 + 1)
+ assertByteEquals((byte)1, $opt$noinline$CharToByte((char)1));
+ assertByteEquals((byte)0, $opt$noinline$CharToByte((char)0));
+ assertByteEquals((byte)51, $opt$noinline$CharToByte((char)51));
+ assertByteEquals((byte)127, $opt$noinline$CharToByte((char)127)); // 2^7 - 1
+ assertByteEquals((byte)-128, $opt$noinline$CharToByte((char)128)); // 2^7
+ assertByteEquals((byte)-1, $opt$noinline$CharToByte((char)32767)); // 2^15 - 1
+ assertByteEquals((byte)-1, $opt$noinline$CharToByte((char)65535)); // 2^16 - 1
+ assertByteEquals((byte)-1, $opt$noinline$CharToByte((char)-1));
+ assertByteEquals((byte)-51, $opt$noinline$CharToByte((char)-51));
+ assertByteEquals((byte)-127, $opt$noinline$CharToByte((char)-127)); // -(2^7 - 1)
+ assertByteEquals((byte)-128, $opt$noinline$CharToByte((char)-128)); // -(2^7)
+ assertByteEquals((byte)127, $opt$noinline$CharToByte((char)-129)); // -(2^7 + 1)
}
private static void byteToShort() {
- assertShortEquals((short)1, $opt$ByteToShort((byte)1));
- assertShortEquals((short)0, $opt$ByteToShort((byte)0));
- assertShortEquals((short)-1, $opt$ByteToShort((byte)-1));
- assertShortEquals((short)51, $opt$ByteToShort((byte)51));
- assertShortEquals((short)-51, $opt$ByteToShort((byte)-51));
- assertShortEquals((short)127, $opt$ByteToShort((byte)127)); // 2^7 - 1
- assertShortEquals((short)-127, $opt$ByteToShort((byte)-127)); // -(2^7 - 1)
- assertShortEquals((short)-128, $opt$ByteToShort((byte)-128)); // -(2^7)
+ assertShortEquals((short)1, $opt$noinline$ByteToShort((byte)1));
+ assertShortEquals((short)0, $opt$noinline$ByteToShort((byte)0));
+ assertShortEquals((short)-1, $opt$noinline$ByteToShort((byte)-1));
+ assertShortEquals((short)51, $opt$noinline$ByteToShort((byte)51));
+ assertShortEquals((short)-51, $opt$noinline$ByteToShort((byte)-51));
+ assertShortEquals((short)127, $opt$noinline$ByteToShort((byte)127)); // 2^7 - 1
+ assertShortEquals((short)-127, $opt$noinline$ByteToShort((byte)-127)); // -(2^7 - 1)
+ assertShortEquals((short)-128, $opt$noinline$ByteToShort((byte)-128)); // -(2^7)
}
private static void intToShort() {
- assertShortEquals((short)1, $opt$IntToShort(1));
- assertShortEquals((short)0, $opt$IntToShort(0));
- assertShortEquals((short)-1, $opt$IntToShort(-1));
- assertShortEquals((short)51, $opt$IntToShort(51));
- assertShortEquals((short)-51, $opt$IntToShort(-51));
- assertShortEquals((short)32767, $opt$IntToShort(32767)); // 2^15 - 1
- assertShortEquals((short)-32767, $opt$IntToShort(-32767)); // -(2^15 - 1)
- assertShortEquals((short)-32768, $opt$IntToShort(-32768)); // -(2^15)
- assertShortEquals((short)-32768, $opt$IntToShort(32768)); // 2^15
- assertShortEquals((short)32767, $opt$IntToShort(-32769)); // -(2^15 + 1)
- assertShortEquals((short)-1, $opt$IntToShort(2147483647)); // 2^31 - 1
- assertShortEquals((short)0, $opt$IntToShort(-2147483648)); // -(2^31)
+ assertShortEquals((short)1, $opt$noinline$IntToShort(1));
+ assertShortEquals((short)0, $opt$noinline$IntToShort(0));
+ assertShortEquals((short)-1, $opt$noinline$IntToShort(-1));
+ assertShortEquals((short)51, $opt$noinline$IntToShort(51));
+ assertShortEquals((short)-51, $opt$noinline$IntToShort(-51));
+ assertShortEquals((short)32767, $opt$noinline$IntToShort(32767)); // 2^15 - 1
+ assertShortEquals((short)-32767, $opt$noinline$IntToShort(-32767)); // -(2^15 - 1)
+ assertShortEquals((short)-32768, $opt$noinline$IntToShort(-32768)); // -(2^15)
+ assertShortEquals((short)-32768, $opt$noinline$IntToShort(32768)); // 2^15
+ assertShortEquals((short)32767, $opt$noinline$IntToShort(-32769)); // -(2^15 + 1)
+ assertShortEquals((short)-1, $opt$noinline$IntToShort(2147483647)); // 2^31 - 1
+ assertShortEquals((short)0, $opt$noinline$IntToShort(-2147483648)); // -(2^31)
}
private static void charToShort() {
- assertShortEquals((short)1, $opt$CharToShort((char)1));
- assertShortEquals((short)0, $opt$CharToShort((char)0));
- assertShortEquals((short)51, $opt$CharToShort((char)51));
- assertShortEquals((short)32767, $opt$CharToShort((char)32767)); // 2^15 - 1
- assertShortEquals((short)-32768, $opt$CharToShort((char)32768)); // 2^15
- assertShortEquals((short)-32767, $opt$CharToShort((char)32769)); // 2^15
- assertShortEquals((short)-1, $opt$CharToShort((char)65535)); // 2^16 - 1
- assertShortEquals((short)-1, $opt$CharToShort((char)-1));
- assertShortEquals((short)-51, $opt$CharToShort((char)-51));
- assertShortEquals((short)-32767, $opt$CharToShort((char)-32767)); // -(2^15 - 1)
- assertShortEquals((short)-32768, $opt$CharToShort((char)-32768)); // -(2^15)
- assertShortEquals((short)32767, $opt$CharToShort((char)-32769)); // -(2^15 + 1)
+ assertShortEquals((short)1, $opt$noinline$CharToShort((char)1));
+ assertShortEquals((short)0, $opt$noinline$CharToShort((char)0));
+ assertShortEquals((short)51, $opt$noinline$CharToShort((char)51));
+ assertShortEquals((short)32767, $opt$noinline$CharToShort((char)32767)); // 2^15 - 1
+ assertShortEquals((short)-32768, $opt$noinline$CharToShort((char)32768)); // 2^15
+ assertShortEquals((short)-32767, $opt$noinline$CharToShort((char)32769)); // 2^15
+ assertShortEquals((short)-1, $opt$noinline$CharToShort((char)65535)); // 2^16 - 1
+ assertShortEquals((short)-1, $opt$noinline$CharToShort((char)-1));
+ assertShortEquals((short)-51, $opt$noinline$CharToShort((char)-51));
+ assertShortEquals((short)-32767, $opt$noinline$CharToShort((char)-32767)); // -(2^15 - 1)
+ assertShortEquals((short)-32768, $opt$noinline$CharToShort((char)-32768)); // -(2^15)
+ assertShortEquals((short)32767, $opt$noinline$CharToShort((char)-32769)); // -(2^15 + 1)
}
private static void byteToChar() {
- assertCharEquals((char)1, $opt$ByteToChar((byte)1));
- assertCharEquals((char)0, $opt$ByteToChar((byte)0));
- assertCharEquals((char)65535, $opt$ByteToChar((byte)-1));
- assertCharEquals((char)51, $opt$ByteToChar((byte)51));
- assertCharEquals((char)65485, $opt$ByteToChar((byte)-51));
- assertCharEquals((char)127, $opt$ByteToChar((byte)127)); // 2^7 - 1
- assertCharEquals((char)65409, $opt$ByteToChar((byte)-127)); // -(2^7 - 1)
- assertCharEquals((char)65408, $opt$ByteToChar((byte)-128)); // -(2^7)
+ assertCharEquals((char)1, $opt$noinline$ByteToChar((byte)1));
+ assertCharEquals((char)0, $opt$noinline$ByteToChar((byte)0));
+ assertCharEquals((char)65535, $opt$noinline$ByteToChar((byte)-1));
+ assertCharEquals((char)51, $opt$noinline$ByteToChar((byte)51));
+ assertCharEquals((char)65485, $opt$noinline$ByteToChar((byte)-51));
+ assertCharEquals((char)127, $opt$noinline$ByteToChar((byte)127)); // 2^7 - 1
+ assertCharEquals((char)65409, $opt$noinline$ByteToChar((byte)-127)); // -(2^7 - 1)
+ assertCharEquals((char)65408, $opt$noinline$ByteToChar((byte)-128)); // -(2^7)
}
private static void shortToChar() {
- assertCharEquals((char)1, $opt$ShortToChar((short)1));
- assertCharEquals((char)0, $opt$ShortToChar((short)0));
- assertCharEquals((char)65535, $opt$ShortToChar((short)-1));
- assertCharEquals((char)51, $opt$ShortToChar((short)51));
- assertCharEquals((char)65485, $opt$ShortToChar((short)-51));
- assertCharEquals((char)32767, $opt$ShortToChar((short)32767)); // 2^15 - 1
- assertCharEquals((char)32769, $opt$ShortToChar((short)-32767)); // -(2^15 - 1)
- assertCharEquals((char)32768, $opt$ShortToChar((short)-32768)); // -(2^15)
+ assertCharEquals((char)1, $opt$noinline$ShortToChar((short)1));
+ assertCharEquals((char)0, $opt$noinline$ShortToChar((short)0));
+ assertCharEquals((char)65535, $opt$noinline$ShortToChar((short)-1));
+ assertCharEquals((char)51, $opt$noinline$ShortToChar((short)51));
+ assertCharEquals((char)65485, $opt$noinline$ShortToChar((short)-51));
+ assertCharEquals((char)32767, $opt$noinline$ShortToChar((short)32767)); // 2^15 - 1
+ assertCharEquals((char)32769, $opt$noinline$ShortToChar((short)-32767)); // -(2^15 - 1)
+ assertCharEquals((char)32768, $opt$noinline$ShortToChar((short)-32768)); // -(2^15)
}
private static void intToChar() {
- assertCharEquals((char)1, $opt$IntToChar(1));
- assertCharEquals((char)0, $opt$IntToChar(0));
- assertCharEquals((char)65535, $opt$IntToChar(-1));
- assertCharEquals((char)51, $opt$IntToChar(51));
- assertCharEquals((char)65485, $opt$IntToChar(-51));
- assertCharEquals((char)32767, $opt$IntToChar(32767)); // 2^15 - 1
- assertCharEquals((char)32769, $opt$IntToChar(-32767)); // -(2^15 - 1)
- assertCharEquals((char)32768, $opt$IntToChar(32768)); // 2^15
- assertCharEquals((char)32768, $opt$IntToChar(-32768)); // -(2^15)
- assertCharEquals((char)65535, $opt$IntToChar(65535)); // 2^16 - 1
- assertCharEquals((char)1, $opt$IntToChar(-65535)); // -(2^16 - 1)
- assertCharEquals((char)0, $opt$IntToChar(65536)); // 2^16
- assertCharEquals((char)0, $opt$IntToChar(-65536)); // -(2^16)
- assertCharEquals((char)65535, $opt$IntToChar(2147483647)); // 2^31 - 1
- assertCharEquals((char)0, $opt$IntToChar(-2147483648)); // -(2^31)
+ assertCharEquals((char)1, $opt$noinline$IntToChar(1));
+ assertCharEquals((char)0, $opt$noinline$IntToChar(0));
+ assertCharEquals((char)65535, $opt$noinline$IntToChar(-1));
+ assertCharEquals((char)51, $opt$noinline$IntToChar(51));
+ assertCharEquals((char)65485, $opt$noinline$IntToChar(-51));
+ assertCharEquals((char)32767, $opt$noinline$IntToChar(32767)); // 2^15 - 1
+ assertCharEquals((char)32769, $opt$noinline$IntToChar(-32767)); // -(2^15 - 1)
+ assertCharEquals((char)32768, $opt$noinline$IntToChar(32768)); // 2^15
+ assertCharEquals((char)32768, $opt$noinline$IntToChar(-32768)); // -(2^15)
+ assertCharEquals((char)65535, $opt$noinline$IntToChar(65535)); // 2^16 - 1
+ assertCharEquals((char)1, $opt$noinline$IntToChar(-65535)); // -(2^16 - 1)
+ assertCharEquals((char)0, $opt$noinline$IntToChar(65536)); // 2^16
+ assertCharEquals((char)0, $opt$noinline$IntToChar(-65536)); // -(2^16)
+ assertCharEquals((char)65535, $opt$noinline$IntToChar(2147483647)); // 2^31 - 1
+ assertCharEquals((char)0, $opt$noinline$IntToChar(-2147483648)); // -(2^31)
}
// A dummy value to defeat inlining of these routines.
static boolean doThrow = false;
// These methods produce int-to-long Dex instructions.
- static long $opt$ByteToLong(byte a) { if (doThrow) throw new Error(); return (long)a; }
- static long $opt$ShortToLong(short a) { if (doThrow) throw new Error(); return (long)a; }
- static long $opt$IntToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
- static long $opt$CharToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
+ static long $opt$noinline$ByteToLong(byte a) { if (doThrow) throw new Error(); return (long)a; }
+ static long $opt$noinline$ShortToLong(short a) { if (doThrow) throw new Error(); return (long)a; }
+ static long $opt$noinline$IntToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
+ static long $opt$noinline$CharToLong(int a) { if (doThrow) throw new Error(); return (long)a; }
// These methods produce int-to-float Dex instructions.
- static float $opt$ByteToFloat(byte a) { if (doThrow) throw new Error(); return (float)a; }
- static float $opt$ShortToFloat(short a) { if (doThrow) throw new Error(); return (float)a; }
- static float $opt$IntToFloat(int a) { if (doThrow) throw new Error(); return (float)a; }
- static float $opt$CharToFloat(char a) { if (doThrow) throw new Error(); return (float)a; }
+ static float $opt$noinline$ByteToFloat(byte a) { if (doThrow) throw new Error(); return (float)a; }
+ static float $opt$noinline$ShortToFloat(short a) { if (doThrow) throw new Error(); return (float)a; }
+ static float $opt$noinline$IntToFloat(int a) { if (doThrow) throw new Error(); return (float)a; }
+ static float $opt$noinline$CharToFloat(char a) { if (doThrow) throw new Error(); return (float)a; }
// These methods produce int-to-double Dex instructions.
- static double $opt$ByteToDouble(byte a) { if (doThrow) throw new Error(); return (double)a; }
- static double $opt$ShortToDouble(short a) { if (doThrow) throw new Error(); return (double)a; }
- static double $opt$IntToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
- static double $opt$CharToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
+ static double $opt$noinline$ByteToDouble(byte a) { if (doThrow) throw new Error(); return (double)a; }
+ static double $opt$noinline$ShortToDouble(short a) { if (doThrow) throw new Error(); return (double)a; }
+ static double $opt$noinline$IntToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
+ static double $opt$noinline$CharToDouble(int a) { if (doThrow) throw new Error(); return (double)a; }
// These methods produce long-to-int Dex instructions.
- static int $opt$LongToInt(long a) { if (doThrow) throw new Error(); return (int)a; }
- static int $opt$LongLiteralToInt() { if (doThrow) throw new Error(); return (int)42L; }
+ static int $opt$noinline$LongToInt(long a) { if (doThrow) throw new Error(); return (int)a; }
+ static int $opt$noinline$LongLiteralToInt() { if (doThrow) throw new Error(); return (int)42L; }
// This method produces a long-to-float Dex instruction.
- static float $opt$LongToFloat(long a) { if (doThrow) throw new Error(); return (float)a; }
+ static float $opt$noinline$LongToFloat(long a) { if (doThrow) throw new Error(); return (float)a; }
// This method produces a long-to-double Dex instruction.
- static double $opt$LongToDouble(long a) { if (doThrow) throw new Error(); return (double)a; }
+ static double $opt$noinline$LongToDouble(long a) { if (doThrow) throw new Error(); return (double)a; }
// This method produces a float-to-int Dex instruction.
- static int $opt$FloatToInt(float a) { if (doThrow) throw new Error(); return (int)a; }
+ static int $opt$noinline$FloatToInt(float a) { if (doThrow) throw new Error(); return (int)a; }
// This method produces a float-to-long Dex instruction.
- static long $opt$FloatToLong(float a){ if (doThrow) throw new Error(); return (long)a; }
+ static long $opt$noinline$FloatToLong(float a){ if (doThrow) throw new Error(); return (long)a; }
// This method produces a float-to-double Dex instruction.
- static double $opt$FloatToDouble(float a) { if (doThrow) throw new Error(); return (double)a; }
+ static double $opt$noinline$FloatToDouble(float a) { if (doThrow) throw new Error(); return (double)a; }
// This method produces a double-to-int Dex instruction.
- static int $opt$DoubleToInt(double a){ if (doThrow) throw new Error(); return (int)a; }
+ static int $opt$noinline$DoubleToInt(double a){ if (doThrow) throw new Error(); return (int)a; }
// This method produces a double-to-long Dex instruction.
- static long $opt$DoubleToLong(double a){ if (doThrow) throw new Error(); return (long)a; }
+ static long $opt$noinline$DoubleToLong(double a){ if (doThrow) throw new Error(); return (long)a; }
// This method produces a double-to-float Dex instruction.
- static float $opt$DoubleToFloat(double a) { if (doThrow) throw new Error(); return (float)a; }
+ static float $opt$noinline$DoubleToFloat(double a) { if (doThrow) throw new Error(); return (float)a; }
// These methods produce int-to-byte Dex instructions.
- static byte $opt$ShortToByte(short a) { if (doThrow) throw new Error(); return (byte)a; }
- static byte $opt$IntToByte(int a) { if (doThrow) throw new Error(); return (byte)a; }
- static byte $opt$CharToByte(char a) { if (doThrow) throw new Error(); return (byte)a; }
+ static byte $opt$noinline$ShortToByte(short a) { if (doThrow) throw new Error(); return (byte)a; }
+ static byte $opt$noinline$IntToByte(int a) { if (doThrow) throw new Error(); return (byte)a; }
+ static byte $opt$noinline$CharToByte(char a) { if (doThrow) throw new Error(); return (byte)a; }
// These methods produce int-to-short Dex instructions.
- static short $opt$ByteToShort(byte a) { if (doThrow) throw new Error(); return (short)a; }
- static short $opt$IntToShort(int a) { if (doThrow) throw new Error(); return (short)a; }
- static short $opt$CharToShort(char a) { if (doThrow) throw new Error(); return (short)a; }
+ static short $opt$noinline$ByteToShort(byte a) { if (doThrow) throw new Error(); return (short)a; }
+ static short $opt$noinline$IntToShort(int a) { if (doThrow) throw new Error(); return (short)a; }
+ static short $opt$noinline$CharToShort(char a) { if (doThrow) throw new Error(); return (short)a; }
// These methods produce int-to-char Dex instructions.
- static char $opt$ByteToChar(byte a) { if (doThrow) throw new Error(); return (char)a; }
- static char $opt$ShortToChar(short a) { if (doThrow) throw new Error(); return (char)a; }
- static char $opt$IntToChar(int a) { if (doThrow) throw new Error(); return (char)a; }
+ static char $opt$noinline$ByteToChar(byte a) { if (doThrow) throw new Error(); return (char)a; }
+ static char $opt$noinline$ShortToChar(short a) { if (doThrow) throw new Error(); return (char)a; }
+ static char $opt$noinline$IntToChar(int a) { if (doThrow) throw new Error(); return (char)a; }
}
diff --git a/test/441-checker-inliner/src/Main.java b/test/441-checker-inliner/src/Main.java
index df969a4..3899d7f 100644
--- a/test/441-checker-inliner/src/Main.java
+++ b/test/441-checker-inliner/src/Main.java
@@ -19,7 +19,7 @@
/// CHECK-START: void Main.InlineVoid() inliner (before)
/// CHECK-DAG: <<Const42:i\d+>> IntConstant 42
/// CHECK-DAG: InvokeStaticOrDirect
- /// CHECK-DAG: InvokeStaticOrDirect [<<Const42>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [<<Const42>>,{{[ij]\d+}}]
/// CHECK-START: void Main.InlineVoid() inliner (after)
/// CHECK-NOT: InvokeStaticOrDirect
@@ -31,7 +31,7 @@
/// CHECK-START: int Main.InlineParameter(int) inliner (before)
/// CHECK-DAG: <<Param:i\d+>> ParameterValue
- /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>]
+ /// CHECK-DAG: <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: int Main.InlineParameter(int) inliner (after)
@@ -44,7 +44,7 @@
/// CHECK-START: long Main.InlineWideParameter(long) inliner (before)
/// CHECK-DAG: <<Param:j\d+>> ParameterValue
- /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>]
+ /// CHECK-DAG: <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: long Main.InlineWideParameter(long) inliner (after)
@@ -57,7 +57,7 @@
/// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
/// CHECK-DAG: <<Param:l\d+>> ParameterValue
- /// CHECK-DAG: <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>]
+ /// CHECK-DAG: <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>,{{[ij]\d+}}]
/// CHECK-DAG: Return [<<Result>>]
/// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
@@ -130,8 +130,8 @@
/// CHECK-DAG: <<Const1:i\d+>> IntConstant 1
/// CHECK-DAG: <<Const3:i\d+>> IntConstant 3
/// CHECK-DAG: <<Const5:i\d+>> IntConstant 5
- /// CHECK-DAG: <<Add:i\d+>> InvokeStaticOrDirect [<<Const1>>,<<Const3>>]
- /// CHECK-DAG: <<Sub:i\d+>> InvokeStaticOrDirect [<<Const5>>,<<Const3>>]
+ /// CHECK-DAG: <<Add:i\d+>> InvokeStaticOrDirect [<<Const1>>,<<Const3>>,{{[ij]\d+}}]
+ /// CHECK-DAG: <<Sub:i\d+>> InvokeStaticOrDirect [<<Const5>>,<<Const3>>,{{[ij]\d+}}]
/// CHECK-DAG: <<Phi:i\d+>> Phi [<<Add>>,<<Sub>>]
/// CHECK-DAG: Return [<<Phi>>]
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index 9bf7cdf..4056275 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -16,25 +16,25 @@
interface Interface {
- void f();
+ void $noinline$f();
}
class Super implements Interface {
- public void f() {
+ public void $noinline$f() {
throw new RuntimeException();
}
}
class SubclassA extends Super {
- public void f() {
+ public void $noinline$f() {
throw new RuntimeException();
}
- public String h() {
+ public String $noinline$h() {
throw new RuntimeException();
}
- void g() {
+ void $noinline$g() {
throw new RuntimeException();
}
}
@@ -43,11 +43,11 @@
}
class SubclassB extends Super {
- public void f() {
+ public void $noinline$f() {
throw new RuntimeException();
}
- void g() {
+ void $noinline$g() {
throw new RuntimeException();
}
}
@@ -61,7 +61,7 @@
/// CHECK-NOT: CheckCast
public void testSimpleRemove() {
Super s = new SubclassA();
- ((SubclassA)s).g();
+ ((SubclassA)s).$noinline$g();
}
/// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier_after_types (before)
@@ -70,7 +70,7 @@
/// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier_after_types (after)
/// CHECK: CheckCast
public void testSimpleKeep(Super s) {
- ((SubclassA)s).f();
+ ((SubclassA)s).$noinline$f();
}
/// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier_after_types (before)
@@ -90,7 +90,7 @@
/// CHECK: CheckCast
public String testClassKeep() {
Object s = SubclassA.class;
- return ((SubclassA)s).h();
+ return ((SubclassA)s).$noinline$h();
}
/// CHECK-START: void Main.testIfRemove(int) instruction_simplifier_after_types (before)
@@ -105,7 +105,7 @@
} else {
s = new SubclassC();
}
- ((SubclassA)s).g();
+ ((SubclassA)s).$noinline$g();
}
/// CHECK-START: void Main.testIfKeep(int) instruction_simplifier_after_types (before)
@@ -120,7 +120,7 @@
} else {
s = new SubclassB();
}
- ((SubclassA)s).g();
+ ((SubclassA)s).$noinline$g();
}
/// CHECK-START: void Main.testForRemove(int) instruction_simplifier_after_types (before)
@@ -135,7 +135,7 @@
s = new SubclassC();
}
}
- ((SubclassA)s).g();
+ ((SubclassA)s).$noinline$g();
}
/// CHECK-START: void Main.testForKeep(int) instruction_simplifier_after_types (before)
@@ -150,7 +150,7 @@
s = new SubclassC();
}
}
- ((SubclassC)s).g();
+ ((SubclassC)s).$noinline$g();
}
/// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier_after_types (before)
@@ -165,7 +165,7 @@
} else {
x = newObject(); // this one will have an unknown type.
}
- ((SubclassC)x).g();
+ ((SubclassC)x).$noinline$g();
}
/// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier_after_types (before)
@@ -176,10 +176,10 @@
/// CHECK-NOT: CheckCast
public void testInstanceOf(Object o) {
if (o instanceof SubclassC) {
- ((SubclassC)o).g();
+ ((SubclassC)o).$noinline$g();
}
if (o instanceof SubclassB) {
- ((SubclassB)o).g();
+ ((SubclassB)o).$noinline$g();
}
}
@@ -192,10 +192,10 @@
/// CHECK: CheckCast
public void testInstanceOfKeep(Object o) {
if (o instanceof SubclassC) {
- ((SubclassB)o).g();
+ ((SubclassB)o).$noinline$g();
}
if (o instanceof SubclassB) {
- ((SubclassA)o).g();
+ ((SubclassA)o).$noinline$g();
}
}
@@ -208,9 +208,9 @@
public void testInstanceOfNested(Object o) {
if (o instanceof SubclassC) {
if (o instanceof SubclassB) {
- ((SubclassB)o).g();
+ ((SubclassB)o).$noinline$g();
} else {
- ((SubclassC)o).g();
+ ((SubclassC)o).$noinline$g();
}
}
}
@@ -229,7 +229,7 @@
}
if (o instanceof SubclassB) {
- ((SubclassB)o).g();
+ ((SubclassB)o).$noinline$g();
}
}
@@ -245,7 +245,7 @@
o = new SubclassB();
}
if (o instanceof SubclassB) {
- ((SubclassB)o).g();
+ ((SubclassB)o).$noinline$g();
}
}
}
@@ -258,7 +258,7 @@
public void testInstanceOfSubclass() {
Object o = new SubclassA();
if (o instanceof Super) {
- ((SubclassA)o).g();
+ ((SubclassA)o).$noinline$g();
}
}
@@ -276,7 +276,7 @@
}
if (o instanceof Super) {
- ((SubclassA)o).g();
+ ((SubclassA)o).$noinline$g();
}
}
@@ -294,7 +294,7 @@
}
if (o instanceof Super) {
- ((Super)o).f();
+ ((Super)o).$noinline$f();
}
}
@@ -307,7 +307,7 @@
Object o = new SubclassA();
for (int i = 0; i < n; i++) {
if (o instanceof Super) {
- ((SubclassA)o).g();
+ ((SubclassA)o).$noinline$g();
}
if (i / 2 == 0) {
o = new SubclassC();
@@ -324,7 +324,7 @@
Object o = new SubclassA();
for (int i = 0; i < n; i++) {
if (o instanceof Super) {
- ((Super)o).f();
+ ((Super)o).$noinline$f();
}
if (i / 2 == 0) {
o = new Object();
@@ -351,7 +351,7 @@
public void testInstanceFieldGetSimpleRemove() {
Main m = new Main();
Super a = m.a;
- ((SubclassA)a).g();
+ ((SubclassA)a).$noinline$g();
}
/// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier_after_types (before)
@@ -361,7 +361,7 @@
/// CHECK-NOT: CheckCast
public void testStaticFieldGetSimpleRemove() {
Super b = Main.b;
- ((SubclassA)b).g();
+ ((SubclassA)b).$noinline$g();
}
public static void main(String[] args) {
diff --git a/test/451-spill-splot/src/Main.java b/test/451-spill-splot/src/Main.java
index f631ebd..b2f39f3 100644
--- a/test/451-spill-splot/src/Main.java
+++ b/test/451-spill-splot/src/Main.java
@@ -48,37 +48,37 @@
for (int count = 0; count < 2; count++) {
System.out.println(aa + bb + cc + dd + ee + ff + gg + hh + ii + jj + kk + ll + mm + nn);
System.out.println(a + b + c + d + e + f + g + h + i + j);
- a = computeDouble();
- b = computeDouble();
- c = computeDouble();
- d = computeDouble();
- e = computeDouble();
- f = computeDouble();
- g = computeDouble();
- h = computeDouble();
- i = computeDouble();
- j = computeDouble();
+ a = $noinline$computeDouble();
+ b = $noinline$computeDouble();
+ c = $noinline$computeDouble();
+ d = $noinline$computeDouble();
+ e = $noinline$computeDouble();
+ f = $noinline$computeDouble();
+ g = $noinline$computeDouble();
+ h = $noinline$computeDouble();
+ i = $noinline$computeDouble();
+ j = $noinline$computeDouble();
System.out.println(a + b + c + d + e + f + g + h + i + j);
- aa = computeFloat();
- bb = computeFloat();
- cc = computeFloat();
- dd = computeFloat();
- ee = computeFloat();
- ff = computeFloat();
- gg = computeFloat();
- hh = computeFloat();
- ii = computeFloat();
- jj = computeFloat();
- kk = computeFloat();
- ll = computeFloat();
- mm = computeFloat();
- nn = computeFloat();
+ aa = $noinline$computeFloat();
+ bb = $noinline$computeFloat();
+ cc = $noinline$computeFloat();
+ dd = $noinline$computeFloat();
+ ee = $noinline$computeFloat();
+ ff = $noinline$computeFloat();
+ gg = $noinline$computeFloat();
+ hh = $noinline$computeFloat();
+ ii = $noinline$computeFloat();
+ jj = $noinline$computeFloat();
+ kk = $noinline$computeFloat();
+ ll = $noinline$computeFloat();
+ mm = $noinline$computeFloat();
+ nn = $noinline$computeFloat();
}
}
static boolean doThrow = false;
- public static double computeDouble() {
+ public static double $noinline$computeDouble() {
if (doThrow) {
// Try defeating inlining.
throw new Error();
@@ -86,7 +86,7 @@
return 2.0;
}
- public static float computeFloat() {
+ public static float $noinline$computeFloat() {
if (doThrow) {
// Try defeating inlining.
throw new Error();
diff --git a/test/478-checker-clinit-check-pruning/src/Main.java b/test/478-checker-clinit-check-pruning/src/Main.java
index 51be912..e6aab63 100644
--- a/test/478-checker-clinit-check-pruning/src/Main.java
+++ b/test/478-checker-clinit-check-pruning/src/Main.java
@@ -26,7 +26,7 @@
/// CHECK-START: void Main.invokeStaticInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
@@ -69,12 +69,12 @@
/// CHECK-START: void Main.invokeStaticNotInlined() builder (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
/// CHECK-START: void Main.invokeStaticNotInlined() inliner (after)
/// CHECK-DAG: <<LoadClass:l\d+>> LoadClass gen_clinit_check:false
/// CHECK-DAG: <<ClinitCheck:l\d+>> ClinitCheck [<<LoadClass>>]
- /// CHECK-DAG: InvokeStaticOrDirect [<<ClinitCheck>>]
+ /// CHECK-DAG: InvokeStaticOrDirect [{{[ij]\d+}},<<ClinitCheck>>]
// The following checks ensure the clinit check and load class
// instructions added by the builder are pruned by the
@@ -90,7 +90,7 @@
/// CHECK-NOT: ClinitCheck
static void invokeStaticNotInlined() {
- ClassWithClinit2.staticMethod();
+ ClassWithClinit2.$noinline$staticMethod();
}
static class ClassWithClinit2 {
@@ -100,7 +100,7 @@
static boolean doThrow = false;
- static void staticMethod() {
+ static void $noinline$staticMethod() {
if (doThrow) {
// Try defeating inlining.
throw new Error();
@@ -169,7 +169,7 @@
// initialization of ClassWithClinit4, meaning that the
// call to staticMethod below does not need a clinit
// check.
- staticMethod();
+ $noinline$staticMethod();
}
static {
@@ -178,7 +178,7 @@
static boolean doThrow = false;
- static void staticMethod() {
+ static void $noinline$staticMethod() {
if (doThrow) {
// Try defeating inlining.
throw new Error();
@@ -242,7 +242,7 @@
static class ClassWithClinit6 {
static boolean doThrow = false;
- static void staticMethod() {
+ static void $noinline$staticMethod() {
if (doThrow) {
// Try defeating inlining.
throw new Error();
@@ -256,7 +256,7 @@
static class SubClassOfClassWithClinit6 extends ClassWithClinit6 {
static void invokeStaticNotInlined() {
- ClassWithClinit6.staticMethod();
+ ClassWithClinit6.$noinline$staticMethod();
}
}
@@ -276,7 +276,7 @@
/// CHECK-NOT: ClinitCheck
static void noClinitBecauseOfInvokeStatic() {
- ClassWithClinit2.staticMethod();
+ ClassWithClinit2.$noinline$staticMethod();
ClassWithClinit2.doThrow = false;
}
@@ -295,7 +295,7 @@
/// CHECK-NOT: ClinitCheck
static void clinitBecauseOfFieldAccess() {
ClassWithClinit2.doThrow = false;
- ClassWithClinit2.staticMethod();
+ ClassWithClinit2.$noinline$staticMethod();
}
// TODO: Add a test for the case of a static method whose declaring
diff --git a/test/486-checker-must-do-null-check/src/Main.java b/test/486-checker-must-do-null-check/src/Main.java
index ea72718..e8ff6a4 100644
--- a/test/486-checker-must-do-null-check/src/Main.java
+++ b/test/486-checker-must-do-null-check/src/Main.java
@@ -36,16 +36,16 @@
/// CHECK: CheckCast must_do_null_check:false
public void CheckCastPreChecked(Object o) {
o.toString();
- ((Main)o).Bar();
+ ((Main)o).$noinline$Bar();
}
/// CHECK-START: void Main.CheckCast(java.lang.Object) instruction_simplifier (after)
/// CHECK: CheckCast must_do_null_check:true
public void CheckCast(Object o) {
- ((Main)o).Bar();
+ ((Main)o).$noinline$Bar();
}
- void Bar() {throw new RuntimeException();}
+ void $noinline$Bar() {throw new RuntimeException();}
public static void main(String[] sa) {
Main t = new Main();