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

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

Issue 9615035: Generate dynamic type errors according to spec. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 1284 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 intptr_t token_index, 1295 intptr_t token_index,
1296 const AbstractType& type, 1296 const AbstractType& type,
1297 bool negate_result) { 1297 bool negate_result) {
1298 ASSERT(type.IsFinalized() && !type.IsMalformed()); 1298 ASSERT(type.IsFinalized() && !type.IsMalformed());
1299 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1299 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1300 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1300 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1301 1301
1302 // All instances are of a subtype of the Object type. 1302 // All instances are of a subtype of the Object type.
1303 const Type& object_type = 1303 const Type& object_type =
1304 Type::Handle(Isolate::Current()->object_store()->object_type()); 1304 Type::Handle(Isolate::Current()->object_store()->object_type());
1305 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { 1305 Error& malformed_error = Error::Handle();
1306 if (type.IsInstantiated() &&
1307 object_type.IsSubtypeOf(type, &malformed_error)) {
1306 __ PushObject(negate_result ? bool_false : bool_true); 1308 __ PushObject(negate_result ? bool_false : bool_true);
1307 return; 1309 return;
1308 } 1310 }
1309 1311
1310 const Immediate raw_null = 1312 const Immediate raw_null =
1311 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1313 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1312 Label done; 1314 Label done;
1313 // If type is instantiated and non-parameterized, we can inline code 1315 // If type is instantiated and non-parameterized, we can inline code
1314 // checking whether the tested instance is a Smi. 1316 // checking whether the tested instance is a Smi.
1315 if (type.IsInstantiated()) { 1317 if (type.IsInstantiated()) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1364 } 1366 }
1365 __ Bind(&runtime_call); 1367 __ Bind(&runtime_call);
1366 // Fall through to runtime call. 1368 // Fall through to runtime call.
1367 } else { 1369 } else {
1368 Label compare_classes; 1370 Label compare_classes;
1369 __ testq(RAX, Immediate(kSmiTagMask)); 1371 __ testq(RAX, Immediate(kSmiTagMask));
1370 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1372 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1371 // Object is Smi. 1373 // Object is Smi.
1372 const Class& smi_class = Class::Handle(Smi::Class()); 1374 const Class& smi_class = Class::Handle(Smi::Class());
1373 // TODO(regis): We should introduce a SmiType. 1375 // TODO(regis): We should introduce a SmiType.
1376 Error& malformed_error = Error::Handle();
1374 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1377 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1375 type_class, 1378 type_class,
1376 TypeArguments::Handle())) { 1379 TypeArguments::Handle(),
1380 &malformed_error)) {
1377 __ PushObject(negate_result ? bool_false : bool_true); 1381 __ PushObject(negate_result ? bool_false : bool_true);
1378 } else { 1382 } else {
1379 __ PushObject(negate_result ? bool_true : bool_false); 1383 __ PushObject(negate_result ? bool_true : bool_false);
1380 } 1384 }
1381 __ jmp(&done); 1385 __ jmp(&done);
1382 1386
1383 // Compare if the classes are equal. 1387 // Compare if the classes are equal.
1384 __ Bind(&compare_classes); 1388 __ Bind(&compare_classes);
1385 const Class* compare_class = NULL; 1389 const Class* compare_class = NULL;
1386 if (type.IsStringInterface()) { 1390 if (type.IsStringInterface()) {
(...skipping 10 matching lines...) Expand all
1397 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1401 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1398 __ CompareObject(RCX, *compare_class); 1402 __ CompareObject(RCX, *compare_class);
1399 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1403 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1400 __ PushObject(negate_result ? bool_false : bool_true); 1404 __ PushObject(negate_result ? bool_false : bool_true);
1401 __ jmp(&done, Assembler::kNearJump); 1405 __ jmp(&done, Assembler::kNearJump);
1402 __ Bind(&runtime_call); 1406 __ Bind(&runtime_call);
1403 } 1407 }
1404 } 1408 }
1405 } 1409 }
1406 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1410 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1411 const Immediate location =
1412 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
1413 __ pushq(location); // Push the source location.
1407 __ pushq(RAX); // Push the instance. 1414 __ pushq(RAX); // Push the instance.
1408 __ PushObject(type); // Push the type. 1415 __ PushObject(type); // Push the type.
1409 if (!type.IsInstantiated()) { 1416 if (!type.IsInstantiated()) {
1410 GenerateInstantiatorTypeArguments(token_index); 1417 GenerateInstantiatorTypeArguments(token_index);
1411 } else { 1418 } else {
1412 __ pushq(raw_null); // Null instantiator. 1419 __ pushq(raw_null); // Null instantiator.
1413 } 1420 }
1414 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); 1421 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
1415 // Pop the two parameters supplied to the runtime entry. The result of the 1422 // Pop the two parameters supplied to the runtime entry. The result of the
1416 // instanceof runtime call will be left as the result of the operation. 1423 // instanceof runtime call will be left as the result of the operation.
1417 __ addq(RSP, Immediate(3 * kWordSize)); 1424 __ addq(RSP, Immediate(4 * kWordSize));
1418 if (negate_result) { 1425 if (negate_result) {
1419 Label negate_done; 1426 Label negate_done;
1420 __ popq(RDX); 1427 __ popq(RDX);
1421 __ LoadObject(RAX, bool_true); 1428 __ LoadObject(RAX, bool_true);
1422 __ cmpq(RDX, RAX); 1429 __ cmpq(RDX, RAX);
1423 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); 1430 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump);
1424 __ LoadObject(RAX, bool_false); 1431 __ LoadObject(RAX, bool_false);
1425 __ Bind(&negate_done); 1432 __ Bind(&negate_done);
1426 __ pushq(RAX); 1433 __ pushq(RAX);
1427 } 1434 }
(...skipping 21 matching lines...) Expand all
1449 // - object in RAX for successful assignable check (or throws TypeError). 1456 // - object in RAX for successful assignable check (or throws TypeError).
1450 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1457 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1451 intptr_t token_index, 1458 intptr_t token_index,
1452 const AbstractType& dst_type, 1459 const AbstractType& dst_type,
1453 const String& dst_name) { 1460 const String& dst_name) {
1454 ASSERT(FLAG_enable_type_checks); 1461 ASSERT(FLAG_enable_type_checks);
1455 ASSERT(token_index >= 0); 1462 ASSERT(token_index >= 0);
1456 ASSERT(!dst_type.IsNull()); 1463 ASSERT(!dst_type.IsNull());
1457 ASSERT(dst_type.IsFinalized()); 1464 ASSERT(dst_type.IsFinalized());
1458 1465
1459 // Generate throw new TypeError() if the type is malformed.
1460 if (dst_type.IsMalformed()) {
1461 const Error& error = Error::Handle(dst_type.malformed_error());
1462 const String& error_message = String::ZoneHandle(
1463 String::NewSymbol(error.ToErrorCString()));
1464 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1465 const Immediate location =
1466 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
1467 __ pushq(location); // Push the source location.
1468 __ pushq(RAX); // Push the source object.
1469 __ PushObject(error_message);
1470 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1471 // We should never return here.
1472 __ int3();
1473 return;
1474 }
1475
1476 // Any expression is assignable to the Dynamic type and to the Object type. 1466 // Any expression is assignable to the Dynamic type and to the Object type.
1477 // Skip the test. 1467 // Skip the test.
1478 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { 1468 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
1479 return; 1469 return;
1480 } 1470 }
1481 1471
1482 // It is a compile-time error to explicitly return a value (including null) 1472 // It is a compile-time error to explicitly return a value (including null)
1483 // from a void function. However, functions that do not explicitly return a 1473 // from a void function. However, functions that do not explicitly return a
1484 // value, implicitly return null. This includes void functions. Therefore, we 1474 // value, implicitly return null. This includes void functions. Therefore, we
1485 // skip the type test here and trust the parser to only return null in void 1475 // skip the type test here and trust the parser to only return null in void
1486 // function. 1476 // function.
1487 if (dst_type.IsVoidType()) { 1477 if (dst_type.IsVoidType()) {
1488 return; 1478 return;
1489 } 1479 }
1490 1480
1491 // A NULL object is always assignable and is returned as result. 1481 // A null object is always assignable and is returned as result.
1492 const Immediate raw_null = 1482 const Immediate raw_null =
1493 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1483 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1494 Label done, runtime_call; 1484 Label done, runtime_call;
1495 __ cmpq(RAX, raw_null); 1485 __ cmpq(RAX, raw_null);
1496 __ j(EQUAL, &done); 1486 __ j(EQUAL, &done);
1497 1487
1488 // Generate throw new TypeError() if the type is malformed.
1489 if (dst_type.IsMalformed()) {
1490 const Error& error = Error::Handle(dst_type.malformed_error());
1491 const String& error_message = String::ZoneHandle(
1492 String::NewSymbol(error.ToErrorCString()));
1493 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1494 const Immediate location =
1495 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
1496 __ pushq(location); // Push the source location.
1497 __ pushq(RAX); // Push the source object.
1498 __ PushObject(dst_name); // Push the name of the destination.
1499 __ PushObject(error_message);
1500 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1501 // We should never return here.
1502 __ int3();
1503 return;
1504 }
1505
1498 // If dst_type is instantiated and non-parameterized, we can inline code 1506 // If dst_type is instantiated and non-parameterized, we can inline code
1499 // checking whether the assigned instance is a Smi. 1507 // checking whether the assigned instance is a Smi.
1500 if (dst_type.IsInstantiated()) { 1508 if (dst_type.IsInstantiated()) {
1501 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); 1509 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class());
1502 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); 1510 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments();
1503 // A Smi object cannot be the instance of a parameterized class. 1511 // A Smi object cannot be the instance of a parameterized class.
1504 // A class equality check is only applicable with a dst type of a 1512 // A class equality check is only applicable with a dst type of a
1505 // non-parameterized class or with a raw dst type of a parameterized class. 1513 // non-parameterized class or with a raw dst type of a parameterized class.
1506 if (dst_class_has_type_arguments) { 1514 if (dst_class_has_type_arguments) {
1507 const AbstractTypeArguments& dst_type_arguments = 1515 const AbstractTypeArguments& dst_type_arguments =
(...skipping 17 matching lines...) Expand all
1525 } 1533 }
1526 // Fall through to runtime class. 1534 // Fall through to runtime class.
1527 } 1535 }
1528 } else { // dst_type has NO type arguments. 1536 } else { // dst_type has NO type arguments.
1529 Label compare_classes; 1537 Label compare_classes;
1530 __ testq(RAX, Immediate(kSmiTagMask)); 1538 __ testq(RAX, Immediate(kSmiTagMask));
1531 __ j(NOT_ZERO, &compare_classes); 1539 __ j(NOT_ZERO, &compare_classes);
1532 // Object is Smi. 1540 // Object is Smi.
1533 const Class& smi_class = Class::Handle(Smi::Class()); 1541 const Class& smi_class = Class::Handle(Smi::Class());
1534 // TODO(regis): We should introduce a SmiType. 1542 // TODO(regis): We should introduce a SmiType.
1543 Error& malformed_error = Error::Handle();
1535 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1544 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1536 dst_type_class, 1545 dst_type_class,
1537 TypeArguments::Handle())) { 1546 TypeArguments::Handle(),
1547 &malformed_error)) {
1538 // Successful assignable type check: return object in RAX. 1548 // Successful assignable type check: return object in RAX.
1539 __ jmp(&done); 1549 __ jmp(&done);
1540 } else { 1550 } else {
1541 // Failed assignable type check: call runtime to throw TypeError. 1551 // Failed assignable type check: call runtime to throw TypeError.
1542 __ jmp(&runtime_call); 1552 __ jmp(&runtime_call);
1543 } 1553 }
1544 // Compare if the classes are equal. 1554 // Compare if the classes are equal.
1545 __ Bind(&compare_classes); 1555 __ Bind(&compare_classes);
1546 // If dst_type is an interface, we can skip the class equality check, 1556 // If dst_type is an interface, we can skip the class equality check,
1547 // because instances cannot be of an interface type. 1557 // because instances cannot be of an interface type.
1548 if (!dst_type_class.is_interface()) { 1558 if (!dst_type_class.is_interface()) {
1549 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1559 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1550 TestClassAndJump(dst_type_class, &done); 1560 TestClassAndJump(dst_type_class, &done);
1551 } else { 1561 } else {
1552 // However, for specific core library interfaces, we can check for 1562 // However, for specific core library interfaces, we can check for
1553 // specific core library classes. 1563 // specific core library classes.
1564 Error& malformed_error = Error::Handle();
1554 if (dst_type.IsBoolInterface()) { 1565 if (dst_type.IsBoolInterface()) {
1555 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1566 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1556 const Class& bool_class = Class::ZoneHandle( 1567 const Class& bool_class = Class::ZoneHandle(
1557 Isolate::Current()->object_store()->bool_class()); 1568 Isolate::Current()->object_store()->bool_class());
1558 TestClassAndJump(bool_class, &done); 1569 TestClassAndJump(bool_class, &done);
1559 } else if (dst_type.IsSubtypeOf( 1570 } else if (dst_type.IsSubtypeOf(
1560 Type::Handle(Type::NumberInterface()))) { 1571 Type::Handle(Type::NumberInterface()), &malformed_error)) {
1561 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1572 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1562 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { 1573 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) {
1563 // We already checked for Smi above. 1574 // We already checked for Smi above.
1564 const Class& mint_class = Class::ZoneHandle( 1575 const Class& mint_class = Class::ZoneHandle(
1565 Isolate::Current()->object_store()->mint_class()); 1576 Isolate::Current()->object_store()->mint_class());
1566 TestClassAndJump(mint_class, &done); 1577 TestClassAndJump(mint_class, &done);
1567 const Class& bigint_class = Class::ZoneHandle( 1578 const Class& bigint_class = Class::ZoneHandle(
1568 Isolate::Current()->object_store()->bigint_class()); 1579 Isolate::Current()->object_store()->bigint_class());
1569 TestClassAndJump(bigint_class, &done); 1580 TestClassAndJump(bigint_class, &done);
1570 } 1581 }
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2704 const Error& error = Error::Handle( 2715 const Error& error = Error::Handle(
2705 Parser::FormatError(script, token_index, "Error", format, args)); 2716 Parser::FormatError(script, token_index, "Error", format, args));
2706 va_end(args); 2717 va_end(args);
2707 Isolate::Current()->long_jump_base()->Jump(1, error); 2718 Isolate::Current()->long_jump_base()->Jump(1, error);
2708 UNREACHABLE(); 2719 UNREACHABLE();
2709 } 2720 }
2710 2721
2711 } // namespace dart 2722 } // namespace dart
2712 2723
2713 #endif // defined TARGET_ARCH_X64 2724 #endif // defined TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698