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

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

Issue 10051011: Eliminate type checks that can successfully be performed at compile time. (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_ia32.h ('k') | runtime/vm/code_generator_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/code_generator.h" 8 #include "vm/code_generator.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
660 __ pushl(EAX); // Preserve result. 660 __ pushl(EAX); // Preserve result.
661 __ pushl(EBX); // Argument for runtime: function to optimize. 661 __ pushl(EBX); // Argument for runtime: function to optimize.
662 __ CallRuntimeFromDart(kOptimizeInvokedFunctionRuntimeEntry); 662 __ CallRuntimeFromDart(kOptimizeInvokedFunctionRuntimeEntry);
663 __ popl(EBX); // Remove argument. 663 __ popl(EBX); // Remove argument.
664 __ popl(EAX); // Restore result. 664 __ popl(EAX); // Restore result.
665 __ Bind(&not_yet_hot); 665 __ Bind(&not_yet_hot);
666 } 666 }
667 } 667 }
668 if (FLAG_trace_functions) { 668 if (FLAG_trace_functions) {
669 const Function& function = 669 const Function& function =
670 Function::ZoneHandle(parsed_function_.function().raw()); 670 Function::ZoneHandle(parsed_function_.function().raw());
671 __ LoadObject(EBX, function); 671 __ LoadObject(EBX, function);
672 __ pushl(EAX); // Preserve result. 672 __ pushl(EAX); // Preserve result.
673 __ pushl(EBX); 673 __ pushl(EBX);
674 GenerateCallRuntime(AstNode::kNoId, 674 GenerateCallRuntime(AstNode::kNoId,
675 0, 675 0,
676 kTraceFunctionExitRuntimeEntry); 676 kTraceFunctionExitRuntimeEntry);
677 __ popl(EAX); // Remove argument. 677 __ popl(EAX); // Remove argument.
678 __ popl(EAX); // Restore result. 678 __ popl(EAX); // Restore result.
679 } 679 }
680 __ LeaveFrame(); 680 __ LeaveFrame();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 } else { 716 } else {
717 __ LoadObject(EAX, literal); 717 __ LoadObject(EAX, literal);
718 } 718 }
719 } else { 719 } else {
720 // Pop the previously evaluated result value into EAX. 720 // Pop the previously evaluated result value into EAX.
721 __ popl(EAX); 721 __ popl(EAX);
722 } 722 }
723 723
724 // Generate type check. 724 // Generate type check.
725 if (FLAG_enable_type_checks) { 725 if (FLAG_enable_type_checks) {
726 const bool returns_null = node->value()->IsLiteralNode() &&
727 node->value()->AsLiteralNode()->literal().IsNull();
728 const RawFunction::Kind kind = parsed_function().function().kind(); 726 const RawFunction::Kind kind = parsed_function().function().kind();
729 const bool is_implicit_getter = 727 const bool is_implicit_getter =
730 (kind == RawFunction::kImplicitGetter) || 728 (kind == RawFunction::kImplicitGetter) ||
731 (kind == RawFunction::kConstImplicitGetter); 729 (kind == RawFunction::kConstImplicitGetter);
732 const bool is_static = parsed_function().function().is_static(); 730 const bool is_static = parsed_function().function().is_static();
733 // Implicit getters do not need a type check at return, unless they compute 731 // Implicit getters do not need a type check at return, unless they compute
734 // the initial value of a static field. 732 // the initial value of a static field.
735 if (!returns_null && (is_static || !is_implicit_getter)) { 733 if (is_static || !is_implicit_getter) {
736 GenerateAssertAssignable( 734 GenerateAssertAssignable(
737 node->id(), 735 node->id(),
738 node->value()->token_index(), 736 node->value()->token_index(),
737 node->value(),
739 AbstractType::ZoneHandle(parsed_function().function().result_type()), 738 AbstractType::ZoneHandle(parsed_function().function().result_type()),
740 String::ZoneHandle(String::NewSymbol("function result"))); 739 String::ZoneHandle(String::NewSymbol("function result")));
741 } 740 }
742 } 741 }
743 GenerateReturnEpilog(node); 742 GenerateReturnEpilog(node);
744 } 743 }
745 744
746 745
747 void CodeGenerator::VisitLiteralNode(LiteralNode* node) { 746 void CodeGenerator::VisitLiteralNode(LiteralNode* node) {
748 if (!IsResultNeeded(node)) return; 747 if (!IsResultNeeded(node)) return;
749 __ PushObject(node->literal()); 748 __ PushObject(node->literal());
750 } 749 }
751 750
752 751
753 void CodeGenerator::VisitTypeNode(TypeNode* node) { 752 void CodeGenerator::VisitTypeNode(TypeNode* node) {
754 // Type nodes are handled specially by the code generator. 753 // Type nodes are handled specially by the code generator.
755 UNREACHABLE(); 754 UNREACHABLE();
756 } 755 }
757 756
758 757
759 void CodeGenerator::VisitAssignableNode(AssignableNode* node) { 758 void CodeGenerator::VisitAssignableNode(AssignableNode* node) {
760 ASSERT(FLAG_enable_type_checks); 759 ASSERT(FLAG_enable_type_checks);
761 node->expr()->Visit(this); 760 node->expr()->Visit(this);
762 __ popl(EAX); 761 __ popl(EAX);
763 GenerateAssertAssignable(node->id(), 762 GenerateAssertAssignable(node->id(),
764 node->token_index(), 763 node->token_index(),
764 node->expr(),
765 node->type(), 765 node->type(),
766 node->dst_name()); 766 node->dst_name());
767 if (IsResultNeeded(node)) { 767 if (IsResultNeeded(node)) {
768 __ pushl(EAX); 768 __ pushl(EAX);
769 } 769 }
770 } 770 }
771 771
772 772
773 void CodeGenerator::VisitClosureNode(ClosureNode* node) { 773 void CodeGenerator::VisitClosureNode(ClosureNode* node) {
774 const Function& function = node->function(); 774 const Function& function = node->function();
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 } 964 }
965 } 965 }
966 966
967 967
968 void CodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { 968 void CodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) {
969 node->value()->Visit(this); 969 node->value()->Visit(this);
970 __ popl(EAX); 970 __ popl(EAX);
971 if (FLAG_enable_type_checks) { 971 if (FLAG_enable_type_checks) {
972 GenerateAssertAssignable(node->id(), 972 GenerateAssertAssignable(node->id(),
973 node->value()->token_index(), 973 node->value()->token_index(),
974 node->value(),
974 node->local().type(), 975 node->local().type(),
975 node->local().name()); 976 node->local().name());
976 } 977 }
977 GenerateStoreVariable(node->local(), EAX, EDX); 978 GenerateStoreVariable(node->local(), EAX, EDX);
978 if (IsResultNeeded(node)) { 979 if (IsResultNeeded(node)) {
979 __ pushl(EAX); 980 __ pushl(EAX);
980 } 981 }
981 } 982 }
982 983
983 984
984 void CodeGenerator::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) { 985 void CodeGenerator::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) {
985 node->instance()->Visit(this); 986 node->instance()->Visit(this);
986 MarkDeoptPoint(node->id(), node->token_index()); 987 MarkDeoptPoint(node->id(), node->token_index());
987 __ popl(EAX); // Instance. 988 __ popl(EAX); // Instance.
988 __ movl(EAX, FieldAddress(EAX, node->field().Offset())); 989 __ movl(EAX, FieldAddress(EAX, node->field().Offset()));
989 if (IsResultNeeded(node)) { 990 if (IsResultNeeded(node)) {
990 __ pushl(EAX); 991 __ pushl(EAX);
991 } 992 }
992 } 993 }
993 994
994 995
995 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) { 996 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) {
996 node->instance()->Visit(this); 997 node->instance()->Visit(this);
997 node->value()->Visit(this); 998 node->value()->Visit(this);
998 MarkDeoptPoint(node->id(), node->token_index()); 999 MarkDeoptPoint(node->id(), node->token_index());
999 __ popl(EAX); // Value. 1000 __ popl(EAX); // Value.
1000 if (FLAG_enable_type_checks) { 1001 if (FLAG_enable_type_checks) {
1001 GenerateAssertAssignable(node->id(), 1002 GenerateAssertAssignable(node->id(),
1002 node->value()->token_index(), 1003 node->value()->token_index(),
1004 node->value(),
1003 AbstractType::ZoneHandle(node->field().type()), 1005 AbstractType::ZoneHandle(node->field().type()),
1004 String::ZoneHandle(node->field().name())); 1006 String::ZoneHandle(node->field().name()));
1005 } 1007 }
1006 __ popl(EDX); // Instance. 1008 __ popl(EDX); // Instance.
1007 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); 1009 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX);
1008 ASSERT(!IsResultNeeded(node)); 1010 ASSERT(!IsResultNeeded(node));
1009 } 1011 }
1010 1012
1011 1013
1012 // Expects array and index on stack and returns result in EAX. 1014 // Expects array and index on stack and returns result in EAX.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1096 } 1098 }
1097 1099
1098 1100
1099 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { 1101 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
1100 node->value()->Visit(this); 1102 node->value()->Visit(this);
1101 MarkDeoptPoint(node->id(), node->token_index()); 1103 MarkDeoptPoint(node->id(), node->token_index());
1102 __ popl(EAX); // Value. 1104 __ popl(EAX); // Value.
1103 if (FLAG_enable_type_checks) { 1105 if (FLAG_enable_type_checks) {
1104 GenerateAssertAssignable(node->id(), 1106 GenerateAssertAssignable(node->id(),
1105 node->value()->token_index(), 1107 node->value()->token_index(),
1108 node->value(),
1106 AbstractType::ZoneHandle(node->field().type()), 1109 AbstractType::ZoneHandle(node->field().type()),
1107 String::ZoneHandle(node->field().name())); 1110 String::ZoneHandle(node->field().name()));
1108 } 1111 }
1109 __ LoadObject(EDX, node->field()); 1112 __ LoadObject(EDX, node->field());
1110 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); 1113 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX);
1111 if (IsResultNeeded(node)) { 1114 if (IsResultNeeded(node)) {
1112 // The result is the input value. 1115 // The result is the input value.
1113 __ pushl(EAX); 1116 __ pushl(EAX);
1114 } 1117 }
1115 } 1118 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1182 } 1185 }
1183 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); 1186 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1)));
1184 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; 1187 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-";
1185 __ pushl(EAX); 1188 __ pushl(EAX);
1186 __ pushl(value); 1189 __ pushl(value);
1187 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); 1190 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name);
1188 // result is in EAX. 1191 // result is in EAX.
1189 if (FLAG_enable_type_checks) { 1192 if (FLAG_enable_type_checks) {
1190 GenerateAssertAssignable(node->id(), 1193 GenerateAssertAssignable(node->id(),
1191 node->token_index(), 1194 node->token_index(),
1195 NULL,
1192 node->local().type(), 1196 node->local().type(),
1193 node->local().name()); 1197 node->local().name());
1194 } 1198 }
1195 GenerateStoreVariable(node->local(), EAX, EDX); 1199 GenerateStoreVariable(node->local(), EAX, EDX);
1196 if (node->prefix() && IsResultNeeded(node)) { 1200 if (node->prefix() && IsResultNeeded(node)) {
1197 __ pushl(EAX); 1201 __ pushl(EAX);
1198 } 1202 }
1199 } 1203 }
1200 1204
1201 1205
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1274 1278
1275 static const Class* CoreClass(const char* c_name) { 1279 static const Class* CoreClass(const char* c_name) {
1276 const String& class_name = String::Handle(String::NewSymbol(c_name)); 1280 const String& class_name = String::Handle(String::NewSymbol(c_name));
1277 const Class& cls = Class::ZoneHandle(Library::Handle( 1281 const Class& cls = Class::ZoneHandle(Library::Handle(
1278 Library::CoreImplLibrary()).LookupClass(class_name)); 1282 Library::CoreImplLibrary()).LookupClass(class_name));
1279 ASSERT(!cls.IsNull()); 1283 ASSERT(!cls.IsNull());
1280 return &cls; 1284 return &cls;
1281 } 1285 }
1282 1286
1283 1287
1284 // Optimize instanceof type test by adding inlined tests for: 1288 // If instanceof type test cannot be performed successfully at compile time and
1289 // therefore eliminated, optimize it by adding inlined tests for:
1285 // - NULL -> return false. 1290 // - NULL -> return false.
1286 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1291 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1287 // - Class equality (only if class is not parameterized). 1292 // - Class equality (only if class is not parameterized).
1288 // Inputs: 1293 // Inputs:
1289 // - EAX: object. 1294 // - EAX: object.
1290 // Destroys ECX. 1295 // Destroys ECX.
1291 // Returns: 1296 // Returns:
1292 // - true or false on stack. 1297 // - true or false on stack.
1293 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, 1298 void CodeGenerator::GenerateInstanceOf(intptr_t node_id,
1294 intptr_t token_index, 1299 intptr_t token_index,
1300 AstNode* value,
1295 const AbstractType& type, 1301 const AbstractType& type,
1296 bool negate_result) { 1302 bool negate_result) {
1297 ASSERT(type.IsFinalized() && !type.IsMalformed()); 1303 ASSERT(type.IsFinalized() && !type.IsMalformed());
1298 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1304 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1299 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1305 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1300 1306
1301 // All instances are of a subtype of the Object type. 1307 // All objects are instances of type T if Object type is a subtype of type T.
1302 const Type& object_type = 1308 const Type& object_type =
1303 Type::Handle(Isolate::Current()->object_store()->object_type()); 1309 Type::Handle(Isolate::Current()->object_store()->object_type());
1304 Error& malformed_error = Error::Handle(); 1310 Error& malformed_error = Error::Handle();
1305 if (type.IsInstantiated() && 1311 if (type.IsInstantiated() &&
1306 object_type.IsSubtypeOf(type, &malformed_error)) { 1312 object_type.IsSubtypeOf(type, &malformed_error)) {
1307 __ PushObject(negate_result ? bool_false : bool_true); 1313 __ PushObject(negate_result ? bool_false : bool_true);
1308 return; 1314 return;
1309 } 1315 }
1310 1316
1317 // Eliminate the test if it can be performed successfully at compile time.
1318 if ((value != NULL) && value->IsLiteralNode() && type.IsInstantiated()) {
1319 const Instance& literal_value = value->AsLiteralNode()->literal();
1320 const Class& cls = Class::Handle(literal_value.clazz());
1321 if (cls.IsNullClass()) {
1322 ASSERT(literal_value.IsNull() ||
1323 (literal_value.raw() == Object::sentinel()) ||
1324 (literal_value.raw() == Object::transition_sentinel()));
1325 // A null object is only an instance of Object and Dynamic, which has
1326 // already been checked above (if the type is instantiated). So we can
1327 // return false here if the instance is null (and if the type is
1328 // instantiated).
1329 __ PushObject(negate_result ? bool_true : bool_false);
1330 } else {
1331 Error& malformed_error = Error::Handle();
1332 if (literal_value.IsInstanceOf(type,
1333 TypeArguments::Handle(),
1334 &malformed_error)) {
1335 __ PushObject(negate_result ? bool_false : bool_true);
1336 } else {
1337 ASSERT(malformed_error.IsNull());
1338 __ PushObject(negate_result ? bool_true : bool_false);
1339 }
1340 }
1341 return;
1342 }
1343
1311 const Immediate raw_null = 1344 const Immediate raw_null =
1312 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1345 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1313 Label done, check_negate_done; 1346 Label done, check_negate_done;
1314 // If type is instantiated and non-parameterized, we can inline code 1347 // If type is instantiated and non-parameterized, we can inline code
1315 // checking whether the tested instance is a Smi. 1348 // checking whether the tested instance is a Smi.
1316 if (type.IsInstantiated()) { 1349 if (type.IsInstantiated()) {
1317 // A null object is only an instance of Object and Dynamic, which has 1350 // 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 1351 // 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 1352 // return false here if the instance is null (and if the type is
1320 // instantiated). 1353 // instantiated).
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 1514
1482 // Jumps to label if ECX equals the given class. 1515 // Jumps to label if ECX equals the given class.
1483 // Inputs: 1516 // Inputs:
1484 // - ECX: tested class. 1517 // - ECX: tested class.
1485 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) { 1518 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) {
1486 __ CompareObject(ECX, cls); 1519 __ CompareObject(ECX, cls);
1487 __ j(EQUAL, label, Assembler::kNearJump); 1520 __ j(EQUAL, label, Assembler::kNearJump);
1488 } 1521 }
1489 1522
1490 1523
1491 // Optimize assignable type check by adding inlined tests for: 1524 // If type check cannot be performed successfully at compile time and therefore
1525 // eliminated, optimize it by adding inlined tests for:
1492 // - NULL -> return NULL. 1526 // - NULL -> return NULL.
1493 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1527 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1494 // - Class equality (only if class is not parameterized). 1528 // - Class equality (only if class is not parameterized).
1495 // Inputs: 1529 // Inputs:
1496 // - EAX: object. 1530 // - EAX: object.
1497 // Destroys ECX and EDX. 1531 // Destroys ECX and EDX.
1498 // Returns: 1532 // Returns:
1499 // - object in EAX for successful assignable check (or throws TypeError). 1533 // - object in EAX for successful assignable check (or throws TypeError).
1500 // Performance notes: positive checks must be quick, negative checks can be slow 1534 // Performance notes: positive checks must be quick, negative checks can be slow
1501 // as they throw an exception. 1535 // as they throw an exception.
1502 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1536 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1503 intptr_t token_index, 1537 intptr_t token_index,
1538 AstNode* value,
1504 const AbstractType& dst_type, 1539 const AbstractType& dst_type,
1505 const String& dst_name) { 1540 const String& dst_name) {
1506 ASSERT(FLAG_enable_type_checks); 1541 ASSERT(FLAG_enable_type_checks);
1507 ASSERT(token_index >= 0); 1542 ASSERT(token_index >= 0);
1508 ASSERT(!dst_type.IsNull()); 1543 ASSERT(!dst_type.IsNull());
1509 ASSERT(dst_type.IsFinalized()); 1544 ASSERT(dst_type.IsFinalized());
1510 1545
1511 // Any expression is assignable to the Dynamic type and to the Object type. 1546 // Any expression is assignable to the Dynamic type and to the Object type.
1512 // Skip the test. 1547 // Skip the test.
1513 if (!dst_type.IsMalformed() && 1548 if (!dst_type.IsMalformed() &&
1514 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { 1549 (dst_type.IsDynamicType() || dst_type.IsObjectType())) {
1515 return; 1550 return;
1516 } 1551 }
1517 1552
1518 // It is a compile-time error to explicitly return a value (including null) 1553 // It is a compile-time error to explicitly return a value (including null)
1519 // from a void function. However, functions that do not explicitly return a 1554 // from a void function. However, functions that do not explicitly return a
1520 // value, implicitly return null. This includes void functions. Therefore, we 1555 // value, implicitly return null. This includes void functions. Therefore, we
1521 // skip the type test here and trust the parser to only return null in void 1556 // skip the type test here and trust the parser to only return null in void
1522 // function. 1557 // function.
1523 if (dst_type.IsVoidType()) { 1558 if (dst_type.IsVoidType()) {
1524 return; 1559 return;
1525 } 1560 }
1526 1561
1562 // Eliminate the test if it can be performed successfully at compile time.
1563 if ((value != NULL) && value->IsLiteralNode()) {
1564 const Instance& literal_value = value->AsLiteralNode()->literal();
1565 const Class& cls = Class::Handle(literal_value.clazz());
1566 if (cls.IsNullClass()) {
1567 ASSERT(literal_value.IsNull() ||
1568 (literal_value.raw() == Object::sentinel()) ||
1569 (literal_value.raw() == Object::transition_sentinel()));
1570 return;
1571 }
1572 Error& malformed_error = Error::Handle();
1573 if (!dst_type.IsMalformed() &&
1574 dst_type.IsInstantiated() &&
1575 literal_value.IsInstanceOf(dst_type,
1576 TypeArguments::Handle(),
1577 &malformed_error)) {
1578 return;
1579 }
1580 }
1581
1527 // A null object is always assignable and is returned as result. 1582 // A null object is always assignable and is returned as result.
1528 const Immediate raw_null = 1583 const Immediate raw_null =
1529 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1584 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1530 Label done, runtime_call; 1585 Label done, runtime_call;
1531 __ cmpl(EAX, raw_null); 1586 __ cmpl(EAX, raw_null);
1532 __ j(EQUAL, &done); 1587 __ j(EQUAL, &done);
1533 1588
1534 // Generate throw new TypeError() if the type is malformed. 1589 // Generate throw new TypeError() if the type is malformed.
1535 if (dst_type.IsMalformed()) { 1590 if (dst_type.IsMalformed()) {
1536 const Error& error = Error::Handle(dst_type.malformed_error()); 1591 const Error& error = Error::Handle(dst_type.malformed_error());
(...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 const Function& function = parsed_function_.function(); 1796 const Function& function = parsed_function_.function();
1742 LocalScope* scope = parsed_function_.node_sequence()->scope(); 1797 LocalScope* scope = parsed_function_.node_sequence()->scope();
1743 const int num_fixed_params = function.num_fixed_parameters(); 1798 const int num_fixed_params = function.num_fixed_parameters();
1744 const int num_opt_params = function.num_optional_parameters(); 1799 const int num_opt_params = function.num_optional_parameters();
1745 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables()); 1800 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables());
1746 for (int i = 0; i < num_fixed_params + num_opt_params; i++) { 1801 for (int i = 0; i < num_fixed_params + num_opt_params; i++) {
1747 LocalVariable* parameter = scope->VariableAt(i); 1802 LocalVariable* parameter = scope->VariableAt(i);
1748 GenerateLoadVariable(EAX, *parameter); 1803 GenerateLoadVariable(EAX, *parameter);
1749 GenerateAssertAssignable(AstNode::kNoId, 1804 GenerateAssertAssignable(AstNode::kNoId,
1750 parameter->token_index(), 1805 parameter->token_index(),
1806 NULL,
1751 parameter->type(), 1807 parameter->type(),
1752 parameter->name()); 1808 parameter->name());
1753 } 1809 }
1754 } 1810 }
1755 1811
1756 1812
1757 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id, 1813 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id,
1758 intptr_t token_index) { 1814 intptr_t token_index) {
1759 if (!FLAG_enable_type_checks) { 1815 if (!FLAG_enable_type_checks) {
1760 return; 1816 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1853 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1798 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1854 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1799 node->left()->Visit(this); 1855 node->left()->Visit(this);
1800 1856
1801 // The instanceof operator needs special handling. 1857 // The instanceof operator needs special handling.
1802 if (Token::IsInstanceofOperator(node->kind())) { 1858 if (Token::IsInstanceofOperator(node->kind())) {
1803 __ popl(EAX); // Left operand. 1859 __ popl(EAX); // Left operand.
1804 ASSERT(node->right()->IsTypeNode()); 1860 ASSERT(node->right()->IsTypeNode());
1805 GenerateInstanceOf(node->id(), 1861 GenerateInstanceOf(node->id(),
1806 node->token_index(), 1862 node->token_index(),
1863 node->left(),
1807 node->right()->AsTypeNode()->type(), 1864 node->right()->AsTypeNode()->type(),
1808 (node->kind() == Token::kISNOT)); 1865 (node->kind() == Token::kISNOT));
1809 if (!IsResultNeeded(node)) { 1866 if (!IsResultNeeded(node)) {
1810 __ popl(EAX); // Pop the result of the instanceof operation. 1867 __ popl(EAX); // Pop the result of the instanceof operation.
1811 } 1868 }
1812 return; 1869 return;
1813 } 1870 }
1814 1871
1815 node->right()->Visit(this); 1872 node->right()->Visit(this);
1816 // Both left and right values on stack. 1873 // Both left and right values on stack.
(...skipping 1016 matching lines...) Expand 10 before | Expand all | Expand 10 after
2833 const Error& error = Error::Handle( 2890 const Error& error = Error::Handle(
2834 Parser::FormatError(script, token_index, "Error", format, args)); 2891 Parser::FormatError(script, token_index, "Error", format, args));
2835 va_end(args); 2892 va_end(args);
2836 Isolate::Current()->long_jump_base()->Jump(1, error); 2893 Isolate::Current()->long_jump_base()->Jump(1, error);
2837 UNREACHABLE(); 2894 UNREACHABLE();
2838 } 2895 }
2839 2896
2840 } // namespace dart 2897 } // namespace dart
2841 2898
2842 #endif // defined TARGET_ARCH_IA32 2899 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/code_generator_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698