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

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

Issue 8503034: Add type check tracing (--trace_type_checks). Inline type checks with class types that have only ... (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 1 month 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_ia32.h ('k') | runtime/vm/object.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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 1462 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 __ Bind(&negate_done); 1473 __ Bind(&negate_done);
1474 __ pushl(EAX); 1474 __ pushl(EAX);
1475 } 1475 }
1476 __ Bind(&done); 1476 __ Bind(&done);
1477 } 1477 }
1478 1478
1479 1479
1480 // Jumps to label if ECX equals the given class. 1480 // Jumps to label if ECX equals the given class.
1481 // Inputs: 1481 // Inputs:
1482 // - ECX: tested class. 1482 // - ECX: tested class.
1483 // Destroys EDX. 1483 void CodeGenerator::TestClassAndJump(const Class& cls, Label *label) {
1484 static void TestClassAndJump(Assembler* assembler, 1484 __ CompareObject(ECX, cls);
1485 const Class& cls, 1485 __ j(EQUAL, label, Assembler::kNearJump);
1486 Label *label) { 1486 }
1487 assembler->LoadObject(EDX, cls); 1487
1488 assembler->cmpl(EDX, ECX); 1488
1489 assembler->j(EQUAL, label, Assembler::kNearJump); 1489 static const Class* CoreClass(const char* c_name) {
1490 const String& class_name = String::Handle(String::NewSymbol(c_name));
1491 const Class& cls = Class::ZoneHandle(Library::Handle(
1492 Library::CoreImplLibrary()).LookupClass(class_name));
1493 ASSERT(!cls.IsNull());
1494 return &cls;
1490 } 1495 }
1491 1496
1492 1497
1493 // Optimize assignable type check by adding inlined tests for: 1498 // Optimize assignable type check by adding inlined tests for:
1494 // - NULL -> return NULL. 1499 // - NULL -> return NULL.
1495 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1500 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1496 // - Class equality (only if class is not parameterized). 1501 // - Class equality (only if class is not parameterized).
1497 // Inputs: 1502 // Inputs:
1498 // - EAX: object. 1503 // - EAX: object.
1499 // Destroys ECX and EDX. 1504 // Destroys ECX and EDX.
(...skipping 27 matching lines...) Expand all
1527 const Immediate raw_null = 1532 const Immediate raw_null =
1528 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1533 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1529 Label done, runtime_call; 1534 Label done, runtime_call;
1530 __ cmpl(EAX, raw_null); 1535 __ cmpl(EAX, raw_null);
1531 __ j(EQUAL, &done, Assembler::kNearJump); 1536 __ j(EQUAL, &done, Assembler::kNearJump);
1532 1537
1533 // If dst_type is instantiated and non-parameterized, we can inline code 1538 // If dst_type is instantiated and non-parameterized, we can inline code
1534 // checking whether the assigned instance is a Smi. 1539 // checking whether the assigned instance is a Smi.
1535 if (dst_type.IsInstantiated()) { 1540 if (dst_type.IsInstantiated()) {
1536 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); 1541 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class());
1537 const bool dst_has_type_arguments = dst_type_class.HasTypeArguments(); 1542 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments();
1538 // A Smi object cannot be the instance of a parameterized class. 1543 // A Smi object cannot be the instance of a parameterized class.
1539 // A class equality check is only applicable to a non-parameterized class. 1544 // A class equality check is only applicable with a dst type of a
1540 if (!dst_has_type_arguments) { 1545 // non-parameterized class or with a raw dst type of a parameterized class.
1546 if (dst_class_has_type_arguments) {
1547 const TypeArguments& dst_type_arguments =
1548 TypeArguments::Handle(dst_type.arguments());
1549 const bool is_raw_dst_type = dst_type_arguments.IsNull() ||
1550 dst_type_arguments.IsDynamicTypes(dst_type_arguments.Length());
1551 if (is_raw_dst_type) {
1552 // Dynamic type argument, check only classes.
1553 if (dst_type.IsListInterface()) {
1554 // TODO(srdjan) also accept List<Object>.
1555 __ testl(EAX, Immediate(kSmiTagMask));
1556 __ j(ZERO, &runtime_call, Assembler::kNearJump);
1557 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1558 TestClassAndJump(*CoreClass("ObjectArray"), &done);
1559 TestClassAndJump(*CoreClass("GrowableObjectArray"), &done);
1560 } else if (!dst_type_class.is_interface()) {
1561 __ testl(EAX, Immediate(kSmiTagMask));
1562 __ j(ZERO, &runtime_call, Assembler::kNearJump);
1563 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1564 TestClassAndJump(dst_type_class, &done);
1565 }
1566 // Fall through to runtime class.
1567 }
1568 } else {
1541 Label compare_classes; 1569 Label compare_classes;
1542 __ testl(EAX, Immediate(kSmiTagMask)); 1570 __ testl(EAX, Immediate(kSmiTagMask));
1543 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1571 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1544 // Object is Smi. 1572 // Object is Smi.
1545 const Class& smi_class = Class::Handle(Smi::Class()); 1573 const Class& smi_class = Class::Handle(Smi::Class());
1546 // TODO(regis): We should introduce a SmiType. 1574 // TODO(regis): We should introduce a SmiType.
1547 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1575 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1548 dst_type_class, 1576 dst_type_class,
1549 TypeArguments::Handle())) { 1577 TypeArguments::Handle())) {
1550 // Successful assignable type check: return object in EAX. 1578 // Successful assignable type check: return object in EAX.
1551 __ jmp(&done, Assembler::kNearJump); 1579 __ jmp(&done, Assembler::kNearJump);
1552 } else { 1580 } else {
1553 // Failed assignable type check: call runtime to throw TypeError. 1581 // Failed assignable type check: call runtime to throw TypeError.
1554 __ jmp(&runtime_call, Assembler::kNearJump); 1582 __ jmp(&runtime_call, Assembler::kNearJump);
1555 } 1583 }
1556 // Compare if the classes are equal. 1584 // Compare if the classes are equal.
1557 __ Bind(&compare_classes); 1585 __ Bind(&compare_classes);
1558 // If dst_type is an interface, we can skip the class equality check, 1586 // If dst_type is an interface, we can skip the class equality check,
1559 // because instances cannot be of an interface type. 1587 // because instances cannot be of an interface type.
1560 if (!dst_type_class.is_interface()) { 1588 if (!dst_type_class.is_interface()) {
1561 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1589 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1562 TestClassAndJump(assembler_, dst_type_class, &done); 1590 TestClassAndJump(dst_type_class, &done);
1563 } else { 1591 } else {
1564 // However, for specific core library interfaces, we can check for 1592 // However, for specific core library interfaces, we can check for
1565 // specific core library classes. 1593 // specific core library classes.
1566 if (dst_type.IsBoolInterface()) { 1594 if (dst_type.IsBoolInterface()) {
1567 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1595 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1568 const Class& bool_class = Class::ZoneHandle( 1596 const Class& bool_class = Class::ZoneHandle(
1569 Isolate::Current()->object_store()->bool_class()); 1597 Isolate::Current()->object_store()->bool_class());
1570 TestClassAndJump(assembler_, bool_class, &done); 1598 TestClassAndJump(bool_class, &done);
1571 } else if (dst_type.IsSubtypeOf( 1599 } else if (dst_type.IsSubtypeOf(
1572 Type::Handle(Type::NumberInterface()))) { 1600 Type::Handle(Type::NumberInterface()))) {
1573 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1601 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1574 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { 1602 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) {
1575 // We already checked for Smi above. 1603 // We already checked for Smi above.
1576 const Class& mint_class = Class::ZoneHandle( 1604 const Class& mint_class = Class::ZoneHandle(
1577 Isolate::Current()->object_store()->mint_class()); 1605 Isolate::Current()->object_store()->mint_class());
1578 TestClassAndJump(assembler_, mint_class, &done); 1606 TestClassAndJump(mint_class, &done);
1579 const Class& bigint_class = Class::ZoneHandle( 1607 const Class& bigint_class = Class::ZoneHandle(
1580 Isolate::Current()->object_store()->bigint_class()); 1608 Isolate::Current()->object_store()->bigint_class());
1581 TestClassAndJump(assembler_, bigint_class, &done); 1609 TestClassAndJump(bigint_class, &done);
1582 } 1610 }
1583 if (dst_type.IsDoubleInterface() || dst_type.IsNumberInterface()) { 1611 if (dst_type.IsDoubleInterface() || dst_type.IsNumberInterface()) {
1584 const Class& double_class = Class::ZoneHandle( 1612 const Class& double_class = Class::ZoneHandle(
1585 Isolate::Current()->object_store()->double_class()); 1613 Isolate::Current()->object_store()->double_class());
1586 TestClassAndJump(assembler_, double_class, &done); 1614 TestClassAndJump(double_class, &done);
1587 } 1615 }
1588 } else if (dst_type.IsStringInterface()) { 1616 } else if (dst_type.IsStringInterface()) {
1589 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1617 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1590 const Class& one_byte_string_class = Class::ZoneHandle( 1618 const Class& one_byte_string_class = Class::ZoneHandle(
1591 Isolate::Current()->object_store()->one_byte_string_class()); 1619 Isolate::Current()->object_store()->one_byte_string_class());
1592 TestClassAndJump(assembler_, one_byte_string_class, &done); 1620 TestClassAndJump(one_byte_string_class, &done);
1593 const Class& two_byte_string_class = Class::ZoneHandle( 1621 const Class& two_byte_string_class = Class::ZoneHandle(
1594 Isolate::Current()->object_store()->two_byte_string_class()); 1622 Isolate::Current()->object_store()->two_byte_string_class());
1595 TestClassAndJump(assembler_, two_byte_string_class, &done); 1623 TestClassAndJump(two_byte_string_class, &done);
1596 const Class& four_byte_string_class = Class::ZoneHandle( 1624 const Class& four_byte_string_class = Class::ZoneHandle(
1597 Isolate::Current()->object_store()->four_byte_string_class()); 1625 Isolate::Current()->object_store()->four_byte_string_class());
1598 TestClassAndJump(assembler_, four_byte_string_class, &done); 1626 TestClassAndJump(four_byte_string_class, &done);
1599 } else if (dst_type.IsFunctionInterface()) { 1627 } else if (dst_type.IsFunctionInterface()) {
1600 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1628 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1601 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset())); 1629 __ movl(ECX, FieldAddress(ECX, Class::signature_function_offset()));
1602 __ cmpl(ECX, raw_null); 1630 __ cmpl(ECX, raw_null);
1603 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 1631 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
1604 } 1632 }
1605 } 1633 }
1606 } 1634 }
1607 } 1635 }
1608 __ Bind(&runtime_call); 1636 __ Bind(&runtime_call);
(...skipping 1071 matching lines...) Expand 10 before | Expand all | Expand 10 after
2680 const Class& cls = Class::Handle(parsed_function_.function().owner()); 2708 const Class& cls = Class::Handle(parsed_function_.function().owner());
2681 const Script& script = Script::Handle(cls.script()); 2709 const Script& script = Script::Handle(cls.script());
2682 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); 2710 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args);
2683 Isolate::Current()->long_jump_base()->Jump(1, error_msg); 2711 Isolate::Current()->long_jump_base()->Jump(1, error_msg);
2684 UNREACHABLE(); 2712 UNREACHABLE();
2685 } 2713 }
2686 2714
2687 } // namespace dart 2715 } // namespace dart
2688 2716
2689 #endif // defined TARGET_ARCH_IA32 2717 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698