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

Side by Side Diff: runtime/vm/code_generator_ia32.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_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 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 intptr_t token_index, 1307 intptr_t token_index,
1308 const AbstractType& type, 1308 const AbstractType& type,
1309 bool negate_result) { 1309 bool negate_result) {
1310 ASSERT(type.IsFinalized() && !type.IsMalformed()); 1310 ASSERT(type.IsFinalized() && !type.IsMalformed());
1311 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1311 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1312 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1312 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1313 1313
1314 // All instances are of a subtype of the Object type. 1314 // All instances are of a subtype of the Object type.
1315 const Type& object_type = 1315 const Type& object_type =
1316 Type::Handle(Isolate::Current()->object_store()->object_type()); 1316 Type::Handle(Isolate::Current()->object_store()->object_type());
1317 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { 1317 Error& malformed_error = Error::Handle();
1318 if (type.IsInstantiated() &&
1319 object_type.IsSubtypeOf(type, &malformed_error)) {
1318 __ PushObject(negate_result ? bool_false : bool_true); 1320 __ PushObject(negate_result ? bool_false : bool_true);
1319 return; 1321 return;
1320 } 1322 }
1321 1323
1322 const Immediate raw_null = 1324 const Immediate raw_null =
1323 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1325 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1324 Label done; 1326 Label done;
1325 // If type is instantiated and non-parameterized, we can inline code 1327 // If type is instantiated and non-parameterized, we can inline code
1326 // checking whether the tested instance is a Smi. 1328 // checking whether the tested instance is a Smi.
1327 if (type.IsInstantiated()) { 1329 if (type.IsInstantiated()) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1376 } 1378 }
1377 __ Bind(&runtime_call); 1379 __ Bind(&runtime_call);
1378 // Fall through to runtime call. 1380 // Fall through to runtime call.
1379 } else { 1381 } else {
1380 Label compare_classes; 1382 Label compare_classes;
1381 __ testl(EAX, Immediate(kSmiTagMask)); 1383 __ testl(EAX, Immediate(kSmiTagMask));
1382 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1384 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1383 // Object is Smi. 1385 // Object is Smi.
1384 const Class& smi_class = Class::Handle(Smi::Class()); 1386 const Class& smi_class = Class::Handle(Smi::Class());
1385 // TODO(regis): We should introduce a SmiType. 1387 // TODO(regis): We should introduce a SmiType.
1388 Error& malformed_error = Error::Handle();
1386 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1389 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1387 type_class, 1390 type_class,
1388 TypeArguments::Handle())) { 1391 TypeArguments::Handle(),
1392 &malformed_error)) {
1389 __ PushObject(negate_result ? bool_false : bool_true); 1393 __ PushObject(negate_result ? bool_false : bool_true);
1390 } else { 1394 } else {
1391 __ PushObject(negate_result ? bool_true : bool_false); 1395 __ PushObject(negate_result ? bool_true : bool_false);
1392 } 1396 }
1393 __ jmp(&done, Assembler::kNearJump); 1397 __ jmp(&done, Assembler::kNearJump);
1394 1398
1395 // Compare if the classes are equal. 1399 // Compare if the classes are equal.
1396 __ Bind(&compare_classes); 1400 __ Bind(&compare_classes);
1397 const Class* compare_class = NULL; 1401 const Class* compare_class = NULL;
1398 if (type.IsStringInterface()) { 1402 if (type.IsStringInterface()) {
(...skipping 10 matching lines...) Expand all
1409 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1413 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1410 __ CompareObject(ECX, *compare_class); 1414 __ CompareObject(ECX, *compare_class);
1411 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1415 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1412 __ PushObject(negate_result ? bool_false : bool_true); 1416 __ PushObject(negate_result ? bool_false : bool_true);
1413 __ jmp(&done, Assembler::kNearJump); 1417 __ jmp(&done, Assembler::kNearJump);
1414 __ Bind(&runtime_call); 1418 __ Bind(&runtime_call);
1415 } 1419 }
1416 } 1420 }
1417 } 1421 }
1418 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1422 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1423 const Immediate location =
1424 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1425 __ pushl(location); // Push the source location.
1419 __ pushl(EAX); // Push the instance. 1426 __ pushl(EAX); // Push the instance.
1420 __ PushObject(type); // Push the type. 1427 __ PushObject(type); // Push the type.
1421 if (!type.IsInstantiated()) { 1428 if (!type.IsInstantiated()) {
1422 GenerateInstantiatorTypeArguments(token_index); 1429 GenerateInstantiatorTypeArguments(token_index);
1423 } else { 1430 } else {
1424 __ pushl(raw_null); // Null instantiator. 1431 __ pushl(raw_null); // Null instantiator.
1425 } 1432 }
1426 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); 1433 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
1427 // Pop the two parameters supplied to the runtime entry. The result of the 1434 // Pop the two parameters supplied to the runtime entry. The result of the
1428 // instanceof runtime call will be left as the result of the operation. 1435 // instanceof runtime call will be left as the result of the operation.
1429 __ addl(ESP, Immediate(3 * kWordSize)); 1436 __ addl(ESP, Immediate(4 * kWordSize));
1430 if (negate_result) { 1437 if (negate_result) {
1431 Label negate_done; 1438 Label negate_done;
1432 __ popl(EDX); 1439 __ popl(EDX);
1433 __ LoadObject(EAX, bool_true); 1440 __ LoadObject(EAX, bool_true);
1434 __ cmpl(EDX, EAX); 1441 __ cmpl(EDX, EAX);
1435 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); 1442 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump);
1436 __ LoadObject(EAX, bool_false); 1443 __ LoadObject(EAX, bool_false);
1437 __ Bind(&negate_done); 1444 __ Bind(&negate_done);
1438 __ pushl(EAX); 1445 __ pushl(EAX);
1439 } 1446 }
(...skipping 21 matching lines...) Expand all
1461 // - object in EAX for successful assignable check (or throws TypeError). 1468 // - object in EAX for successful assignable check (or throws TypeError).
1462 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1469 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1463 intptr_t token_index, 1470 intptr_t token_index,
1464 const AbstractType& dst_type, 1471 const AbstractType& dst_type,
1465 const String& dst_name) { 1472 const String& dst_name) {
1466 ASSERT(FLAG_enable_type_checks); 1473 ASSERT(FLAG_enable_type_checks);
1467 ASSERT(token_index >= 0); 1474 ASSERT(token_index >= 0);
1468 ASSERT(!dst_type.IsNull()); 1475 ASSERT(!dst_type.IsNull());
1469 ASSERT(dst_type.IsFinalized()); 1476 ASSERT(dst_type.IsFinalized());
1470 1477
1471 // Generate throw new TypeError() if the type is malformed.
1472 if (dst_type.IsMalformed()) {
1473 const Error& error = Error::Handle(dst_type.malformed_error());
1474 const String& error_message = String::ZoneHandle(
1475 String::NewSymbol(error.ToErrorCString()));
1476 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1477 const Immediate location =
1478 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1479 __ pushl(location); // Push the source location.
1480 __ pushl(EAX); // Push the source object.
1481 __ PushObject(error_message);
1482 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1483 // We should never return here.
1484 __ int3();
1485 return;
1486 }
1487
1488 // Any expression is assignable to the Dynamic type and to the Object type. 1478 // Any expression is assignable to the Dynamic type and to the Object type.
1489 // Skip the test. 1479 // Skip the test.
1490 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { 1480 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
1491 return; 1481 return;
1492 } 1482 }
1493 1483
1494 // It is a compile-time error to explicitly return a value (including null) 1484 // It is a compile-time error to explicitly return a value (including null)
1495 // from a void function. However, functions that do not explicitly return a 1485 // from a void function. However, functions that do not explicitly return a
1496 // value, implicitly return null. This includes void functions. Therefore, we 1486 // value, implicitly return null. This includes void functions. Therefore, we
1497 // skip the type test here and trust the parser to only return null in void 1487 // skip the type test here and trust the parser to only return null in void
1498 // function. 1488 // function.
1499 if (dst_type.IsVoidType()) { 1489 if (dst_type.IsVoidType()) {
1500 return; 1490 return;
1501 } 1491 }
1502 1492
1503 // A NULL object is always assignable and is returned as result. 1493 // A null object is always assignable and is returned as result.
1504 const Immediate raw_null = 1494 const Immediate raw_null =
1505 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1495 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1506 Label done, runtime_call; 1496 Label done, runtime_call;
1507 __ cmpl(EAX, raw_null); 1497 __ cmpl(EAX, raw_null);
1508 __ j(EQUAL, &done, Assembler::kNearJump); 1498 __ j(EQUAL, &done, Assembler::kNearJump);
1509 1499
1500 // Generate throw new TypeError() if the type is malformed.
1501 if (dst_type.IsMalformed()) {
1502 const Error& error = Error::Handle(dst_type.malformed_error());
1503 const String& error_message = String::ZoneHandle(
1504 String::NewSymbol(error.ToErrorCString()));
1505 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1506 const Immediate location =
1507 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1508 __ pushl(location); // Push the source location.
1509 __ pushl(EAX); // Push the source object.
1510 __ PushObject(dst_name); // Push the name of the destination.
1511 __ PushObject(error_message);
1512 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1513 // We should never return here.
1514 __ int3();
1515 return;
1516 }
1517
1510 // If dst_type is instantiated and non-parameterized, we can inline code 1518 // If dst_type is instantiated and non-parameterized, we can inline code
1511 // checking whether the assigned instance is a Smi. 1519 // checking whether the assigned instance is a Smi.
1512 if (dst_type.IsInstantiated()) { 1520 if (dst_type.IsInstantiated()) {
1513 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); 1521 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class());
1514 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); 1522 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments();
1515 // A Smi object cannot be the instance of a parameterized class. 1523 // A Smi object cannot be the instance of a parameterized class.
1516 // A class equality check is only applicable with a dst type of a 1524 // A class equality check is only applicable with a dst type of a
1517 // non-parameterized class or with a raw dst type of a parameterized class. 1525 // non-parameterized class or with a raw dst type of a parameterized class.
1518 if (dst_class_has_type_arguments) { 1526 if (dst_class_has_type_arguments) {
1519 const AbstractTypeArguments& dst_type_arguments = 1527 const AbstractTypeArguments& dst_type_arguments =
(...skipping 17 matching lines...) Expand all
1537 } 1545 }
1538 // Fall through to runtime class. 1546 // Fall through to runtime class.
1539 } 1547 }
1540 } else { // dst_type has NO type arguments. 1548 } else { // dst_type has NO type arguments.
1541 Label compare_classes; 1549 Label compare_classes;
1542 __ testl(EAX, Immediate(kSmiTagMask)); 1550 __ testl(EAX, Immediate(kSmiTagMask));
1543 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1551 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1544 // Object is Smi. 1552 // Object is Smi.
1545 const Class& smi_class = Class::Handle(Smi::Class()); 1553 const Class& smi_class = Class::Handle(Smi::Class());
1546 // TODO(regis): We should introduce a SmiType. 1554 // TODO(regis): We should introduce a SmiType.
1555 Error& malformed_error = Error::Handle();
1547 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1556 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1548 dst_type_class, 1557 dst_type_class,
1549 TypeArguments::Handle())) { 1558 TypeArguments::Handle(),
1559 &malformed_error)) {
1550 // Successful assignable type check: return object in EAX. 1560 // Successful assignable type check: return object in EAX.
1551 __ jmp(&done, Assembler::kNearJump); 1561 __ jmp(&done, Assembler::kNearJump);
1552 } else { 1562 } else {
1553 // Failed assignable type check: call runtime to throw TypeError. 1563 // Failed assignable type check: call runtime to throw TypeError.
1554 __ jmp(&runtime_call, Assembler::kNearJump); 1564 __ jmp(&runtime_call, Assembler::kNearJump);
1555 } 1565 }
1556 // Compare if the classes are equal. 1566 // Compare if the classes are equal.
1557 __ Bind(&compare_classes); 1567 __ Bind(&compare_classes);
1558 // If dst_type is an interface, we can skip the class equality check, 1568 // If dst_type is an interface, we can skip the class equality check,
1559 // because instances cannot be of an interface type. 1569 // because instances cannot be of an interface type.
1560 if (!dst_type_class.is_interface()) { 1570 if (!dst_type_class.is_interface()) {
1561 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1571 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1562 TestClassAndJump(dst_type_class, &done); 1572 TestClassAndJump(dst_type_class, &done);
1563 } else { 1573 } else {
1564 // However, for specific core library interfaces, we can check for 1574 // However, for specific core library interfaces, we can check for
1565 // specific core library classes. 1575 // specific core library classes.
1576 Error& malformed_error = Error::Handle();
1566 if (dst_type.IsBoolInterface()) { 1577 if (dst_type.IsBoolInterface()) {
1567 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1578 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1568 const Class& bool_class = Class::ZoneHandle( 1579 const Class& bool_class = Class::ZoneHandle(
1569 Isolate::Current()->object_store()->bool_class()); 1580 Isolate::Current()->object_store()->bool_class());
1570 TestClassAndJump(bool_class, &done); 1581 TestClassAndJump(bool_class, &done);
1571 } else if (dst_type.IsSubtypeOf( 1582 } else if (dst_type.IsSubtypeOf(
1572 Type::Handle(Type::NumberInterface()))) { 1583 Type::Handle(Type::NumberInterface()), &malformed_error)) {
1573 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1584 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1574 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { 1585 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) {
1575 // We already checked for Smi above. 1586 // We already checked for Smi above.
1576 const Class& mint_class = Class::ZoneHandle( 1587 const Class& mint_class = Class::ZoneHandle(
1577 Isolate::Current()->object_store()->mint_class()); 1588 Isolate::Current()->object_store()->mint_class());
1578 TestClassAndJump(mint_class, &done); 1589 TestClassAndJump(mint_class, &done);
1579 const Class& bigint_class = Class::ZoneHandle( 1590 const Class& bigint_class = Class::ZoneHandle(
1580 Isolate::Current()->object_store()->bigint_class()); 1591 Isolate::Current()->object_store()->bigint_class());
1581 TestClassAndJump(bigint_class, &done); 1592 TestClassAndJump(bigint_class, &done);
1582 } 1593 }
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2716 const Error& error = Error::Handle( 2727 const Error& error = Error::Handle(
2717 Parser::FormatError(script, token_index, "Error", format, args)); 2728 Parser::FormatError(script, token_index, "Error", format, args));
2718 va_end(args); 2729 va_end(args);
2719 Isolate::Current()->long_jump_base()->Jump(1, error); 2730 Isolate::Current()->long_jump_base()->Jump(1, error);
2720 UNREACHABLE(); 2731 UNREACHABLE();
2721 } 2732 }
2722 2733
2723 } // namespace dart 2734 } // namespace dart
2724 2735
2725 #endif // defined TARGET_ARCH_IA32 2736 #endif // defined TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698