Chromium Code Reviews| Index: runtime/vm/intermediate_language_arm.cc |
| diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc |
| index 977763a9f7b2749f376a2cd5581cc834be60b806..9cff0ad5ceeb1987531118f3c24d2980d4771b9e 100644 |
| --- a/runtime/vm/intermediate_language_arm.cc |
| +++ b/runtime/vm/intermediate_language_arm.cc |
| @@ -1581,36 +1581,82 @@ void GuardFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| } |
| +bool Field::IsUnboxedField() const { |
|
Florian Schneider
2014/02/06 12:38:49
Maybe this should still be in object.cc? In this c
srdjan
2014/02/06 16:55:31
I do not like architecture dependent code in share
Cutch
2014/02/06 23:15:38
Done.
|
| + bool valid_class = (guarded_cid() == kDoubleCid) || |
| + (guarded_cid() == kFloat32x4Cid); |
| + return is_unboxing_candidate() && !is_final() && !is_nullable() && |
| + valid_class; |
| +} |
| + |
| + |
| class StoreInstanceFieldSlowPath : public SlowPathCode { |
| public: |
| - StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction, |
| - const Class& cls) |
| - : instruction_(instruction), cls_(cls) { } |
| + explicit StoreInstanceFieldSlowPath(StoreInstanceFieldInstr* instruction) |
| + : instruction_(instruction) { } |
| virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| __ Comment("StoreInstanceFieldSlowPath"); |
| - __ Bind(entry_label()); |
| - const Code& stub = |
| - Code::Handle(StubCode::GetAllocationStubForClass(cls_)); |
| - const ExternalLabel label(cls_.ToCString(), stub.EntryPoint()); |
| + { |
| + __ Bind(double_entry_label()); |
| + |
| + const Class& cls = compiler->double_class(); |
| + const Code& stub = |
| + Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| + const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| + |
| + LocationSummary* locs = instruction_->locs(); |
| + locs->live_registers()->Remove(locs->out()); |
| + |
| + compiler->SaveLiveRegisters(locs); |
| + compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| + &label, |
| + PcDescriptors::kOther, |
| + locs); |
| + __ MoveRegister(locs->temp(0).reg(), R0); |
| + compiler->RestoreLiveRegisters(locs); |
| + |
| + __ b(double_exit_label()); |
| + } |
| - LocationSummary* locs = instruction_->locs(); |
| - locs->live_registers()->Remove(locs->out()); |
| + { |
| + __ Bind(float32x4_entry_label()); |
| - compiler->SaveLiveRegisters(locs); |
| - compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| - &label, |
| - PcDescriptors::kOther, |
| - locs); |
| - __ MoveRegister(locs->temp(0).reg(), R0); |
| - compiler->RestoreLiveRegisters(locs); |
| + const Class& cls = compiler->float32x4_class(); |
| + const Code& stub = |
| + Code::Handle(StubCode::GetAllocationStubForClass(cls)); |
| + const ExternalLabel label(cls.ToCString(), stub.EntryPoint()); |
| - __ b(exit_label()); |
| + LocationSummary* locs = instruction_->locs(); |
| + locs->live_registers()->Remove(locs->out()); |
|
Florian Schneider
2014/02/06 12:38:49
locs->live_registers is already modified in the sa
Cutch
2014/02/06 23:15:38
Done.
|
| + |
| + compiler->SaveLiveRegisters(locs); |
| + compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| + &label, |
| + PcDescriptors::kOther, |
| + locs); |
| + __ MoveRegister(locs->temp(0).reg(), R0); |
| + compiler->RestoreLiveRegisters(locs); |
| + |
| + __ b(float32x4_exit_label()); |
| + } |
| + } |
| + |
| + Label* double_entry_label() { |
| + // Use default SlowPathCode label for double. |
| + return entry_label(); |
| } |
| + Label* double_exit_label() { |
| + // Use default SlowPathCode label for double. |
| + return exit_label(); |
| + } |
| + |
| + Label* float32x4_entry_label() { return &float32x4_entry_label_; } |
| + Label* float32x4_exit_label() { return &float32x4_exit_label_; } |
| private: |
| + Label float32x4_entry_label_; |
| + Label float32x4_exit_label_; |
| StoreInstanceFieldInstr* instruction_; |
| - const Class& cls_; |
| }; |
| @@ -1652,28 +1698,39 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| if (IsUnboxedStore() && compiler->is_optimizing()) { |
| DRegister value = EvenDRegisterOf(locs()->in(1).fpu_reg()); |
| + DRegister value_odd = OddDRegisterOf(locs()->in(1).fpu_reg()); |
| Register temp = locs()->temp(0).reg(); |
| Register temp2 = locs()->temp(1).reg(); |
| const intptr_t cid = field().UnboxedFieldCid(); |
| if (is_initialization_) { |
| + StoreInstanceFieldSlowPath* slow_path = |
| + new StoreInstanceFieldSlowPath(this); |
| + compiler->AddSlowPathCode(slow_path); |
| + |
| const Class* cls = NULL; |
| + Label* entry_label = NULL; |
| + Label* exit_label = NULL; |
| switch (cid) { |
| case kDoubleCid: |
| cls = &compiler->double_class(); |
| + entry_label = slow_path->double_entry_label(); |
| + exit_label = slow_path->double_exit_label(); |
| + break; |
| + case kFloat32x4Cid: |
| + cls = &compiler->float32x4_class(); |
| + entry_label = slow_path->float32x4_entry_label(); |
| + exit_label = slow_path->float32x4_exit_label(); |
| break; |
| - // TODO(johnmccutchan): Add kFloat32x4Cid here. |
| default: |
| UNREACHABLE(); |
| } |
| - StoreInstanceFieldSlowPath* slow_path = |
| - new StoreInstanceFieldSlowPath(this, *cls); |
| - compiler->AddSlowPathCode(slow_path); |
| + |
| __ TryAllocate(*cls, |
| - slow_path->entry_label(), |
| + entry_label, |
| temp, |
| temp2); |
| - __ Bind(slow_path->exit_label()); |
| + __ Bind(exit_label); |
| __ MoveRegister(temp2, temp); |
| __ StoreIntoObject(instance_reg, |
| FieldAddress(instance_reg, field().Offset()), |
| @@ -1683,9 +1740,16 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| } |
| switch (cid) { |
| case kDoubleCid: |
| - __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| - // TODO(johnmccutchan): Add kFloat32x4Cid here. |
| - break; |
| + __ Comment("UnboxedDoubleStoreInstanceFieldInstr"); |
| + __ StoreDToOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| + break; |
| + case kFloat32x4Cid: |
| + __ Comment("UnboxedFloat32x4StoreInstanceFieldInstr"); |
| + __ StoreDToOffset(value, temp, |
| + Float32x4::value_offset() - kHeapObjectTag); |
| + __ StoreDToOffset(value_odd, temp, |
| + Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| + break; |
| default: |
| UNREACHABLE(); |
| } |
| @@ -1698,10 +1762,11 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| Register temp = locs()->temp(0).reg(); |
| Register temp2 = locs()->temp(1).reg(); |
| DRegister fpu_temp = EvenDRegisterOf(locs()->temp(2).fpu_reg()); |
| + DRegister fpu_temp_odd = OddDRegisterOf(locs()->temp(2).fpu_reg()); |
| Label store_pointer; |
| - Label copy_double; |
| Label store_double; |
| + Label store_float32x4; |
| __ LoadObject(temp, Field::ZoneHandle(field().raw())); |
| @@ -1717,40 +1782,85 @@ void StoreInstanceFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| __ CompareImmediate(temp2, kDoubleCid); |
| __ b(&store_double, EQ); |
| + __ ldr(temp2, FieldAddress(temp, Field::guarded_cid_offset())); |
| + __ CompareImmediate(temp2, kFloat32x4Cid); |
| + __ b(&store_float32x4, EQ); |
| + |
| // Fall through. |
| __ b(&store_pointer); |
| - __ Bind(&store_double); |
| - |
| - __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
| - __ CompareImmediate(temp, |
| - reinterpret_cast<intptr_t>(Object::null())); |
| - __ b(©_double, NE); |
| - |
| StoreInstanceFieldSlowPath* slow_path = |
| - new StoreInstanceFieldSlowPath(this, compiler->double_class()); |
| + new StoreInstanceFieldSlowPath(this); |
| compiler->AddSlowPathCode(slow_path); |
| - if (!compiler->is_optimizing()) { |
| - locs()->live_registers()->Add(locs()->in(0)); |
| - locs()->live_registers()->Add(locs()->in(1)); |
| + { |
| + __ Bind(&store_double); |
| + Label copy_double; |
| + |
| + __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
| + __ CompareImmediate(temp, |
| + reinterpret_cast<intptr_t>(Object::null())); |
| + __ b(©_double, NE); |
| + |
| + if (!compiler->is_optimizing()) { |
| + locs()->live_registers()->Add(locs()->in(0)); |
| + locs()->live_registers()->Add(locs()->in(1)); |
| + } |
| + |
| + __ TryAllocate(compiler->double_class(), |
| + slow_path->double_entry_label(), |
| + temp, |
| + temp2); |
| + __ Bind(slow_path->double_exit_label()); |
| + __ MoveRegister(temp2, temp); |
| + __ StoreIntoObject(instance_reg, |
| + FieldAddress(instance_reg, field().Offset()), |
| + temp2); |
| + __ Bind(©_double); |
| + __ LoadDFromOffset(fpu_temp, |
| + value_reg, |
| + Double::value_offset() - kHeapObjectTag); |
| + __ StoreDToOffset(fpu_temp, |
| + temp, |
| + Double::value_offset() - kHeapObjectTag); |
| + __ b(&skip_store); |
| + } |
| + |
| + { |
| + __ Bind(&store_float32x4); |
| + Label copy_float32x4; |
| + |
| + __ ldr(temp, FieldAddress(instance_reg, field().Offset())); |
| + __ CompareImmediate(temp, |
| + reinterpret_cast<intptr_t>(Object::null())); |
| + __ b(©_float32x4, NE); |
| + |
| + if (!compiler->is_optimizing()) { |
| + locs()->live_registers()->Add(locs()->in(0)); |
|
Florian Schneider
2014/02/06 12:38:49
locs() is already modified in the same way above,
Cutch
2014/02/06 23:15:38
Done.
|
| + locs()->live_registers()->Add(locs()->in(1)); |
| + } |
| + |
| + __ TryAllocate(compiler->float32x4_class(), |
| + slow_path->float32x4_entry_label(), |
| + temp, |
| + temp2); |
| + __ Bind(slow_path->float32x4_exit_label()); |
| + __ MoveRegister(temp2, temp); |
| + __ StoreIntoObject(instance_reg, |
| + FieldAddress(instance_reg, field().Offset()), |
| + temp2); |
| + __ Bind(©_float32x4); |
| + __ LoadDFromOffset(fpu_temp, value_reg, |
| + Float32x4::value_offset() - kHeapObjectTag); |
| + __ LoadDFromOffset(fpu_temp_odd, value_reg, |
| + Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| + __ StoreDToOffset(fpu_temp, temp, |
| + Float32x4::value_offset() - kHeapObjectTag); |
| + __ StoreDToOffset(fpu_temp_odd, temp, |
| + Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| + __ b(&skip_store); |
| } |
| - __ TryAllocate(compiler->double_class(), |
| - slow_path->entry_label(), |
| - temp, |
| - temp2); |
| - __ Bind(slow_path->exit_label()); |
| - __ MoveRegister(temp2, temp); |
| - __ StoreIntoObject(instance_reg, |
| - FieldAddress(instance_reg, field().Offset()), |
| - temp2); |
| - __ Bind(©_double); |
| - __ LoadDFromOffset(fpu_temp, |
| - value_reg, |
| - Double::value_offset() - kHeapObjectTag); |
| - __ StoreDToOffset(fpu_temp, temp, Double::value_offset() - kHeapObjectTag); |
| - __ b(&skip_store); |
| __ Bind(&store_pointer); |
| } |
| @@ -1894,34 +2004,70 @@ void AllocateObjectWithBoundsCheckInstr::EmitNativeCode( |
| } |
| -class BoxDoubleSlowPath : public SlowPathCode { |
| +class LoadFieldSlowPath : public SlowPathCode { |
| public: |
| - explicit BoxDoubleSlowPath(Instruction* instruction) |
| + explicit LoadFieldSlowPath(Instruction* instruction) |
| : instruction_(instruction) { } |
| virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| - __ Comment("BoxDoubleSlowPath"); |
| - __ Bind(entry_label()); |
| - const Class& double_class = compiler->double_class(); |
| - const Code& stub = |
| - Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| - const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| - |
| - LocationSummary* locs = instruction_->locs(); |
| - locs->live_registers()->Remove(locs->out()); |
| - |
| - compiler->SaveLiveRegisters(locs); |
| - compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| - &label, |
| - PcDescriptors::kOther, |
| - locs); |
| - __ MoveRegister(locs->out().reg(), R0); |
| - compiler->RestoreLiveRegisters(locs); |
| + __ Comment("LoadFieldSlowPath"); |
| + { |
| + __ Bind(double_entry_label()); |
| + const Class& double_class = compiler->double_class(); |
| + const Code& stub = |
| + Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| + const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| + |
| + LocationSummary* locs = instruction_->locs(); |
| + locs->live_registers()->Remove(locs->out()); |
| + |
| + compiler->SaveLiveRegisters(locs); |
| + compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| + &label, |
| + PcDescriptors::kOther, |
| + locs); |
| + __ MoveRegister(locs->out().reg(), R0); |
| + compiler->RestoreLiveRegisters(locs); |
| + |
| + __ b(double_exit_label()); |
| + } |
| + { |
| + __ Bind(float32x4_entry_label()); |
| + const Class& float32x4_class = compiler->float32x4_class(); |
| + const Code& stub = |
| + Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class)); |
| + const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint()); |
| + |
| + LocationSummary* locs = instruction_->locs(); |
| + locs->live_registers()->Remove(locs->out()); |
| + |
| + compiler->SaveLiveRegisters(locs); |
| + compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| + &label, |
| + PcDescriptors::kOther, |
| + locs); |
| + __ MoveRegister(locs->out().reg(), R0); |
| + compiler->RestoreLiveRegisters(locs); |
| + |
| + __ b(float32x4_exit_label()); |
| + } |
| + } |
| - __ b(exit_label()); |
| + Label* double_entry_label() { |
| + // Use default SlowPathCode label for double. |
| + return entry_label(); |
| } |
| + Label* double_exit_label() { |
| + // Use default SlowPathCode label for double. |
| + return exit_label(); |
| + } |
| + |
| + Label* float32x4_entry_label() { return &float32x4_entry_label_; } |
| + Label* float32x4_exit_label() { return &float32x4_exit_label_; } |
| private: |
| + Label float32x4_entry_label_; |
| + Label float32x4_exit_label_; |
| Instruction* instruction_; |
| }; |
| @@ -1954,15 +2100,23 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| Register instance_reg = locs()->in(0).reg(); |
| if (IsUnboxedLoad() && compiler->is_optimizing()) { |
| DRegister result = EvenDRegisterOf(locs()->out().fpu_reg()); |
| + DRegister result_odd = OddDRegisterOf(locs()->out().fpu_reg()); |
| Register temp = locs()->temp(0).reg(); |
| __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| intptr_t cid = field()->UnboxedFieldCid(); |
| switch (cid) { |
| case kDoubleCid: |
| + __ Comment("UnboxedDoubleLoadFieldInstr"); |
| __ LoadDFromOffset(result, temp, |
| Double::value_offset() - kHeapObjectTag); |
| break; |
| - // TODO(johnmccutchan): Add Float32x4 path here. |
| + case kFloat32x4Cid: |
| + __ Comment("UnboxedFloat32x4LoadFieldInstr"); |
| + __ LoadDFromOffset(result, temp, |
| + Float32x4::value_offset() - kHeapObjectTag); |
| + __ LoadDFromOffset(result_odd, temp, |
| + Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| + break; |
| default: |
| UNREACHABLE(); |
| } |
| @@ -1974,9 +2128,14 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| if (IsPotentialUnboxedLoad()) { |
| Register temp = locs()->temp(1).reg(); |
| DRegister value = EvenDRegisterOf(locs()->temp(0).fpu_reg()); |
| + DRegister value_odd = OddDRegisterOf(locs()->temp(0).fpu_reg()); |
| + |
| + LoadFieldSlowPath* slow_path = new LoadFieldSlowPath(this); |
| + compiler->AddSlowPathCode(slow_path); |
| Label load_pointer; |
| Label load_double; |
| + Label load_float32x4; |
| __ LoadObject(result_reg, Field::ZoneHandle(field()->raw())); |
| @@ -1992,31 +2151,56 @@ void LoadFieldInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| __ CompareImmediate(temp, kDoubleCid); |
| __ b(&load_double, EQ); |
| + __ ldr(temp, field_cid_operand); |
| + __ CompareImmediate(temp, kFloat32x4Cid); |
| + __ b(&load_float32x4, EQ); |
| + |
| // Fall through. |
| __ b(&load_pointer); |
| - __ Bind(&load_double); |
| + { |
| + __ Bind(&load_double); |
| - BoxDoubleSlowPath* slow_path = new BoxDoubleSlowPath(this); |
| - compiler->AddSlowPathCode(slow_path); |
| + if (!compiler->is_optimizing()) { |
| + locs()->live_registers()->Add(locs()->in(0)); |
| + } |
| - if (!compiler->is_optimizing()) { |
| - locs()->live_registers()->Add(locs()->in(0)); |
| + __ TryAllocate(compiler->double_class(), |
| + slow_path->double_entry_label(), |
| + result_reg, |
| + temp); |
| + __ Bind(slow_path->double_exit_label()); |
| + __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| + __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| + __ StoreDToOffset(value, |
| + result_reg, |
| + Double::value_offset() - kHeapObjectTag); |
| + __ b(&done); |
| } |
| - __ TryAllocate(compiler->double_class(), |
| - slow_path->entry_label(), |
| - result_reg, |
| - temp); |
| - __ Bind(slow_path->exit_label()); |
| - __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| - __ LoadDFromOffset(value, temp, Double::value_offset() - kHeapObjectTag); |
| - __ StoreDToOffset(value, |
| - result_reg, |
| - Double::value_offset() - kHeapObjectTag); |
| - __ b(&done); |
| + { |
| + __ Bind(&load_float32x4); |
| - // TODO(johnmccutchan): Add Float32x4 path here. |
| + if (!compiler->is_optimizing()) { |
| + locs()->live_registers()->Add(locs()->in(0)); |
| + } |
| + |
| + __ TryAllocate(compiler->float32x4_class(), |
| + slow_path->float32x4_entry_label(), |
| + result_reg, |
| + temp); |
| + __ Bind(slow_path->float32x4_exit_label()); |
| + __ ldr(temp, FieldAddress(instance_reg, offset_in_bytes())); |
| + __ LoadDFromOffset(value, temp, |
| + Float32x4::value_offset() - kHeapObjectTag); |
| + __ LoadDFromOffset(value_odd, temp, |
| + Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| + __ StoreDToOffset(value, result_reg, |
| + Float32x4::value_offset() - kHeapObjectTag); |
| + __ StoreDToOffset(value_odd, result_reg, |
| + Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag); |
| + __ b(&done); |
| + } |
| __ Bind(&load_pointer); |
| } |
| @@ -2824,6 +3008,38 @@ void CheckEitherNonSmiInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| } |
| +class BoxDoubleSlowPath : public SlowPathCode { |
| + public: |
| + explicit BoxDoubleSlowPath(BoxDoubleInstr* instruction) |
| + : instruction_(instruction) { } |
| + |
| + virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| + __ Comment("BoxDoubleSlowPath"); |
| + __ Bind(entry_label()); |
| + const Class& double_class = compiler->double_class(); |
| + const Code& stub = |
| + Code::Handle(StubCode::GetAllocationStubForClass(double_class)); |
| + const ExternalLabel label(double_class.ToCString(), stub.EntryPoint()); |
| + |
| + LocationSummary* locs = instruction_->locs(); |
| + locs->live_registers()->Remove(locs->out()); |
| + |
| + compiler->SaveLiveRegisters(locs); |
| + compiler->GenerateCall(Scanner::kNoSourcePos, // No token position. |
| + &label, |
| + PcDescriptors::kOther, |
| + locs); |
| + __ MoveRegister(locs->out().reg(), R0); |
| + compiler->RestoreLiveRegisters(locs); |
| + |
| + __ b(exit_label()); |
| + } |
| + |
| + private: |
| + BoxDoubleInstr* instruction_; |
| +}; |
| + |
| + |
| LocationSummary* BoxDoubleInstr::MakeLocationSummary(bool opt) const { |
| const intptr_t kNumInputs = 1; |
| const intptr_t kNumTemps = 1; |