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

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

Issue 10010029: When checking against non-parametrized types use a cache to hold result tuples (class, result). Tha… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 8 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/code_generator.cc ('k') | runtime/vm/code_generator_x64.cc » ('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/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 1292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1303 Type::Handle(Isolate::Current()->object_store()->object_type()); 1303 Type::Handle(Isolate::Current()->object_store()->object_type());
1304 Error& malformed_error = Error::Handle(); 1304 Error& malformed_error = Error::Handle();
1305 if (type.IsInstantiated() && 1305 if (type.IsInstantiated() &&
1306 object_type.IsSubtypeOf(type, &malformed_error)) { 1306 object_type.IsSubtypeOf(type, &malformed_error)) {
1307 __ PushObject(negate_result ? bool_false : bool_true); 1307 __ PushObject(negate_result ? bool_false : bool_true);
1308 return; 1308 return;
1309 } 1309 }
1310 1310
1311 const Immediate raw_null = 1311 const Immediate raw_null =
1312 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1312 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1313 Label done; 1313 Label done, check_negate_done;
1314 // If type is instantiated and non-parameterized, we can inline code 1314 // If type is instantiated and non-parameterized, we can inline code
1315 // checking whether the tested instance is a Smi. 1315 // checking whether the tested instance is a Smi.
1316 if (type.IsInstantiated()) { 1316 if (type.IsInstantiated()) {
1317 // A null object is only an instance of Object and Dynamic, which has 1317 // A null object is only an instance of Object and Dynamic, which has
1318 // already been checked above (if the type is instantiated). So we can 1318 // already been checked above (if the type is instantiated). So we can
1319 // return false here if the instance is null (and if the type is 1319 // return false here if the instance is null (and if the type is
1320 // instantiated). 1320 // instantiated).
1321 // We can only inline this null check if the type is instantiated at compile 1321 // We can only inline this null check if the type is instantiated at compile
1322 // time, since an uninstantiated type at compile time could be Object or 1322 // time, since an uninstantiated type at compile time could be Object or
1323 // Dynamic at run time. 1323 // Dynamic at run time.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1359 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1359 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1360 __ CompareObject(ECX, type_class); 1360 __ CompareObject(ECX, type_class);
1361 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1361 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1362 __ PushObject(negate_result ? bool_false : bool_true); 1362 __ PushObject(negate_result ? bool_false : bool_true);
1363 __ jmp(&done, Assembler::kNearJump); 1363 __ jmp(&done, Assembler::kNearJump);
1364 } 1364 }
1365 } 1365 }
1366 __ Bind(&runtime_call); 1366 __ Bind(&runtime_call);
1367 // Fall through to runtime call. 1367 // Fall through to runtime call.
1368 } else { 1368 } else {
1369 ASSERT(!requires_type_arguments);
1370 // Test if object is Smi and for a couple known test-classes.
1369 Label compare_classes; 1371 Label compare_classes;
1370 __ testl(EAX, Immediate(kSmiTagMask)); 1372 __ testl(EAX, Immediate(kSmiTagMask));
1371 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1373 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1372 // Object is Smi. 1374 // Object is Smi.
1373 const Class& smi_class = Class::Handle(Smi::Class()); 1375 const Class& smi_class = Class::Handle(Smi::Class());
1374 // TODO(regis): We should introduce a SmiType. 1376 // TODO(regis): We should introduce a SmiType.
1375 Error& malformed_error = Error::Handle(); 1377 Error& malformed_error = Error::Handle();
1376 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1378 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1377 type_class, 1379 type_class,
1378 TypeArguments::Handle(), 1380 TypeArguments::Handle(),
1379 &malformed_error)) { 1381 &malformed_error)) {
1380 __ PushObject(negate_result ? bool_false : bool_true); 1382 __ PushObject(negate_result ? bool_false : bool_true);
1381 } else { 1383 } else {
1382 __ PushObject(negate_result ? bool_true : bool_false); 1384 __ PushObject(negate_result ? bool_true : bool_false);
1383 } 1385 }
1384 __ jmp(&done, Assembler::kNearJump); 1386 __ jmp(&done, Assembler::kNearJump);
1385 1387
1386 // Compare if the classes are equal. 1388 // Compare if the classes are equal.
1387 __ Bind(&compare_classes); 1389 __ Bind(&compare_classes);
1388 const Class* compare_class = NULL; 1390 const Class* compare_class = NULL;
1389 if (type.IsStringInterface()) { 1391 if (type.IsStringInterface()) {
1390 compare_class = &Class::ZoneHandle( 1392 compare_class = &Class::ZoneHandle(
1391 Isolate::Current()->object_store()->one_byte_string_class()); 1393 Isolate::Current()->object_store()->one_byte_string_class());
1392 } else if (type.IsBoolInterface()) { 1394 } else if (type.IsBoolInterface()) {
1393 compare_class = &Class::ZoneHandle( 1395 compare_class = &Class::ZoneHandle(
1394 Isolate::Current()->object_store()->bool_class()); 1396 Isolate::Current()->object_store()->bool_class());
1395 } else if (!type_class.is_interface()) { 1397 } else if (!type_class.is_interface()) {
1396 compare_class = &type_class; 1398 // Use equality test in prolog of cache test.
1399 compare_class = NULL;
1397 } 1400 }
1398 if (compare_class != NULL) { 1401 // EAX: instance being tested.
1402 if (compare_class == NULL) {
1403 // Optional quick equality check and then the type test cache test.
1404 Label loop, runtime_call, found_in_cache, cache_test;
1405 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1406 if (!type_class.is_interface()) {
1407 // Class equality test first.
1408 __ CompareObject(ECX, type_class);
1409 __ j(NOT_EQUAL, &cache_test, Assembler::kNearJump);
1410 // Equal!
1411 __ PushObject(negate_result ? bool_false : bool_true);
1412 __ jmp(&done, Assembler::kNearJump);
1413 }
1414 __ Bind(&cache_test);
1415 // TODO(srdjan): Convert other tests to this simple form.
1416 // Class we are testing against has no type arguments.
1417 // TODO(srdjan): Canonicalize initial array?
1418 // TODO(srdjan): Account for 'negate_result' in cache.
1419 // The type test array is null-terminated. Two consecutive
1420 // array elements correspond to one test:
1421 // array[i + 0] : class.
1422 // array[i + 1] : result for the class.
1423 AddCurrentDescriptor(PcDescriptors::kTypeTest, node_id, token_index);
1424 __ LoadObject(EDX, Array::ZoneHandle(Array::New(2)));
1425 __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag));
1426 __ Bind(&loop);
1427 __ movl(EBX, Address(EDX, 0));
1428 __ cmpl(ECX, EBX);
1429 __ j(EQUAL, &found_in_cache, Assembler::kNearJump);
1430 __ addl(EDX, Immediate(kWordSize * 2));
1431 __ cmpl(EBX, raw_null);
1432 __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
1433 __ jmp(&runtime_call, Assembler::kNearJump);
1434 __ Bind(&found_in_cache);
1435 __ pushl(Address(EDX, kWordSize));
1436 __ jmp(&check_negate_done);
1437 __ Bind(&runtime_call);
1438 } else {
1399 Label runtime_call; 1439 Label runtime_call;
1400 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1440 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1401 __ CompareObject(ECX, *compare_class); 1441 __ CompareObject(ECX, *compare_class);
1402 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1442 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1403 __ PushObject(negate_result ? bool_false : bool_true); 1443 __ PushObject(negate_result ? bool_false : bool_true);
1404 __ jmp(&done, Assembler::kNearJump); 1444 __ jmp(&done, Assembler::kNearJump);
1405 __ Bind(&runtime_call); 1445 __ Bind(&runtime_call);
1406 } 1446 }
1407 } 1447 }
1408 } 1448 }
1409 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1449 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1410 const Immediate location = 1450 const Immediate location =
1411 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); 1451 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1452 const Immediate node_id_as_smi =
1453 Immediate(reinterpret_cast<int32_t>(Smi::New(node_id)));
1412 __ pushl(location); // Push the source location. 1454 __ pushl(location); // Push the source location.
1455 __ pushl(node_id_as_smi); // node-id.
1413 __ pushl(EAX); // Push the instance. 1456 __ pushl(EAX); // Push the instance.
1414 __ PushObject(type); // Push the type. 1457 __ PushObject(type); // Push the type.
1415 if (!type.IsInstantiated()) { 1458 if (!type.IsInstantiated()) {
1416 GenerateInstantiatorTypeArguments(token_index); 1459 GenerateInstantiatorTypeArguments(token_index);
1417 } else { 1460 } else {
1418 __ pushl(raw_null); // Null instantiator. 1461 __ pushl(raw_null); // Null instantiator.
1419 } 1462 }
1420 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); 1463 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
1421 // Pop the two parameters supplied to the runtime entry. The result of the 1464 // Pop the two parameters supplied to the runtime entry. The result of the
1422 // instanceof runtime call will be left as the result of the operation. 1465 // instanceof runtime call will be left as the result of the operation.
1423 __ addl(ESP, Immediate(4 * kWordSize)); 1466 __ addl(ESP, Immediate(5 * kWordSize));
1467 __ Bind(&check_negate_done);
1424 if (negate_result) { 1468 if (negate_result) {
1425 Label negate_done; 1469 Label negate_done;
1426 __ popl(EDX); 1470 __ popl(EDX);
1427 __ LoadObject(EAX, bool_true); 1471 __ LoadObject(EAX, bool_true);
1428 __ cmpl(EDX, EAX); 1472 __ cmpl(EDX, EAX);
1429 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); 1473 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump);
1430 __ LoadObject(EAX, bool_false); 1474 __ LoadObject(EAX, bool_false);
1431 __ Bind(&negate_done); 1475 __ Bind(&negate_done);
1432 __ pushl(EAX); 1476 __ pushl(EAX);
1433 } 1477 }
(...skipping 1355 matching lines...) Expand 10 before | Expand all | Expand 10 after
2789 const Error& error = Error::Handle( 2833 const Error& error = Error::Handle(
2790 Parser::FormatError(script, token_index, "Error", format, args)); 2834 Parser::FormatError(script, token_index, "Error", format, args));
2791 va_end(args); 2835 va_end(args);
2792 Isolate::Current()->long_jump_base()->Jump(1, error); 2836 Isolate::Current()->long_jump_base()->Jump(1, error);
2793 UNREACHABLE(); 2837 UNREACHABLE();
2794 } 2838 }
2795 2839
2796 } // namespace dart 2840 } // namespace dart
2797 2841
2798 #endif // defined TARGET_ARCH_IA32 2842 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/code_generator_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698