namespace art {
-/**
- * Helper class to add HTemporary instructions. This class is used when
- * converting a DEX instruction to multiple HInstruction, and where those
- * instructions do not die at the following instruction, but instead spans
- * multiple instructions.
- */
-class Temporaries : public ValueObject {
- public:
- explicit Temporaries(HGraph* graph) : graph_(graph), index_(0) {}
-
- void Add(HInstruction* instruction) {
- HInstruction* temp = new (graph_->GetArena()) HTemporary(index_, instruction->GetDexPc());
- instruction->GetBlock()->AddInstruction(temp);
-
- DCHECK(temp->GetPrevious() == instruction);
-
- size_t offset;
- if (instruction->GetType() == Primitive::kPrimLong
- || instruction->GetType() == Primitive::kPrimDouble) {
- offset = 2;
- } else {
- offset = 1;
- }
- index_ += offset;
-
- graph_->UpdateTemporariesVRegSlots(index_);
- }
-
- private:
- HGraph* const graph_;
-
- // Current index in the temporary stack, updated by `Add`.
- size_t index_;
-};
-
void HGraphBuilder::InitializeLocals(uint16_t count) {
graph_->SetNumberOfVRegs(count);
locals_.resize(count);
size_t start_index = 0;
size_t argument_index = 0;
if (invoke->GetOriginalInvokeType() != InvokeType::kStatic) { // Instance call.
- Temporaries temps(graph_);
HInstruction* arg = LoadLocal(
is_range ? register_index : args[0], Primitive::kPrimNot, invoke->GetDexPc());
HNullCheck* null_check = new (arena_) HNullCheck(arg, invoke->GetDexPc());
current_block_->AddInstruction(null_check);
- temps.Add(null_check);
invoke->SetArgumentAt(0, null_check);
start_index = 1;
argument_index = 1;
? GetFieldAccessType(*dex_file_, field_index)
: resolved_field->GetTypeAsPrimitiveType();
if (is_put) {
- Temporaries temps(graph_);
- // We need one temporary for the null check.
- temps.Add(null_check);
HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc);
HInstruction* field_set = nullptr;
if (resolved_field == nullptr) {
uint16_t class_def_index = klass->GetDexClassDefIndex();
if (is_put) {
// We need to keep the class alive before loading the value.
- Temporaries temps(graph_);
- temps.Add(cls);
HInstruction* value = LoadLocal(source_or_dest_reg, field_type, dex_pc);
DCHECK_EQ(value->GetType(), field_type);
current_block_->AddInstruction(new (arena_) HStaticFieldSet(cls,
|| (type == Primitive::kPrimInt && second->AsIntConstant()->GetValue() == 0)
|| (type == Primitive::kPrimLong && second->AsLongConstant()->GetValue() == 0)) {
second = new (arena_) HDivZeroCheck(second, dex_pc);
- Temporaries temps(graph_);
current_block_->AddInstruction(second);
- temps.Add(current_block_->GetLastInstruction());
}
if (isDiv) {
uint8_t array_reg = instruction.VRegB_23x();
uint8_t index_reg = instruction.VRegC_23x();
- // We need one temporary for the null check, one for the index, and one for the length.
- Temporaries temps(graph_);
-
HInstruction* object = LoadLocal(array_reg, Primitive::kPrimNot, dex_pc);
object = new (arena_) HNullCheck(object, dex_pc);
current_block_->AddInstruction(object);
- temps.Add(object);
HInstruction* length = new (arena_) HArrayLength(object, dex_pc);
current_block_->AddInstruction(length);
- temps.Add(length);
HInstruction* index = LoadLocal(index_reg, Primitive::kPrimInt, dex_pc);
index = new (arena_) HBoundsCheck(index, length, dex_pc);
current_block_->AddInstruction(index);
- temps.Add(index);
if (is_put) {
HInstruction* value = LoadLocal(source_or_dest_reg, anticipated_type, dex_pc);
// TODO: Insert a type check node if the type is Object.
bool is_reference_array = (primitive == 'L') || (primitive == '[');
Primitive::Type type = is_reference_array ? Primitive::kPrimNot : Primitive::kPrimInt;
- Temporaries temps(graph_);
- temps.Add(object);
for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type, dex_pc);
HInstruction* index = graph_->GetIntConstant(i, dex_pc);
}
void HGraphBuilder::BuildFillArrayData(const Instruction& instruction, uint32_t dex_pc) {
- Temporaries temps(graph_);
HInstruction* array = LoadLocal(instruction.VRegA_31t(), Primitive::kPrimNot, dex_pc);
HNullCheck* null_check = new (arena_) HNullCheck(array, dex_pc);
current_block_->AddInstruction(null_check);
- temps.Add(null_check);
HInstruction* length = new (arena_) HArrayLength(null_check, dex_pc);
current_block_->AddInstruction(length);
compiler_driver_->CanAssumeTypeIsPresentInDexCache(dex_file, type_index));
current_block_->AddInstruction(cls);
- // The class needs a temporary before being used by the type check.
- Temporaries temps(graph_);
- temps.Add(cls);
-
TypeCheckKind check_kind = ComputeTypeCheckKind(resolved_class);
if (instruction.Opcode() == Instruction::INSTANCE_OF) {
current_block_->AddInstruction(new (arena_) HInstanceOf(object, cls, check_kind, dex_pc));
case Instruction::ARRAY_LENGTH: {
HInstruction* object = LoadLocal(instruction.VRegB_12x(), Primitive::kPrimNot, dex_pc);
- // No need for a temporary for the null check, it is the only input of the following
- // instruction.
object = new (arena_) HNullCheck(object, dex_pc);
current_block_->AddInstruction(object);
current_block_->AddInstruction(new (arena_) HArrayLength(object, dex_pc));
}
}
-Location CodeGenerator::GetTemporaryLocation(HTemporary* temp) const {
- uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
- // The type of the previous instruction tells us if we need a single or double stack slot.
- Primitive::Type type = temp->GetType();
- int32_t temp_size = (type == Primitive::kPrimLong) || (type == Primitive::kPrimDouble) ? 2 : 1;
- // Use the temporary region (right below the dex registers).
- int32_t slot = GetFrameSize() - FrameEntrySpillSize()
- - kVRegSize // filler
- - (number_of_locals * kVRegSize)
- - ((temp_size + temp->GetIndex()) * kVRegSize);
- return temp_size == 2 ? Location::DoubleStackSlot(slot) : Location::StackSlot(slot);
-}
-
int32_t CodeGenerator::GetStackSlot(HLocal* local) const {
uint16_t reg_number = local->GetRegNumber();
uint16_t number_of_locals = GetGraph()->GetNumberOfLocalVRegs();
virtual void GenerateFrameEntry() = 0;
virtual void GenerateFrameExit() = 0;
virtual void Bind(HBasicBlock* block) = 0;
- virtual void Move(HInstruction* instruction, Location location, HInstruction* move_for) = 0;
virtual void MoveConstant(Location destination, int32_t value) = 0;
virtual void MoveLocation(Location dst, Location src, Primitive::Type dst_type) = 0;
virtual void AddLocationAsTemp(Location location, LocationSummary* locations) = 0;
size_t number_of_out_slots,
const ArenaVector<HBasicBlock*>& block_order);
int32_t GetStackSlot(HLocal* local) const;
- Location GetTemporaryLocation(HTemporary* temp) const;
uint32_t GetFrameSize() const { return frame_size_; }
void SetFrameSize(uint32_t size) { frame_size_ = size; }
}
}
-void CodeGeneratorARM::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
- LocationSummary* locations = instruction->GetLocations();
- if (instruction->IsCurrentMethod()) {
- Move32(location, Location::StackSlot(kCurrentMethodStackOffset));
- } else if (locations != nullptr && locations->Out().Equals(location)) {
- return;
- } else if (locations != nullptr && locations->Out().IsConstant()) {
- HConstant* const_to_move = locations->Out().GetConstant();
- if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
- int32_t value = GetInt32ValueOf(const_to_move);
- if (location.IsRegister()) {
- __ LoadImmediate(location.AsRegister<Register>(), value);
- } else {
- DCHECK(location.IsStackSlot());
- __ LoadImmediate(IP, value);
- __ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex());
- }
- } else {
- DCHECK(const_to_move->IsLongConstant()) << const_to_move->DebugName();
- int64_t value = const_to_move->AsLongConstant()->GetValue();
- if (location.IsRegisterPair()) {
- __ LoadImmediate(location.AsRegisterPairLow<Register>(), Low32Bits(value));
- __ LoadImmediate(location.AsRegisterPairHigh<Register>(), High32Bits(value));
- } else {
- DCHECK(location.IsDoubleStackSlot());
- __ LoadImmediate(IP, Low32Bits(value));
- __ StoreToOffset(kStoreWord, IP, SP, location.GetStackIndex());
- __ LoadImmediate(IP, High32Bits(value));
- __ StoreToOffset(kStoreWord, IP, SP, location.GetHighStackIndex(kArmWordSize));
- }
- }
- } else if (instruction->IsLoadLocal()) {
- uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
- switch (instruction->GetType()) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- case Primitive::kPrimInt:
- case Primitive::kPrimNot:
- case Primitive::kPrimFloat:
- Move32(location, Location::StackSlot(stack_slot));
- break;
-
- case Primitive::kPrimLong:
- case Primitive::kPrimDouble:
- Move64(location, Location::DoubleStackSlot(stack_slot));
- break;
-
- default:
- LOG(FATAL) << "Unexpected type " << instruction->GetType();
- }
- } else if (instruction->IsTemporary()) {
- Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
- if (temp_location.IsStackSlot()) {
- Move32(location, temp_location);
- } else {
- DCHECK(temp_location.IsDoubleStackSlot());
- Move64(location, temp_location);
- }
- } else {
- DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
- switch (instruction->GetType()) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- case Primitive::kPrimNot:
- case Primitive::kPrimInt:
- case Primitive::kPrimFloat:
- Move32(location, locations->Out());
- break;
-
- case Primitive::kPrimLong:
- case Primitive::kPrimDouble:
- Move64(location, locations->Out());
- break;
-
- default:
- LOG(FATAL) << "Unexpected type " << instruction->GetType();
- }
- }
-}
-
void CodeGeneratorARM::MoveConstant(Location location, int32_t value) {
DCHECK(location.IsRegister());
__ LoadImmediate(location.AsRegister<Register>(), value);
}
}
-void LocationsBuilderARM::VisitTemporary(HTemporary* temp) {
- temp->SetLocations(nullptr);
-}
-
-void InstructionCodeGeneratorARM::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) {
- // Nothing to do, this is driven by the code generator.
-}
-
void LocationsBuilderARM::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) {
LOG(FATAL) << "Unreachable";
}
void GenerateFrameEntry() OVERRIDE;
void GenerateFrameExit() OVERRIDE;
void Bind(HBasicBlock* block) OVERRIDE;
- void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
void MoveConstant(Location destination, int32_t value) OVERRIDE;
void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
__ Bind(GetLabelOf(block));
}
-void CodeGeneratorARM64::Move(HInstruction* instruction,
- Location location,
- HInstruction* move_for) {
- LocationSummary* locations = instruction->GetLocations();
- Primitive::Type type = instruction->GetType();
- DCHECK_NE(type, Primitive::kPrimVoid);
-
- if (instruction->IsCurrentMethod()) {
- MoveLocation(location,
- Location::DoubleStackSlot(kCurrentMethodStackOffset),
- Primitive::kPrimVoid);
- } else if (locations != nullptr && locations->Out().Equals(location)) {
- return;
- } else if (instruction->IsIntConstant()
- || instruction->IsLongConstant()
- || instruction->IsNullConstant()) {
- int64_t value = GetInt64ValueOf(instruction->AsConstant());
- if (location.IsRegister()) {
- Register dst = RegisterFrom(location, type);
- DCHECK(((instruction->IsIntConstant() || instruction->IsNullConstant()) && dst.Is32Bits()) ||
- (instruction->IsLongConstant() && dst.Is64Bits()));
- __ Mov(dst, value);
- } else {
- DCHECK(location.IsStackSlot() || location.IsDoubleStackSlot());
- UseScratchRegisterScope temps(GetVIXLAssembler());
- Register temp = (instruction->IsIntConstant() || instruction->IsNullConstant())
- ? temps.AcquireW()
- : temps.AcquireX();
- __ Mov(temp, value);
- __ Str(temp, StackOperandFrom(location));
- }
- } else if (instruction->IsTemporary()) {
- Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
- MoveLocation(location, temp_location, type);
- } else if (instruction->IsLoadLocal()) {
- uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
- if (Primitive::Is64BitType(type)) {
- MoveLocation(location, Location::DoubleStackSlot(stack_slot), type);
- } else {
- MoveLocation(location, Location::StackSlot(stack_slot), type);
- }
-
- } else {
- DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
- MoveLocation(location, locations->Out(), type);
- }
-}
-
void CodeGeneratorARM64::MoveConstant(Location location, int32_t value) {
DCHECK(location.IsRegister());
__ Mov(RegisterFrom(location, Primitive::kPrimInt), value);
GenerateSuspendCheck(instruction, nullptr);
}
-void LocationsBuilderARM64::VisitTemporary(HTemporary* temp) {
- temp->SetLocations(nullptr);
-}
-
-void InstructionCodeGeneratorARM64::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) {
- // Nothing to do, this is driven by the code generator.
-}
-
void LocationsBuilderARM64::VisitThrow(HThrow* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
return CommonGetLabelOf<vixl::Label>(block_labels_, block);
}
- void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
-
size_t GetWordSize() const OVERRIDE {
return kArm64WordSize;
}
__ LoadConst32(dst, value);
}
-void CodeGeneratorMIPS::Move(HInstruction* instruction,
- Location location,
- HInstruction* move_for) {
- LocationSummary* locations = instruction->GetLocations();
- Primitive::Type type = instruction->GetType();
- DCHECK_NE(type, Primitive::kPrimVoid);
-
- if (instruction->IsCurrentMethod()) {
- Move32(location, Location::StackSlot(kCurrentMethodStackOffset));
- } else if (locations != nullptr && locations->Out().Equals(location)) {
- return;
- } else if (instruction->IsIntConstant()
- || instruction->IsLongConstant()
- || instruction->IsNullConstant()) {
- MoveConstant(location, instruction->AsConstant());
- } else if (instruction->IsTemporary()) {
- Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
- if (temp_location.IsStackSlot()) {
- Move32(location, temp_location);
- } else {
- DCHECK(temp_location.IsDoubleStackSlot());
- Move64(location, temp_location);
- }
- } else if (instruction->IsLoadLocal()) {
- uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
- if (Primitive::Is64BitType(type)) {
- Move64(location, Location::DoubleStackSlot(stack_slot));
- } else {
- Move32(location, Location::StackSlot(stack_slot));
- }
- } else {
- DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
- if (Primitive::Is64BitType(type)) {
- Move64(location, locations->Out());
- } else {
- Move32(location, locations->Out());
- }
- }
-}
-
void CodeGeneratorMIPS::AddLocationAsTemp(Location location, LocationSummary* locations) {
if (location.IsRegister()) {
locations->AddTemp(location);
GenerateSuspendCheck(instruction, nullptr);
}
-void LocationsBuilderMIPS::VisitTemporary(HTemporary* temp) {
- temp->SetLocations(nullptr);
-}
-
-void InstructionCodeGeneratorMIPS::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) {
- // Nothing to do, this is driven by the code generator.
-}
-
void LocationsBuilderMIPS::VisitThrow(HThrow* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
void Bind(HBasicBlock* block) OVERRIDE;
- void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
void Move32(Location destination, Location source);
void Move64(Location destination, Location source);
void MoveConstant(Location location, HConstant* c);
}
}
-void CodeGeneratorMIPS64::Move(HInstruction* instruction,
- Location location,
- HInstruction* move_for) {
- LocationSummary* locations = instruction->GetLocations();
- Primitive::Type type = instruction->GetType();
- DCHECK_NE(type, Primitive::kPrimVoid);
-
- if (instruction->IsCurrentMethod()) {
- MoveLocation(location, Location::DoubleStackSlot(kCurrentMethodStackOffset), type);
- } else if (locations != nullptr && locations->Out().Equals(location)) {
- return;
- } else if (instruction->IsIntConstant()
- || instruction->IsLongConstant()
- || instruction->IsNullConstant()) {
- if (location.IsRegister()) {
- // Move to GPR from constant
- GpuRegister dst = location.AsRegister<GpuRegister>();
- if (instruction->IsNullConstant() || instruction->IsIntConstant()) {
- __ LoadConst32(dst, GetInt32ValueOf(instruction->AsConstant()));
- } else {
- __ LoadConst64(dst, instruction->AsLongConstant()->GetValue());
- }
- } else {
- DCHECK(location.IsStackSlot() || location.IsDoubleStackSlot());
- // Move to stack from constant
- GpuRegister gpr = ZERO;
- if (location.IsStackSlot()) {
- int32_t value = GetInt32ValueOf(instruction->AsConstant());
- if (value != 0) {
- gpr = TMP;
- __ LoadConst32(gpr, value);
- }
- __ StoreToOffset(kStoreWord, gpr, SP, location.GetStackIndex());
- } else {
- DCHECK(location.IsDoubleStackSlot());
- int64_t value = instruction->AsLongConstant()->GetValue();
- if (value != 0) {
- gpr = TMP;
- __ LoadConst64(gpr, value);
- }
- __ StoreToOffset(kStoreDoubleword, gpr, SP, location.GetStackIndex());
- }
- }
- } else if (instruction->IsTemporary()) {
- Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
- MoveLocation(location, temp_location, type);
- } else if (instruction->IsLoadLocal()) {
- uint32_t stack_slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
- if (Primitive::Is64BitType(type)) {
- MoveLocation(location, Location::DoubleStackSlot(stack_slot), type);
- } else {
- MoveLocation(location, Location::StackSlot(stack_slot), type);
- }
- } else {
- DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
- MoveLocation(location, locations->Out(), type);
- }
-}
-
void CodeGeneratorMIPS64::MoveConstant(Location location, int32_t value) {
DCHECK(location.IsRegister());
__ LoadConst32(location.AsRegister<GpuRegister>(), value);
GenerateSuspendCheck(instruction, nullptr);
}
-void LocationsBuilderMIPS64::VisitTemporary(HTemporary* temp) {
- temp->SetLocations(nullptr);
-}
-
-void InstructionCodeGeneratorMIPS64::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) {
- // Nothing to do, this is driven by the code generator.
-}
-
void LocationsBuilderMIPS64::VisitThrow(HThrow* instruction) {
LocationSummary* locations =
new (GetGraph()->GetArena()) LocationSummary(instruction, LocationSummary::kCall);
void Bind(HBasicBlock* block) OVERRIDE;
- void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
-
size_t GetWordSize() const OVERRIDE { return kMips64DoublewordSize; }
size_t GetFloatingPointSpillSlotSize() const OVERRIDE { return kMips64DoublewordSize; }
}
}
-void CodeGeneratorX86::Move(HInstruction* instruction, Location location, HInstruction* move_for) {
- LocationSummary* locations = instruction->GetLocations();
- if (instruction->IsCurrentMethod()) {
- Move32(location, Location::StackSlot(kCurrentMethodStackOffset));
- } else if (locations != nullptr && locations->Out().Equals(location)) {
- return;
- } else if (locations != nullptr && locations->Out().IsConstant()) {
- HConstant* const_to_move = locations->Out().GetConstant();
- if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
- Immediate imm(GetInt32ValueOf(const_to_move));
- if (location.IsRegister()) {
- __ movl(location.AsRegister<Register>(), imm);
- } else if (location.IsStackSlot()) {
- __ movl(Address(ESP, location.GetStackIndex()), imm);
- } else {
- DCHECK(location.IsConstant());
- DCHECK_EQ(location.GetConstant(), const_to_move);
- }
- } else if (const_to_move->IsLongConstant()) {
- int64_t value = const_to_move->AsLongConstant()->GetValue();
- if (location.IsRegisterPair()) {
- __ movl(location.AsRegisterPairLow<Register>(), Immediate(Low32Bits(value)));
- __ movl(location.AsRegisterPairHigh<Register>(), Immediate(High32Bits(value)));
- } else if (location.IsDoubleStackSlot()) {
- __ movl(Address(ESP, location.GetStackIndex()), Immediate(Low32Bits(value)));
- __ movl(Address(ESP, location.GetHighStackIndex(kX86WordSize)),
- Immediate(High32Bits(value)));
- } else {
- DCHECK(location.IsConstant());
- DCHECK_EQ(location.GetConstant(), instruction);
- }
- }
- } else if (instruction->IsTemporary()) {
- Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
- if (temp_location.IsStackSlot()) {
- Move32(location, temp_location);
- } else {
- DCHECK(temp_location.IsDoubleStackSlot());
- Move64(location, temp_location);
- }
- } else if (instruction->IsLoadLocal()) {
- int slot = GetStackSlot(instruction->AsLoadLocal()->GetLocal());
- switch (instruction->GetType()) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- case Primitive::kPrimInt:
- case Primitive::kPrimNot:
- case Primitive::kPrimFloat:
- Move32(location, Location::StackSlot(slot));
- break;
-
- case Primitive::kPrimLong:
- case Primitive::kPrimDouble:
- Move64(location, Location::DoubleStackSlot(slot));
- break;
-
- default:
- LOG(FATAL) << "Unimplemented local type " << instruction->GetType();
- }
- } else {
- DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
- switch (instruction->GetType()) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- case Primitive::kPrimInt:
- case Primitive::kPrimNot:
- case Primitive::kPrimFloat:
- Move32(location, locations->Out());
- break;
-
- case Primitive::kPrimLong:
- case Primitive::kPrimDouble:
- Move64(location, locations->Out());
- break;
-
- default:
- LOG(FATAL) << "Unexpected type " << instruction->GetType();
- }
- }
-}
-
void CodeGeneratorX86::MoveConstant(Location location, int32_t value) {
DCHECK(location.IsRegister());
__ movl(location.AsRegister<Register>(), Immediate(value));
}
}
-void LocationsBuilderX86::VisitTemporary(HTemporary* temp) {
- temp->SetLocations(nullptr);
-}
-
-void InstructionCodeGeneratorX86::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) {
- // Nothing to do, this is driven by the code generator.
-}
-
void LocationsBuilderX86::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) {
LOG(FATAL) << "Unreachable";
}
void GenerateFrameEntry() OVERRIDE;
void GenerateFrameExit() OVERRIDE;
void Bind(HBasicBlock* block) OVERRIDE;
- void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
void MoveConstant(Location destination, int32_t value) OVERRIDE;
void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
}
}
-void CodeGeneratorX86_64::Move(HInstruction* instruction,
- Location location,
- HInstruction* move_for) {
- LocationSummary* locations = instruction->GetLocations();
- if (instruction->IsCurrentMethod()) {
- Move(location, Location::DoubleStackSlot(kCurrentMethodStackOffset));
- } else if (locations != nullptr && locations->Out().Equals(location)) {
- return;
- } else if (locations != nullptr && locations->Out().IsConstant()) {
- HConstant* const_to_move = locations->Out().GetConstant();
- if (const_to_move->IsIntConstant() || const_to_move->IsNullConstant()) {
- Immediate imm(GetInt32ValueOf(const_to_move));
- if (location.IsRegister()) {
- __ movl(location.AsRegister<CpuRegister>(), imm);
- } else if (location.IsStackSlot()) {
- __ movl(Address(CpuRegister(RSP), location.GetStackIndex()), imm);
- } else {
- DCHECK(location.IsConstant());
- DCHECK_EQ(location.GetConstant(), const_to_move);
- }
- } else if (const_to_move->IsLongConstant()) {
- int64_t value = const_to_move->AsLongConstant()->GetValue();
- if (location.IsRegister()) {
- Load64BitValue(location.AsRegister<CpuRegister>(), value);
- } else if (location.IsDoubleStackSlot()) {
- Store64BitValueToStack(location, value);
- } else {
- DCHECK(location.IsConstant());
- DCHECK_EQ(location.GetConstant(), const_to_move);
- }
- }
- } else if (instruction->IsLoadLocal()) {
- switch (instruction->GetType()) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- case Primitive::kPrimInt:
- case Primitive::kPrimNot:
- case Primitive::kPrimFloat:
- Move(location, Location::StackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
- break;
-
- case Primitive::kPrimLong:
- case Primitive::kPrimDouble:
- Move(location,
- Location::DoubleStackSlot(GetStackSlot(instruction->AsLoadLocal()->GetLocal())));
- break;
-
- default:
- LOG(FATAL) << "Unexpected local type " << instruction->GetType();
- }
- } else if (instruction->IsTemporary()) {
- Location temp_location = GetTemporaryLocation(instruction->AsTemporary());
- Move(location, temp_location);
- } else {
- DCHECK((instruction->GetNext() == move_for) || instruction->GetNext()->IsTemporary());
- switch (instruction->GetType()) {
- case Primitive::kPrimBoolean:
- case Primitive::kPrimByte:
- case Primitive::kPrimChar:
- case Primitive::kPrimShort:
- case Primitive::kPrimInt:
- case Primitive::kPrimNot:
- case Primitive::kPrimLong:
- case Primitive::kPrimFloat:
- case Primitive::kPrimDouble:
- Move(location, locations->Out());
- break;
-
- default:
- LOG(FATAL) << "Unexpected type " << instruction->GetType();
- }
- }
-}
-
void CodeGeneratorX86_64::MoveConstant(Location location, int32_t value) {
DCHECK(location.IsRegister());
Load64BitValue(location.AsRegister<CpuRegister>(), static_cast<int64_t>(value));
}
}
-void LocationsBuilderX86_64::VisitTemporary(HTemporary* temp) {
- temp->SetLocations(nullptr);
-}
-
-void InstructionCodeGeneratorX86_64::VisitTemporary(HTemporary* temp ATTRIBUTE_UNUSED) {
- // Nothing to do, this is driven by the code generator.
-}
-
void LocationsBuilderX86_64::VisitParallelMove(HParallelMove* instruction ATTRIBUTE_UNUSED) {
LOG(FATAL) << "Unimplemented";
}
void GenerateFrameEntry() OVERRIDE;
void GenerateFrameExit() OVERRIDE;
void Bind(HBasicBlock* block) OVERRIDE;
- void Move(HInstruction* instruction, Location location, HInstruction* move_for) OVERRIDE;
void MoveConstant(Location destination, int32_t value) OVERRIDE;
void MoveLocation(Location dst, Location src, Primitive::Type dst_type) OVERRIDE;
void AddLocationAsTemp(Location location, LocationSummary* locations) OVERRIDE;
HIntConstant* cst_rhs = graph->GetIntConstant(rhs[i]);
HLessThan cmp_lt(cst_lhs, cst_rhs);
if_block->AddInstruction(&cmp_lt);
- // We insert a temporary to separate the HIf from the HLessThan and force
- // the materialization of the condition.
- HTemporary force_materialization(0);
+ // We insert a dummy instruction to separate the HIf from the HLessThan
+ // and force the materialization of the condition.
+ HMemoryBarrier force_materialization(MemBarrierKind::kAnyAny, 0);
if_block->AddInstruction(&force_materialization);
HIf if_lt(&cmp_lt);
if_block->AddInstruction(&if_lt);
M(StoreLocal, Instruction) \
M(Sub, BinaryOperation) \
M(SuspendCheck, Instruction) \
- M(Temporary, Instruction) \
M(Throw, Instruction) \
M(TryBoundary, Instruction) \
M(TypeConversion, Instruction) \
DISALLOW_COPY_AND_ASSIGN(HBoundsCheck);
};
-/**
- * Some DEX instructions are folded into multiple HInstructions that need
- * to stay live until the last HInstruction. This class
- * is used as a marker for the baseline compiler to ensure its preceding
- * HInstruction stays live. `index` represents the stack location index of the
- * instruction (the actual offset is computed as index * vreg_size).
- */
-class HTemporary : public HTemplateInstruction<0> {
- public:
- explicit HTemporary(size_t index, uint32_t dex_pc = kNoDexPc)
- : HTemplateInstruction(SideEffects::None(), dex_pc), index_(index) {}
-
- size_t GetIndex() const { return index_; }
-
- Primitive::Type GetType() const OVERRIDE {
- // The previous instruction is the one that will be stored in the temporary location.
- DCHECK(GetPrevious() != nullptr);
- return GetPrevious()->GetType();
- }
-
- DECLARE_INSTRUCTION(Temporary);
-
- private:
- const size_t index_;
- DISALLOW_COPY_AND_ASSIGN(HTemporary);
-};
-
class HSuspendCheck : public HTemplateInstruction<0> {
public:
explicit HSuspendCheck(uint32_t dex_pc)
}
}
-void SsaBuilder::VisitTemporary(HTemporary* temp) {
- // Temporaries are only used by the baseline register allocator.
- temp->GetBlock()->RemoveInstruction(temp);
-}
-
void SsaBuilder::VisitArrayGet(HArrayGet* aget) {
Primitive::Type type = aget->GetType();
DCHECK(!Primitive::IsFloatingPointType(type));
void VisitLoadLocal(HLoadLocal* load) OVERRIDE;
void VisitStoreLocal(HStoreLocal* store) OVERRIDE;
void VisitInstruction(HInstruction* instruction) OVERRIDE;
- void VisitTemporary(HTemporary* instruction) OVERRIDE;
void VisitArrayGet(HArrayGet* aget) OVERRIDE;
void VisitArraySet(HArraySet* aset) OVERRIDE;
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;