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

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
« no previous file with comments | « runtime/vm/code_generator_ia32.cc ('k') | runtime/vm/dart_api_impl.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_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 1239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1250 intptr_t token_index, 1250 intptr_t token_index,
1251 const AbstractType& type, 1251 const AbstractType& type,
1252 bool negate_result) { 1252 bool negate_result) {
1253 ASSERT(type.IsFinalized() && !type.IsMalformed()); 1253 ASSERT(type.IsFinalized() && !type.IsMalformed());
1254 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 1254 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
1255 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); 1255 const Bool& bool_false = Bool::ZoneHandle(Bool::False());
1256 1256
1257 // All instances are of a subtype of the Object type. 1257 // All instances are of a subtype of the Object type.
1258 const Type& object_type = 1258 const Type& object_type =
1259 Type::Handle(Isolate::Current()->object_store()->object_type()); 1259 Type::Handle(Isolate::Current()->object_store()->object_type());
1260 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { 1260 Error& malformed_error = Error::Handle();
1261 if (type.IsInstantiated() &&
1262 object_type.IsSubtypeOf(type, &malformed_error)) {
1261 __ PushObject(negate_result ? bool_false : bool_true); 1263 __ PushObject(negate_result ? bool_false : bool_true);
1262 return; 1264 return;
1263 } 1265 }
1264 1266
1265 const Immediate raw_null = 1267 const Immediate raw_null =
1266 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1268 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1267 Label done; 1269 Label done;
1268 // If type is instantiated and non-parameterized, we can inline code 1270 // If type is instantiated and non-parameterized, we can inline code
1269 // checking whether the tested instance is a Smi. 1271 // checking whether the tested instance is a Smi.
1270 if (type.IsInstantiated()) { 1272 if (type.IsInstantiated()) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 } 1321 }
1320 __ Bind(&runtime_call); 1322 __ Bind(&runtime_call);
1321 // Fall through to runtime call. 1323 // Fall through to runtime call.
1322 } else { 1324 } else {
1323 Label compare_classes; 1325 Label compare_classes;
1324 __ testq(RAX, Immediate(kSmiTagMask)); 1326 __ testq(RAX, Immediate(kSmiTagMask));
1325 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump); 1327 __ j(NOT_ZERO, &compare_classes, Assembler::kNearJump);
1326 // Object is Smi. 1328 // Object is Smi.
1327 const Class& smi_class = Class::Handle(Smi::Class()); 1329 const Class& smi_class = Class::Handle(Smi::Class());
1328 // TODO(regis): We should introduce a SmiType. 1330 // TODO(regis): We should introduce a SmiType.
1331 Error& malformed_error = Error::Handle();
1329 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1332 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1330 type_class, 1333 type_class,
1331 TypeArguments::Handle())) { 1334 TypeArguments::Handle(),
1335 &malformed_error)) {
1332 __ PushObject(negate_result ? bool_false : bool_true); 1336 __ PushObject(negate_result ? bool_false : bool_true);
1333 } else { 1337 } else {
1334 __ PushObject(negate_result ? bool_true : bool_false); 1338 __ PushObject(negate_result ? bool_true : bool_false);
1335 } 1339 }
1336 __ jmp(&done); 1340 __ jmp(&done);
1337 1341
1338 // Compare if the classes are equal. 1342 // Compare if the classes are equal.
1339 __ Bind(&compare_classes); 1343 __ Bind(&compare_classes);
1340 const Class* compare_class = NULL; 1344 const Class* compare_class = NULL;
1341 if (type.IsStringInterface()) { 1345 if (type.IsStringInterface()) {
(...skipping 10 matching lines...) Expand all
1352 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1356 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1353 __ CompareObject(RCX, *compare_class); 1357 __ CompareObject(RCX, *compare_class);
1354 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump); 1358 __ j(NOT_EQUAL, &runtime_call, Assembler::kNearJump);
1355 __ PushObject(negate_result ? bool_false : bool_true); 1359 __ PushObject(negate_result ? bool_false : bool_true);
1356 __ jmp(&done, Assembler::kNearJump); 1360 __ jmp(&done, Assembler::kNearJump);
1357 __ Bind(&runtime_call); 1361 __ Bind(&runtime_call);
1358 } 1362 }
1359 } 1363 }
1360 } 1364 }
1361 __ PushObject(Object::ZoneHandle()); // Make room for the result. 1365 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1366 const Immediate location =
1367 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
1368 __ pushq(location); // Push the source location.
1362 __ pushq(RAX); // Push the instance. 1369 __ pushq(RAX); // Push the instance.
1363 __ PushObject(type); // Push the type. 1370 __ PushObject(type); // Push the type.
1364 if (!type.IsInstantiated()) { 1371 if (!type.IsInstantiated()) {
1365 GenerateInstantiatorTypeArguments(token_index); 1372 GenerateInstantiatorTypeArguments(token_index);
1366 } else { 1373 } else {
1367 __ pushq(raw_null); // Null instantiator. 1374 __ pushq(raw_null); // Null instantiator.
1368 } 1375 }
1369 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); 1376 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry);
1370 // Pop the two parameters supplied to the runtime entry. The result of the 1377 // Pop the two parameters supplied to the runtime entry. The result of the
1371 // instanceof runtime call will be left as the result of the operation. 1378 // instanceof runtime call will be left as the result of the operation.
1372 __ addq(RSP, Immediate(3 * kWordSize)); 1379 __ addq(RSP, Immediate(4 * kWordSize));
1373 if (negate_result) { 1380 if (negate_result) {
1374 Label negate_done; 1381 Label negate_done;
1375 __ popq(RDX); 1382 __ popq(RDX);
1376 __ LoadObject(RAX, bool_true); 1383 __ LoadObject(RAX, bool_true);
1377 __ cmpq(RDX, RAX); 1384 __ cmpq(RDX, RAX);
1378 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); 1385 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump);
1379 __ LoadObject(RAX, bool_false); 1386 __ LoadObject(RAX, bool_false);
1380 __ Bind(&negate_done); 1387 __ Bind(&negate_done);
1381 __ pushq(RAX); 1388 __ pushq(RAX);
1382 } 1389 }
(...skipping 21 matching lines...) Expand all
1404 // - object in RAX for successful assignable check (or throws TypeError). 1411 // - object in RAX for successful assignable check (or throws TypeError).
1405 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, 1412 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id,
1406 intptr_t token_index, 1413 intptr_t token_index,
1407 const AbstractType& dst_type, 1414 const AbstractType& dst_type,
1408 const String& dst_name) { 1415 const String& dst_name) {
1409 ASSERT(FLAG_enable_type_checks); 1416 ASSERT(FLAG_enable_type_checks);
1410 ASSERT(token_index >= 0); 1417 ASSERT(token_index >= 0);
1411 ASSERT(!dst_type.IsNull()); 1418 ASSERT(!dst_type.IsNull());
1412 ASSERT(dst_type.IsFinalized()); 1419 ASSERT(dst_type.IsFinalized());
1413 1420
1414 // Generate throw new TypeError() if the type is malformed.
1415 if (dst_type.IsMalformed()) {
1416 const Error& error = Error::Handle(dst_type.malformed_error());
1417 const String& error_message = String::ZoneHandle(
1418 String::NewSymbol(error.ToErrorCString()));
1419 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1420 const Immediate location =
1421 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
1422 __ pushq(location); // Push the source location.
1423 __ pushq(RAX); // Push the source object.
1424 __ PushObject(error_message);
1425 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1426 // We should never return here.
1427 __ int3();
1428 return;
1429 }
1430
1431 // Any expression is assignable to the Dynamic type and to the Object type. 1421 // Any expression is assignable to the Dynamic type and to the Object type.
1432 // Skip the test. 1422 // Skip the test.
1433 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) { 1423 if (dst_type.IsDynamicType() || dst_type.IsObjectType()) {
1434 return; 1424 return;
1435 } 1425 }
1436 1426
1437 // It is a compile-time error to explicitly return a value (including null) 1427 // It is a compile-time error to explicitly return a value (including null)
1438 // from a void function. However, functions that do not explicitly return a 1428 // from a void function. However, functions that do not explicitly return a
1439 // value, implicitly return null. This includes void functions. Therefore, we 1429 // value, implicitly return null. This includes void functions. Therefore, we
1440 // skip the type test here and trust the parser to only return null in void 1430 // skip the type test here and trust the parser to only return null in void
1441 // function. 1431 // function.
1442 if (dst_type.IsVoidType()) { 1432 if (dst_type.IsVoidType()) {
1443 return; 1433 return;
1444 } 1434 }
1445 1435
1446 // A NULL object is always assignable and is returned as result. 1436 // A null object is always assignable and is returned as result.
1447 const Immediate raw_null = 1437 const Immediate raw_null =
1448 Immediate(reinterpret_cast<intptr_t>(Object::null())); 1438 Immediate(reinterpret_cast<intptr_t>(Object::null()));
1449 Label done, runtime_call; 1439 Label done, runtime_call;
1450 __ cmpq(RAX, raw_null); 1440 __ cmpq(RAX, raw_null);
1451 __ j(EQUAL, &done); 1441 __ j(EQUAL, &done);
1452 1442
1443 // Generate throw new TypeError() if the type is malformed.
1444 if (dst_type.IsMalformed()) {
1445 const Error& error = Error::Handle(dst_type.malformed_error());
1446 const String& error_message = String::ZoneHandle(
1447 String::NewSymbol(error.ToErrorCString()));
1448 __ PushObject(Object::ZoneHandle()); // Make room for the result.
1449 const Immediate location =
1450 Immediate(reinterpret_cast<int64_t>(Smi::New(token_index)));
1451 __ pushq(location); // Push the source location.
1452 __ pushq(RAX); // Push the source object.
1453 __ PushObject(dst_name); // Push the name of the destination.
1454 __ PushObject(error_message);
1455 GenerateCallRuntime(node_id, token_index, kMalformedTypeErrorRuntimeEntry);
1456 // We should never return here.
1457 __ int3();
1458 return;
1459 }
1460
1453 // If dst_type is instantiated and non-parameterized, we can inline code 1461 // If dst_type is instantiated and non-parameterized, we can inline code
1454 // checking whether the assigned instance is a Smi. 1462 // checking whether the assigned instance is a Smi.
1455 if (dst_type.IsInstantiated()) { 1463 if (dst_type.IsInstantiated()) {
1456 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class()); 1464 const Class& dst_type_class = Class::ZoneHandle(dst_type.type_class());
1457 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments(); 1465 const bool dst_class_has_type_arguments = dst_type_class.HasTypeArguments();
1458 // A Smi object cannot be the instance of a parameterized class. 1466 // A Smi object cannot be the instance of a parameterized class.
1459 // A class equality check is only applicable with a dst type of a 1467 // A class equality check is only applicable with a dst type of a
1460 // non-parameterized class or with a raw dst type of a parameterized class. 1468 // non-parameterized class or with a raw dst type of a parameterized class.
1461 if (dst_class_has_type_arguments) { 1469 if (dst_class_has_type_arguments) {
1462 const AbstractTypeArguments& dst_type_arguments = 1470 const AbstractTypeArguments& dst_type_arguments =
(...skipping 17 matching lines...) Expand all
1480 } 1488 }
1481 // Fall through to runtime class. 1489 // Fall through to runtime class.
1482 } 1490 }
1483 } else { // dst_type has NO type arguments. 1491 } else { // dst_type has NO type arguments.
1484 Label compare_classes; 1492 Label compare_classes;
1485 __ testq(RAX, Immediate(kSmiTagMask)); 1493 __ testq(RAX, Immediate(kSmiTagMask));
1486 __ j(NOT_ZERO, &compare_classes); 1494 __ j(NOT_ZERO, &compare_classes);
1487 // Object is Smi. 1495 // Object is Smi.
1488 const Class& smi_class = Class::Handle(Smi::Class()); 1496 const Class& smi_class = Class::Handle(Smi::Class());
1489 // TODO(regis): We should introduce a SmiType. 1497 // TODO(regis): We should introduce a SmiType.
1498 Error& malformed_error = Error::Handle();
1490 if (smi_class.IsSubtypeOf(TypeArguments::Handle(), 1499 if (smi_class.IsSubtypeOf(TypeArguments::Handle(),
1491 dst_type_class, 1500 dst_type_class,
1492 TypeArguments::Handle())) { 1501 TypeArguments::Handle(),
1502 &malformed_error)) {
1493 // Successful assignable type check: return object in RAX. 1503 // Successful assignable type check: return object in RAX.
1494 __ jmp(&done); 1504 __ jmp(&done);
1495 } else { 1505 } else {
1496 // Failed assignable type check: call runtime to throw TypeError. 1506 // Failed assignable type check: call runtime to throw TypeError.
1497 __ jmp(&runtime_call); 1507 __ jmp(&runtime_call);
1498 } 1508 }
1499 // Compare if the classes are equal. 1509 // Compare if the classes are equal.
1500 __ Bind(&compare_classes); 1510 __ Bind(&compare_classes);
1501 // If dst_type is an interface, we can skip the class equality check, 1511 // If dst_type is an interface, we can skip the class equality check,
1502 // because instances cannot be of an interface type. 1512 // because instances cannot be of an interface type.
1503 if (!dst_type_class.is_interface()) { 1513 if (!dst_type_class.is_interface()) {
1504 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1514 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1505 TestClassAndJump(dst_type_class, &done); 1515 TestClassAndJump(dst_type_class, &done);
1506 } else { 1516 } else {
1507 // However, for specific core library interfaces, we can check for 1517 // However, for specific core library interfaces, we can check for
1508 // specific core library classes. 1518 // specific core library classes.
1519 Error& malformed_error = Error::Handle();
1509 if (dst_type.IsBoolInterface()) { 1520 if (dst_type.IsBoolInterface()) {
1510 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1521 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1511 const Class& bool_class = Class::ZoneHandle( 1522 const Class& bool_class = Class::ZoneHandle(
1512 Isolate::Current()->object_store()->bool_class()); 1523 Isolate::Current()->object_store()->bool_class());
1513 TestClassAndJump(bool_class, &done); 1524 TestClassAndJump(bool_class, &done);
1514 } else if (dst_type.IsSubtypeOf( 1525 } else if (dst_type.IsSubtypeOf(
1515 Type::Handle(Type::NumberInterface()))) { 1526 Type::Handle(Type::NumberInterface()), &malformed_error)) {
1516 __ movq(RCX, FieldAddress(RAX, Object::class_offset())); 1527 __ movq(RCX, FieldAddress(RAX, Object::class_offset()));
1517 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) { 1528 if (dst_type.IsIntInterface() || dst_type.IsNumberInterface()) {
1518 // We already checked for Smi above. 1529 // We already checked for Smi above.
1519 const Class& mint_class = Class::ZoneHandle( 1530 const Class& mint_class = Class::ZoneHandle(
1520 Isolate::Current()->object_store()->mint_class()); 1531 Isolate::Current()->object_store()->mint_class());
1521 TestClassAndJump(mint_class, &done); 1532 TestClassAndJump(mint_class, &done);
1522 const Class& bigint_class = Class::ZoneHandle( 1533 const Class& bigint_class = Class::ZoneHandle(
1523 Isolate::Current()->object_store()->bigint_class()); 1534 Isolate::Current()->object_store()->bigint_class());
1524 TestClassAndJump(bigint_class, &done); 1535 TestClassAndJump(bigint_class, &done);
1525 } 1536 }
(...skipping 1133 matching lines...) Expand 10 before | Expand all | Expand 10 after
2659 const Error& error = Error::Handle( 2670 const Error& error = Error::Handle(
2660 Parser::FormatError(script, token_index, "Error", format, args)); 2671 Parser::FormatError(script, token_index, "Error", format, args));
2661 va_end(args); 2672 va_end(args);
2662 Isolate::Current()->long_jump_base()->Jump(1, error); 2673 Isolate::Current()->long_jump_base()->Jump(1, error);
2663 UNREACHABLE(); 2674 UNREACHABLE();
2664 } 2675 }
2665 2676
2666 } // namespace dart 2677 } // namespace dart
2667 2678
2668 #endif // defined TARGET_ARCH_X64 2679 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.cc ('k') | runtime/vm/dart_api_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698