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

Side by Side Diff: runtime/vm/flow_graph_compiler_ia32.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_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.h » ('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/flow_graph_compiler.h" 8 #include "vm/flow_graph_compiler.h"
9 9
10 #include "lib/error.h" 10 #include "lib/error.h"
(...skipping 429 matching lines...) Expand 10 before | Expand all | Expand 10 after
440 // - NULL -> return false. 440 // - NULL -> return false.
441 // - Smi -> compile time subtype check (only if dst class is not parameterized). 441 // - Smi -> compile time subtype check (only if dst class is not parameterized).
442 // - Class equality (only if class is not parameterized). 442 // - Class equality (only if class is not parameterized).
443 // Inputs: 443 // Inputs:
444 // - EAX: object. 444 // - EAX: object.
445 // - EDX: instantiator type arguments or raw_null. 445 // - EDX: instantiator type arguments or raw_null.
446 // - ECX: instantiator or raw_null. 446 // - ECX: instantiator or raw_null.
447 // Clobbers ECX and EDX. 447 // Clobbers ECX and EDX.
448 // Returns: 448 // Returns:
449 // - true or false in EAX. 449 // - true or false in EAX.
450 void FlowGraphCompiler::GenerateInstanceOf(intptr_t deopt_id, 450 void FlowGraphCompiler::GenerateInstanceOf(intptr_t token_pos,
451 intptr_t token_pos,
452 const AbstractType& type, 451 const AbstractType& type,
453 bool negate_result, 452 bool negate_result,
454 LocationSummary* locs) { 453 LocationSummary* locs) {
455 ASSERT(type.IsFinalized() && !type.IsMalformed()); 454 ASSERT(type.IsFinalized() && !type.IsMalformed());
456 455
457 const Immediate raw_null = 456 const Immediate raw_null =
458 Immediate(reinterpret_cast<intptr_t>(Object::null())); 457 Immediate(reinterpret_cast<intptr_t>(Object::null()));
459 Label is_instance, is_not_instance; 458 Label is_instance, is_not_instance;
460 __ pushl(ECX); // Store instantiator on stack. 459 __ pushl(ECX); // Store instantiator on stack.
461 __ pushl(EDX); // Store instantiator type arguments. 460 __ pushl(EDX); // Store instantiator type arguments.
(...skipping 22 matching lines...) Expand all
484 // Generate runtime call. 483 // Generate runtime call.
485 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 484 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
486 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 485 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
487 __ PushObject(Object::ZoneHandle()); // Make room for the result. 486 __ PushObject(Object::ZoneHandle()); // Make room for the result.
488 __ pushl(EAX); // Push the instance. 487 __ pushl(EAX); // Push the instance.
489 __ PushObject(type); // Push the type. 488 __ PushObject(type); // Push the type.
490 __ pushl(ECX); // Instantiator. 489 __ pushl(ECX); // Instantiator.
491 __ pushl(EDX); // Instantiator type arguments. 490 __ pushl(EDX); // Instantiator type arguments.
492 __ LoadObject(EAX, test_cache); 491 __ LoadObject(EAX, test_cache);
493 __ pushl(EAX); 492 __ pushl(EAX);
494 GenerateCallRuntime(deopt_id, token_pos, kInstanceofRuntimeEntry, locs); 493 GenerateCallRuntime(token_pos, kInstanceofRuntimeEntry, locs);
495 // Pop the parameters supplied to the runtime entry. The result of the 494 // Pop the parameters supplied to the runtime entry. The result of the
496 // instanceof runtime call will be left as the result of the operation. 495 // instanceof runtime call will be left as the result of the operation.
497 __ Drop(5); 496 __ Drop(5);
498 if (negate_result) { 497 if (negate_result) {
499 __ popl(EDX); 498 __ popl(EDX);
500 __ LoadObject(EAX, bool_true()); 499 __ LoadObject(EAX, bool_true());
501 __ cmpl(EDX, EAX); 500 __ cmpl(EDX, EAX);
502 __ j(NOT_EQUAL, &done, Assembler::kNearJump); 501 __ j(NOT_EQUAL, &done, Assembler::kNearJump);
503 __ LoadObject(EAX, bool_false()); 502 __ LoadObject(EAX, bool_false());
504 } else { 503 } else {
(...skipping 18 matching lines...) Expand all
523 // - Smi -> compile time subtype check (only if dst class is not parameterized). 522 // - Smi -> compile time subtype check (only if dst class is not parameterized).
524 // - Class equality (only if class is not parameterized). 523 // - Class equality (only if class is not parameterized).
525 // Inputs: 524 // Inputs:
526 // - EAX: object. 525 // - EAX: object.
527 // - EDX: instantiator type arguments or raw_null. 526 // - EDX: instantiator type arguments or raw_null.
528 // - ECX: instantiator or raw_null. 527 // - ECX: instantiator or raw_null.
529 // Returns: 528 // Returns:
530 // - object in EAX for successful assignable check (or throws TypeError). 529 // - object in EAX for successful assignable check (or throws TypeError).
531 // Performance notes: positive checks must be quick, negative checks can be slow 530 // Performance notes: positive checks must be quick, negative checks can be slow
532 // as they throw an exception. 531 // as they throw an exception.
533 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t deopt_id, 532 void FlowGraphCompiler::GenerateAssertAssignable(intptr_t token_pos,
534 intptr_t token_pos,
535 const AbstractType& dst_type, 533 const AbstractType& dst_type,
536 const String& dst_name, 534 const String& dst_name,
537 LocationSummary* locs) { 535 LocationSummary* locs) {
538 ASSERT(token_pos >= 0); 536 ASSERT(token_pos >= 0);
539 ASSERT(!dst_type.IsNull()); 537 ASSERT(!dst_type.IsNull());
540 ASSERT(dst_type.IsFinalized()); 538 ASSERT(dst_type.IsFinalized());
541 // Assignable check is skipped in FlowGraphBuilder, not here. 539 // Assignable check is skipped in FlowGraphBuilder, not here.
542 ASSERT(dst_type.IsMalformed() || 540 ASSERT(dst_type.IsMalformed() ||
543 (!dst_type.IsDynamicType() && !dst_type.IsObjectType())); 541 (!dst_type.IsDynamicType() && !dst_type.IsObjectType()));
544 __ pushl(ECX); // Store instantiator. 542 __ pushl(ECX); // Store instantiator.
545 __ pushl(EDX); // Store instantiator type arguments. 543 __ pushl(EDX); // Store instantiator type arguments.
546 // A null object is always assignable and is returned as result. 544 // A null object is always assignable and is returned as result.
547 const Immediate raw_null = 545 const Immediate raw_null =
548 Immediate(reinterpret_cast<intptr_t>(Object::null())); 546 Immediate(reinterpret_cast<intptr_t>(Object::null()));
549 Label is_assignable, runtime_call; 547 Label is_assignable, runtime_call;
550 __ cmpl(EAX, raw_null); 548 __ cmpl(EAX, raw_null);
551 __ j(EQUAL, &is_assignable); 549 __ j(EQUAL, &is_assignable);
552 550
553 // Generate throw new TypeError() if the type is malformed. 551 // Generate throw new TypeError() if the type is malformed.
554 if (dst_type.IsMalformed()) { 552 if (dst_type.IsMalformed()) {
555 const Error& error = Error::Handle(dst_type.malformed_error()); 553 const Error& error = Error::Handle(dst_type.malformed_error());
556 const String& error_message = String::ZoneHandle( 554 const String& error_message = String::ZoneHandle(
557 Symbols::New(error.ToErrorCString())); 555 Symbols::New(error.ToErrorCString()));
558 __ PushObject(Object::ZoneHandle()); // Make room for the result. 556 __ PushObject(Object::ZoneHandle()); // Make room for the result.
559 __ pushl(EAX); // Push the source object. 557 __ pushl(EAX); // Push the source object.
560 __ PushObject(dst_name); // Push the name of the destination. 558 __ PushObject(dst_name); // Push the name of the destination.
561 __ PushObject(error_message); 559 __ PushObject(error_message);
562 GenerateCallRuntime(deopt_id, 560 GenerateCallRuntime(token_pos,
563 token_pos,
564 kMalformedTypeErrorRuntimeEntry, 561 kMalformedTypeErrorRuntimeEntry,
565 locs); 562 locs);
566 // We should never return here. 563 // We should never return here.
567 __ int3(); 564 __ int3();
568 565
569 __ Bind(&is_assignable); // For a null object. 566 __ Bind(&is_assignable); // For a null object.
570 __ popl(EDX); // Remove pushed instantiator type arguments. 567 __ popl(EDX); // Remove pushed instantiator type arguments.
571 __ popl(ECX); // Remove pushed instantiator. 568 __ popl(ECX); // Remove pushed instantiator.
572 return; 569 return;
573 } 570 }
574 571
575 // Generate inline type check, linking to runtime call if not assignable. 572 // Generate inline type check, linking to runtime call if not assignable.
576 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle(); 573 SubtypeTestCache& test_cache = SubtypeTestCache::ZoneHandle();
577 test_cache = GenerateInlineInstanceof(token_pos, dst_type, 574 test_cache = GenerateInlineInstanceof(token_pos, dst_type,
578 &is_assignable, &runtime_call); 575 &is_assignable, &runtime_call);
579 576
580 __ Bind(&runtime_call); 577 __ Bind(&runtime_call);
581 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments. 578 __ movl(EDX, Address(ESP, 0)); // Get instantiator type arguments.
582 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator. 579 __ movl(ECX, Address(ESP, kWordSize)); // Get instantiator.
583 __ PushObject(Object::ZoneHandle()); // Make room for the result. 580 __ PushObject(Object::ZoneHandle()); // Make room for the result.
584 __ pushl(EAX); // Push the source object. 581 __ pushl(EAX); // Push the source object.
585 __ PushObject(dst_type); // Push the type of the destination. 582 __ PushObject(dst_type); // Push the type of the destination.
586 __ pushl(ECX); // Instantiator. 583 __ pushl(ECX); // Instantiator.
587 __ pushl(EDX); // Instantiator type arguments. 584 __ pushl(EDX); // Instantiator type arguments.
588 __ PushObject(dst_name); // Push the name of the destination. 585 __ PushObject(dst_name); // Push the name of the destination.
589 __ LoadObject(EAX, test_cache); 586 __ LoadObject(EAX, test_cache);
590 __ pushl(EAX); 587 __ pushl(EAX);
591 GenerateCallRuntime(deopt_id, token_pos, kTypeCheckRuntimeEntry, locs); 588 GenerateCallRuntime(token_pos, kTypeCheckRuntimeEntry, locs);
592 // Pop the parameters supplied to the runtime entry. The result of the 589 // Pop the parameters supplied to the runtime entry. The result of the
593 // type check runtime call is the checked value. 590 // type check runtime call is the checked value.
594 __ Drop(6); 591 __ Drop(6);
595 __ popl(EAX); 592 __ popl(EAX);
596 593
597 __ Bind(&is_assignable); 594 __ Bind(&is_assignable);
598 __ popl(EDX); // Remove pushed instantiator type arguments. 595 __ popl(EDX); // Remove pushed instantiator type arguments.
599 __ popl(ECX); // Remove pushed instantiator. 596 __ popl(ECX); // Remove pushed instantiator.
600 } 597 }
601 598
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 #endif 930 #endif
934 if (check_arguments) { 931 if (check_arguments) {
935 __ Comment("Check argument count"); 932 __ Comment("Check argument count");
936 // Check that num_fixed <= argc <= num_params. 933 // Check that num_fixed <= argc <= num_params.
937 Label argc_in_range; 934 Label argc_in_range;
938 // Total number of args is the first Smi in args descriptor array (EDX). 935 // Total number of args is the first Smi in args descriptor array (EDX).
939 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); 936 __ movl(EAX, FieldAddress(EDX, Array::data_offset()));
940 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count))); 937 __ cmpl(EAX, Immediate(Smi::RawValue(parameter_count)));
941 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); 938 __ j(EQUAL, &argc_in_range, Assembler::kNearJump);
942 if (function.IsClosureFunction()) { 939 if (function.IsClosureFunction()) {
943 GenerateCallRuntime(Isolate::kNoDeoptId, 940 GenerateCallRuntime(function.token_pos(),
944 function.token_pos(),
945 kClosureArgumentMismatchRuntimeEntry, 941 kClosureArgumentMismatchRuntimeEntry,
946 prologue_locs); 942 prologue_locs);
947 } else { 943 } else {
948 __ Stop("Wrong number of arguments"); 944 __ Stop("Wrong number of arguments");
949 } 945 }
950 __ Bind(&argc_in_range); 946 __ Bind(&argc_in_range);
951 } 947 }
952 // The arguments descriptor is never saved in the absence of optional 948 // The arguments descriptor is never saved in the absence of optional
953 // parameters, since any argument definition test would always yield true. 949 // parameters, since any argument definition test would always yield true.
954 ASSERT(saved_args_desc_var == NULL); 950 ASSERT(saved_args_desc_var == NULL);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 } else { 1027 } else {
1032 // Add deoptimization continuation point after the call and before the 1028 // Add deoptimization continuation point after the call and before the
1033 // arguments are removed. 1029 // arguments are removed.
1034 AddCurrentDescriptor(PcDescriptors::kDeoptAfter, 1030 AddCurrentDescriptor(PcDescriptors::kDeoptAfter,
1035 deopt_id, 1031 deopt_id,
1036 token_pos); 1032 token_pos);
1037 } 1033 }
1038 } 1034 }
1039 1035
1040 1036
1041 void FlowGraphCompiler::GenerateCallRuntime(intptr_t deopt_id, 1037 void FlowGraphCompiler::GenerateCallRuntime(intptr_t token_pos,
1042 intptr_t token_pos,
1043 const RuntimeEntry& entry, 1038 const RuntimeEntry& entry,
1044 LocationSummary* locs) { 1039 LocationSummary* locs) {
1045 ASSERT(!IsLeaf()); 1040 ASSERT(!IsLeaf());
1046 __ CallRuntime(entry); 1041 __ CallRuntime(entry);
1047 AddCurrentDescriptor(PcDescriptors::kOther, deopt_id, token_pos); 1042 AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos);
1048 RecordSafepoint(locs); 1043 RecordSafepoint(locs);
1049 } 1044 }
1050 1045
1051 1046
1052 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label, 1047 void FlowGraphCompiler::EmitInstanceCall(ExternalLabel* target_label,
1053 const ICData& ic_data, 1048 const ICData& ic_data,
1054 const Array& arguments_descriptor, 1049 const Array& arguments_descriptor,
1055 intptr_t argument_count, 1050 intptr_t argument_count,
1056 intptr_t deopt_id, 1051 intptr_t deopt_id,
1057 intptr_t token_pos, 1052 intptr_t token_pos,
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
1319 __ popl(ECX); 1314 __ popl(ECX);
1320 __ popl(EAX); 1315 __ popl(EAX);
1321 } 1316 }
1322 1317
1323 1318
1324 #undef __ 1319 #undef __
1325 1320
1326 } // namespace dart 1321 } // namespace dart
1327 1322
1328 #endif // defined TARGET_ARCH_IA32 1323 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler_ia32.h ('k') | runtime/vm/flow_graph_compiler_x64.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698