| 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/flow_graph_compiler.h" | 8 #include "vm/flow_graph_compiler.h" |
| 9 | 9 |
| 10 #include "lib/error.h" | 10 #include "lib/error.h" |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 | 42 |
| 43 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, | 43 void CompilerDeoptInfoWithStub::GenerateCode(FlowGraphCompiler* compiler, |
| 44 intptr_t stub_ix) { | 44 intptr_t stub_ix) { |
| 45 UNIMPLEMENTED(); | 45 UNIMPLEMENTED(); |
| 46 } | 46 } |
| 47 | 47 |
| 48 | 48 |
| 49 #define __ assembler()-> | 49 #define __ assembler()-> |
| 50 | 50 |
| 51 | 51 |
| 52 // Fall through if bool_register contains null. |
| 52 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, | 53 void FlowGraphCompiler::GenerateBoolToJump(Register bool_register, |
| 53 Label* is_true, | 54 Label* is_true, |
| 54 Label* is_false) { | 55 Label* is_false) { |
| 55 UNIMPLEMENTED(); | 56 Label fall_through; |
| 57 __ CompareImmediate(bool_register, |
| 58 reinterpret_cast<intptr_t>(Object::null())); |
| 59 __ b(&fall_through, EQ); |
| 60 __ CompareObject(bool_register, Bool::True()); |
| 61 __ b(is_true, EQ); |
| 62 __ b(is_false); |
| 63 __ Bind(&fall_through); |
| 56 } | 64 } |
| 57 | 65 |
| 58 | 66 |
| 67 // R0: instance (must be preserved). |
| 68 // R1: instantiator type arguments (if used). |
| 59 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( | 69 RawSubtypeTestCache* FlowGraphCompiler::GenerateCallSubtypeTestStub( |
| 60 TypeTestStubKind test_kind, | 70 TypeTestStubKind test_kind, |
| 61 Register instance_reg, | 71 Register instance_reg, |
| 62 Register type_arguments_reg, | 72 Register type_arguments_reg, |
| 63 Register temp_reg, | 73 Register temp_reg, |
| 64 Label* is_instance_lbl, | 74 Label* is_instance_lbl, |
| 65 Label* is_not_instance_lbl) { | 75 Label* is_not_instance_lbl) { |
| 66 UNIMPLEMENTED(); | 76 ASSERT(instance_reg == R0); |
| 67 return NULL; | 77 ASSERT(temp_reg == kNoRegister); // Unused on ARM. |
| 78 const SubtypeTestCache& type_test_cache = |
| 79 SubtypeTestCache::ZoneHandle(SubtypeTestCache::New()); |
| 80 __ LoadObject(R2, type_test_cache); |
| 81 if (test_kind == kTestTypeOneArg) { |
| 82 ASSERT(type_arguments_reg == kNoRegister); |
| 83 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
| 84 __ BranchLink(&StubCode::Subtype1TestCacheLabel()); |
| 85 } else if (test_kind == kTestTypeTwoArgs) { |
| 86 ASSERT(type_arguments_reg == kNoRegister); |
| 87 __ LoadImmediate(R1, reinterpret_cast<intptr_t>(Object::null())); |
| 88 __ BranchLink(&StubCode::Subtype2TestCacheLabel()); |
| 89 } else if (test_kind == kTestTypeThreeArgs) { |
| 90 ASSERT(type_arguments_reg == R1); |
| 91 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); |
| 92 } else { |
| 93 UNREACHABLE(); |
| 94 } |
| 95 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. |
| 96 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); |
| 97 return type_test_cache.raw(); |
| 68 } | 98 } |
| 69 | 99 |
| 70 | 100 |
| 71 RawSubtypeTestCache* | 101 RawSubtypeTestCache* |
| 72 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( | 102 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
| 73 intptr_t token_pos, | 103 intptr_t token_pos, |
| 74 const AbstractType& type, | 104 const AbstractType& type, |
| 75 Label* is_instance_lbl, | 105 Label* is_instance_lbl, |
| 76 Label* is_not_instance_lbl) { | 106 Label* is_not_instance_lbl) { |
| 77 UNIMPLEMENTED(); | 107 UNIMPLEMENTED(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 } | 178 } |
| 149 if (type.IsStringType()) { | 179 if (type.IsStringType()) { |
| 150 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); | 180 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); |
| 151 return false; | 181 return false; |
| 152 } | 182 } |
| 153 // Otherwise fallthrough. | 183 // Otherwise fallthrough. |
| 154 return true; | 184 return true; |
| 155 } | 185 } |
| 156 | 186 |
| 157 | 187 |
| 188 // Uses SubtypeTestCache to store instance class and result. |
| 189 // R0: instance to test. |
| 190 // Clobbers R1-R5. |
| 191 // Immediate class test already done. |
| 192 // TODO(srdjan): Implement a quicker subtype check, as type test |
| 193 // arrays can grow too high, but they may be useful when optimizing |
| 194 // code (type-feedback). |
| 158 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( | 195 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( |
| 159 intptr_t token_pos, | 196 intptr_t token_pos, |
| 160 const Class& type_class, | 197 const Class& type_class, |
| 161 Label* is_instance_lbl, | 198 Label* is_instance_lbl, |
| 162 Label* is_not_instance_lbl) { | 199 Label* is_not_instance_lbl) { |
| 163 UNIMPLEMENTED(); | 200 __ Comment("Subtype1TestCacheLookup"); |
| 164 return NULL; | 201 const Register kInstanceReg = R0; |
| 202 __ LoadClass(R1, kInstanceReg, R2); |
| 203 // R1: instance class. |
| 204 // Check immediate superclass equality. |
| 205 __ ldr(R2, FieldAddress(R1, Class::super_type_offset())); |
| 206 __ ldr(R2, FieldAddress(R2, Type::type_class_offset())); |
| 207 __ CompareObject(R2, type_class); |
| 208 __ b(is_instance_lbl, EQ); |
| 209 |
| 210 const Register kTypeArgumentsReg = kNoRegister; |
| 211 const Register kTempReg = kNoRegister; |
| 212 return GenerateCallSubtypeTestStub(kTestTypeOneArg, |
| 213 kInstanceReg, |
| 214 kTypeArgumentsReg, |
| 215 kTempReg, |
| 216 is_instance_lbl, |
| 217 is_not_instance_lbl); |
| 165 } | 218 } |
| 166 | 219 |
| 167 | 220 |
| 168 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( | 221 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( |
| 169 intptr_t token_pos, | 222 intptr_t token_pos, |
| 170 const AbstractType& type, | 223 const AbstractType& type, |
| 171 Label* is_instance_lbl, | 224 Label* is_instance_lbl, |
| 172 Label* is_not_instance_lbl) { | 225 Label* is_not_instance_lbl) { |
| 173 UNIMPLEMENTED(); | 226 UNIMPLEMENTED(); |
| 174 return NULL; | 227 return NULL; |
| (...skipping 652 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 827 deopt_id, | 880 deopt_id, |
| 828 token_pos); | 881 token_pos); |
| 829 } | 882 } |
| 830 } | 883 } |
| 831 | 884 |
| 832 | 885 |
| 833 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, | 886 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos, |
| 834 intptr_t deopt_id, | 887 intptr_t deopt_id, |
| 835 const RuntimeEntry& entry, | 888 const RuntimeEntry& entry, |
| 836 LocationSummary* locs) { | 889 LocationSummary* locs) { |
| 837 __ Unimplemented("call runtime"); | 890 __ CallRuntime(entry); |
| 891 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); |
| 892 RecordSafepoint(locs); |
| 893 if (deopt_id != Isolate::kNoDeoptId) { |
| 894 // Marks either the continuation point in unoptimized code or the |
| 895 // deoptimization point in optimized code, after call. |
| 896 if (is_optimizing()) { |
| 897 AddDeoptIndexAtCall(deopt_id, token_pos); |
| 898 } else { |
| 899 // Add deoptimization continuation point after the call and before the |
| 900 // arguments are removed. |
| 901 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, |
| 902 deopt_id, |
| 903 token_pos); |
| 904 } |
| 905 } |
| 838 } | 906 } |
| 839 | 907 |
| 840 | 908 |
| 841 void FlowGraphCompiler::EmitOptimizedInstanceCall( | 909 void FlowGraphCompiler::EmitOptimizedInstanceCall( |
| 842 ExternalLabel* target_label, | 910 ExternalLabel* target_label, |
| 843 const ICData& ic_data, | 911 const ICData& ic_data, |
| 844 const Array& arguments_descriptor, | 912 const Array& arguments_descriptor, |
| 845 intptr_t argument_count, | 913 intptr_t argument_count, |
| 846 intptr_t deopt_id, | 914 intptr_t deopt_id, |
| 847 intptr_t token_pos, | 915 intptr_t token_pos, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, | 969 void FlowGraphCompiler::EmitEqualityRegConstCompare(Register reg, |
| 902 const Object& obj, | 970 const Object& obj, |
| 903 bool needs_number_check) { | 971 bool needs_number_check) { |
| 904 UNIMPLEMENTED(); | 972 UNIMPLEMENTED(); |
| 905 } | 973 } |
| 906 | 974 |
| 907 | 975 |
| 908 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, | 976 void FlowGraphCompiler::EmitEqualityRegRegCompare(Register left, |
| 909 Register right, | 977 Register right, |
| 910 bool needs_number_check) { | 978 bool needs_number_check) { |
| 911 UNIMPLEMENTED(); | 979 if (needs_number_check) { |
| 980 __ Push(left); |
| 981 __ Push(right); |
| 982 __ BranchLink(&StubCode::IdenticalWithNumberCheckLabel()); |
| 983 // Stub returns result in flags (result of a cmpl, we need ZF computed). |
| 984 __ Pop(right); |
| 985 __ Pop(left); |
| 986 } else { |
| 987 __ cmp(left, ShifterOperand(right)); |
| 988 } |
| 912 } | 989 } |
| 913 | 990 |
| 914 | 991 |
| 915 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, | 992 void FlowGraphCompiler::EmitSuperEqualityCallPrologue(Register result, |
| 916 Label* skip_call) { | 993 Label* skip_call) { |
| 917 UNIMPLEMENTED(); | 994 UNIMPLEMENTED(); |
| 918 } | 995 } |
| 919 | 996 |
| 920 | 997 |
| 921 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { | 998 void FlowGraphCompiler::SaveLiveRegisters(LocationSummary* locs) { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 | 1129 |
| 1053 | 1130 |
| 1054 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { | 1131 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { |
| 1055 UNIMPLEMENTED(); | 1132 UNIMPLEMENTED(); |
| 1056 } | 1133 } |
| 1057 | 1134 |
| 1058 | 1135 |
| 1059 } // namespace dart | 1136 } // namespace dart |
| 1060 | 1137 |
| 1061 #endif // defined TARGET_ARCH_ARM | 1138 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |