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 |