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

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
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 return;
1331 }
1332 Error& malformed_error = Error::Handle();
1333 if (literal_value.IsInstanceOf(type,
1334 TypeArguments::Handle(),
1335 &malformed_error)) {
1336 __ PushObject(negate_result ? bool_false : bool_true);
1337 return;
1338 }
srdjan 2012/04/11 17:25:08 shouldn't there be an else with __PushObject(negat
regis 2012/04/11 17:42:12 Yes, indeed. I wanted to handle the malformed type
1339 }
1340
1311 const Immediate raw_null = 1341 const Immediate raw_null =
1312 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1342 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1313 Label done, check_negate_done; 1343 Label done, check_negate_done;
1314 // If type is instantiated and non-parameterized, we can inline code 1344 // If type is instantiated and non-parameterized, we can inline code
1315 // checking whether the tested instance is a Smi. 1345 // checking whether the tested instance is a Smi.
1316 if (type.IsInstantiated()) { 1346 if (type.IsInstantiated()) {
1317 // A null object is only an instance of Object and Dynamic, which has 1347 // 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 1348 // 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 1349 // return false here if the instance is null (and if the type is
1320 // instantiated). 1350 // instantiated).
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
1481 1511
1482 // Jumps to label if ECX equals the given class. 1512 // Jumps to label if ECX equals the given class.
1483 // Inputs: 1513 // Inputs:
1484 // - ECX: tested class. 1514 // - ECX: tested class.
1485 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) { 1515 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) {
1486 __ CompareObject(ECX, cls); 1516 __ CompareObject(ECX, cls);
1487 __ j(EQUAL, label, Assembler::kNearJump); 1517 __ j(EQUAL, label, Assembler::kNearJump);
1488 } 1518 }
1489 1519
1490 1520
1491 // Optimize assignable type check by adding inlined tests for: 1521 // If type check cannot be performed successfully at compile time and therefore
1522 // eliminated, optimize it by adding inlined tests for:
1492 // - NULL -> return NULL. 1523 // - NULL -> return NULL.
1493 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1524 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1494 // - Class equality (only if class is not parameterized). 1525 // - Class equality (only if class is not parameterized).
1495 // Inputs: 1526 // Inputs:
1496 // - EAX: object. 1527 // - EAX: object.
1497 // Destroys ECX and EDX. 1528 // Destroys ECX and EDX.
1498 // Returns: 1529 // Returns:
1499 // - object in EAX for successful assignable check (or throws TypeError). 1530 // - object in EAX for successful assignable check (or throws TypeError).
1500 // Performance notes: positive checks must be quick, negative checks can be slow 1531 // Performance notes: positive checks must be quick, negative checks can be slow
1501 // as they throw an exception. 1532 // as they throw an exception.
1502 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1533 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1503 intptr_t token_index, 1534 intptr_t token_index,
1535 AstNode* value,
1504 const AbstractType& dst_type, 1536 const AbstractType& dst_type,
1505 const String& dst_name) { 1537 const String& dst_name) {
1506 ASSERT(FLAG_enable_type_checks); 1538 ASSERT(FLAG_enable_type_checks);
1507 ASSERT(token_index >= 0); 1539 ASSERT(token_index >= 0);
1508 ASSERT(!dst_type.IsNull()); 1540 ASSERT(!dst_type.IsNull());
1509 ASSERT(dst_type.IsFinalized()); 1541 ASSERT(dst_type.IsFinalized());
1510 1542
1511 // Any expression is assignable to the Dynamic type and to the Object type. 1543 // Any expression is assignable to the Dynamic type and to the Object type.
1512 // Skip the test. 1544 // Skip the test.
1513 if (!dst_type.IsMalformed() && 1545 if (!dst_type.IsMalformed() &&
1514 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { 1546 (dst_type.IsDynamicType() || dst_type.IsObjectType())) {
1515 return; 1547 return;
1516 } 1548 }
1517 1549
1518 // It is a compile-time error to explicitly return a value (including null) 1550 // 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 1551 // from a void function. However, functions that do not explicitly return a
1520 // value, implicitly return null. This includes void functions. Therefore, we 1552 // 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 1553 // skip the type test here and trust the parser to only return null in void
1522 // function. 1554 // function.
1523 if (dst_type.IsVoidType()) { 1555 if (dst_type.IsVoidType()) {
1524 return; 1556 return;
1525 } 1557 }
1526 1558
1559 // Eliminate the test if it can be performed successfully at compile time.
1560 if ((value != NULL) && value->IsLiteralNode()) {
1561 const Instance& literal_value = value->AsLiteralNode()->literal();
1562 const Class& cls = Class::Handle(literal_value.clazz());
1563 if (cls.IsNullClass()) {
1564 ASSERT(literal_value.IsNull() ||
1565 (literal_value.raw() == Object::sentinel()) ||
1566 (literal_value.raw() == Object::transition_sentinel()));
1567 return;
1568 }
1569 Error& malformed_error = Error::Handle();
1570 if (!dst_type.IsMalformed() &&
1571 dst_type.IsInstantiated() &&
1572 literal_value.IsInstanceOf(dst_type,
1573 TypeArguments::Handle(),
1574 &malformed_error)) {
1575 return;
1576 }
1577 }
1578
1527 // A null object is always assignable and is returned as result. 1579 // A null object is always assignable and is returned as result.
1528 const Immediate raw_null = 1580 const Immediate raw_null =
1529 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1581 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1530 Label done, runtime_call; 1582 Label done, runtime_call;
1531 __ cmpl(EAX, raw_null); 1583 __ cmpl(EAX, raw_null);
1532 __ j(EQUAL, &done); 1584 __ j(EQUAL, &done);
1533 1585
1534 // Generate throw new TypeError() if the type is malformed. 1586 // Generate throw new TypeError() if the type is malformed.
1535 if (dst_type.IsMalformed()) { 1587 if (dst_type.IsMalformed()) {
1536 const Error& error = Error::Handle(dst_type.malformed_error()); 1588 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(); 1793 const Function& function = parsed_function_.function();
1742 LocalScope* scope = parsed_function_.node_sequence()->scope(); 1794 LocalScope* scope = parsed_function_.node_sequence()->scope();
1743 const int num_fixed_params = function.num_fixed_parameters(); 1795 const int num_fixed_params = function.num_fixed_parameters();
1744 const int num_opt_params = function.num_optional_parameters(); 1796 const int num_opt_params = function.num_optional_parameters();
1745 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables()); 1797 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables());
1746 for (int i = 0; i < num_fixed_params + num_opt_params; i++) { 1798 for (int i = 0; i < num_fixed_params + num_opt_params; i++) {
1747 LocalVariable* parameter = scope->VariableAt(i); 1799 LocalVariable* parameter = scope->VariableAt(i);
1748 GenerateLoadVariable(EAX, *parameter); 1800 GenerateLoadVariable(EAX, *parameter);
1749 GenerateAssertAssignable(AstNode::kNoId, 1801 GenerateAssertAssignable(AstNode::kNoId,
1750 parameter->token_index(), 1802 parameter->token_index(),
1803 NULL,
1751 parameter->type(), 1804 parameter->type(),
1752 parameter->name()); 1805 parameter->name());
1753 } 1806 }
1754 } 1807 }
1755 1808
1756 1809
1757 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id, 1810 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id,
1758 intptr_t token_index) { 1811 intptr_t token_index) {
1759 if (!FLAG_enable_type_checks) { 1812 if (!FLAG_enable_type_checks) {
1760 return; 1813 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1797 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1850 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1798 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1851 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1799 node->left()->Visit(this); 1852 node->left()->Visit(this);
1800 1853
1801 // The instanceof operator needs special handling. 1854 // The instanceof operator needs special handling.
1802 if (Token::IsInstanceofOperator(node->kind())) { 1855 if (Token::IsInstanceofOperator(node->kind())) {
1803 __ popl(EAX); // Left operand. 1856 __ popl(EAX); // Left operand.
1804 ASSERT(node->right()->IsTypeNode()); 1857 ASSERT(node->right()->IsTypeNode());
1805 GenerateInstanceOf(node->id(), 1858 GenerateInstanceOf(node->id(),
1806 node->token_index(), 1859 node->token_index(),
1860 node->left(),
1807 node->right()->AsTypeNode()->type(), 1861 node->right()->AsTypeNode()->type(),
1808 (node->kind() == Token::kISNOT)); 1862 (node->kind() == Token::kISNOT));
1809 if (!IsResultNeeded(node)) { 1863 if (!IsResultNeeded(node)) {
1810 __ popl(EAX); // Pop the result of the instanceof operation. 1864 __ popl(EAX); // Pop the result of the instanceof operation.
1811 } 1865 }
1812 return; 1866 return;
1813 } 1867 }
1814 1868
1815 node->right()->Visit(this); 1869 node->right()->Visit(this);
1816 // Both left and right values on stack. 1870 // 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( 2887 const Error& error = Error::Handle(
2834 Parser::FormatError(script, token_index, "Error", format, args)); 2888 Parser::FormatError(script, token_index, "Error", format, args));
2835 va_end(args); 2889 va_end(args);
2836 Isolate::Current()->long_jump_base()->Jump(1, error); 2890 Isolate::Current()->long_jump_base()->Jump(1, error);
2837 UNREACHABLE(); 2891 UNREACHABLE();
2838 } 2892 }
2839 2893
2840 } // namespace dart 2894 } // namespace dart
2841 2895
2842 #endif // defined TARGET_ARCH_IA32 2896 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698