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

Side by Side Diff: runtime/vm/code_generator_x64.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_X64. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_X64.
6 #if defined(TARGET_ARCH_X64) 6 #if defined(TARGET_ARCH_X64)
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 639 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 } else { 650 } else {
651 __ LoadObject(RAX, literal); 651 __ LoadObject(RAX, literal);
652 } 652 }
653 } else { 653 } else {
654 // Pop the previously evaluated result value into RAX. 654 // Pop the previously evaluated result value into RAX.
655 __ popq(RAX); 655 __ popq(RAX);
656 } 656 }
657 657
658 // Generate type check. 658 // Generate type check.
659 if (FLAG_enable_type_checks) { 659 if (FLAG_enable_type_checks) {
660 const bool returns_null = node->value()->IsLiteralNode() &&
661 node->value()->AsLiteralNode()->literal().IsNull();
662 const RawFunction::Kind kind = parsed_function().function().kind(); 660 const RawFunction::Kind kind = parsed_function().function().kind();
663 const bool is_implicit_getter = 661 const bool is_implicit_getter =
664 (kind == RawFunction::kImplicitGetter) || 662 (kind == RawFunction::kImplicitGetter) ||
665 (kind == RawFunction::kConstImplicitGetter); 663 (kind == RawFunction::kConstImplicitGetter);
666 const bool is_static = parsed_function().function().is_static(); 664 const bool is_static = parsed_function().function().is_static();
667 // Implicit getters do not need a type check at return, unless they compute 665 // Implicit getters do not need a type check at return, unless they compute
668 // the initial value of a static field. 666 // the initial value of a static field.
669 if (!returns_null && (is_static || !is_implicit_getter)) { 667 if (is_static || !is_implicit_getter) {
670 GenerateAssertAssignable( 668 GenerateAssertAssignable(
671 node->id(), 669 node->id(),
672 node->value()->token_index(), 670 node->value()->token_index(),
671 node->value(),
673 AbstractType::ZoneHandle(parsed_function().function().result_type()), 672 AbstractType::ZoneHandle(parsed_function().function().result_type()),
674 String::ZoneHandle(String::NewSymbol("function result"))); 673 String::ZoneHandle(String::NewSymbol("function result")));
675 } 674 }
676 } 675 }
677 GenerateReturnEpilog(node); 676 GenerateReturnEpilog(node);
678 } 677 }
679 678
680 679
681 void CodeGenerator::VisitLiteralNode(LiteralNode* node) { 680 void CodeGenerator::VisitLiteralNode(LiteralNode* node) {
682 if (!IsResultNeeded(node)) return; 681 if (!IsResultNeeded(node)) return;
683 __ PushObject(node->literal()); 682 __ PushObject(node->literal());
684 } 683 }
685 684
686 685
687 void CodeGenerator::VisitTypeNode(TypeNode* node) { 686 void CodeGenerator::VisitTypeNode(TypeNode* node) {
688 // Type nodes are handled specially by the code generator. 687 // Type nodes are handled specially by the code generator.
689 UNREACHABLE(); 688 UNREACHABLE();
690 } 689 }
691 690
692 691
693 void CodeGenerator::VisitAssignableNode(AssignableNode* node) { 692 void CodeGenerator::VisitAssignableNode(AssignableNode* node) {
694 ASSERT(FLAG_enable_type_checks); 693 ASSERT(FLAG_enable_type_checks);
695 node->expr()->Visit(this); 694 node->expr()->Visit(this);
696 __ popq(RAX); 695 __ popq(RAX);
697 GenerateAssertAssignable(node->id(), 696 GenerateAssertAssignable(node->id(),
698 node->token_index(), 697 node->token_index(),
698 node->expr(),
699 node->type(), 699 node->type(),
700 node->dst_name()); 700 node->dst_name());
701 if (IsResultNeeded(node)) { 701 if (IsResultNeeded(node)) {
702 __ pushq(RAX); 702 __ pushq(RAX);
703 } 703 }
704 } 704 }
705 705
706 706
707 void CodeGenerator::VisitClosureNode(ClosureNode* node) { 707 void CodeGenerator::VisitClosureNode(ClosureNode* node) {
708 const Function& function = node->function(); 708 const Function& function = node->function();
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
900 } 900 }
901 } 901 }
902 902
903 903
904 void CodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { 904 void CodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) {
905 node->value()->Visit(this); 905 node->value()->Visit(this);
906 __ popq(RAX); 906 __ popq(RAX);
907 if (FLAG_enable_type_checks) { 907 if (FLAG_enable_type_checks) {
908 GenerateAssertAssignable(node->id(), 908 GenerateAssertAssignable(node->id(),
909 node->value()->token_index(), 909 node->value()->token_index(),
910 node->value(),
910 node->local().type(), 911 node->local().type(),
911 node->local().name()); 912 node->local().name());
912 } 913 }
913 GenerateStoreVariable(node->local(), RAX, R10); 914 GenerateStoreVariable(node->local(), RAX, R10);
914 if (IsResultNeeded(node)) { 915 if (IsResultNeeded(node)) {
915 __ pushq(RAX); 916 __ pushq(RAX);
916 } 917 }
917 } 918 }
918 919
919 920
920 void CodeGenerator::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) { 921 void CodeGenerator::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) {
921 node->instance()->Visit(this); 922 node->instance()->Visit(this);
922 MarkDeoptPoint(node->id(), node->token_index()); 923 MarkDeoptPoint(node->id(), node->token_index());
923 __ popq(RAX); // Instance. 924 __ popq(RAX); // Instance.
924 __ movq(RAX, FieldAddress(RAX, node->field().Offset())); 925 __ movq(RAX, FieldAddress(RAX, node->field().Offset()));
925 if (IsResultNeeded(node)) { 926 if (IsResultNeeded(node)) {
926 __ pushq(RAX); 927 __ pushq(RAX);
927 } 928 }
928 } 929 }
929 930
930 931
931 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) { 932 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) {
932 node->instance()->Visit(this); 933 node->instance()->Visit(this);
933 node->value()->Visit(this); 934 node->value()->Visit(this);
934 MarkDeoptPoint(node->id(), node->token_index()); 935 MarkDeoptPoint(node->id(), node->token_index());
935 __ popq(RAX); // Value. 936 __ popq(RAX); // Value.
936 if (FLAG_enable_type_checks) { 937 if (FLAG_enable_type_checks) {
937 GenerateAssertAssignable(node->id(), 938 GenerateAssertAssignable(node->id(),
938 node->value()->token_index(), 939 node->value()->token_index(),
940 node->value(),
939 AbstractType::ZoneHandle(node->field().type()), 941 AbstractType::ZoneHandle(node->field().type()),
940 String::ZoneHandle(node->field().name())); 942 String::ZoneHandle(node->field().name()));
941 } 943 }
942 __ popq(R10); // Instance. 944 __ popq(R10); // Instance.
943 __ StoreIntoObject(R10, FieldAddress(R10, node->field().Offset()), RAX); 945 __ StoreIntoObject(R10, FieldAddress(R10, node->field().Offset()), RAX);
944 ASSERT(!IsResultNeeded(node)); 946 ASSERT(!IsResultNeeded(node));
945 } 947 }
946 948
947 949
948 // Expects array and index on stack and returns result in RAX. 950 // Expects array and index on stack and returns result in RAX.
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 } 1034 }
1033 1035
1034 1036
1035 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { 1037 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) {
1036 node->value()->Visit(this); 1038 node->value()->Visit(this);
1037 MarkDeoptPoint(node->id(), node->token_index()); 1039 MarkDeoptPoint(node->id(), node->token_index());
1038 __ popq(RAX); // Value. 1040 __ popq(RAX); // Value.
1039 if (FLAG_enable_type_checks) { 1041 if (FLAG_enable_type_checks) {
1040 GenerateAssertAssignable(node->id(), 1042 GenerateAssertAssignable(node->id(),
1041 node->value()->token_index(), 1043 node->value()->token_index(),
1044 node->value(),
1042 AbstractType::ZoneHandle(node->field().type()), 1045 AbstractType::ZoneHandle(node->field().type()),
1043 String::ZoneHandle(node->field().name())); 1046 String::ZoneHandle(node->field().name()));
1044 } 1047 }
1045 __ LoadObject(RDX, node->field()); 1048 __ LoadObject(RDX, node->field());
1046 __ StoreIntoObject(RDX, FieldAddress(RDX, Field::value_offset()), RAX); 1049 __ StoreIntoObject(RDX, FieldAddress(RDX, Field::value_offset()), RAX);
1047 if (IsResultNeeded(node)) { 1050 if (IsResultNeeded(node)) {
1048 // The result is the input value. 1051 // The result is the input value.
1049 __ pushq(RAX); 1052 __ pushq(RAX);
1050 } 1053 }
1051 } 1054 }
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1118 } 1121 }
1119 const Immediate value = Immediate(reinterpret_cast<int64_t>(Smi::New(1))); 1122 const Immediate value = Immediate(reinterpret_cast<int64_t>(Smi::New(1)));
1120 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; 1123 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-";
1121 __ pushq(RAX); 1124 __ pushq(RAX);
1122 __ pushq(value); 1125 __ pushq(value);
1123 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); 1126 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name);
1124 // result is in RAX. 1127 // result is in RAX.
1125 if (FLAG_enable_type_checks) { 1128 if (FLAG_enable_type_checks) {
1126 GenerateAssertAssignable(node->id(), 1129 GenerateAssertAssignable(node->id(),
1127 node->token_index(), 1130 node->token_index(),
1131 NULL,
1128 node->local().type(), 1132 node->local().type(),
1129 node->local().name()); 1133 node->local().name());
1130 } 1134 }
1131 GenerateStoreVariable(node->local(), RAX, RDX); 1135 GenerateStoreVariable(node->local(), RAX, RDX);
1132 if (node->prefix() && IsResultNeeded(node)) { 1136 if (node->prefix() && IsResultNeeded(node)) {
1133 __ pushq(RAX); 1137 __ pushq(RAX);
1134 } 1138 }
1135 } 1139 }
1136 1140
1137 1141
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1210 1214
1211 static const Class* CoreClass(const char* c_name) { 1215 static const Class* CoreClass(const char* c_name) {
1212 const String& class_name = String::Handle(String::NewSymbol(c_name)); 1216 const String& class_name = String::Handle(String::NewSymbol(c_name));
1213 const Class& cls = Class::ZoneHandle(Library::Handle( 1217 const Class& cls = Class::ZoneHandle(Library::Handle(
1214 Library::CoreImplLibrary()).LookupClass(class_name)); 1218 Library::CoreImplLibrary()).LookupClass(class_name));
1215 ASSERT(!cls.IsNull()); 1219 ASSERT(!cls.IsNull());
1216 return &cls; 1220 return &cls;
1217 } 1221 }
1218 1222
1219 1223
1220 // Optimize instanceof type test by adding inlined tests for: 1224 // If instanceof type test cannot be performed successfully at compile time and
1225 // therefore eliminated, optimize it by adding inlined tests for:
1221 // - NULL -> return false. 1226 // - NULL -> return false.
1222 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1227 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1223 // - Class equality (only if class is not parameterized). 1228 // - Class equality (only if class is not parameterized).
1224 // Inputs: 1229 // Inputs:
1225 // - RAX: object. 1230 // - RAX: object.
1226 // Destroys RCX. 1231 // Destroys RCX.
1227 // Returns: 1232 // Returns:
1228 // - true or false on stack. 1233 // - true or false on stack.
1229 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, 1234 void CodeGenerator::GenerateInstanceOf(intptr_t node_id,
1230 intptr_t token_index, 1235 intptr_t token_index,
1236 AstNode* value,
1231 const AbstractType& type, 1237 const AbstractType& type,
1232 bool negate_result) { 1238 bool negate_result) {
1233 ASSERT(type.IsFinalized() && !type.IsMalformed()); 1239 ASSERT(type.IsFinalized() && !type.IsMalformed());
1234 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1240 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1235 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1241 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1236 1242
1237 // All instances are of a subtype of the Object type. 1243 // All objects are instances of type T if Object type is a subtype of type T.
1238 const Type& object_type = 1244 const Type& object_type =
1239 Type::Handle(Isolate::Current()->object_store()->object_type()); 1245 Type::Handle(Isolate::Current()->object_store()->object_type());
1240 Error& malformed_error = Error::Handle(); 1246 Error& malformed_error = Error::Handle();
1241 if (type.IsInstantiated() && 1247 if (type.IsInstantiated() &&
1242 object_type.IsSubtypeOf(type, &malformed_error)) { 1248 object_type.IsSubtypeOf(type, &malformed_error)) {
1243 __ PushObject(negate_result ? bool_false : bool_true); 1249 __ PushObject(negate_result ? bool_false : bool_true);
1244 return; 1250 return;
1245 } 1251 }
1246 1252
1253 // Eliminate the test if it can be performed successfully at compile time.
1254 if ((value != NULL) && value->IsLiteralNode() && type.IsInstantiated()) {
1255 const Instance& literal_value = value->AsLiteralNode()->literal();
1256 const Class& cls = Class::Handle(literal_value.clazz());
1257 if (cls.IsNullClass()) {
1258 ASSERT(literal_value.IsNull() ||
1259 (literal_value.raw() == Object::sentinel()) ||
1260 (literal_value.raw() == Object::transition_sentinel()));
1261 // A null object is only an instance of Object and Dynamic, which has
1262 // already been checked above (if the type is instantiated). So we can
1263 // return false here if the instance is null (and if the type is
1264 // instantiated).
1265 __ PushObject(negate_result ? bool_true : bool_false);
1266 return;
1267 }
1268 Error& malformed_error = Error::Handle();
1269 if (literal_value.IsInstanceOf(type,
1270 TypeArguments::Handle(),
1271 &malformed_error)) {
1272 __ PushObject(negate_result ? bool_false : bool_true);
1273 return;
1274 }
1275 }
1276
1247 const Immediate raw_null = 1277 const Immediate raw_null =
1248 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1278 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1249 Label done; 1279 Label done;
1250 // If type is instantiated and non-parameterized, we can inline code 1280 // If type is instantiated and non-parameterized, we can inline code
1251 // checking whether the tested instance is a Smi. 1281 // checking whether the tested instance is a Smi.
1252 if (type.IsInstantiated()) { 1282 if (type.IsInstantiated()) {
1253 // A null object is only an instance of Object and Dynamic, which has 1283 // A null object is only an instance of Object and Dynamic, which has
1254 // already been checked above (if the type is instantiated). So we can 1284 // already been checked above (if the type is instantiated). So we can
1255 // return false here if the instance is null (and if the type is 1285 // return false here if the instance is null (and if the type is
1256 // instantiated). 1286 // instantiated).
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1325 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1296 __ CompareObject(RCX, type_class); 1326 __ CompareObject(RCX, type_class);
1297 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1327 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1298 __ PushObject(negate_result ? bool_false : bool_true); 1328 __ PushObject(negate_result ? bool_false : bool_true);
1299 __ jmp(&done); 1329 __ jmp(&done);
1300 } 1330 }
1301 } 1331 }
1302 __ Bind(&runtime_call); 1332 __ Bind(&runtime_call);
1303 // Fall through to runtime call. 1333 // Fall through to runtime call.
1304 } else { 1334 } else {
1335 ASSERT(!requires_type_arguments);
1336 // Test if object is Smi and for a couple known test-classes.
1305 Label compare_classes; 1337 Label compare_classes;
1306 __ testq(RAX, Immediate(kSmiTagMask)); 1338 __ testq(RAX, Immediate(kSmiTagMask));
1307 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1339 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1308 // Object is Smi. 1340 // Object is Smi.
1309 const Class& smi_class = Class::Handle(Smi::Class()); 1341 const Class& smi_class = Class::Handle(Smi::Class());
1310 // TODO(regis): We should introduce a SmiType. 1342 // TODO(regis): We should introduce a SmiType.
1311 Error& malformed_error = Error::Handle(); 1343 Error& malformed_error = Error::Handle();
1312 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1344 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1313 type_class, 1345 type_class,
1314 TypeArguments::Handle(), 1346 TypeArguments::Handle(),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 1408
1377 // Jumps to label if RCX equals the given class. 1409 // Jumps to label if RCX equals the given class.
1378 // Inputs: 1410 // Inputs:
1379 // - RCX: tested class. 1411 // - RCX: tested class.
1380 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) { 1412 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) {
1381 __ CompareObject(RCX, cls); 1413 __ CompareObject(RCX, cls);
1382 __ j(EQUAL, label); 1414 __ j(EQUAL, label);
1383 } 1415 }
1384 1416
1385 1417
1386 // Optimize assignable type check by adding inlined tests for: 1418 // If type check cannot be performed successfully at compile time and therefore
1419 // eliminated, optimize it by adding inlined tests for:
1387 // - NULL -> return NULL. 1420 // - NULL -> return NULL.
1388 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1421 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1389 // - Class equality (only if class is not parameterized). 1422 // - Class equality (only if class is not parameterized).
1390 // Inputs: 1423 // Inputs:
1391 // - RAX: object. 1424 // - RAX: object.
1392 // Destroys RCX and RDX. 1425 // Destroys RCX and RDX.
1393 // Returns: 1426 // Returns:
1394 // - object in RAX for successful assignable check (or throws TypeError). 1427 // - object in RAX for successful assignable check (or throws TypeError).
1428 // Performance notes: positive checks must be quick, negative checks can be slow
1429 // as they throw an exception.
1395 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1430 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1396 intptr_t token_index, 1431 intptr_t token_index,
1432 AstNode* value,
1397 const AbstractType& dst_type, 1433 const AbstractType& dst_type,
1398 const String& dst_name) { 1434 const String& dst_name) {
1399 ASSERT(FLAG_enable_type_checks); 1435 ASSERT(FLAG_enable_type_checks);
1400 ASSERT(token_index >= 0); 1436 ASSERT(token_index >= 0);
1401 ASSERT(!dst_type.IsNull()); 1437 ASSERT(!dst_type.IsNull());
1402 ASSERT(dst_type.IsFinalized()); 1438 ASSERT(dst_type.IsFinalized());
1403 1439
1404 // Any expression is assignable to the Dynamic type and to the Object type. 1440 // Any expression is assignable to the Dynamic type and to the Object type.
1405 // Skip the test. 1441 // Skip the test.
1406 if (!dst_type.IsMalformed() && 1442 if (!dst_type.IsMalformed() &&
1407 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { 1443 (dst_type.IsDynamicType() || dst_type.IsObjectType())) {
1408 return; 1444 return;
1409 } 1445 }
1410 1446
1411 // It is a compile-time error to explicitly return a value (including null) 1447 // It is a compile-time error to explicitly return a value (including null)
1412 // from a void function. However, functions that do not explicitly return a 1448 // from a void function. However, functions that do not explicitly return a
1413 // value, implicitly return null. This includes void functions. Therefore, we 1449 // value, implicitly return null. This includes void functions. Therefore, we
1414 // skip the type test here and trust the parser to only return null in void 1450 // skip the type test here and trust the parser to only return null in void
1415 // function. 1451 // function.
1416 if (dst_type.IsVoidType()) { 1452 if (dst_type.IsVoidType()) {
1417 return; 1453 return;
1418 } 1454 }
1419 1455
1456 // Eliminate the test if it can be performed successfully at compile time.
1457 if ((value != NULL) && value->IsLiteralNode()) {
1458 const Instance& literal_value = value->AsLiteralNode()->literal();
1459 const Class& cls = Class::Handle(literal_value.clazz());
1460 if (cls.IsNullClass()) {
1461 ASSERT(literal_value.IsNull() ||
1462 (literal_value.raw() == Object::sentinel()) ||
1463 (literal_value.raw() == Object::transition_sentinel()));
1464 return;
1465 }
1466 Error& malformed_error = Error::Handle();
1467 if (!dst_type.IsMalformed() &&
1468 dst_type.IsInstantiated() &&
1469 literal_value.IsInstanceOf(dst_type,
1470 TypeArguments::Handle(),
1471 &malformed_error)) {
1472 return;
1473 }
1474 }
1475
1420 // A null object is always assignable and is returned as result. 1476 // A null object is always assignable and is returned as result.
1421 const Immediate raw_null = 1477 const Immediate raw_null =
1422 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1478 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1423 Label done, runtime_call; 1479 Label done, runtime_call;
1424 __ cmpq(RAX, raw_null); 1480 __ cmpq(RAX, raw_null);
1425 __ j(EQUAL, &done); 1481 __ j(EQUAL, &done);
1426 1482
1427 // Generate throw new TypeError() if the type is malformed. 1483 // Generate throw new TypeError() if the type is malformed.
1428 if (dst_type.IsMalformed()) { 1484 if (dst_type.IsMalformed()) {
1429 const Error& error = Error::Handle(dst_type.malformed_error()); 1485 const Error& error = Error::Handle(dst_type.malformed_error());
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1572 const Function& function = parsed_function_.function(); 1628 const Function& function = parsed_function_.function();
1573 LocalScope* scope = parsed_function_.node_sequence()->scope(); 1629 LocalScope* scope = parsed_function_.node_sequence()->scope();
1574 const int num_fixed_params = function.num_fixed_parameters(); 1630 const int num_fixed_params = function.num_fixed_parameters();
1575 const int num_opt_params = function.num_optional_parameters(); 1631 const int num_opt_params = function.num_optional_parameters();
1576 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables()); 1632 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables());
1577 for (int i = 0; i < num_fixed_params + num_opt_params; i++) { 1633 for (int i = 0; i < num_fixed_params + num_opt_params; i++) {
1578 LocalVariable* parameter = scope->VariableAt(i); 1634 LocalVariable* parameter = scope->VariableAt(i);
1579 GenerateLoadVariable(RAX, *parameter); 1635 GenerateLoadVariable(RAX, *parameter);
1580 GenerateAssertAssignable(AstNode::kNoId, 1636 GenerateAssertAssignable(AstNode::kNoId,
1581 parameter->token_index(), 1637 parameter->token_index(),
1638 NULL,
1582 parameter->type(), 1639 parameter->type(),
1583 parameter->name()); 1640 parameter->name());
1584 } 1641 }
1585 } 1642 }
1586 1643
1587 1644
1588 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id, 1645 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id,
1589 intptr_t token_index) { 1646 intptr_t token_index) {
1590 if (!FLAG_enable_type_checks) { 1647 if (!FLAG_enable_type_checks) {
1591 return; 1648 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1685 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1629 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1686 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1630 node->left()->Visit(this); 1687 node->left()->Visit(this);
1631 1688
1632 // The instanceof operator needs special handling. 1689 // The instanceof operator needs special handling.
1633 if (Token::IsInstanceofOperator(node->kind())) { 1690 if (Token::IsInstanceofOperator(node->kind())) {
1634 __ popq(RAX); // Left operand. 1691 __ popq(RAX); // Left operand.
1635 ASSERT(node->right()->IsTypeNode()); 1692 ASSERT(node->right()->IsTypeNode());
1636 GenerateInstanceOf(node->id(), 1693 GenerateInstanceOf(node->id(),
1637 node->token_index(), 1694 node->token_index(),
1695 node->left(),
1638 node->right()->AsTypeNode()->type(), 1696 node->right()->AsTypeNode()->type(),
1639 (node->kind() == Token::kISNOT)); 1697 (node->kind() == Token::kISNOT));
1640 if (!IsResultNeeded(node)) { 1698 if (!IsResultNeeded(node)) {
1641 __ popq(RAX); // Pop the result of the instanceof operation. 1699 __ popq(RAX); // Pop the result of the instanceof operation.
1642 } 1700 }
1643 return; 1701 return;
1644 } 1702 }
1645 1703
1646 node->right()->Visit(this); 1704 node->right()->Visit(this);
1647 // Both left and right values on stack. 1705 // Both left and right values on stack.
(...skipping 1015 matching lines...) Expand 10 before | Expand all | Expand 10 after
2663 const Error& error = Error::Handle( 2721 const Error& error = Error::Handle(
2664 Parser::FormatError(script, token_index, "Error", format, args)); 2722 Parser::FormatError(script, token_index, "Error", format, args));
2665 va_end(args); 2723 va_end(args);
2666 Isolate::Current()->long_jump_base()->Jump(1, error); 2724 Isolate::Current()->long_jump_base()->Jump(1, error);
2667 UNREACHABLE(); 2725 UNREACHABLE();
2668 } 2726 }
2669 2727
2670 } // namespace dart 2728 } // namespace dart
2671 2729
2672 #endif // defined TARGET_ARCH_X64 2730 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698