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

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

Issue 10915026: We can throw an exception but we cannot deoptimize at a runtime call. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 3 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/flow_graph_compiler_x64.h ('k') | runtime/vm/il_printer.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/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 // - NULL -> return false. 444 // - NULL -> return false.
445 // - Smi -> compile time subtype check (only if dst class is not parameterized). 445 // - Smi -> compile time subtype check (only if dst class is not parameterized).
446 // - Class equality (only if class is not parameterized). 446 // - Class equality (only if class is not parameterized).
447 // Inputs: 447 // Inputs:
448 // - RAX: object. 448 // - RAX: object.
449 // - RDX: instantiator type arguments or raw_null. 449 // - RDX: instantiator type arguments or raw_null.
450 // - RCX: instantiator or raw_null. 450 // - RCX: instantiator or raw_null.
451 // Clobbers RCX and RDX. 451 // Clobbers RCX and RDX.
452 // Returns: 452 // Returns:
453 // - true or false in RAX. 453 // - true or false in RAX.
454 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, 454 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
455 intptr_t token_pos,
456 const AbstractType& type, 455 const AbstractType& type,
457 bool negate_result, 456 bool negate_result,
458 LocationSummary* locs) { 457 LocationSummary* locs) {
459 ASSERT(type.IsFinalized() && !type.IsMalformed()); 458 ASSERT(type.IsFinalized() && !type.IsMalformed());
460 459
461 const Immediate raw_null = 460 const Immediate raw_null =
462 Immediate(reinterpret_cast<intptr_t>(Object::null())); 461 Immediate(reinterpret_cast<intptr_t>(Object::null()));
463 Label is_instance, is_not_instance; 462 Label is_instance, is_not_instance;
464 __ pushq(RCX); // Store instantiator on stack. 463 __ pushq(RCX); // Store instantiator on stack.
465 __ pushq(RDX); // Store instantiator type arguments. 464 __ pushq(RDX); // Store instantiator type arguments.
(...skipping 22 matching lines...) Expand all
488 // Generate runtime call. 487 // Generate runtime call.
489 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. 488 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
490 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. 489 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
491 __ PushObject(Object::ZoneHandle()); // Make room for the result. 490 __ PushObject(Object::ZoneHandle()); // Make room for the result.
492 __ pushq(RAX); // Push the instance. 491 __ pushq(RAX); // Push the instance.
493 __ PushObject(type); // Push the type. 492 __ PushObject(type); // Push the type.
494 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. 493 __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null.
495 __ pushq(RDX); // Instantiator type arguments. 494 __ pushq(RDX); // Instantiator type arguments.
496 __ LoadObject(RAX, test_cache); 495 __ LoadObject(RAX, test_cache);
497 __ pushq(RAX); 496 __ pushq(RAX);
498 GenerateCallRuntime(deopt_id, token_pos, kInstanceofRuntimeEntry, locs); 497 GenerateCallRuntime(token_pos, kInstanceofRuntimeEntry, locs);
499 // Pop the parameters supplied to the runtime entry. The result of the 498 // Pop the parameters supplied to the runtime entry. The result of the
500 // instanceof runtime call will be left as the result of the operation. 499 // instanceof runtime call will be left as the result of the operation.
501 __ Drop(5); 500 __ Drop(5);
502 if (negate_result) { 501 if (negate_result) {
503 __ popq(RDX); 502 __ popq(RDX);
504 __ LoadObject(RAX, bool_true()); 503 __ LoadObject(RAX, bool_true());
505 __ cmpq(RDX, RAX); 504 __ cmpq(RDX, RAX);
506 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 505 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
507 __ LoadObject(RAX, bool_false()); 506 __ LoadObject(RAX, bool_false());
508 } else { 507 } else {
(...skipping 18 matching lines...) Expand all
527 // - Smi -> compile time subtype check (only if dst class is not parameterized). 526 // - Smi -> compile time subtype check (only if dst class is not parameterized).
528 // - Class equality (only if class is not parameterized). 527 // - Class equality (only if class is not parameterized).
529 // Inputs: 528 // Inputs:
530 // - RAX: object. 529 // - RAX: object.
531 // - RDX: instantiator type arguments or raw_null. 530 // - RDX: instantiator type arguments or raw_null.
532 // - RCX: instantiator or raw_null. 531 // - RCX: instantiator or raw_null.
533 // Returns: 532 // Returns:
534 // - object in RAX for successful assignable check (or throws TypeError). 533 // - object in RAX for successful assignable check (or throws TypeError).
535 // Performance notes: positive checks must be quick, negative checks can be slow 534 // Performance notes: positive checks must be quick, negative checks can be slow
536 // as they throw an exception. 535 // as they throw an exception.
537 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, 536 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
538 intptr_t token_pos,
539 const AbstractType& dst_type, 537 const AbstractType& dst_type,
540 const String& dst_name, 538 const String& dst_name,
541 LocationSummary* locs) { 539 LocationSummary* locs) {
542 ASSERT(token_pos >= 0); 540 ASSERT(token_pos >= 0);
543 ASSERT(!dst_type.IsNull()); 541 ASSERT(!dst_type.IsNull());
544 ASSERT(dst_type.IsFinalized()); 542 ASSERT(dst_type.IsFinalized());
545 // Assignable check is skipped in FlowGraphBuilder, not here. 543 // Assignable check is skipped in FlowGraphBuilder, not here.
546 ASSERT(dst_type.IsMalformed() || 544 ASSERT(dst_type.IsMalformed() ||
547 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 545 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
548 __ pushq(RCX); // Store instantiator. 546 __ pushq(RCX); // Store instantiator.
549 __ pushq(RDX); // Store instantiator type arguments. 547 __ pushq(RDX); // Store instantiator type arguments.
550 // A null object is always assignable and is returned as result. 548 // A null object is always assignable and is returned as result.
551 const Immediate raw_null = 549 const Immediate raw_null =
552 Immediate(reinterpret_cast<intptr_t>(Object::null())); 550 Immediate(reinterpret_cast<intptr_t>(Object::null()));
553 Label is_assignable, runtime_call; 551 Label is_assignable, runtime_call;
554 __ cmpq(RAX, raw_null); 552 __ cmpq(RAX, raw_null);
555 __ j(EQUAL, &is_assignable); 553 __ j(EQUAL, &is_assignable);
556 554
557 // Generate throw new TypeError() if the type is malformed. 555 // Generate throw new TypeError() if the type is malformed.
558 if (dst_type.IsMalformed()) { 556 if (dst_type.IsMalformed()) {
559 const Error& error = Error::Handle(dst_type.malformed_error()); 557 const Error& error = Error::Handle(dst_type.malformed_error());
560 const String& error_message = String::ZoneHandle( 558 const String& error_message = String::ZoneHandle(
561 Symbols::New(error.ToErrorCString())); 559 Symbols::New(error.ToErrorCString()));
562 __ PushObject(Object::ZoneHandle()); // Make room for the result. 560 __ PushObject(Object::ZoneHandle()); // Make room for the result.
563 __ pushq(RAX); // Push the source object. 561 __ pushq(RAX); // Push the source object.
564 __ PushObject(dst_name); // Push the name of the destination. 562 __ PushObject(dst_name); // Push the name of the destination.
565 __ PushObject(error_message); 563 __ PushObject(error_message);
566 GenerateCallRuntime(deopt_id, 564 GenerateCallRuntime(token_pos,
567 token_pos,
568 kMalformedTypeErrorRuntimeEntry, 565 kMalformedTypeErrorRuntimeEntry,
569 locs); 566 locs);
570 // We should never return here. 567 // We should never return here.
571 __ int3(); 568 __ int3();
572 569
573 __ Bind(&is_assignable); // For a null object. 570 __ Bind(&is_assignable); // For a null object.
574 __ popq(RDX); // Remove pushed instantiator type arguments. 571 __ popq(RDX); // Remove pushed instantiator type arguments.
575 __ popq(RCX); // Remove pushed instantiator. 572 __ popq(RCX); // Remove pushed instantiator.
576 return; 573 return;
577 } 574 }
578 575
579 // Generate inline type check, linking to runtime call if not assignable. 576 // Generate inline type check, linking to runtime call if not assignable.
580 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 577 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
581 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 578 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
582 &is_assignable, &runtime_call); 579 &is_assignable, &runtime_call);
583 580
584 __ Bind(&runtime_call); 581 __ Bind(&runtime_call);
585 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. 582 __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments.
586 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. 583 __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator.
587 __ PushObject(Object::ZoneHandle()); // Make room for the result. 584 __ PushObject(Object::ZoneHandle()); // Make room for the result.
588 __ pushq(RAX); // Push the source object. 585 __ pushq(RAX); // Push the source object.
589 __ PushObject(dst_type); // Push the type of the destination. 586 __ PushObject(dst_type); // Push the type of the destination.
590 __ pushq(RCX); // Instantiator. 587 __ pushq(RCX); // Instantiator.
591 __ pushq(RDX); // Instantiator type arguments. 588 __ pushq(RDX); // Instantiator type arguments.
592 __ PushObject(dst_name); // Push the name of the destination. 589 __ PushObject(dst_name); // Push the name of the destination.
593 __ LoadObject(RAX, test_cache); 590 __ LoadObject(RAX, test_cache);
594 __ pushq(RAX); 591 __ pushq(RAX);
595 GenerateCallRuntime(deopt_id, 592 GenerateCallRuntime(token_pos,
596 token_pos,
597 kTypeCheckRuntimeEntry, 593 kTypeCheckRuntimeEntry,
598 locs); 594 locs);
599 // Pop the parameters supplied to the runtime entry. The result of the 595 // Pop the parameters supplied to the runtime entry. The result of the
600 // type check runtime call is the checked value. 596 // type check runtime call is the checked value.
601 __ Drop(6); 597 __ Drop(6);
602 __ popq(RAX); 598 __ popq(RAX);
603 599
604 __ Bind(&is_assignable); 600 __ Bind(&is_assignable);
605 __ popq(RDX); // Remove pushed instantiator type arguments. 601 __ popq(RDX); // Remove pushed instantiator type arguments.
606 __ popq(RCX); // Remove pushed instantiator. 602 __ popq(RCX); // Remove pushed instantiator.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
942 #endif 938 #endif
943 if (check_arguments) { 939 if (check_arguments) {
944 __ Comment("Check argument count"); 940 __ Comment("Check argument count");
945 // Check that num_fixed <= argc <= num_params. 941 // Check that num_fixed <= argc <= num_params.
946 Label argc_in_range; 942 Label argc_in_range;
947 // Total number of args is the first Smi in args descriptor array (R10). 943 // Total number of args is the first Smi in args descriptor array (R10).
948 __ movq(RAX, FieldAddress(R10, Array::data_offset())); 944 __ movq(RAX, FieldAddress(R10, Array::data_offset()));
949 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count))); 945 __ cmpq(RAX, Immediate(Smi::RawValue(parameter_count)));
950 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); 946 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
951 if (function.IsClosureFunction()) { 947 if (function.IsClosureFunction()) {
952 GenerateCallRuntime(Isolate::kNoDeoptId, 948 GenerateCallRuntime(function.token_pos(),
953 function.token_pos(),
954 kClosureArgumentMismatchRuntimeEntry, 949 kClosureArgumentMismatchRuntimeEntry,
955 prologue_locs); 950 prologue_locs);
956 } else { 951 } else {
957 __ Stop("Wrong number of arguments"); 952 __ Stop("Wrong number of arguments");
958 } 953 }
959 __ Bind(&argc_in_range); 954 __ Bind(&argc_in_range);
960 } 955 }
961 // The arguments descriptor is never saved in the absence of optional 956 // The arguments descriptor is never saved in the absence of optional
962 // parameters, since any argument definition test would always yield true. 957 // parameters, since any argument definition test would always yield true.
963 ASSERT(saved_args_desc_var == NULL); 958 ASSERT(saved_args_desc_var == NULL);
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 } else { 1038 } else {
1044 // Add deoptimization continuation point after the call and before the 1039 // Add deoptimization continuation point after the call and before the
1045 // arguments are removed. 1040 // arguments are removed.
1046 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, 1041 AddCurrentDescriptor(PcDescriptors::kDeoptAfter,
1047 deopt_id, 1042 deopt_id,
1048 token_pos); 1043 token_pos);
1049 } 1044 }
1050 } 1045 }
1051 1046
1052 1047
1053 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, 1048 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos,
1054 intptr_t token_pos,
1055 const RuntimeEntry& entry, 1049 const RuntimeEntry& entry,
1056 LocationSummary* locs) { 1050 LocationSummary* locs) {
1057 ASSERT(!IsLeaf()); 1051 ASSERT(!IsLeaf());
1058 __ CallRuntime(entry); 1052 __ CallRuntime(entry);
1059 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); 1053 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
1060 RecordSafepoint(locs); 1054 RecordSafepoint(locs);
1061 } 1055 }
1062 1056
1063 1057
1064 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 1058 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
1065 const ICData& ic_data, 1059 const ICData& ic_data,
1066 const Array& arguments_descriptor, 1060 const Array& arguments_descriptor,
1067 intptr_t argument_count, 1061 intptr_t argument_count,
1068 intptr_t deopt_id, 1062 intptr_t deopt_id,
1069 intptr_t token_pos, 1063 intptr_t token_pos,
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) { 1303 void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
1310 __ Exchange(mem1, mem2); 1304 __ Exchange(mem1, mem2);
1311 } 1305 }
1312 1306
1313 1307
1314 #undef __ 1308 #undef __
1315 1309
1316 } // namespace dart 1310 } // namespace dart
1317 1311
1318 #endif // defined TARGET_ARCH_X64 1312 #endif // defined TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_x64.h ('k') | runtime/vm/il_printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698