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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); | 104 __ BranchLink(&StubCode::Subtype3TestCacheLabel()); |
105 } else { | 105 } else { |
106 UNREACHABLE(); | 106 UNREACHABLE(); |
107 } | 107 } |
108 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. | 108 // Result is in R1: null -> not found, otherwise Bool::True or Bool::False. |
109 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); | 109 GenerateBoolToJump(R1, is_instance_lbl, is_not_instance_lbl); |
110 return type_test_cache.raw(); | 110 return type_test_cache.raw(); |
111 } | 111 } |
112 | 112 |
113 | 113 |
| 114 // Jumps to labels 'is_instance' or 'is_not_instance' respectively, if |
| 115 // type test is conclusive, otherwise fallthrough if a type test could not |
| 116 // be completed. |
| 117 // R0: instance being type checked (preserved). |
| 118 // Clobbers R2. |
114 RawSubtypeTestCache* | 119 RawSubtypeTestCache* |
115 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( | 120 FlowGraphCompiler::GenerateInstantiatedTypeWithArgumentsTest( |
116 intptr_t token_pos, | 121 intptr_t token_pos, |
117 const AbstractType& type, | 122 const AbstractType& type, |
118 Label* is_instance_lbl, | 123 Label* is_instance_lbl, |
119 Label* is_not_instance_lbl) { | 124 Label* is_not_instance_lbl) { |
120 UNIMPLEMENTED(); | 125 __ Comment("InstantiatedTypeWithArgumentsTest"); |
121 return NULL; | 126 ASSERT(type.IsInstantiated()); |
| 127 const Class& type_class = Class::ZoneHandle(type.type_class()); |
| 128 ASSERT(type_class.HasTypeArguments()); |
| 129 const Register kInstanceReg = R0; |
| 130 // A Smi object cannot be the instance of a parameterized class. |
| 131 __ tst(kInstanceReg, ShifterOperand(kSmiTagMask)); |
| 132 __ b(is_not_instance_lbl, EQ); |
| 133 const AbstractTypeArguments& type_arguments = |
| 134 AbstractTypeArguments::ZoneHandle(type.arguments()); |
| 135 const bool is_raw_type = type_arguments.IsNull() || |
| 136 type_arguments.IsRaw(type_arguments.Length()); |
| 137 if (is_raw_type) { |
| 138 const Register kClassIdReg = R2; |
| 139 // dynamic type argument, check only classes. |
| 140 __ LoadClassId(kClassIdReg, kInstanceReg); |
| 141 __ CompareImmediate(kClassIdReg, type_class.id()); |
| 142 __ b(is_instance_lbl, EQ); |
| 143 // List is a very common case. |
| 144 if (type_class.IsListClass()) { |
| 145 GenerateListTypeCheck(kClassIdReg, is_instance_lbl); |
| 146 } |
| 147 return GenerateSubtype1TestCacheLookup( |
| 148 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); |
| 149 } |
| 150 // If one type argument only, check if type argument is Object or dynamic. |
| 151 if (type_arguments.Length() == 1) { |
| 152 const AbstractType& tp_argument = AbstractType::ZoneHandle( |
| 153 type_arguments.TypeAt(0)); |
| 154 ASSERT(!tp_argument.IsMalformed()); |
| 155 if (tp_argument.IsType()) { |
| 156 ASSERT(tp_argument.HasResolvedTypeClass()); |
| 157 // Check if type argument is dynamic or Object. |
| 158 const Type& object_type = Type::Handle(Type::ObjectType()); |
| 159 if (object_type.IsSubtypeOf(tp_argument, NULL)) { |
| 160 // Instance class test only necessary. |
| 161 return GenerateSubtype1TestCacheLookup( |
| 162 token_pos, type_class, is_instance_lbl, is_not_instance_lbl); |
| 163 } |
| 164 } |
| 165 } |
| 166 // Regular subtype test cache involving instance's type arguments. |
| 167 const Register kTypeArgumentsReg = kNoRegister; |
| 168 const Register kTempReg = kNoRegister; |
| 169 // R0: instance (must be preserved). |
| 170 return GenerateCallSubtypeTestStub(kTestTypeTwoArgs, |
| 171 kInstanceReg, |
| 172 kTypeArgumentsReg, |
| 173 kTempReg, |
| 174 is_instance_lbl, |
| 175 is_not_instance_lbl); |
122 } | 176 } |
123 | 177 |
124 | 178 |
125 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, | 179 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, |
126 const GrowableArray<intptr_t>& class_ids, | 180 const GrowableArray<intptr_t>& class_ids, |
127 Label* is_equal_lbl, | 181 Label* is_equal_lbl, |
128 Label* is_not_equal_lbl) { | 182 Label* is_not_equal_lbl) { |
129 for (intptr_t i = 0; i < class_ids.length(); i++) { | 183 for (intptr_t i = 0; i < class_ids.length(); i++) { |
130 __ CompareImmediate(class_id_reg, class_ids[i]); | 184 __ CompareImmediate(class_id_reg, class_ids[i]); |
131 __ b(is_equal_lbl, EQ); | 185 __ b(is_equal_lbl, EQ); |
(...skipping 1184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1316 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { | 1370 void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { |
1317 __ vldrd(reg, Address(SP, kDoubleSize, Address::PostIndex)); | 1371 __ vldrd(reg, Address(SP, kDoubleSize, Address::PostIndex)); |
1318 } | 1372 } |
1319 | 1373 |
1320 | 1374 |
1321 #undef __ | 1375 #undef __ |
1322 | 1376 |
1323 } // namespace dart | 1377 } // namespace dart |
1324 | 1378 |
1325 #endif // defined TARGET_ARCH_ARM | 1379 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |