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

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

Issue 10787024: Shorter code for simple type comparisons. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 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/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.h » ('j') | 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) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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_IA32. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_IA32.
6 #if defined(TARGET_ARCH_IA32) 6 #if defined(TARGET_ARCH_IA32)
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 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 __ j(EQUAL, is_equal_lbl); 211 __ j(EQUAL, is_equal_lbl);
212 } 212 }
213 __ jmp(is_not_equal_lbl); 213 __ jmp(is_not_equal_lbl);
214 } 214 }
215 215
216 216
217 // Testing against an instantiated type with no arguments, without 217 // Testing against an instantiated type with no arguments, without
218 // SubtypeTestCache. 218 // SubtypeTestCache.
219 // EAX: instance to test against (preserved). 219 // EAX: instance to test against (preserved).
220 // Clobbers ECX, EDI. 220 // Clobbers ECX, EDI.
221 void FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest( 221 // Returns true if there is a fallthrough.
222 bool FlowGraphCompiler::GenerateInstantiatedTypeNoArgumentsTest(
222 intptr_t cid, 223 intptr_t cid,
223 intptr_t token_pos, 224 intptr_t token_pos,
224 const AbstractType& type, 225 const AbstractType& type,
225 Label* is_instance_lbl, 226 Label* is_instance_lbl,
226 Label* is_not_instance_lbl) { 227 Label* is_not_instance_lbl) {
227 ASSERT(type.IsInstantiated()); 228 ASSERT(type.IsInstantiated());
228 const Class& type_class = Class::Handle(type.type_class()); 229 const Class& type_class = Class::Handle(type.type_class());
229 ASSERT(!type_class.HasTypeArguments()); 230 ASSERT(!type_class.HasTypeArguments());
230 231
231 const Register kInstanceReg = EAX; 232 const Register kInstanceReg = EAX;
(...skipping 19 matching lines...) Expand all
251 if (!type_class.is_interface()) { 252 if (!type_class.is_interface()) {
252 __ cmpl(kClassIdReg, Immediate(type_class.id())); 253 __ cmpl(kClassIdReg, Immediate(type_class.id()));
253 __ j(EQUAL, is_instance_lbl); 254 __ j(EQUAL, is_instance_lbl);
254 } 255 }
255 // Bool interface can be implemented only by core class Bool. 256 // Bool interface can be implemented only by core class Bool.
256 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces). 257 // (see ClassFinalizer::ResolveInterfaces for list of restricted interfaces).
257 if (type.IsBoolInterface()) { 258 if (type.IsBoolInterface()) {
258 __ cmpl(kClassIdReg, Immediate(kBool)); 259 __ cmpl(kClassIdReg, Immediate(kBool));
259 __ j(EQUAL, is_instance_lbl); 260 __ j(EQUAL, is_instance_lbl);
260 __ jmp(is_not_instance_lbl); 261 __ jmp(is_not_instance_lbl);
261 return; 262 return false;
262 } 263 }
263 if (type.IsFunctionInterface()) { 264 if (type.IsFunctionInterface()) {
264 // Check if instance is a closure. 265 // Check if instance is a closure.
265 const Immediate raw_null = 266 const Immediate raw_null =
266 Immediate(reinterpret_cast<intptr_t>(Object::null())); 267 Immediate(reinterpret_cast<intptr_t>(Object::null()));
267 __ LoadClassById(EDI, kClassIdReg); 268 __ LoadClassById(EDI, kClassIdReg);
268 __ movl(EDI, FieldAddress(EDI, Class::signature_function_offset())); 269 __ movl(EDI, FieldAddress(EDI, Class::signature_function_offset()));
269 __ cmpl(EDI, raw_null); 270 __ cmpl(EDI, raw_null);
270 __ j(NOT_EQUAL, is_instance_lbl); 271 __ j(NOT_EQUAL, is_instance_lbl);
271 __ jmp(is_not_instance_lbl); 272 __ jmp(is_not_instance_lbl);
272 return; 273 return false;
273 } 274 }
274 // Custom checking for numbers (Smi, Mint, Bigint and Double). 275 // Custom checking for numbers (Smi, Mint, Bigint and Double).
275 // Note that instance is not Smi(checked above). 276 // Note that instance is not Smi (checked above).
276 if (type.IsSubtypeOf( 277 if (type.IsSubtypeOf(
277 Type::Handle(Type::NumberInterface()), &malformed_error)) { 278 Type::Handle(Type::NumberInterface()), &malformed_error)) {
278 GenerateNumberTypeCheck( 279 GenerateNumberTypeCheck(
279 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl); 280 kClassIdReg, type, is_instance_lbl, is_not_instance_lbl);
280 return; 281 return false;
281 } 282 }
282 if (type.IsStringInterface()) { 283 if (type.IsStringInterface()) {
283 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl); 284 GenerateStringTypeCheck(kClassIdReg, is_instance_lbl, is_not_instance_lbl);
284 return; 285 return false;
285 } 286 }
286 // Otherwise fallthrough. 287 // Otherwise fallthrough.
288 return true;
287 } 289 }
288 290
289 291
290 // Uses SubtypeTestCache to store instance class and result. 292 // Uses SubtypeTestCache to store instance class and result.
291 // EAX: instance to test. 293 // EAX: instance to test.
292 // Clobbers EDI, ECX. 294 // Clobbers EDI, ECX.
293 // Immediate class test already done. 295 // Immediate class test already done.
294 // TODO(srdjan): Implement a quicker subtype check, as type test 296 // TODO(srdjan): Implement a quicker subtype check, as type test
295 // arrays can grow too high, but they may be useful when optimizing 297 // arrays can grow too high, but they may be useful when optimizing
296 // code (type-feedback). 298 // code (type-feedback).
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
432 // A class equality check is only applicable with a dst type of a 434 // A class equality check is only applicable with a dst type of a
433 // non-parameterized class or with a raw dst type of a parameterized class. 435 // non-parameterized class or with a raw dst type of a parameterized class.
434 if (type_class.HasTypeArguments()) { 436 if (type_class.HasTypeArguments()) {
435 return GenerateInstantiatedTypeWithArgumentsTest(cid, 437 return GenerateInstantiatedTypeWithArgumentsTest(cid,
436 token_pos, 438 token_pos,
437 type, 439 type,
438 is_instance_lbl, 440 is_instance_lbl,
439 is_not_instance_lbl); 441 is_not_instance_lbl);
440 // Fall through to runtime call. 442 // Fall through to runtime call.
441 } 443 }
442 GenerateInstantiatedTypeNoArgumentsTest(cid, 444 const bool has_fall_through =
443 token_pos, 445 GenerateInstantiatedTypeNoArgumentsTest(cid,
444 type, 446 token_pos,
445 is_instance_lbl, 447 type,
446 is_not_instance_lbl); 448 is_instance_lbl,
447 // If test non-conclusive so far, try the inlined type-test cache. 449 is_not_instance_lbl);
448 // 'type' is known at compile time. 450 if (has_fall_through) {
449 return GenerateSubtype1TestCacheLookup( 451 // If test non-conclusive so far, try the inlined type-test cache.
450 cid, token_pos, type_class, 452 // 'type' is known at compile time.
451 is_instance_lbl, is_not_instance_lbl); 453 return GenerateSubtype1TestCacheLookup(
454 cid, token_pos, type_class,
455 is_instance_lbl, is_not_instance_lbl);
456 } else {
457 return SubtypeTestCache::null();
458 }
452 } 459 }
453 return GenerateUninstantiatedTypeTest(cid, 460 return GenerateUninstantiatedTypeTest(cid,
454 token_pos, 461 token_pos,
455 type, 462 type,
456 is_instance_lbl, 463 is_instance_lbl,
457 is_not_instance_lbl); 464 is_not_instance_lbl);
458 } 465 }
459 466
460 467
461 // If instanceof type test cannot be performed successfully at compile time and 468 // If instanceof type test cannot be performed successfully at compile time and
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
494 // Dynamic at run time. 501 // Dynamic at run time.
495 __ cmpl(EAX, raw_null); 502 __ cmpl(EAX, raw_null);
496 __ j(EQUAL, &is_not_instance); 503 __ j(EQUAL, &is_not_instance);
497 } 504 }
498 505
499 // Generate inline instanceof test. 506 // Generate inline instanceof test.
500 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 507 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
501 test_cache = GenerateInlineInstanceof(cid, token_pos, type, 508 test_cache = GenerateInlineInstanceof(cid, token_pos, type,
502 &is_instance, &is_not_instance); 509 &is_instance, &is_not_instance);
503 510
504 // Generate runtime call. 511 // test_cache is null if there is no fall-through.
505 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
506 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
507 __ PushObject(Object::ZoneHandle()); // Make room for the result.
508 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
509 __ pushl(EAX); // Push the instance.
510 __ PushObject(type); // Push the type.
511 __ pushl(ECX); // TODO(srdjan): Pass instantiator instead of null.
512 __ pushl(EDX); // Instantiator type arguments.
513 __ LoadObject(EAX, test_cache);
514 __ pushl(EAX);
515 GenerateCallRuntime(cid, token_pos, try_index, kInstanceofRuntimeEntry);
516 // Pop the parameters supplied to the runtime entry. The result of the
517 // instanceof runtime call will be left as the result of the operation.
518 __ Drop(6);
519 Label done; 512 Label done;
520 if (negate_result) { 513 if (!test_cache.IsNull()) {
521 __ popl(EDX); 514 // Generate runtime call.
522 __ LoadObject(EAX, bool_true()); 515 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
523 __ cmpl(EDX, EAX); 516 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
524 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 517 __ PushObject(Object::ZoneHandle()); // Make room for the result.
525 __ LoadObject(EAX, bool_false()); 518 __ pushl(Immediate(Smi::RawValue(cid))); // Computation id.
526 } else { 519 __ pushl(EAX); // Push the instance.
527 __ popl(EAX); 520 __ PushObject(type); // Push the type.
521 __ pushl(ECX); // Instantiator.
522 __ pushl(EDX); // Instantiator type arguments.
523 __ LoadObject(EAX, test_cache);
524 __ pushl(EAX);
525 GenerateCallRuntime(cid, token_pos, try_index, kInstanceofRuntimeEntry);
526 // Pop the parameters supplied to the runtime entry. The result of the
527 // instanceof runtime call will be left as the result of the operation.
528 __ Drop(6);
529 if (negate_result) {
530 __ popl(EDX);
531 __ LoadObject(EAX, bool_true());
532 __ cmpl(EDX, EAX);
533 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
534 __ LoadObject(EAX, bool_false());
535 } else {
536 __ popl(EAX);
537 }
538 __ jmp(&done, Assembler::kNearJump);
528 } 539 }
529 __ jmp(&done, Assembler::kNearJump);
530
531 __ Bind(&is_not_instance); 540 __ Bind(&is_not_instance);
532 __ LoadObject(EAX, negate_result ? bool_true() : bool_false()); 541 __ LoadObject(EAX, negate_result ? bool_true() : bool_false());
533 __ jmp(&done, Assembler::kNearJump); 542 __ jmp(&done, Assembler::kNearJump);
534 543
535 __ Bind(&is_instance); 544 __ Bind(&is_instance);
536 __ LoadObject(EAX, negate_result ? bool_false() : bool_true()); 545 __ LoadObject(EAX, negate_result ? bool_false() : bool_true());
537 __ Bind(&done); 546 __ Bind(&done);
538 __ popl(EDX); // Remove pushed instantiator type arguments. 547 __ popl(EDX); // Remove pushed instantiator type arguments.
539 __ popl(ECX); // Remove pushed instantiator. 548 __ popl(ECX); // Remove pushed instantiator.
540 } 549 }
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
1139 } 1148 }
1140 } 1149 }
1141 } 1150 }
1142 1151
1143 1152
1144 #undef __ 1153 #undef __
1145 1154
1146 } // namespace dart 1155 } // namespace dart
1147 1156
1148 #endif // defined TARGET_ARCH_IA32 1157 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698