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

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
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/code_generator_x64.cc » ('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_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 1251 matching lines...) Expand 10 before | Expand all | Expand 10 after
1262 intptr_t token_index, 1262 intptr_t token_index,
1263 const AbstractType& type, 1263 const AbstractType& type,
1264 bool negate_result) { 1264 bool negate_result) {
1265 ASSERT(type.IsFinalized() && !type.IsMalformed()); 1265 ASSERT(type.IsFinalized() && !type.IsMalformed());
1266 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1266 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1267 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1267 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1268 1268
1269 // All instances are of a subtype of the Object type. 1269 // All instances are of a subtype of the Object type.
1270 const Type& object_type = 1270 const Type& object_type =
1271 Type::Handle(Isolate::Current()->object_store()->object_type()); 1271 Type::Handle(Isolate::Current()->object_store()->object_type());
1272 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { 1272 Error& malformed_error = Error::Handle();
1273 if (type.IsInstantiated() &&
1274 object_type.IsSubtypeOf(type, &malformed_error)) {
1273 __ PushObject(negate_result ? bool_false : bool_true); 1275 __ PushObject(negate_result ? bool_false : bool_true);
1274 return; 1276 return;
1275 } 1277 }
1276 1278
1277 const Immediate raw_null = 1279 const Immediate raw_null =
1278 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1280 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1279 Label done; 1281 Label done;
1280 // If type is instantiated and non-parameterized, we can inline code 1282 // If type is instantiated and non-parameterized, we can inline code
1281 // checking whether the tested instance is a Smi. 1283 // checking whether the tested instance is a Smi.
1282 if (type.IsInstantiated()) { 1284 if (type.IsInstantiated()) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1331 } 1333 }
1332 __ Bind(&runtime_call); 1334 __ Bind(&runtime_call);
1333 // Fall through to runtime call. 1335 // Fall through to runtime call.
1334 } else { 1336 } else {
1335 Label compare_classes; 1337 Label compare_classes;
1336 __ testl(EAX, Immediate(kSmiTagMask)); 1338 __ testl(EAX, Immediate(kSmiTagMask));
1337 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1339 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1338 // Object is Smi. 1340 // Object is Smi.
1339 const Class& smi_class = Class::Handle(Smi::Class()); 1341 const Class& smi_class = Class::Handle(Smi::Class());
1340 // TODO(regis): We should introduce a SmiType. 1342 // TODO(regis): We should introduce a SmiType.
1343 Error& malformed_error = Error::Handle();
1341 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1344 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1342 type_class, 1345 type_class,
1343 TypeArguments::Handle())) { 1346 TypeArguments::Handle(),
1347 &malformed_error)) {
1344 __ PushObject(negate_result ? bool_false : bool_true); 1348 __ PushObject(negate_result ? bool_false : bool_true);
1345 } else { 1349 } else {
1346 __ PushObject(negate_result ? bool_true : bool_false); 1350 __ PushObject(negate_result ? bool_true : bool_false);
1347 } 1351 }
1348 __ jmp(&done, Assembler::kNearJump); 1352 __ jmp(&done, Assembler::kNearJump);
1349 1353
1350 // Compare if the classes are equal. 1354 // Compare if the classes are equal.
1351 __ Bind(&compare_classes); 1355 __ Bind(&compare_classes);
1352 const Class* compare_class = NULL; 1356 const Class* compare_class = NULL;
1353 if (type.IsStringInterface()) { 1357 if (type.IsStringInterface()) {
(...skipping 10 matching lines...) Expand all
1364 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1368 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1365 __ CompareObject(ECX, *compare_class); 1369 __ CompareObject(ECX, *compare_class);
1366 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1370 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1367 __ PushObject(negate_result ? bool_false : bool_true); 1371 __ PushObject(negate_result ? bool_false : bool_true);
1368 __ jmp(&done, Assembler::kNearJump); 1372 __ jmp(&done, Assembler::kNearJump);
1369 __ Bind(&runtime_call); 1373 __ Bind(&runtime_call);
1370 } 1374 }
1371 } 1375 }
1372 } 1376 }
1373 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1377 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1378 const Immediate location =
1379 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1380 __ pushl(location); // Push the source location.
1374 __ pushl(EAX); // Push the instance. 1381 __ pushl(EAX); // Push the instance.
1375 __ PushObject(type); // Push the type. 1382 __ PushObject(type); // Push the type.
1376 if (!type.IsInstantiated()) { 1383 if (!type.IsInstantiated()) {
1377 GenerateInstantiatorTypeArguments(token_index); 1384 GenerateInstantiatorTypeArguments(token_index);
1378 } else { 1385 } else {
1379 __ pushl(raw_null); // Null instantiator. 1386 __ pushl(raw_null); // Null instantiator.
1380 } 1387 }
1381 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); 1388 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
1382 // Pop the two parameters supplied to the runtime entry. The result of the 1389 // Pop the two parameters supplied to the runtime entry. The result of the
1383 // instanceof runtime call will be left as the result of the operation. 1390 // instanceof runtime call will be left as the result of the operation.
1384 __ addl(ESP, Immediate(3 * kWordSize)); 1391 __ addl(ESP, Immediate(4 * kWordSize));
1385 if (negate_result) { 1392 if (negate_result) {
1386 Label negate_done; 1393 Label negate_done;
1387 __ popl(EDX); 1394 __ popl(EDX);
1388 __ LoadObject(EAX, bool_true); 1395 __ LoadObject(EAX, bool_true);
1389 __ cmpl(EDX, EAX); 1396 __ cmpl(EDX, EAX);
1390 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); 1397 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump);
1391 __ LoadObject(EAX, bool_false); 1398 __ LoadObject(EAX, bool_false);
1392 __ Bind(&negate_done); 1399 __ Bind(&negate_done);
1393 __ pushl(EAX); 1400 __ pushl(EAX);
1394 } 1401 }
(...skipping 21 matching lines...) Expand all
1416 // - object in EAX for successful assignable check (or throws TypeError). 1423 // - object in EAX for successful assignable check (or throws TypeError).
1417 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1424 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1418 intptr_t token_index, 1425 intptr_t token_index,
1419 const AbstractType& dst_type, 1426 const AbstractType& dst_type,
1420 const String& dst_name) { 1427 const String& dst_name) {
1421 ASSERT(FLAG_enable_type_checks); 1428 ASSERT(FLAG_enable_type_checks);
1422 ASSERT(token_index >= 0); 1429 ASSERT(token_index >= 0);
1423 ASSERT(!dst_type.IsNull()); 1430 ASSERT(!dst_type.IsNull());
1424 ASSERT(dst_type.IsFinalized()); 1431 ASSERT(dst_type.IsFinalized());
1425 1432
1426 // Generate throw new TypeError() if the type is malformed.
1427 if (dst_type.IsMalformed()) {
1428 const Error& error = Error::Handle(dst_type.malformed_error());
1429 const String& error_message = String::ZoneHandle(
1430 String::NewSymbol(error.ToErrorCString()));
1431 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1432 const Immediate location =
1433 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1434 __ pushl(location); // Push the source location.
1435 __ pushl(EAX); // Push the source object.
1436 __ PushObject(error_message);
1437 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1438 // We should never return here.
1439 __ int3();
1440 return;
1441 }
1442
1443 // Any expression is assignable to the Dynamic type and to the Object type. 1433 // Any expression is assignable to the Dynamic type and to the Object type.
1444 // Skip the test. 1434 // Skip the test.
1445 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { 1435 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
1446 return; 1436 return;
1447 } 1437 }
1448 1438
1449 // It is a compile-time error to explicitly return a value (including null) 1439 // It is a compile-time error to explicitly return a value (including null)
1450 // from a void function. However, functions that do not explicitly return a 1440 // from a void function. However, functions that do not explicitly return a
1451 // value, implicitly return null. This includes void functions. Therefore, we 1441 // value, implicitly return null. This includes void functions. Therefore, we
1452 // skip the type test here and trust the parser to only return null in void 1442 // skip the type test here and trust the parser to only return null in void
1453 // function. 1443 // function.
1454 if (dst_type.IsVoidType()) { 1444 if (dst_type.IsVoidType()) {
1455 return; 1445 return;
1456 } 1446 }
1457 1447
1458 // A NULL object is always assignable and is returned as result. 1448 // A null object is always assignable and is returned as result.
1459 const Immediate raw_null = 1449 const Immediate raw_null =
1460 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1450 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1461 Label done, runtime_call; 1451 Label done, runtime_call;
1462 __ cmpl(EAX, raw_null); 1452 __ cmpl(EAX, raw_null);
1463 __ j(EQUAL, &done, Assembler::kNearJump); 1453 __ j(EQUAL, &done, Assembler::kNearJump);
1464 1454
1455 // Generate throw new TypeError() if the type is malformed.
1456 if (dst_type.IsMalformed()) {
1457 const Error& error = Error::Handle(dst_type.malformed_error());
1458 const String& error_message = String::ZoneHandle(
1459 String::NewSymbol(error.ToErrorCString()));
1460 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1461 const Immediate location =
1462 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index)));
1463 __ pushl(location); // Push the source location.
1464 __ pushl(EAX); // Push the source object.
1465 __ PushObject(dst_name); // Push the name of the destination.
1466 __ PushObject(error_message);
1467 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1468 // We should never return here.
1469 __ int3();
1470 return;
1471 }
1472
1465 // If dst_type is instantiated and non-parameterized, we can inline code 1473 // If dst_type is instantiated and non-parameterized, we can inline code
1466 // checking whether the assigned instance is a Smi. 1474 // checking whether the assigned instance is a Smi.
1467 if (dst_type.IsInstantiated()) { 1475 if (dst_type.IsInstantiated()) {
1468 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); 1476 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class());
1469 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); 1477 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments();
1470 // A Smi object cannot be the instance of a parameterized class. 1478 // A Smi object cannot be the instance of a parameterized class.
1471 // A class equality check is only applicable with a dst type of a 1479 // A class equality check is only applicable with a dst type of a
1472 // non-parameterized class or with a raw dst type of a parameterized class. 1480 // non-parameterized class or with a raw dst type of a parameterized class.
1473 if (dst_class_has_type_arguments) { 1481 if (dst_class_has_type_arguments) {
1474 const AbstractTypeArguments& dst_type_arguments = 1482 const AbstractTypeArguments& dst_type_arguments =
(...skipping 17 matching lines...) Expand all
1492 } 1500 }
1493 // Fall through to runtime class. 1501 // Fall through to runtime class.
1494 } 1502 }
1495 } else { // dst_type has NO type arguments. 1503 } else { // dst_type has NO type arguments.
1496 Label compare_classes; 1504 Label compare_classes;
1497 __ testl(EAX, Immediate(kSmiTagMask)); 1505 __ testl(EAX, Immediate(kSmiTagMask));
1498 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1506 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1499 // Object is Smi. 1507 // Object is Smi.
1500 const Class& smi_class = Class::Handle(Smi::Class()); 1508 const Class& smi_class = Class::Handle(Smi::Class());
1501 // TODO(regis): We should introduce a SmiType. 1509 // TODO(regis): We should introduce a SmiType.
1510 Error& malformed_error = Error::Handle();
1502 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1511 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1503 dst_type_class, 1512 dst_type_class,
1504 TypeArguments::Handle())) { 1513 TypeArguments::Handle(),
1514 &malformed_error)) {
1505 // Successful assignable type check: return object in EAX. 1515 // Successful assignable type check: return object in EAX.
1506 __ jmp(&done, Assembler::kNearJump); 1516 __ jmp(&done, Assembler::kNearJump);
1507 } else { 1517 } else {
1508 // Failed assignable type check: call runtime to throw TypeError. 1518 // Failed assignable type check: call runtime to throw TypeError.
1509 __ jmp(&runtime_call, Assembler::kNearJump); 1519 __ jmp(&runtime_call, Assembler::kNearJump);
1510 } 1520 }
1511 // Compare if the classes are equal. 1521 // Compare if the classes are equal.
1512 __ Bind(&compare_classes); 1522 __ Bind(&compare_classes);
1513 // If dst_type is an interface, we can skip the class equality check, 1523 // If dst_type is an interface, we can skip the class equality check,
1514 // because instances cannot be of an interface type. 1524 // because instances cannot be of an interface type.
1515 if (!dst_type_class.is_interface()) { 1525 if (!dst_type_class.is_interface()) {
1516 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1526 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1517 TestClassAndJump(dst_type_class, &done); 1527 TestClassAndJump(dst_type_class, &done);
1518 } else { 1528 } else {
1519 // However, for specific core library interfaces, we can check for 1529 // However, for specific core library interfaces, we can check for
1520 // specific core library classes. 1530 // specific core library classes.
1531 Error& malformed_error = Error::Handle();
1521 if (dst_type.IsBoolInterface()) { 1532 if (dst_type.IsBoolInterface()) {
1522 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1533 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1523 const Class& bool_class = Class::ZoneHandle( 1534 const Class& bool_class = Class::ZoneHandle(
1524 Isolate::Current()->object_store()->bool_class()); 1535 Isolate::Current()->object_store()->bool_class());
1525 TestClassAndJump(bool_class, &done); 1536 TestClassAndJump(bool_class, &done);
1526 } else if (dst_type.IsSubtypeOf( 1537 } else if (dst_type.IsSubtypeOf(
1527 Type::Handle(Type::NumberInterface()))) { 1538 Type::Handle(Type::NumberInterface()), &malformed_error)) {
1528 __ movl(ECX, FieldAddress(EAX, Object::class_offset())); 1539 __ movl(ECX, FieldAddress(EAX, Object::class_offset()));
1529 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { 1540 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) {
1530 // We already checked for Smi above. 1541 // We already checked for Smi above.
1531 const Class& mint_class = Class::ZoneHandle( 1542 const Class& mint_class = Class::ZoneHandle(
1532 Isolate::Current()->object_store()->mint_class()); 1543 Isolate::Current()->object_store()->mint_class());
1533 TestClassAndJump(mint_class, &done); 1544 TestClassAndJump(mint_class, &done);
1534 const Class& bigint_class = Class::ZoneHandle( 1545 const Class& bigint_class = Class::ZoneHandle(
1535 Isolate::Current()->object_store()->bigint_class()); 1546 Isolate::Current()->object_store()->bigint_class());
1536 TestClassAndJump(bigint_class, &done); 1547 TestClassAndJump(bigint_class, &done);
1537 } 1548 }
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2671 const Error& error = Error::Handle( 2682 const Error& error = Error::Handle(
2672 Parser::FormatError(script, token_index, "Error", format, args)); 2683 Parser::FormatError(script, token_index, "Error", format, args));
2673 va_end(args); 2684 va_end(args);
2674 Isolate::Current()->long_jump_base()->Jump(1, error); 2685 Isolate::Current()->long_jump_base()->Jump(1, error);
2675 UNREACHABLE(); 2686 UNREACHABLE();
2676 } 2687 }
2677 2688
2678 } // namespace dart 2689 } // namespace dart
2679 2690
2680 #endif // defined TARGET_ARCH_IA32 2691 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/code_generator.cc ('k') | runtime/vm/code_generator_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698