Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(288)

Side by Side Diff: runtime/vm/flow_graph_compiler_arm.cc

Issue 12773008: Support checked mode for VM tests on ARM. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/assembler_arm.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "vm/ast_printer.h" 11 #include "vm/ast_printer.h"
12 #include "vm/dart_entry.h" 12 #include "vm/dart_entry.h"
13 #include "vm/il_printer.h" 13 #include "vm/il_printer.h"
14 #include "vm/locations.h" 14 #include "vm/locations.h"
15 #include "vm/object_store.h" 15 #include "vm/object_store.h"
16 #include "vm/parser.h" 16 #include "vm/parser.h"
17 #include "vm/stub_code.h" 17 #include "vm/stub_code.h"
18 #include "vm/symbols.h" 18 #include "vm/symbols.h"
19 19
20 namespace dart { 20 namespace dart {
21 21
22 DECLARE_FLAG(int, optimization_counter_threshold); 22 DECLARE_FLAG(int, optimization_counter_threshold);
23 DECLARE_FLAG(bool, print_ast); 23 DECLARE_FLAG(bool, print_ast);
24 DECLARE_FLAG(bool, print_scopes); 24 DECLARE_FLAG(bool, print_scopes);
25 DECLARE_FLAG(bool, enable_type_checks); 25 DECLARE_FLAG(bool, enable_type_checks);
26 DECLARE_FLAG(bool, eliminate_type_checks);
26 27
27 28
28 FlowGraphCompiler::~FlowGraphCompiler() { 29 FlowGraphCompiler::~FlowGraphCompiler() {
29 // BlockInfos are zone-allocated, so their destructors are not called. 30 // BlockInfos are zone-allocated, so their destructors are not called.
30 // Verify the labels explicitly here. 31 // Verify the labels explicitly here.
31 for (int i = 0; i < block_info_.length(); ++i) { 32 for (int i = 0; i < block_info_.length(); ++i) {
32 ASSERT(!block_info_[i]->jump_label()->IsLinked()); 33 ASSERT(!block_info_[i]->jump_label()->IsLinked());
33 } 34 }
34 } 35 }
35 36
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 Label* is_not_instance_lbl) { 76 Label* is_not_instance_lbl) {
76 UNIMPLEMENTED(); 77 UNIMPLEMENTED();
77 return NULL; 78 return NULL;
78 } 79 }
79 80
80 81
81 void FlowGraphCompiler::CheckClassIds(Register class_id_reg, 82 void FlowGraphCompiler::CheckClassIds(Register class_id_reg,
82 const GrowableArray<intptr_t>& class_ids, 83 const GrowableArray<intptr_t>& class_ids,
83 Label* is_equal_lbl, 84 Label* is_equal_lbl,
84 Label* is_not_equal_lbl) { 85 Label* is_not_equal_lbl) {
85 UNIMPLEMENTED(); 86 for (intptr_t i = 0; i < class_ids.length(); i++) {
87 __ CompareImmediate(class_id_reg, class_ids[i]);
88 __ b(is_equal_lbl, EQ);
89 }
90 __ b(is_not_equal_lbl);
86 } 91 }
87 92
88 93
94 // Testing against an instantiated type with no arguments, without
95 // SubtypeTestCache.
96 // R0: instance to test against (preserved).
97 // Clobbers R2, R3.
98 // Returns true if there is a fallthrough.
89 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 99 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
90 intptr_t token_pos, 100 intptr_t token_pos,
91 const AbstractType& type, 101 const AbstractType& type,
92 Label* is_instance_lbl, 102 Label* is_instance_lbl,
93 Label* is_not_instance_lbl) { 103 Label* is_not_instance_lbl) {
94 UNIMPLEMENTED(); 104 __ Comment("InstantiatedTypeNoArgumentsTest");
95 return false; 105 ASSERT(type.IsInstantiated());
106 const Class& type_class = Class::Handle(type.type_class());
107 ASSERT(!type_class.HasTypeArguments());
108
109 const Register kInstanceReg = R0;
110 __ tst(kInstanceReg, ShifterOperand(kSmiTagMask));
111 // If instance is Smi, check directly.
112 const Class& smi_class = Class::Handle(Smi::Class());
113 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
114 type_class,
115 TypeArguments::Handle(),
116 NULL)) {
117 __ b(is_instance_lbl, EQ);
118 } else {
119 __ b(is_not_instance_lbl, EQ);
120 }
121 // Compare if the classes are equal.
122 const Register kClassIdReg = R2;
123 __ LoadClassId(kClassIdReg, kInstanceReg);
124 __ CompareImmediate(kClassIdReg, type_class.id());
125 __ b(is_instance_lbl, EQ);
126 // Bool interface can be implemented only by core class Bool.
127 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces).
zra 2013/03/28 16:57:51 I can't seem to find ClassFinalizer::ResolveInterf
regis 2013/03/28 17:40:21 The function was renamed to ClassFinalizer::Resolv
128 if (type.IsBoolType()) {
129 __ CompareImmediate(kClassIdReg, kBoolCid);
130 __ b(is_instance_lbl, EQ);
131 __ b(is_not_instance_lbl);
132 return false;
133 }
134 if (type.IsFunctionType()) {
135 // Check if instance is a closure.
136 __ LoadClassById(R3, kClassIdReg);
137 __ ldr(R3, FieldAddress(R3, Class::signature_function_offset()));
138 __ CompareImmediate(R3, reinterpret_cast<int32_t>(Object::null()));
139 __ b(is_instance_lbl, NE);
140 }
141 // Custom checking for numbers (Smi, Mint, Bigint and Double).
142 // Note that instance is not Smi (checked above).
143 if (type.IsSubtypeOf(Type::Handle(Type::Number()), NULL)) {
144 GenerateNumberTypeCheck(
145 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
146 return false;
147 }
148 if (type.IsStringType()) {
149 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
150 return false;
151 }
152 // Otherwise fallthrough.
153 return true;
96 } 154 }
97 155
98 156
99 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup( 157 RawSubtypeTestCache* FlowGraphCompiler::GenerateSubtype1TestCacheLookup(
100 intptr_t token_pos, 158 intptr_t token_pos,
101 const Class& type_class, 159 const Class& type_class,
102 Label* is_instance_lbl, 160 Label* is_instance_lbl,
103 Label* is_not_instance_lbl) { 161 Label* is_not_instance_lbl) {
104 UNIMPLEMENTED(); 162 UNIMPLEMENTED();
105 return NULL; 163 return NULL;
106 } 164 }
107 165
108 166
109 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest( 167 RawSubtypeTestCache* FlowGraphCompiler::GenerateUninstantiatedTypeTest(
110 intptr_t token_pos, 168 intptr_t token_pos,
111 const AbstractType& type, 169 const AbstractType& type,
112 Label* is_instance_lbl, 170 Label* is_instance_lbl,
113 Label* is_not_instance_lbl) { 171 Label* is_not_instance_lbl) {
114 UNIMPLEMENTED(); 172 UNIMPLEMENTED();
115 return NULL; 173 return NULL;
116 } 174 }
117 175
118 176
177 // Inputs:
178 // - R0: instance to test against (preserved).
179 // - R1: optional instantiator type arguments (preserved).
180 // Clobbers R2, R3.
181 // Returns:
182 // - preserved instance in R0 and optional instantiator type arguments in R1.
183 // Note that this inlined code must be followed by the runtime_call code, as it
184 // may fall through to it. Otherwise, this inline code will jump to the label
185 // is_instance or to the label is_not_instance.
119 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof( 186 RawSubtypeTestCache* FlowGraphCompiler::GenerateInlineInstanceof(
120 intptr_t token_pos, 187 intptr_t token_pos,
121 const AbstractType& type, 188 const AbstractType& type,
122 Label* is_instance_lbl, 189 Label* is_instance_lbl,
123 Label* is_not_instance_lbl) { 190 Label* is_not_instance_lbl) {
124 UNIMPLEMENTED(); 191 __ Comment("InlineInstanceof");
125 return NULL; 192 if (type.IsVoidType()) {
193 // A non-null value is returned from a void function, which will result in a
194 // type error. A null value is handled prior to executing this inline code.
195 return SubtypeTestCache::null();
196 }
197 if (TypeCheckAsClassEquality(type)) {
198 const intptr_t type_cid = Class::Handle(type.type_class()).id();
199 const Register kInstanceReg = R0;
200 __ tst(kInstanceReg, ShifterOperand(kSmiTagMask));
201 if (type_cid == kSmiCid) {
202 __ b(is_instance_lbl, EQ);
203 } else {
204 __ b(is_not_instance_lbl, EQ);
205 __ CompareClassId(kInstanceReg, type_cid, R3);
206 __ b(is_instance_lbl, EQ);
207 }
208 __ b(is_not_instance_lbl);
209 return SubtypeTestCache::null();
210 }
211 if (type.IsInstantiated()) {
212 const Class& type_class = Class::ZoneHandle(type.type_class());
213 // A Smi object cannot be the instance of a parameterized class.
214 // A class equality check is only applicable with a dst type of a
215 // non-parameterized class or with a raw dst type of a parameterized class.
216 if (type_class.HasTypeArguments()) {
217 return GenerateInstantiatedTypeWithArgumentsTest(token_pos,
218 type,
219 is_instance_lbl,
220 is_not_instance_lbl);
221 // Fall through to runtime call.
222 }
223 const bool has_fall_through =
224 GenerateInstantiatedTypeNoArgumentsTest(token_pos,
225 type,
226 is_instance_lbl,
227 is_not_instance_lbl);
228 if (has_fall_through) {
229 // If test non-conclusive so far, try the inlined type-test cache.
230 // 'type' is known at compile time.
231 return GenerateSubtype1TestCacheLookup(
232 token_pos, type_class, is_instance_lbl, is_not_instance_lbl);
233 } else {
234 return SubtypeTestCache::null();
235 }
236 }
237 return GenerateUninstantiatedTypeTest(token_pos,
238 type,
239 is_instance_lbl,
240 is_not_instance_lbl);
126 } 241 }
127 242
128 243
129 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos, 244 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
130 intptr_t deopt_id, 245 intptr_t deopt_id,
131 const AbstractType& type, 246 const AbstractType& type,
132 bool negate_result, 247 bool negate_result,
133 LocationSummary* locs) { 248 LocationSummary* locs) {
134 UNIMPLEMENTED(); 249 UNIMPLEMENTED();
135 } 250 }
136 251
137 252
253 // Optimize assignable type check by adding inlined tests for:
254 // - NULL -> return NULL.
255 // - Smi -> compile time subtype check (only if dst class is not parameterized).
256 // - Class equality (only if class is not parameterized).
257 // Inputs:
258 // - R0: object.
zra 2013/03/28 16:57:51 Source object?
regis 2013/03/28 17:40:21 Changed to "instance being type checked."
259 // - R1: instantiator type arguments or raw_null.
260 // - R2: instantiator or raw_null.
261 // Returns:
262 // - object in R0 for successful assignable check (or throws TypeError).
263 // Performance notes: positive checks must be quick, negative checks can be slow
264 // as they throw an exception.
138 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos, 265 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
139 intptr_t deopt_id, 266 intptr_t deopt_id,
140 const AbstractType& dst_type, 267 const AbstractType& dst_type,
141 const String& dst_name, 268 const String& dst_name,
142 LocationSummary* locs) { 269 LocationSummary* locs) {
143 UNIMPLEMENTED(); 270 ASSERT(token_pos >= 0);
271 ASSERT(!dst_type.IsNull());
272 ASSERT(dst_type.IsFinalized());
273 // Assignable check is skipped in FlowGraphBuilder, not here.
274 ASSERT(dst_type.IsMalformed() ||
275 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
276 // Preserve instantiator and its type arguments.
277 __ PushList((1 << R1) | (1 << R2));
278 // A null object is always assignable and is returned as result.
279 Label is_assignable, runtime_call;
280 __ CompareImmediate(R0, reinterpret_cast<int32_t>(Object::null()));
281 __ b(&is_assignable, EQ);
282
283 if (!FLAG_eliminate_type_checks) {
284 // If type checks are not eliminated during the graph building then
285 // a transition sentinel can be seen here.
286 __ CompareObject(R0, Object::transition_sentinel());
287 __ b(&is_assignable, EQ);
288 }
289
290 // Generate throw new TypeError() if the type is malformed.
291 if (dst_type.IsMalformed()) {
292 const Error& error = Error::Handle(dst_type.malformed_error());
293 const String& error_message = String::ZoneHandle(
294 Symbols::New(error.ToErrorCString()));
295 __ PushObject(Object::ZoneHandle()); // Make room for the result.
296 __ Push(R0); // Push the source object.
297 __ PushObject(dst_name); // Push the name of the destination.
298 __ PushObject(error_message);
299 GenerateCallRuntime(token_pos,
300 deopt_id,
301 kMalformedTypeErrorRuntimeEntry,
302 locs);
303 // We should never return here.
304 __ bkpt(0);
305
306 __ Bind(&is_assignable); // For a null object.
307 // Restore instantiator and its type arguments.
308 __ PopList((1 << R1) | (1 << R2));
309 return;
310 }
311
312 // Generate inline type check, linking to runtime call if not assignable.
313 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
314 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
315 &is_assignable, &runtime_call);
316
317 __ Bind(&runtime_call);
318 // Load instantiator and its type arguments.
319 __ ldm(IA, SP, (1 << R1) | (1 << R2));
320 __ PushObject(Object::ZoneHandle()); // Make room for the result.
321 __ Push(R0); // Push the source object.
322 __ PushObject(dst_type); // Push the type of the destination.
323 // Push instantiator and its type arguments.
324 __ PushList((1 << R1) | (1 << R2));
325 __ PushObject(dst_name); // Push the name of the destination.
326 __ LoadObject(R0, test_cache);
327 __ Push(R0);
328 GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, locs);
329 // Pop the parameters supplied to the runtime entry. The result of the
330 // type check runtime call is the checked value.
331 __ Drop(6);
332 __ Pop(R0);
333
334 __ Bind(&is_assignable);
335 // Restore instantiator and its type arguments.
336 __ PopList((1 << R1) | (1 << R2));
144 } 337 }
145 338
146 339
147 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { 340 void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) {
148 if (!is_optimizing()) { 341 if (!is_optimizing()) {
149 if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { 342 if (FLAG_enable_type_checks && instr->IsAssertAssignable()) {
150 AssertAssignableInstr* assert = instr->AsAssertAssignable(); 343 AssertAssignableInstr* assert = instr->AsAssertAssignable();
151 AddCurrentDescriptor(PcDescriptors::kDeoptBefore, 344 AddCurrentDescriptor(PcDescriptors::kDeoptBefore,
152 assert->deopt_id(), 345 assert->deopt_id(),
153 assert->token_pos()); 346 assert->token_pos());
(...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 1051
859 1052
860 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1053 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
861 UNIMPLEMENTED(); 1054 UNIMPLEMENTED();
862 } 1055 }
863 1056
864 1057
865 } // namespace dart 1058 } // namespace dart
866 1059
867 #endif // defined TARGET_ARCH_ARM 1060 #endif // defined TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698