Replace String.charAt() with HIR.
Replace String.charAt() with HArrayLength, HBoundsCheck and
HArrayGet. This allows GVN on the HArrayLength and BCE on
the HBoundsCheck as well as using the infrastructure for
HArrayGet, i.e. better handling of constant indexes than
the old intrinsic and using the HArm64IntermediateAddress.
Bug: 28330359
Change-Id: I32bf1da7eeafe82537a60416abf6ac412baa80dc
diff --git a/compiler/optimizing/code_generator_arm.cc b/compiler/optimizing/code_generator_arm.cc
index eca9e2c..e629a8e 100644
--- a/compiler/optimizing/code_generator_arm.cc
+++ b/compiler/optimizing/code_generator_arm.cc
@@ -176,8 +176,11 @@
locations->InAt(1),
Location::RegisterLocation(calling_convention.GetRegisterAt(1)),
Primitive::kPrimInt);
- arm_codegen->InvokeRuntime(
- QUICK_ENTRY_POINT(pThrowArrayBounds), instruction_, instruction_->GetDexPc(), this);
+ uint32_t entry_point_offset = instruction_->AsBoundsCheck()->IsStringCharAt()
+ ? QUICK_ENTRY_POINT(pThrowStringBounds)
+ : QUICK_ENTRY_POINT(pThrowArrayBounds);
+ arm_codegen->InvokeRuntime(entry_point_offset, instruction_, instruction_->GetDexPc(), this);
+ CheckEntrypointTypes<kQuickThrowStringBounds, void, int32_t, int32_t>();
CheckEntrypointTypes<kQuickThrowArrayBounds, void, int32_t, int32_t>();
}
@@ -4286,11 +4289,11 @@
Register obj = obj_loc.AsRegister<Register>();
Location index = locations->InAt(1);
Location out_loc = locations->Out();
+ uint32_t data_offset = CodeGenerator::GetArrayDataOffset(instruction);
Primitive::Type type = instruction->GetType();
switch (type) {
case Primitive::kPrimBoolean: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint8_t)).Uint32Value();
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -4304,7 +4307,6 @@
}
case Primitive::kPrimByte: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(int8_t)).Uint32Value();
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -4318,7 +4320,6 @@
}
case Primitive::kPrimShort: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(int16_t)).Uint32Value();
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -4332,7 +4333,6 @@
}
case Primitive::kPrimChar: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(uint16_t)).Uint32Value();
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -4346,7 +4346,6 @@
}
case Primitive::kPrimInt: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
Register out = out_loc.AsRegister<Register>();
if (index.IsConstant()) {
size_t offset =
@@ -4363,7 +4362,6 @@
static_assert(
sizeof(mirror::HeapReference<mirror::Object>) == sizeof(int32_t),
"art::mirror::HeapReference<art::mirror::Object> and int32_t have different sizes.");
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(int32_t)).Uint32Value();
// /* HeapReference<Object> */ out =
// *(obj + data_offset + index * sizeof(HeapReference<Object>))
if (kEmitCompilerReadBarrier && kUseBakerReadBarrier) {
@@ -4398,7 +4396,6 @@
}
case Primitive::kPrimLong: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(int64_t)).Uint32Value();
if (index.IsConstant()) {
size_t offset =
(index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;
@@ -4411,7 +4408,6 @@
}
case Primitive::kPrimFloat: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(float)).Uint32Value();
SRegister out = out_loc.AsFpuRegister<SRegister>();
if (index.IsConstant()) {
size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_4) + data_offset;
@@ -4424,7 +4420,6 @@
}
case Primitive::kPrimDouble: {
- uint32_t data_offset = mirror::Array::DataOffset(sizeof(double)).Uint32Value();
SRegister out = out_loc.AsFpuRegisterPairLow<SRegister>();
if (index.IsConstant()) {
size_t offset = (index.GetConstant()->AsIntConstant()->GetValue() << TIMES_8) + data_offset;