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

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
« no previous file with comments | « runtime/vm/code_generator_x64.h ('k') | runtime/vm/flow_graph_compiler_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_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 } else {
1267 Error& malformed_error = Error::Handle();
1268 if (literal_value.IsInstanceOf(type,
1269 TypeArguments::Handle(),
1270 &malformed_error)) {
1271 __ PushObject(negate_result ? bool_false : bool_true);
1272 } else {
1273 ASSERT(malformed_error.IsNull());
1274 __ PushObject(negate_result ? bool_true : bool_false);
1275 }
1276 }
1277 return;
1278 }
1279
1247 const Immediate raw_null = 1280 const Immediate raw_null =
1248 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1281 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1249 Label done; 1282 Label done;
1250 // If type is instantiated and non-parameterized, we can inline code 1283 // If type is instantiated and non-parameterized, we can inline code
1251 // checking whether the tested instance is a Smi. 1284 // checking whether the tested instance is a Smi.
1252 if (type.IsInstantiated()) { 1285 if (type.IsInstantiated()) {
1253 // A null object is only an instance of Object and Dynamic, which has 1286 // 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 1287 // 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 1288 // return false here if the instance is null (and if the type is
1256 // instantiated). 1289 // instantiated).
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1328 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1296 __ CompareObject(RCX, type_class); 1329 __ CompareObject(RCX, type_class);
1297 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1330 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1298 __ PushObject(negate_result ? bool_false : bool_true); 1331 __ PushObject(negate_result ? bool_false : bool_true);
1299 __ jmp(&done); 1332 __ jmp(&done);
1300 } 1333 }
1301 } 1334 }
1302 __ Bind(&runtime_call); 1335 __ Bind(&runtime_call);
1303 // Fall through to runtime call. 1336 // Fall through to runtime call.
1304 } else { 1337 } else {
1338 ASSERT(!requires_type_arguments);
1339 // Test if object is Smi and for a couple known test-classes.
1305 Label compare_classes; 1340 Label compare_classes;
1306 __ testq(RAX, Immediate(kSmiTagMask)); 1341 __ testq(RAX, Immediate(kSmiTagMask));
1307 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1342 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1308 // Object is Smi. 1343 // Object is Smi.
1309 const Class& smi_class = Class::Handle(Smi::Class()); 1344 const Class& smi_class = Class::Handle(Smi::Class());
1310 // TODO(regis): We should introduce a SmiType. 1345 // TODO(regis): We should introduce a SmiType.
1311 Error& malformed_error = Error::Handle(); 1346 Error& malformed_error = Error::Handle();
1312 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1347 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1313 type_class, 1348 type_class,
1314 TypeArguments::Handle(), 1349 TypeArguments::Handle(),
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 1411
1377 // Jumps to label if RCX equals the given class. 1412 // Jumps to label if RCX equals the given class.
1378 // Inputs: 1413 // Inputs:
1379 // - RCX: tested class. 1414 // - RCX: tested class.
1380 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) { 1415 void CodeGenerator::TestClassAndJump(const Class& cls, Label* label) {
1381 __ CompareObject(RCX, cls); 1416 __ CompareObject(RCX, cls);
1382 __ j(EQUAL, label); 1417 __ j(EQUAL, label);
1383 } 1418 }
1384 1419
1385 1420
1386 // Optimize assignable type check by adding inlined tests for: 1421 // If type check cannot be performed successfully at compile time and therefore
1422 // eliminated, optimize it by adding inlined tests for:
1387 // - NULL -> return NULL. 1423 // - NULL -> return NULL.
1388 // - Smi -> compile time subtype check (only if dst class is not parameterized). 1424 // - Smi -> compile time subtype check (only if dst class is not parameterized).
1389 // - Class equality (only if class is not parameterized). 1425 // - Class equality (only if class is not parameterized).
1390 // Inputs: 1426 // Inputs:
1391 // - RAX: object. 1427 // - RAX: object.
1392 // Destroys RCX and RDX. 1428 // Destroys RCX and RDX.
1393 // Returns: 1429 // Returns:
1394 // - object in RAX for successful assignable check (or throws TypeError). 1430 // - object in RAX for successful assignable check (or throws TypeError).
1431 // Performance notes: positive checks must be quick, negative checks can be slow
1432 // as they throw an exception.
1395 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1433 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1396 intptr_t token_index, 1434 intptr_t token_index,
1435 AstNode* value,
1397 const AbstractType& dst_type, 1436 const AbstractType& dst_type,
1398 const String& dst_name) { 1437 const String& dst_name) {
1399 ASSERT(FLAG_enable_type_checks); 1438 ASSERT(FLAG_enable_type_checks);
1400 ASSERT(token_index >= 0); 1439 ASSERT(token_index >= 0);
1401 ASSERT(!dst_type.IsNull()); 1440 ASSERT(!dst_type.IsNull());
1402 ASSERT(dst_type.IsFinalized()); 1441 ASSERT(dst_type.IsFinalized());
1403 1442
1404 // Any expression is assignable to the Dynamic type and to the Object type. 1443 // Any expression is assignable to the Dynamic type and to the Object type.
1405 // Skip the test. 1444 // Skip the test.
1406 if (!dst_type.IsMalformed() && 1445 if (!dst_type.IsMalformed() &&
1407 (dst_type.IsDynamicType() || dst_type.IsObjectType())) { 1446 (dst_type.IsDynamicType() || dst_type.IsObjectType())) {
1408 return; 1447 return;
1409 } 1448 }
1410 1449
1411 // It is a compile-time error to explicitly return a value (including null) 1450 // 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 1451 // from a void function. However, functions that do not explicitly return a
1413 // value, implicitly return null. This includes void functions. Therefore, we 1452 // 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 1453 // skip the type test here and trust the parser to only return null in void
1415 // function. 1454 // function.
1416 if (dst_type.IsVoidType()) { 1455 if (dst_type.IsVoidType()) {
1417 return; 1456 return;
1418 } 1457 }
1419 1458
1459 // Eliminate the test if it can be performed successfully at compile time.
1460 if ((value != NULL) && value->IsLiteralNode()) {
1461 const Instance& literal_value = value->AsLiteralNode()->literal();
1462 const Class& cls = Class::Handle(literal_value.clazz());
1463 if (cls.IsNullClass()) {
1464 ASSERT(literal_value.IsNull() ||
1465 (literal_value.raw() == Object::sentinel()) ||
1466 (literal_value.raw() == Object::transition_sentinel()));
1467 return;
1468 }
1469 Error& malformed_error = Error::Handle();
1470 if (!dst_type.IsMalformed() &&
1471 dst_type.IsInstantiated() &&
1472 literal_value.IsInstanceOf(dst_type,
1473 TypeArguments::Handle(),
1474 &malformed_error)) {
1475 return;
1476 }
1477 }
1478
1420 // A null object is always assignable and is returned as result. 1479 // A null object is always assignable and is returned as result.
1421 const Immediate raw_null = 1480 const Immediate raw_null =
1422 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1481 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1423 Label done, runtime_call; 1482 Label done, runtime_call;
1424 __ cmpq(RAX, raw_null); 1483 __ cmpq(RAX, raw_null);
1425 __ j(EQUAL, &done); 1484 __ j(EQUAL, &done);
1426 1485
1427 // Generate throw new TypeError() if the type is malformed. 1486 // Generate throw new TypeError() if the type is malformed.
1428 if (dst_type.IsMalformed()) { 1487 if (dst_type.IsMalformed()) {
1429 const Error& error = Error::Handle(dst_type.malformed_error()); 1488 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(); 1631 const Function& function = parsed_function_.function();
1573 LocalScope* scope = parsed_function_.node_sequence()->scope(); 1632 LocalScope* scope = parsed_function_.node_sequence()->scope();
1574 const int num_fixed_params = function.num_fixed_parameters(); 1633 const int num_fixed_params = function.num_fixed_parameters();
1575 const int num_opt_params = function.num_optional_parameters(); 1634 const int num_opt_params = function.num_optional_parameters();
1576 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables()); 1635 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables());
1577 for (int i = 0; i < num_fixed_params + num_opt_params; i++) { 1636 for (int i = 0; i < num_fixed_params + num_opt_params; i++) {
1578 LocalVariable* parameter = scope->VariableAt(i); 1637 LocalVariable* parameter = scope->VariableAt(i);
1579 GenerateLoadVariable(RAX, *parameter); 1638 GenerateLoadVariable(RAX, *parameter);
1580 GenerateAssertAssignable(AstNode::kNoId, 1639 GenerateAssertAssignable(AstNode::kNoId,
1581 parameter->token_index(), 1640 parameter->token_index(),
1641 NULL,
1582 parameter->type(), 1642 parameter->type(),
1583 parameter->name()); 1643 parameter->name());
1584 } 1644 }
1585 } 1645 }
1586 1646
1587 1647
1588 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id, 1648 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id,
1589 intptr_t token_index) { 1649 intptr_t token_index) {
1590 if (!FLAG_enable_type_checks) { 1650 if (!FLAG_enable_type_checks) {
1591 return; 1651 return;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1628 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1688 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1629 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1689 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1630 node->left()->Visit(this); 1690 node->left()->Visit(this);
1631 1691
1632 // The instanceof operator needs special handling. 1692 // The instanceof operator needs special handling.
1633 if (Token::IsInstanceofOperator(node->kind())) { 1693 if (Token::IsInstanceofOperator(node->kind())) {
1634 __ popq(RAX); // Left operand. 1694 __ popq(RAX); // Left operand.
1635 ASSERT(node->right()->IsTypeNode()); 1695 ASSERT(node->right()->IsTypeNode());
1636 GenerateInstanceOf(node->id(), 1696 GenerateInstanceOf(node->id(),
1637 node->token_index(), 1697 node->token_index(),
1698 node->left(),
1638 node->right()->AsTypeNode()->type(), 1699 node->right()->AsTypeNode()->type(),
1639 (node->kind() == Token::kISNOT)); 1700 (node->kind() == Token::kISNOT));
1640 if (!IsResultNeeded(node)) { 1701 if (!IsResultNeeded(node)) {
1641 __ popq(RAX); // Pop the result of the instanceof operation. 1702 __ popq(RAX); // Pop the result of the instanceof operation.
1642 } 1703 }
1643 return; 1704 return;
1644 } 1705 }
1645 1706
1646 node->right()->Visit(this); 1707 node->right()->Visit(this);
1647 // Both left and right values on stack. 1708 // 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( 2724 const Error& error = Error::Handle(
2664 Parser::FormatError(script, token_index, "Error", format, args)); 2725 Parser::FormatError(script, token_index, "Error", format, args));
2665 va_end(args); 2726 va_end(args);
2666 Isolate::Current()->long_jump_base()->Jump(1, error); 2727 Isolate::Current()->long_jump_base()->Jump(1, error);
2667 UNREACHABLE(); 2728 UNREACHABLE();
2668 } 2729 }
2669 2730
2670 } // namespace dart 2731 } // namespace dart
2671 2732
2672 #endif // defined TARGET_ARCH_X64 2733 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_x64.h ('k') | runtime/vm/flow_graph_compiler_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698