| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. | 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM. |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/intermediate_language.h" | 8 #include "vm/intermediate_language.h" |
| 9 | 9 |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph.h" | 12 #include "vm/flow_graph.h" |
| 13 #include "vm/flow_graph_compiler.h" | 13 #include "vm/flow_graph_compiler.h" |
| 14 #include "vm/flow_graph_range_analysis.h" | 14 #include "vm/flow_graph_range_analysis.h" |
| 15 #include "vm/locations.h" | 15 #include "vm/locations.h" |
| 16 #include "vm/object_store.h" | 16 #include "vm/object_store.h" |
| 17 #include "vm/parser.h" | 17 #include "vm/parser.h" |
| 18 #include "vm/simulator.h" | 18 #include "vm/simulator.h" |
| 19 #include "vm/stack_frame.h" | 19 #include "vm/stack_frame.h" |
| 20 #include "vm/stub_code.h" | 20 #include "vm/stub_code.h" |
| 21 #include "vm/symbols.h" | 21 #include "vm/symbols.h" |
| 22 | 22 |
| 23 #define __ compiler->assembler()-> | 23 #define __ compiler->assembler()-> |
| 24 | 24 |
| 25 namespace dart { | 25 namespace dart { |
| 26 | 26 |
| 27 DECLARE_FLAG(bool, allow_absolute_addresses); |
| 27 DECLARE_FLAG(bool, emit_edge_counters); | 28 DECLARE_FLAG(bool, emit_edge_counters); |
| 28 DECLARE_FLAG(int, optimization_counter_threshold); | 29 DECLARE_FLAG(int, optimization_counter_threshold); |
| 29 DECLARE_FLAG(bool, use_osr); | 30 DECLARE_FLAG(bool, use_osr); |
| 30 | 31 |
| 31 // Generic summary for call instructions that have all arguments pushed | 32 // Generic summary for call instructions that have all arguments pushed |
| 32 // on the stack and return the result in a fixed register R0. | 33 // on the stack and return the result in a fixed register R0. |
| 33 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { | 34 LocationSummary* Instruction::MakeCallSummary(Zone* zone) { |
| 34 LocationSummary* result = new(zone) LocationSummary( | 35 LocationSummary* result = new(zone) LocationSummary( |
| 35 zone, 0, 0, LocationSummary::kCall); | 36 zone, 0, 0, LocationSummary::kCall); |
| 36 result->set_out(0, Location::RegisterLocation(R0)); | 37 result->set_out(0, Location::RegisterLocation(R0)); |
| (...skipping 1659 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1696 __ b(fail, EQ); | 1697 __ b(fail, EQ); |
| 1697 __ LoadClassId(value_cid_reg, value_reg); | 1698 __ LoadClassId(value_cid_reg, value_reg); |
| 1698 __ CompareImmediate(value_cid_reg, field_cid); | 1699 __ CompareImmediate(value_cid_reg, field_cid); |
| 1699 } | 1700 } |
| 1700 | 1701 |
| 1701 if (field().is_nullable() && (field_cid != kNullCid)) { | 1702 if (field().is_nullable() && (field_cid != kNullCid)) { |
| 1702 __ b(&ok, EQ); | 1703 __ b(&ok, EQ); |
| 1703 if (field_cid != kSmiCid) { | 1704 if (field_cid != kSmiCid) { |
| 1704 __ CompareImmediate(value_cid_reg, kNullCid); | 1705 __ CompareImmediate(value_cid_reg, kNullCid); |
| 1705 } else { | 1706 } else { |
| 1706 __ CompareImmediate(value_reg, | 1707 __ CompareObject(value_reg, Object::null_object()); |
| 1707 reinterpret_cast<intptr_t>(Object::null())); | |
| 1708 } | 1708 } |
| 1709 } | 1709 } |
| 1710 __ b(fail, NE); | 1710 __ b(fail, NE); |
| 1711 } else { | 1711 } else { |
| 1712 // Both value's and field's class id is known. | 1712 // Both value's and field's class id is known. |
| 1713 ASSERT((value_cid != field_cid) && (value_cid != nullability)); | 1713 ASSERT((value_cid != field_cid) && (value_cid != nullability)); |
| 1714 __ b(fail); | 1714 __ b(fail); |
| 1715 } | 1715 } |
| 1716 } | 1716 } |
| 1717 __ Bind(&ok); | 1717 __ Bind(&ok); |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2027 | 2027 |
| 2028 static void EnsureMutableBox(FlowGraphCompiler* compiler, | 2028 static void EnsureMutableBox(FlowGraphCompiler* compiler, |
| 2029 StoreInstanceFieldInstr* instruction, | 2029 StoreInstanceFieldInstr* instruction, |
| 2030 Register box_reg, | 2030 Register box_reg, |
| 2031 const Class& cls, | 2031 const Class& cls, |
| 2032 Register instance_reg, | 2032 Register instance_reg, |
| 2033 intptr_t offset, | 2033 intptr_t offset, |
| 2034 Register temp) { | 2034 Register temp) { |
| 2035 Label done; | 2035 Label done; |
| 2036 __ ldr(box_reg, FieldAddress(instance_reg, offset)); | 2036 __ ldr(box_reg, FieldAddress(instance_reg, offset)); |
| 2037 __ CompareImmediate(box_reg, | 2037 __ CompareObject(box_reg, Object::null_object()); |
| 2038 reinterpret_cast<intptr_t>(Object::null())); | |
| 2039 __ b(&done, NE); | 2038 __ b(&done, NE); |
| 2040 | 2039 |
| 2041 BoxAllocationSlowPath::Allocate( | 2040 BoxAllocationSlowPath::Allocate( |
| 2042 compiler, instruction, cls, box_reg, temp); | 2041 compiler, instruction, cls, box_reg, temp); |
| 2043 | 2042 |
| 2044 __ MoveRegister(temp, box_reg); | 2043 __ MoveRegister(temp, box_reg); |
| 2045 __ StoreIntoObjectOffset(instance_reg, offset, temp); | 2044 __ StoreIntoObjectOffset(instance_reg, offset, temp); |
| 2046 __ Bind(&done); | 2045 __ Bind(&done); |
| 2047 } | 2046 } |
| 2048 | 2047 |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2345 kLengthReg); | 2344 kLengthReg); |
| 2346 | 2345 |
| 2347 // Initialize all array elements to raw_null. | 2346 // Initialize all array elements to raw_null. |
| 2348 // R0: new object start as a tagged pointer. | 2347 // R0: new object start as a tagged pointer. |
| 2349 // R3: new object end address. | 2348 // R3: new object end address. |
| 2350 // R9: iterator which initially points to the start of the variable | 2349 // R9: iterator which initially points to the start of the variable |
| 2351 // data area to be initialized. | 2350 // data area to be initialized. |
| 2352 // R6: null | 2351 // R6: null |
| 2353 if (num_elements > 0) { | 2352 if (num_elements > 0) { |
| 2354 const intptr_t array_size = instance_size - sizeof(RawArray); | 2353 const intptr_t array_size = instance_size - sizeof(RawArray); |
| 2355 __ LoadImmediate(R6, reinterpret_cast<intptr_t>(Object::null())); | 2354 __ LoadObject(R6, Object::null_object()); |
| 2356 if (num_elements >= 2) { | 2355 if (num_elements >= 2) { |
| 2357 __ mov(R7, Operand(R6)); | 2356 __ mov(R7, Operand(R6)); |
| 2358 } else { | 2357 } else { |
| 2359 #if defined(DEBUG) | 2358 #if defined(DEBUG) |
| 2360 // Clobber R7 with an invalid pointer. | 2359 // Clobber R7 with an invalid pointer. |
| 2361 __ LoadImmediate(R7, 0x1); | 2360 __ LoadImmediate(R7, 0x1); |
| 2362 #endif // DEBUG | 2361 #endif // DEBUG |
| 2363 } | 2362 } |
| 2364 __ AddImmediate(R9, R0, sizeof(RawArray) - kHeapObjectTag); | 2363 __ AddImmediate(R9, R0, sizeof(RawArray) - kHeapObjectTag); |
| 2365 if (array_size < (kInlineArraySize * kWordSize)) { | 2364 if (array_size < (kInlineArraySize * kWordSize)) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2614 // 'instantiator_reg' is the instantiator TypeArguments object (or null). | 2613 // 'instantiator_reg' is the instantiator TypeArguments object (or null). |
| 2615 ASSERT(!type_arguments().IsUninstantiatedIdentity() && | 2614 ASSERT(!type_arguments().IsUninstantiatedIdentity() && |
| 2616 !type_arguments().CanShareInstantiatorTypeArguments( | 2615 !type_arguments().CanShareInstantiatorTypeArguments( |
| 2617 instantiator_class())); | 2616 instantiator_class())); |
| 2618 // If the instantiator is null and if the type argument vector | 2617 // If the instantiator is null and if the type argument vector |
| 2619 // instantiated from null becomes a vector of dynamic, then use null as | 2618 // instantiated from null becomes a vector of dynamic, then use null as |
| 2620 // the type arguments. | 2619 // the type arguments. |
| 2621 Label type_arguments_instantiated; | 2620 Label type_arguments_instantiated; |
| 2622 const intptr_t len = type_arguments().Length(); | 2621 const intptr_t len = type_arguments().Length(); |
| 2623 if (type_arguments().IsRawInstantiatedRaw(len)) { | 2622 if (type_arguments().IsRawInstantiatedRaw(len)) { |
| 2624 __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); | 2623 __ LoadObject(IP, Object::null_object()); |
| 2625 __ cmp(instantiator_reg, Operand(IP)); | 2624 __ cmp(instantiator_reg, Operand(IP)); |
| 2626 __ b(&type_arguments_instantiated, EQ); | 2625 __ b(&type_arguments_instantiated, EQ); |
| 2627 } | 2626 } |
| 2628 | 2627 |
| 2629 __ LoadObject(R2, type_arguments()); | 2628 __ LoadObject(R2, type_arguments()); |
| 2630 __ ldr(R2, FieldAddress(R2, TypeArguments::instantiations_offset())); | 2629 __ ldr(R2, FieldAddress(R2, TypeArguments::instantiations_offset())); |
| 2631 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); | 2630 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); |
| 2632 // The instantiations cache is initialized with Object::zero_array() and is | 2631 // The instantiations cache is initialized with Object::zero_array() and is |
| 2633 // therefore guaranteed to contain kNoInstantiator. No length check needed. | 2632 // therefore guaranteed to contain kNoInstantiator. No length check needed. |
| 2634 Label loop, found, slow_case; | 2633 Label loop, found, slow_case; |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2879 public: | 2878 public: |
| 2880 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) | 2879 explicit CheckStackOverflowSlowPath(CheckStackOverflowInstr* instruction) |
| 2881 : instruction_(instruction) { } | 2880 : instruction_(instruction) { } |
| 2882 | 2881 |
| 2883 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { | 2882 virtual void EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2884 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { | 2883 if (FLAG_use_osr && osr_entry_label()->IsLinked()) { |
| 2885 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); | 2884 uword flags_address = Isolate::Current()->stack_overflow_flags_address(); |
| 2886 const Register value = instruction_->locs()->temp(0).reg(); | 2885 const Register value = instruction_->locs()->temp(0).reg(); |
| 2887 __ Comment("CheckStackOverflowSlowPathOsr"); | 2886 __ Comment("CheckStackOverflowSlowPathOsr"); |
| 2888 __ Bind(osr_entry_label()); | 2887 __ Bind(osr_entry_label()); |
| 2888 ASSERT(FLAG_allow_absolute_addresses); |
| 2889 __ LoadImmediate(IP, flags_address); | 2889 __ LoadImmediate(IP, flags_address); |
| 2890 __ LoadImmediate(value, Isolate::kOsrRequest); | 2890 __ LoadImmediate(value, Isolate::kOsrRequest); |
| 2891 __ str(value, Address(IP)); | 2891 __ str(value, Address(IP)); |
| 2892 } | 2892 } |
| 2893 __ Comment("CheckStackOverflowSlowPath"); | 2893 __ Comment("CheckStackOverflowSlowPath"); |
| 2894 __ Bind(entry_label()); | 2894 __ Bind(entry_label()); |
| 2895 compiler->SaveLiveRegisters(instruction_->locs()); | 2895 compiler->SaveLiveRegisters(instruction_->locs()); |
| 2896 // pending_deoptimization_env_ is needed to generate a runtime call that | 2896 // pending_deoptimization_env_ is needed to generate a runtime call that |
| 2897 // may throw an exception. | 2897 // may throw an exception. |
| 2898 ASSERT(compiler->pending_deoptimization_env_ == NULL); | 2898 ASSERT(compiler->pending_deoptimization_env_ == NULL); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2923 private: | 2923 private: |
| 2924 CheckStackOverflowInstr* instruction_; | 2924 CheckStackOverflowInstr* instruction_; |
| 2925 Label osr_entry_label_; | 2925 Label osr_entry_label_; |
| 2926 }; | 2926 }; |
| 2927 | 2927 |
| 2928 | 2928 |
| 2929 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 2929 void CheckStackOverflowInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 2930 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); | 2930 CheckStackOverflowSlowPath* slow_path = new CheckStackOverflowSlowPath(this); |
| 2931 compiler->AddSlowPathCode(slow_path); | 2931 compiler->AddSlowPathCode(slow_path); |
| 2932 | 2932 |
| 2933 if (compiler->is_optimizing()) { | 2933 if (compiler->is_optimizing() && FLAG_allow_absolute_addresses) { |
| 2934 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); | 2934 __ LoadImmediate(IP, Isolate::Current()->stack_limit_address()); |
| 2935 __ ldr(IP, Address(IP)); | 2935 __ ldr(IP, Address(IP)); |
| 2936 } else { | 2936 } else { |
| 2937 __ LoadIsolate(IP); | 2937 __ LoadIsolate(IP); |
| 2938 __ ldr(IP, Address(IP, Isolate::stack_limit_offset())); | 2938 __ ldr(IP, Address(IP, Isolate::stack_limit_offset())); |
| 2939 } | 2939 } |
| 2940 __ cmp(SP, Operand(IP)); | 2940 __ cmp(SP, Operand(IP)); |
| 2941 __ b(slow_path->entry_label(), LS); | 2941 __ b(slow_path->entry_label(), LS); |
| 2942 if (compiler->CanOSRFunction() && in_loop()) { | 2942 if (compiler->CanOSRFunction() && in_loop()) { |
| 2943 const Register temp = locs()->temp(0).reg(); | 2943 const Register temp = locs()->temp(0).reg(); |
| (...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3750 EmitSmiConversion(compiler); | 3750 EmitSmiConversion(compiler); |
| 3751 } else { | 3751 } else { |
| 3752 const Register box = locs()->in(0).reg(); | 3752 const Register box = locs()->in(0).reg(); |
| 3753 const Register temp = locs()->temp(0).reg(); | 3753 const Register temp = locs()->temp(0).reg(); |
| 3754 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), | 3754 Label* deopt = compiler->AddDeoptStub(GetDeoptId(), |
| 3755 ICData::kDeoptCheckClass); | 3755 ICData::kDeoptCheckClass); |
| 3756 Label is_smi; | 3756 Label is_smi; |
| 3757 | 3757 |
| 3758 if ((value()->Type()->ToNullableCid() == box_cid) && | 3758 if ((value()->Type()->ToNullableCid() == box_cid) && |
| 3759 value()->Type()->is_nullable()) { | 3759 value()->Type()->is_nullable()) { |
| 3760 __ CompareImmediate(box, reinterpret_cast<intptr_t>(Object::null())); | 3760 __ CompareObject(box, Object::null_object()); |
| 3761 __ b(deopt, EQ); | 3761 __ b(deopt, EQ); |
| 3762 } else { | 3762 } else { |
| 3763 __ tst(box, Operand(kSmiTagMask)); | 3763 __ tst(box, Operand(kSmiTagMask)); |
| 3764 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); | 3764 __ b(CanConvertSmi() ? &is_smi : deopt, EQ); |
| 3765 __ CompareClassId(box, box_cid, temp); | 3765 __ CompareClassId(box, box_cid, temp); |
| 3766 __ b(deopt, NE); | 3766 __ b(deopt, NE); |
| 3767 } | 3767 } |
| 3768 | 3768 |
| 3769 EmitLoadFromBox(compiler); | 3769 EmitLoadFromBox(compiler); |
| 3770 | 3770 |
| (...skipping 2138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5909 } | 5909 } |
| 5910 return summary; | 5910 return summary; |
| 5911 } | 5911 } |
| 5912 | 5912 |
| 5913 | 5913 |
| 5914 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { | 5914 void CheckClassInstr::EmitNativeCode(FlowGraphCompiler* compiler) { |
| 5915 Label* deopt = compiler->AddDeoptStub(deopt_id(), | 5915 Label* deopt = compiler->AddDeoptStub(deopt_id(), |
| 5916 ICData::kDeoptCheckClass, | 5916 ICData::kDeoptCheckClass, |
| 5917 licm_hoisted_ ? ICData::kHoisted : 0); | 5917 licm_hoisted_ ? ICData::kHoisted : 0); |
| 5918 if (IsNullCheck()) { | 5918 if (IsNullCheck()) { |
| 5919 __ CompareImmediate(locs()->in(0).reg(), | 5919 __ CompareObject(locs()->in(0).reg(), Object::null_object()); |
| 5920 reinterpret_cast<intptr_t>(Object::null())); | |
| 5921 ASSERT(DeoptIfNull() || DeoptIfNotNull()); | 5920 ASSERT(DeoptIfNull() || DeoptIfNotNull()); |
| 5922 Condition cond = DeoptIfNull() ? EQ : NE; | 5921 Condition cond = DeoptIfNull() ? EQ : NE; |
| 5923 __ b(deopt, cond); | 5922 __ b(deopt, cond); |
| 5924 return; | 5923 return; |
| 5925 } | 5924 } |
| 5926 | 5925 |
| 5927 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || | 5926 ASSERT((unary_checks().GetReceiverClassIdAt(0) != kSmiCid) || |
| 5928 (unary_checks().NumberOfChecks() > 1)); | 5927 (unary_checks().NumberOfChecks() > 1)); |
| 5929 const Register value = locs()->in(0).reg(); | 5928 const Register value = locs()->in(0).reg(); |
| 5930 const Register temp = locs()->temp(0).reg(); | 5929 const Register temp = locs()->temp(0).reg(); |
| (...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6863 1, | 6862 1, |
| 6864 locs()); | 6863 locs()); |
| 6865 __ Drop(1); | 6864 __ Drop(1); |
| 6866 __ Pop(result); | 6865 __ Pop(result); |
| 6867 } | 6866 } |
| 6868 | 6867 |
| 6869 | 6868 |
| 6870 } // namespace dart | 6869 } // namespace dart |
| 6871 | 6870 |
| 6872 #endif // defined TARGET_ARCH_ARM | 6871 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |