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

Side by Side Diff: vm/opt_code_generator_ia32.cc

Issue 10632009: Make the parser agnostic to the TokenStream implementation. This is the first step towards compacti… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/runtime/
Patch Set: Created 8 years, 6 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 | « vm/opt_code_generator_ia32.h ('k') | vm/parser.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) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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/opt_code_generator.h" 8 #include "vm/opt_code_generator.h"
9 9
10 #include "vm/assembler_macros.h" 10 #include "vm/assembler_macros.h"
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 deopt_reason_id_(deopt_reason_id) {} 117 deopt_reason_id_(deopt_reason_id) {}
118 118
119 void Push(Register reg) { registers_.Add(reg); } 119 void Push(Register reg) { registers_.Add(reg); }
120 120
121 void Generate(OptimizingCodeGenerator* codegen) { 121 void Generate(OptimizingCodeGenerator* codegen) {
122 codegen->assembler()->Bind(&label_); 122 codegen->assembler()->Bind(&label_);
123 for (int i = 0; i < registers_.length(); i++) { 123 for (int i = 0; i < registers_.length(); i++) {
124 codegen->assembler()->pushl(registers_[i]); 124 codegen->assembler()->pushl(registers_[i]);
125 } 125 }
126 codegen->assembler()->movl(EAX, Immediate(Smi::RawValue(deopt_reason_id_))); 126 codegen->assembler()->movl(EAX, Immediate(Smi::RawValue(deopt_reason_id_)));
127 codegen->CallDeoptimize(node_->id(), node_->token_index()); 127 codegen->CallDeoptimize(node_->id(), node_->token_pos());
128 #if defined(DEBUG) 128 #if defined(DEBUG)
129 // Check that deoptimization point exists in unoptimized code. 129 // Check that deoptimization point exists in unoptimized code.
130 const Code& unoptimized_code = 130 const Code& unoptimized_code =
131 Code::Handle(codegen->parsed_function().function().unoptimized_code()); 131 Code::Handle(codegen->parsed_function().function().unoptimized_code());
132 ASSERT(!unoptimized_code.IsNull()); 132 ASSERT(!unoptimized_code.IsNull());
133 uword continue_at_pc = 133 uword continue_at_pc =
134 unoptimized_code.GetDeoptPcAtNodeId(node_->id()); 134 unoptimized_code.GetDeoptPcAtNodeId(node_->id());
135 ASSERT(continue_at_pc != 0); 135 ASSERT(continue_at_pc != 0);
136 #endif // DEBUG 136 #endif // DEBUG
137 } 137 }
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 // Debugging helper function. TODO(srdjan): Remove 339 // Debugging helper function. TODO(srdjan): Remove
340 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) { 340 void OptimizingCodeGenerator::PrintCollectedClasses(AstNode* node) {
341 const ICData& ic_data = node->ic_data(); 341 const ICData& ic_data = node->ic_data();
342 OS::Print("Collected classes id %d num: %d\n", 342 OS::Print("Collected classes id %d num: %d\n",
343 node->id(), ic_data.NumberOfChecks()); 343 node->id(), ic_data.NumberOfChecks());
344 } 344 }
345 345
346 346
347 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) { 347 void OptimizingCodeGenerator::TraceOpt(AstNode* node, const char* message) {
348 if (FLAG_trace_optimization) { 348 if (FLAG_trace_optimization) {
349 OS::Print("Opt node ix: %d; %s\n", node->token_index(), message); 349 OS::Print("Opt node ix: %d; %s\n", node->token_pos(), message);
350 } 350 }
351 } 351 }
352 352
353 353
354 void OptimizingCodeGenerator::TraceNotOpt(AstNode* node, const char* message) { 354 void OptimizingCodeGenerator::TraceNotOpt(AstNode* node, const char* message) {
355 if (FLAG_trace_optimization) { 355 if (FLAG_trace_optimization) {
356 OS::Print("NOTOpt node ix: %d; %s: ", node->token_index(), message); 356 OS::Print("NOTOpt node ix: %d; %s: ", node->token_pos(), message);
357 AstPrinter::PrintNode(node); 357 AstPrinter::PrintNode(node);
358 OS::Print("\n"); 358 OS::Print("\n");
359 } 359 }
360 } 360 }
361 361
362 362
363 void OptimizingCodeGenerator::CallDeoptimize(intptr_t node_id, 363 void OptimizingCodeGenerator::CallDeoptimize(intptr_t node_id,
364 intptr_t token_index) { 364 intptr_t token_pos) {
365 __ call(&StubCode::DeoptimizeLabel()); 365 __ call(&StubCode::DeoptimizeLabel());
366 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); 366 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_pos);
367 #if defined(DEBUG) 367 #if defined(DEBUG)
368 __ int3(); 368 __ int3();
369 #endif 369 #endif
370 } 370 }
371 371
372 372
373 // Quick loads do not clobber registers. 373 // Quick loads do not clobber registers.
374 static bool IsQuickLoad(AstNode* node) { 374 static bool IsQuickLoad(AstNode* node) {
375 if (node->IsLoadLocalNode() && (!node->AsLoadLocalNode()->HasPseudo())) { 375 if (node->IsLoadLocalNode() && (!node->AsLoadLocalNode()->HasPseudo())) {
376 return true; 376 return true;
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow. 665 __ j(NOT_EQUAL, &slow_case, Assembler::kNearJump); // Overflow.
666 __ shll(EAX, imm); // Shift for result now we know there is no overflow. 666 __ shll(EAX, imm); // Shift for result now we know there is no overflow.
667 __ jmp(&done); 667 __ jmp(&done);
668 __ Bind(&slow_case); 668 __ Bind(&slow_case);
669 __ pushl(EAX); 669 __ pushl(EAX);
670 __ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw()))); 670 __ pushl(Immediate(reinterpret_cast<int32_t>(smi.raw())));
671 const int number_of_arguments = 2; 671 const int number_of_arguments = 2;
672 const Array& no_optional_argument_names = Array::Handle(); 672 const Array& no_optional_argument_names = Array::Handle();
673 GenerateCheckedInstanceCalls(node, 673 GenerateCheckedInstanceCalls(node,
674 node->left(), 674 node->left(),
675 node->token_index(), 675 node->token_pos(),
676 number_of_arguments, 676 number_of_arguments,
677 no_optional_argument_names); 677 no_optional_argument_names);
678 __ Bind(&done); 678 __ Bind(&done);
679 return; 679 return;
680 } 680 }
681 } 681 }
682 682
683 Label slow_case, done; 683 Label slow_case, done;
684 CodeGenInfo left_info(node->left()); 684 CodeGenInfo left_info(node->left());
685 CodeGenInfo right_info(node->right()); 685 CodeGenInfo right_info(node->right());
(...skipping 23 matching lines...) Expand all
709 __ shll(EAX, ECX); // Shift for result now we know there is no overflow. 709 __ shll(EAX, ECX); // Shift for result now we know there is no overflow.
710 // EAX is the correctly tagged Smi. 710 // EAX is the correctly tagged Smi.
711 __ jmp(&done); 711 __ jmp(&done);
712 __ Bind(&slow_case); 712 __ Bind(&slow_case);
713 __ pushl(EAX); 713 __ pushl(EAX);
714 __ pushl(EDX); 714 __ pushl(EDX);
715 const int number_of_arguments = 2; 715 const int number_of_arguments = 2;
716 const Array& no_optional_argument_names = Array::Handle(); 716 const Array& no_optional_argument_names = Array::Handle();
717 GenerateCheckedInstanceCalls(node, 717 GenerateCheckedInstanceCalls(node,
718 node->left(), 718 node->left(),
719 node->token_index(), 719 node->token_pos(),
720 number_of_arguments, 720 number_of_arguments,
721 no_optional_argument_names); 721 no_optional_argument_names);
722 __ Bind(&done); 722 __ Bind(&done);
723 } 723 }
724 724
725 725
726 // Implement Token::kSUB and Token::kBIT_NOT. 726 // Implement Token::kSUB and Token::kBIT_NOT.
727 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) { 727 void OptimizingCodeGenerator::GenerateSmiUnaryOp(UnaryOpNode* node) {
728 const ICData& ic_data = node->ic_data(); 728 const ICData& ic_data = node->ic_data();
729 ASSERT(ic_data.num_args_tested() == 1); 729 ASSERT(ic_data.num_args_tested() == 1);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 deopt_blob->label()); 782 deopt_blob->label());
783 PropagateBackLocalClass(node->operand(), double_class_); 783 PropagateBackLocalClass(node->operand(), double_class_);
784 } 784 }
785 const bool using_temp = 785 const bool using_temp =
786 (node->info() != NULL) && node->info()->allow_temp(); 786 (node->info() != NULL) && node->info()->allow_temp();
787 if (!using_temp) { 787 if (!using_temp) {
788 const Code& stub = 788 const Code& stub =
789 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 789 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
790 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 790 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
791 __ pushl(kOperandRegister); 791 __ pushl(kOperandRegister);
792 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); 792 GenerateCall(node->token_pos(), &label, PcDescriptors::kOther);
793 ASSERT(kResultRegister == EAX); 793 ASSERT(kResultRegister == EAX);
794 __ popl(kOperandRegister); 794 __ popl(kOperandRegister);
795 } else if (info.is_temp()) { 795 } else if (info.is_temp()) {
796 __ movl(kResultRegister, kOperandRegister); 796 __ movl(kResultRegister, kOperandRegister);
797 } else { 797 } else {
798 const Double& double_object = 798 const Double& double_object =
799 Double::ZoneHandle(Double::New(0.0, Heap::kOld)); 799 Double::ZoneHandle(Double::New(0.0, Heap::kOld));
800 __ LoadObject(kResultRegister, double_object); 800 __ LoadObject(kResultRegister, double_object);
801 } 801 }
802 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset())); 802 __ movsd(XMM0, FieldAddress(kOperandRegister, Double::value_offset()));
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 UNREACHABLE(); 928 UNREACHABLE();
929 } 929 }
930 } else if ((kind == Token::kSHL) || (kind == Token::kSHR)) { 930 } else if ((kind == Token::kSHL) || (kind == Token::kSHR)) {
931 GenerateSmiShiftBinaryOp(node); 931 GenerateSmiShiftBinaryOp(node);
932 } else { 932 } else {
933 // Unhandled node kind. 933 // Unhandled node kind.
934 TraceNotOpt(node, kOptMessage); 934 TraceNotOpt(node, kOptMessage);
935 node->left()->Visit(this); 935 node->left()->Visit(this);
936 node->right()->Visit(this); 936 node->right()->Visit(this);
937 CodeGenerator::GenerateBinaryOperatorCall(node->id(), 937 CodeGenerator::GenerateBinaryOperatorCall(node->id(),
938 node->token_index(), 938 node->token_pos(),
939 node->Name()); 939 node->Name());
940 } 940 }
941 __ Bind(&done); 941 __ Bind(&done);
942 HandleResult(node, EAX); 942 HandleResult(node, EAX);
943 } 943 }
944 944
945 945
946 // Supports some mixed Smi/Mint operations. 946 // Supports some mixed Smi/Mint operations.
947 // For BIT_AND operation with right operand being Smi, we can throw away 947 // For BIT_AND operation with right operand being Smi, we can throw away
948 // any Mint bits above the Smi range as long as the right operand is positive. 948 // any Mint bits above the Smi range as long as the right operand is positive.
(...skipping 27 matching lines...) Expand all
976 __ Bind(&is_smi); 976 __ Bind(&is_smi);
977 __ andl(EAX, EDX); 977 __ andl(EAX, EDX);
978 __ jmp(&done); 978 __ jmp(&done);
979 __ Bind(&slow_case); 979 __ Bind(&slow_case);
980 __ pushl(EAX); 980 __ pushl(EAX);
981 __ pushl(EDX); 981 __ pushl(EDX);
982 const int number_of_arguments = 2; 982 const int number_of_arguments = 2;
983 const Array& no_optional_argument_names = Array::Handle(); 983 const Array& no_optional_argument_names = Array::Handle();
984 GenerateCheckedInstanceCalls(node, 984 GenerateCheckedInstanceCalls(node,
985 node->left(), 985 node->left(),
986 node->token_index(), 986 node->token_pos(),
987 number_of_arguments, 987 number_of_arguments,
988 no_optional_argument_names); 988 no_optional_argument_names);
989 __ Bind(&done); 989 __ Bind(&done);
990 HandleResult(node, EAX); 990 HandleResult(node, EAX);
991 return; 991 return;
992 } 992 }
993 if ((kind == Token::kSHL) && allow_smi) { 993 if ((kind == Token::kSHL) && allow_smi) {
994 GenerateSmiShiftBinaryOp(node); 994 GenerateSmiShiftBinaryOp(node);
995 HandleResult(node, EAX); 995 HandleResult(node, EAX);
996 return; 996 return;
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1069 (node->info() != NULL) && node->info()->allow_temp(); 1069 (node->info() != NULL) && node->info()->allow_temp();
1070 if (!using_temp) { 1070 if (!using_temp) {
1071 // Parent node cannot handle a temporary double object, allocate one 1071 // Parent node cannot handle a temporary double object, allocate one
1072 // each time. 1072 // each time.
1073 result_register = kAllocatedRegister; 1073 result_register = kAllocatedRegister;
1074 const Code& stub = 1074 const Code& stub =
1075 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 1075 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
1076 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 1076 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
1077 __ pushl(kLeftRegister); 1077 __ pushl(kLeftRegister);
1078 __ pushl(kRightRegister); 1078 __ pushl(kRightRegister);
1079 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); 1079 GenerateCall(node->token_pos(), &label, PcDescriptors::kOther);
1080 __ movl(result_register, EAX); 1080 __ movl(result_register, EAX);
1081 __ popl(kRightRegister); 1081 __ popl(kRightRegister);
1082 __ popl(kLeftRegister); 1082 __ popl(kLeftRegister);
1083 } else if (left_info.IsClass(double_class_) && left_info.is_temp()) { 1083 } else if (left_info.IsClass(double_class_) && left_info.is_temp()) {
1084 result_register = kLeftRegister; 1084 result_register = kLeftRegister;
1085 } else if (right_info.IsClass(double_class_) && right_info.is_temp()) { 1085 } else if (right_info.IsClass(double_class_) && right_info.is_temp()) {
1086 result_register = kRightRegister; 1086 result_register = kRightRegister;
1087 } else { 1087 } else {
1088 result_register = kAllocatedRegister; 1088 result_register = kAllocatedRegister;
1089 // Use inlined temporary double object. 1089 // Use inlined temporary double object.
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
1320 // TODO(srdjan): Implement "+" for Strings. 1320 // TODO(srdjan): Implement "+" for Strings.
1321 // Type feedback tells this is not a Smi or Double operation. 1321 // Type feedback tells this is not a Smi or Double operation.
1322 TraceNotOpt(node, 1322 TraceNotOpt(node,
1323 "BinaryOp: type feedback tells this is not a Smi, Mint or Double op"); 1323 "BinaryOp: type feedback tells this is not a Smi, Mint or Double op");
1324 node->left()->Visit(this); 1324 node->left()->Visit(this);
1325 node->right()->Visit(this); 1325 node->right()->Visit(this);
1326 const int number_of_arguments = 2; 1326 const int number_of_arguments = 2;
1327 const Array& no_optional_argument_names = Array::Handle(); 1327 const Array& no_optional_argument_names = Array::Handle();
1328 GenerateCheckedInstanceCalls(node, 1328 GenerateCheckedInstanceCalls(node,
1329 node->left(), 1329 node->left(),
1330 node->token_index(), 1330 node->token_pos(),
1331 number_of_arguments, 1331 number_of_arguments,
1332 no_optional_argument_names); 1332 no_optional_argument_names);
1333 HandleResult(node, EAX); 1333 HandleResult(node, EAX);
1334 return; 1334 return;
1335 } 1335 }
1336 1336
1337 1337
1338 // Return offset of a field or -1 if field is not found. 1338 // Return offset of a field or -1 if field is not found.
1339 static intptr_t GetFieldOffset(const Class& field_class, 1339 static intptr_t GetFieldOffset(const Class& field_class,
1340 const String& field_name) { 1340 const String& field_name) {
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1499 receiver, 1499 receiver,
1500 field_name, 1500 field_name,
1501 recv_reg); 1501 recv_reg);
1502 } else { 1502 } else {
1503 // TODO(srdjan): Inline access. 1503 // TODO(srdjan): Inline access.
1504 __ pushl(recv_reg); 1504 __ pushl(recv_reg);
1505 const int kNumberOfArguments = 1; 1505 const int kNumberOfArguments = 1;
1506 const Array& kNoArgumentNames = Array::Handle(); 1506 const Array& kNoArgumentNames = Array::Handle();
1507 GenerateCheckedInstanceCalls(node, 1507 GenerateCheckedInstanceCalls(node,
1508 receiver, 1508 receiver,
1509 node->token_index(), 1509 node->token_pos(),
1510 kNumberOfArguments, 1510 kNumberOfArguments,
1511 kNoArgumentNames); 1511 kNoArgumentNames);
1512 } 1512 }
1513 } 1513 }
1514 1514
1515 1515
1516 // TODO(srdjan): Implement for multiple getter targets. 1516 // TODO(srdjan): Implement for multiple getter targets.
1517 // For every class inline its implicit getter, or call the instance getter. 1517 // For every class inline its implicit getter, or call the instance getter.
1518 void OptimizingCodeGenerator::VisitInstanceGetterNode( 1518 void OptimizingCodeGenerator::VisitInstanceGetterNode(
1519 InstanceGetterNode* node) { 1519 InstanceGetterNode* node) {
(...skipping 18 matching lines...) Expand all
1538 1538
1539 1539
1540 // Helper struct to pass arguments to 'GenerateInstanceSetter'. 1540 // Helper struct to pass arguments to 'GenerateInstanceSetter'.
1541 struct InstanceSetterArgs { 1541 struct InstanceSetterArgs {
1542 const Class* cls; 1542 const Class* cls;
1543 const Function* target; 1543 const Function* target;
1544 const String* field_name; 1544 const String* field_name;
1545 Register recv_reg; 1545 Register recv_reg;
1546 Register value_reg; 1546 Register value_reg;
1547 intptr_t id; 1547 intptr_t id;
1548 intptr_t token_index; 1548 intptr_t token_pos;
1549 }; 1549 };
1550 1550
1551 1551
1552 // Preserves 'args.value_reg'. Either stores instance field directly or 1552 // Preserves 'args.value_reg'. Either stores instance field directly or
1553 // calls the setter method. 1553 // calls the setter method.
1554 void OptimizingCodeGenerator::GenerateInstanceSetter( 1554 void OptimizingCodeGenerator::GenerateInstanceSetter(
1555 const InstanceSetterArgs& args) { 1555 const InstanceSetterArgs& args) {
1556 if (args.target->kind() == RawFunction::kImplicitSetter) { 1556 if (args.target->kind() == RawFunction::kImplicitSetter) {
1557 intptr_t field_offset = GetFieldOffset(*(args.cls), *(args.field_name)); 1557 intptr_t field_offset = GetFieldOffset(*(args.cls), *(args.field_name));
1558 ASSERT(field_offset >= 0); 1558 ASSERT(field_offset >= 0);
1559 __ StoreIntoObject(args.recv_reg, 1559 __ StoreIntoObject(args.recv_reg,
1560 FieldAddress(args.recv_reg, field_offset), args.value_reg); 1560 FieldAddress(args.recv_reg, field_offset), args.value_reg);
1561 } else { 1561 } else {
1562 __ pushl(args.value_reg); 1562 __ pushl(args.value_reg);
1563 __ pushl(args.recv_reg); 1563 __ pushl(args.recv_reg);
1564 __ pushl(args.value_reg); 1564 __ pushl(args.value_reg);
1565 const Array& no_optional_argument_names = Array::Handle(); 1565 const Array& no_optional_argument_names = Array::Handle();
1566 GenerateDirectCall(args.id, 1566 GenerateDirectCall(args.id,
1567 args.token_index, 1567 args.token_pos,
1568 *(args.target), 1568 *(args.target),
1569 2, 1569 2,
1570 no_optional_argument_names); 1570 no_optional_argument_names);
1571 __ popl(args.value_reg); 1571 __ popl(args.value_reg);
1572 } 1572 }
1573 } 1573 }
1574 1574
1575 1575
1576 // Returns value in 'value_reg', clobbers EBX. 1576 // Returns value in 'value_reg', clobbers EBX.
1577 void OptimizingCodeGenerator::InlineInstanceSetter(AstNode* node, 1577 void OptimizingCodeGenerator::InlineInstanceSetter(AstNode* node,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1609 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget); 1609 node, recv_reg, value_reg, kDeoptInstanceSetterSameTarget);
1610 // Deoptimize if Smi, since they do not have setters. 1610 // Deoptimize if Smi, since they do not have setters.
1611 if (NodeMayBeSmi(receiver)) { 1611 if (NodeMayBeSmi(receiver)) {
1612 __ testl(recv_reg, Immediate(kSmiTagMask)); 1612 __ testl(recv_reg, Immediate(kSmiTagMask));
1613 __ j(ZERO, deopt_blob->label()); 1613 __ j(ZERO, deopt_blob->label());
1614 } 1614 }
1615 __ LoadClassId(EBX, recv_reg); 1615 __ LoadClassId(EBX, recv_reg);
1616 // Initialize setter arguments, but leave the class and target fields NULL. 1616 // Initialize setter arguments, but leave the class and target fields NULL.
1617 InstanceSetterArgs setter_args = 1617 InstanceSetterArgs setter_args =
1618 {NULL, NULL, &field_name, recv_reg, value_reg, 1618 {NULL, NULL, &field_name, recv_reg, value_reg,
1619 node->id(), node->token_index()}; 1619 node->id(), node->token_pos()};
1620 1620
1621 if (unique_target) { 1621 if (unique_target) {
1622 Label store_field; 1622 Label store_field;
1623 for (intptr_t i = 0; i < classes.length(); i++) { 1623 for (intptr_t i = 0; i < classes.length(); i++) {
1624 __ cmpl(EBX, Immediate(classes[i]->id())); 1624 __ cmpl(EBX, Immediate(classes[i]->id()));
1625 if (i == (classes.length() - 1)) { 1625 if (i == (classes.length() - 1)) {
1626 __ j(NOT_EQUAL, deopt_blob->label()); 1626 __ j(NOT_EQUAL, deopt_blob->label());
1627 } else { 1627 } else {
1628 __ j(EQUAL, &store_field); 1628 __ j(EQUAL, &store_field);
1629 } 1629 }
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1801 __ jmp(&evaluate_comparison); 1801 __ jmp(&evaluate_comparison);
1802 1802
1803 __ Bind(&call_operator); 1803 __ Bind(&call_operator);
1804 // Left is Smi. 1804 // Left is Smi.
1805 const int kNumberOfArguments = 2; 1805 const int kNumberOfArguments = 2;
1806 const Array& kNoArgumentNames = Array::Handle(); 1806 const Array& kNoArgumentNames = Array::Handle();
1807 __ pushl(EAX); 1807 __ pushl(EAX);
1808 __ pushl(EDX); 1808 __ pushl(EDX);
1809 GenerateCheckedInstanceCalls(node, 1809 GenerateCheckedInstanceCalls(node,
1810 node->left(), 1810 node->left(),
1811 node->token_index(), 1811 node->token_pos(),
1812 kNumberOfArguments, 1812 kNumberOfArguments,
1813 kNoArgumentNames); 1813 kNoArgumentNames);
1814 __ CompareObject(EAX, bool_true); 1814 __ CompareObject(EAX, bool_true);
1815 // Fall through to evaluate result. 1815 // Fall through to evaluate result.
1816 } 1816 }
1817 __ Bind(&evaluate_comparison); 1817 __ Bind(&evaluate_comparison);
1818 // Condition is set by a previous comparison operation. 1818 // Condition is set by a previous comparison operation.
1819 Condition condition = OVERFLOW; // Initialize to something. 1819 Condition condition = OVERFLOW; // Initialize to something.
1820 bool ok = SupportedTokenKindToSmiCondition(node->kind(), &condition); 1820 bool ok = SupportedTokenKindToSmiCondition(node->kind(), &condition);
1821 ASSERT(ok); 1821 ASSERT(ok);
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
2095 __ PushObject(bool_true); 2095 __ PushObject(bool_true);
2096 __ Bind(&done); 2096 __ Bind(&done);
2097 } 2097 }
2098 return; 2098 return;
2099 } 2099 }
2100 2100
2101 if (Token::IsInstanceofOperator(node->kind())) { 2101 if (Token::IsInstanceofOperator(node->kind())) {
2102 VisitLoadOne(node->left(), EAX); 2102 VisitLoadOne(node->left(), EAX);
2103 ASSERT(node->right()->IsTypeNode()); 2103 ASSERT(node->right()->IsTypeNode());
2104 GenerateInstanceOf(node->id(), 2104 GenerateInstanceOf(node->id(),
2105 node->token_index(), 2105 node->token_pos(),
2106 node->left(), 2106 node->left(),
2107 node->right()->AsTypeNode()->type(), 2107 node->right()->AsTypeNode()->type(),
2108 (node->kind() == Token::kISNOT)); 2108 (node->kind() == Token::kISNOT));
2109 if (!IsResultNeeded(node)) { 2109 if (!IsResultNeeded(node)) {
2110 __ popl(EAX); // Pop the result of the instanceof operation. 2110 __ popl(EAX); // Pop the result of the instanceof operation.
2111 } 2111 }
2112 return; 2112 return;
2113 } 2113 }
2114 2114
2115 if (NodeHasClassAt(node, smi_class_, 0)) { 2115 if (NodeHasClassAt(node, smi_class_, 0)) {
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
2317 // Note that EAX is Smi, i.e, times 2. 2317 // Note that EAX is Smi, i.e, times 2.
2318 ASSERT(kSmiTagShift == 1); 2318 ASSERT(kSmiTagShift == 1);
2319 __ StoreIntoObject(EDX, 2319 __ StoreIntoObject(EDX,
2320 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)), 2320 FieldAddress(EDX, EBX, TIMES_2, sizeof(RawArray)),
2321 ECX); 2321 ECX);
2322 HandleResult(node, ECX); 2322 HandleResult(node, ECX);
2323 return; 2323 return;
2324 } 2324 }
2325 node->index_expr()->Visit(this); 2325 node->index_expr()->Visit(this);
2326 node->value()->Visit(this); 2326 node->value()->Visit(this);
2327 GenerateStoreIndexed(node->id(), node->token_index(), IsResultNeeded(node)); 2327 GenerateStoreIndexed(node->id(), node->token_pos(), IsResultNeeded(node));
2328 } 2328 }
2329 2329
2330 2330
2331 void OptimizingCodeGenerator::VisitForNode(ForNode* node) { 2331 void OptimizingCodeGenerator::VisitForNode(ForNode* node) {
2332 if (FLAG_enable_type_checks) { 2332 if (FLAG_enable_type_checks) {
2333 CodeGenerator::VisitForNode(node); 2333 CodeGenerator::VisitForNode(node);
2334 return; 2334 return;
2335 } 2335 }
2336 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 2336 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
2337 node->initializer()->Visit(this); 2337 node->initializer()->Visit(this);
(...skipping 10 matching lines...) Expand all
2348 if (condition_info.labels_used()) { 2348 if (condition_info.labels_used()) {
2349 __ Bind(&iterate_label); 2349 __ Bind(&iterate_label);
2350 } else { 2350 } else {
2351 __ popl(EAX); 2351 __ popl(EAX);
2352 __ LoadObject(EDX, bool_true); 2352 __ LoadObject(EDX, bool_true);
2353 __ cmpl(EAX, EDX); 2353 __ cmpl(EAX, EDX);
2354 __ j(NOT_EQUAL, label->break_label()); 2354 __ j(NOT_EQUAL, label->break_label());
2355 } 2355 }
2356 } 2356 }
2357 node->body()->Visit(this); 2357 node->body()->Visit(this);
2358 HandleBackwardBranch(node->id(), node->token_index()); 2358 HandleBackwardBranch(node->id(), node->token_pos());
2359 __ Bind(label->continue_label()); 2359 __ Bind(label->continue_label());
2360 node->increment()->Visit(this); 2360 node->increment()->Visit(this);
2361 __ jmp(&loop); 2361 __ jmp(&loop);
2362 __ Bind(label->break_label()); 2362 __ Bind(label->break_label());
2363 } 2363 }
2364 2364
2365 2365
2366 void OptimizingCodeGenerator::VisitDoWhileNode(DoWhileNode* node) { 2366 void OptimizingCodeGenerator::VisitDoWhileNode(DoWhileNode* node) {
2367 if (FLAG_enable_type_checks) { 2367 if (FLAG_enable_type_checks) {
2368 CodeGenerator::VisitDoWhileNode(node); 2368 CodeGenerator::VisitDoWhileNode(node);
2369 return; 2369 return;
2370 } 2370 }
2371 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); 2371 const Bool& bool_true = Bool::ZoneHandle(Bool::True());
2372 SourceLabel* label = node->label(); 2372 SourceLabel* label = node->label();
2373 Label loop; 2373 Label loop;
2374 __ Bind(&loop); 2374 __ Bind(&loop);
2375 node->body()->Visit(this); 2375 node->body()->Visit(this);
2376 HandleBackwardBranch(node->id(), node->token_index()); 2376 HandleBackwardBranch(node->id(), node->token_pos());
2377 __ Bind(label->continue_label()); 2377 __ Bind(label->continue_label());
2378 CodeGenInfo condition_info(node->condition()); 2378 CodeGenInfo condition_info(node->condition());
2379 condition_info.set_false_label(label->break_label()); 2379 condition_info.set_false_label(label->break_label());
2380 condition_info.set_true_label(&loop); 2380 condition_info.set_true_label(&loop);
2381 condition_info.set_fallthrough_label(label->break_label()); 2381 condition_info.set_fallthrough_label(label->break_label());
2382 node->condition()->Visit(this); 2382 node->condition()->Visit(this);
2383 if (!condition_info.labels_used()) { 2383 if (!condition_info.labels_used()) {
2384 __ popl(EAX); 2384 __ popl(EAX);
2385 __ LoadObject(EDX, bool_true); 2385 __ LoadObject(EDX, bool_true);
2386 __ cmpl(EAX, EDX); 2386 __ cmpl(EAX, EDX);
(...skipping 19 matching lines...) Expand all
2406 node->condition()->Visit(this); 2406 node->condition()->Visit(this);
2407 if (condition_info.labels_used()) { 2407 if (condition_info.labels_used()) {
2408 __ Bind(&iterate_label); 2408 __ Bind(&iterate_label);
2409 } else { 2409 } else {
2410 __ popl(EAX); 2410 __ popl(EAX);
2411 __ LoadObject(EDX, bool_true); 2411 __ LoadObject(EDX, bool_true);
2412 __ cmpl(EAX, EDX); 2412 __ cmpl(EAX, EDX);
2413 __ j(NOT_EQUAL, label->break_label()); 2413 __ j(NOT_EQUAL, label->break_label());
2414 } 2414 }
2415 node->body()->Visit(this); 2415 node->body()->Visit(this);
2416 HandleBackwardBranch(node->id(), node->token_index()); 2416 HandleBackwardBranch(node->id(), node->token_pos());
2417 __ jmp(label->continue_label()); 2417 __ jmp(label->continue_label());
2418 __ Bind(label->break_label()); 2418 __ Bind(label->break_label());
2419 } 2419 }
2420 2420
2421 2421
2422 void OptimizingCodeGenerator::VisitIfNode(IfNode* node) { 2422 void OptimizingCodeGenerator::VisitIfNode(IfNode* node) {
2423 if (FLAG_enable_type_checks) { 2423 if (FLAG_enable_type_checks) {
2424 CodeGenerator::VisitIfNode(node); 2424 CodeGenerator::VisitIfNode(node);
2425 return; 2425 return;
2426 } 2426 }
(...skipping 20 matching lines...) Expand all
2447 __ Bind(&done); 2447 __ Bind(&done);
2448 } else { 2448 } else {
2449 __ Bind(&false_label); 2449 __ Bind(&false_label);
2450 } 2450 }
2451 __ Bind(&done); 2451 __ Bind(&done);
2452 } 2452 }
2453 2453
2454 2454
2455 void OptimizingCodeGenerator::GenerateDirectCall( 2455 void OptimizingCodeGenerator::GenerateDirectCall(
2456 intptr_t node_id, 2456 intptr_t node_id,
2457 intptr_t token_index, 2457 intptr_t token_pos,
2458 const Function& target, 2458 const Function& target,
2459 intptr_t arg_count, 2459 intptr_t arg_count,
2460 const Array& optional_argument_names) { 2460 const Array& optional_argument_names) {
2461 ASSERT(!target.IsNull()); 2461 ASSERT(!target.IsNull());
2462 const Code& code = Code::Handle(target.CurrentCode()); 2462 const Code& code = Code::Handle(target.CurrentCode());
2463 ASSERT(!code.IsNull()); 2463 ASSERT(!code.IsNull());
2464 ExternalLabel target_label("DirectInstanceCall", code.EntryPoint()); 2464 ExternalLabel target_label("DirectInstanceCall", code.EntryPoint());
2465 2465
2466 __ LoadObject(ECX, target); 2466 __ LoadObject(ECX, target);
2467 __ LoadObject(EDX, ArgumentsDescriptor(arg_count, optional_argument_names)); 2467 __ LoadObject(EDX, ArgumentsDescriptor(arg_count, optional_argument_names));
2468 __ call(&target_label); 2468 __ call(&target_label);
2469 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); 2469 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_pos);
2470 __ addl(ESP, Immediate(arg_count * kWordSize)); 2470 __ addl(ESP, Immediate(arg_count * kWordSize));
2471 } 2471 }
2472 2472
2473 2473
2474 // Generate inline cache calls instead of deoptimizing when no type feedback is 2474 // Generate inline cache calls instead of deoptimizing when no type feedback is
2475 // provided. 2475 // provided.
2476 // TODO(srdjan): Recompilation framework should recognize active IC calls 2476 // TODO(srdjan): Recompilation framework should recognize active IC calls
2477 // in optimized code and mark them for reoptimization since type feedback was 2477 // in optimized code and mark them for reoptimization since type feedback was
2478 // collected in the meantime. 2478 // collected in the meantime.
2479 void OptimizingCodeGenerator::GenerateInlineCacheCall( 2479 void OptimizingCodeGenerator::GenerateInlineCacheCall(
2480 intptr_t node_id, 2480 intptr_t node_id,
2481 intptr_t token_index, 2481 intptr_t token_pos,
2482 const ICData& ic_data, 2482 const ICData& ic_data,
2483 intptr_t num_args, 2483 intptr_t num_args,
2484 const Array& optional_arguments_names) { 2484 const Array& optional_arguments_names) {
2485 __ LoadObject(ECX, ic_data); 2485 __ LoadObject(ECX, ic_data);
2486 __ LoadObject(EDX, ArgumentsDescriptor(num_args, optional_arguments_names)); 2486 __ LoadObject(EDX, ArgumentsDescriptor(num_args, optional_arguments_names));
2487 2487
2488 uword label_address = 0; 2488 uword label_address = 0;
2489 switch (ic_data.num_args_tested()) { 2489 switch (ic_data.num_args_tested()) {
2490 case 1: 2490 case 1:
2491 label_address = StubCode::OneArgCheckInlineCacheEntryPoint(); 2491 label_address = StubCode::OneArgCheckInlineCacheEntryPoint();
2492 break; 2492 break;
2493 case 2: 2493 case 2:
2494 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint(); 2494 label_address = StubCode::TwoArgsCheckInlineCacheEntryPoint();
2495 break; 2495 break;
2496 default: 2496 default:
2497 UNIMPLEMENTED(); 2497 UNIMPLEMENTED();
2498 } 2498 }
2499 2499
2500 ExternalLabel target_label("InlineCache", label_address); 2500 ExternalLabel target_label("InlineCache", label_address);
2501 2501
2502 __ call(&target_label); 2502 __ call(&target_label);
2503 AddCurrentDescriptor(PcDescriptors::kIcCall, 2503 AddCurrentDescriptor(PcDescriptors::kIcCall,
2504 node_id, 2504 node_id,
2505 token_index); 2505 token_pos);
2506 __ addl(ESP, Immediate(num_args * kWordSize)); 2506 __ addl(ESP, Immediate(num_args * kWordSize));
2507 } 2507 }
2508 2508
2509 2509
2510 // Normalizes the ic_data class/target pairs: 2510 // Normalizes the ic_data class/target pairs:
2511 // - If Smi class exists, make it the first one. 2511 // - If Smi class exists, make it the first one.
2512 // - If 'null_target' not null, append null-class/'null_target' 2512 // - If 'null_target' not null, append null-class/'null_target'
2513 void OptimizingCodeGenerator::NormalizeClassChecks( 2513 void OptimizingCodeGenerator::NormalizeClassChecks(
2514 const ICData& ic_data, 2514 const ICData& ic_data,
2515 const Function& null_target, 2515 const Function& null_target,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2551 targets->Add(&null_target); 2551 targets->Add(&null_target);
2552 } 2552 }
2553 } 2553 }
2554 2554
2555 2555
2556 // Use IC data in 'node' to issues checks and calls. 2556 // Use IC data in 'node' to issues checks and calls.
2557 // IC data can contain one or more argument checks. 2557 // IC data can contain one or more argument checks.
2558 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls( 2558 void OptimizingCodeGenerator::GenerateCheckedInstanceCalls(
2559 AstNode* node, 2559 AstNode* node,
2560 AstNode* receiver, 2560 AstNode* receiver,
2561 intptr_t token_index, 2561 intptr_t token_pos,
2562 intptr_t num_args, 2562 intptr_t num_args,
2563 const Array& optional_arguments_names) { 2563 const Array& optional_arguments_names) {
2564 ASSERT(node != NULL); 2564 ASSERT(node != NULL);
2565 ASSERT(receiver != NULL); 2565 ASSERT(receiver != NULL);
2566 ASSERT(num_args > 0); 2566 ASSERT(num_args > 0);
2567 const ICData& ic_data = node->ic_data(); 2567 const ICData& ic_data = node->ic_data();
2568 if (ic_data.NumberOfChecks() == 0) { 2568 if (ic_data.NumberOfChecks() == 0) {
2569 // No type feedback means node was never executed. However that can be 2569 // No type feedback means node was never executed. However that can be
2570 // a common case especially in case of large switch statements. 2570 // a common case especially in case of large switch statements.
2571 // Use a special inline cache call which can help us decide when to 2571 // Use a special inline cache call which can help us decide when to
2572 // re-optimize this optiumized function. 2572 // re-optimize this optiumized function.
2573 GenerateInlineCacheCall( 2573 GenerateInlineCacheCall(
2574 node->id(), token_index, ic_data, num_args, optional_arguments_names); 2574 node->id(), token_pos, ic_data, num_args, optional_arguments_names);
2575 return; 2575 return;
2576 } 2576 }
2577 2577
2578 Function& target_for_null = Function::ZoneHandle(); 2578 Function& target_for_null = Function::ZoneHandle();
2579 ObjectStore* object_store = Isolate::Current()->object_store(); 2579 ObjectStore* object_store = Isolate::Current()->object_store();
2580 int num_optional_args = 2580 int num_optional_args =
2581 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length(); 2581 optional_arguments_names.IsNull() ? 0 : optional_arguments_names.Length();
2582 target_for_null = Resolver::ResolveDynamicForReceiverClass( 2582 target_for_null = Resolver::ResolveDynamicForReceiverClass(
2583 Class::Handle(object_store->object_class()), 2583 Class::Handle(object_store->object_class()),
2584 String::Handle(ic_data.target_name()), 2584 String::Handle(ic_data.target_name()),
(...skipping 12 matching lines...) Expand all
2597 if (classes[0]->raw() == smi_class_.raw()) { 2597 if (classes[0]->raw() == smi_class_.raw()) {
2598 start_ix++; 2598 start_ix++;
2599 // Smi test is needed. 2599 // Smi test is needed.
2600 __ testl(EAX, Immediate(kSmiTagMask)); 2600 __ testl(EAX, Immediate(kSmiTagMask));
2601 if (classes.length() == 1) { 2601 if (classes.length() == 1) {
2602 // Only Smi test. 2602 // Only Smi test.
2603 DeoptimizationBlob* deopt_blob = 2603 DeoptimizationBlob* deopt_blob =
2604 AddDeoptimizationBlob(node, kDeoptPolymorphicInstanceCallSmiOnly); 2604 AddDeoptimizationBlob(node, kDeoptPolymorphicInstanceCallSmiOnly);
2605 __ j(NOT_ZERO, deopt_blob->label()); 2605 __ j(NOT_ZERO, deopt_blob->label());
2606 GenerateDirectCall(node->id(), 2606 GenerateDirectCall(node->id(),
2607 token_index, 2607 token_pos,
2608 *targets[0], 2608 *targets[0],
2609 num_args, 2609 num_args,
2610 optional_arguments_names); 2610 optional_arguments_names);
2611 return; 2611 return;
2612 } 2612 }
2613 Label not_smi; 2613 Label not_smi;
2614 __ j(NOT_ZERO, &not_smi); 2614 __ j(NOT_ZERO, &not_smi);
2615 GenerateDirectCall(node->id(), 2615 GenerateDirectCall(node->id(),
2616 token_index, 2616 token_pos,
2617 *targets[0], 2617 *targets[0],
2618 num_args, 2618 num_args,
2619 optional_arguments_names); 2619 optional_arguments_names);
2620 __ jmp(&done); 2620 __ jmp(&done);
2621 __ Bind(&not_smi); // Continue with other test below. 2621 __ Bind(&not_smi); // Continue with other test below.
2622 } else if (NodeMayBeSmi(receiver)) { 2622 } else if (NodeMayBeSmi(receiver)) {
2623 DeoptimizationBlob* deopt_blob = 2623 DeoptimizationBlob* deopt_blob =
2624 AddDeoptimizationBlob(node, kDeoptPolymorphicInstanceCallSmiFail); 2624 AddDeoptimizationBlob(node, kDeoptPolymorphicInstanceCallSmiFail);
2625 __ testl(EAX, Immediate(kSmiTagMask)); 2625 __ testl(EAX, Immediate(kSmiTagMask));
2626 __ j(ZERO, deopt_blob->label()); 2626 __ j(ZERO, deopt_blob->label());
2627 } else { 2627 } else {
2628 // Receiver cannot be Smi, no need to test it. 2628 // Receiver cannot be Smi, no need to test it.
2629 } 2629 }
2630 __ LoadClassId(EAX, EAX); // Receiver's class id. 2630 __ LoadClassId(EAX, EAX); // Receiver's class id.
2631 for (intptr_t i = start_ix; i < classes.length(); i++) { 2631 for (intptr_t i = start_ix; i < classes.length(); i++) {
2632 const Class& cls = *classes[i]; 2632 const Class& cls = *classes[i];
2633 const Function& target = *targets[i]; 2633 const Function& target = *targets[i];
2634 __ cmpl(EAX, Immediate(cls.id())); 2634 __ cmpl(EAX, Immediate(cls.id()));
2635 if (i == (classes.length() - 1)) { 2635 if (i == (classes.length() - 1)) {
2636 // Last check. 2636 // Last check.
2637 DeoptimizationBlob* deopt_blob = 2637 DeoptimizationBlob* deopt_blob =
2638 AddDeoptimizationBlob(node, kDeoptPolymorphicInstanceCallTestFail); 2638 AddDeoptimizationBlob(node, kDeoptPolymorphicInstanceCallTestFail);
2639 __ j(NOT_EQUAL, deopt_blob->label()); 2639 __ j(NOT_EQUAL, deopt_blob->label());
2640 GenerateDirectCall(node->id(), 2640 GenerateDirectCall(node->id(),
2641 token_index, 2641 token_pos,
2642 target, 2642 target,
2643 num_args, 2643 num_args,
2644 optional_arguments_names); 2644 optional_arguments_names);
2645 } else { 2645 } else {
2646 Label next; 2646 Label next;
2647 __ j(NOT_EQUAL, &next); 2647 __ j(NOT_EQUAL, &next);
2648 GenerateDirectCall(node->id(), 2648 GenerateDirectCall(node->id(),
2649 token_index, 2649 token_pos,
2650 target, 2650 target,
2651 num_args, 2651 num_args,
2652 optional_arguments_names); 2652 optional_arguments_names);
2653 __ jmp(&done); 2653 __ jmp(&done);
2654 __ Bind(&next); 2654 __ Bind(&next);
2655 } 2655 }
2656 } 2656 }
2657 __ Bind(&done); 2657 __ Bind(&done);
2658 } 2658 }
2659 2659
2660 2660
2661 void OptimizingCodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) { 2661 void OptimizingCodeGenerator::VisitInstanceCallNode(InstanceCallNode* node) {
2662 const int number_of_arguments = node->arguments()->length() + 1; 2662 const int number_of_arguments = node->arguments()->length() + 1;
2663 // Compute the receiver object and pass it as first argument to call. 2663 // Compute the receiver object and pass it as first argument to call.
2664 node->receiver()->Visit(this); 2664 node->receiver()->Visit(this);
2665 // Now compute rest of the arguments to the call. 2665 // Now compute rest of the arguments to the call.
2666 node->arguments()->Visit(this); 2666 node->arguments()->Visit(this);
2667 if (TryInlineInstanceCall(node)) { 2667 if (TryInlineInstanceCall(node)) {
2668 // Instance call is inlined. 2668 // Instance call is inlined.
2669 } else { 2669 } else {
2670 GenerateCheckedInstanceCalls(node, 2670 GenerateCheckedInstanceCalls(node,
2671 node->receiver(), 2671 node->receiver(),
2672 node->token_index(), 2672 node->token_pos(),
2673 number_of_arguments, 2673 number_of_arguments,
2674 node->arguments()->names()); 2674 node->arguments()->names());
2675 } 2675 }
2676 // Result is in EAX. 2676 // Result is in EAX.
2677 HandleResult(node, EAX); 2677 HandleResult(node, EAX);
2678 } 2678 }
2679 2679
2680 2680
2681 // Returns true if an instance call was replaced with its intrinsic. 2681 // Returns true if an instance call was replaced with its intrinsic.
2682 // Returns result in EAX. 2682 // Returns result in EAX.
(...skipping 14 matching lines...) Expand all
2697 target.ToFullyQualifiedCString(), 2697 target.ToFullyQualifiedCString(),
2698 Recognizer::KindToCString(recognized)); 2698 Recognizer::KindToCString(recognized));
2699 } 2699 }
2700 if ((recognized == Recognizer::kIntegerToDouble) && 2700 if ((recognized == Recognizer::kIntegerToDouble) &&
2701 NodeHasClassAt(node, smi_class_, 0)) { 2701 NodeHasClassAt(node, smi_class_, 0)) {
2702 // TODO(srdjan): Check if we could use temporary double instead of 2702 // TODO(srdjan): Check if we could use temporary double instead of
2703 // allocating a new object every time. 2703 // allocating a new object every time.
2704 const Code& stub = 2704 const Code& stub =
2705 Code::Handle(StubCode::GetAllocationStubForClass(double_class_)); 2705 Code::Handle(StubCode::GetAllocationStubForClass(double_class_));
2706 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint()); 2706 const ExternalLabel label(double_class_.ToCString(), stub.EntryPoint());
2707 GenerateCall(node->token_index(), &label, PcDescriptors::kOther); 2707 GenerateCall(node->token_pos(), &label, PcDescriptors::kOther);
2708 // EAX is double object. 2708 // EAX is double object.
2709 DeoptimizationBlob* deopt_blob = 2709 DeoptimizationBlob* deopt_blob =
2710 AddDeoptimizationBlob(node, EBX, kDeoptIntegerToDouble); 2710 AddDeoptimizationBlob(node, EBX, kDeoptIntegerToDouble);
2711 __ popl(EBX); // Receiver 2711 __ popl(EBX); // Receiver
2712 __ testl(EBX, Immediate(kSmiTagMask)); 2712 __ testl(EBX, Immediate(kSmiTagMask));
2713 __ j(NOT_ZERO, deopt_blob->label()); // Deoptimize if not Smi. 2713 __ j(NOT_ZERO, deopt_blob->label()); // Deoptimize if not Smi.
2714 __ SmiUntag(EBX); 2714 __ SmiUntag(EBX);
2715 __ cvtsi2sd(XMM0, EBX); 2715 __ cvtsi2sd(XMM0, EBX);
2716 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 2716 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
2717 return true; 2717 return true;
(...skipping 26 matching lines...) Expand all
2744 double_class_, 2744 double_class_,
2745 &call_method, 2745 &call_method,
2746 EAX); // Result register. 2746 EAX); // Result register.
2747 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0); 2747 __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
2748 __ jmp(&done); 2748 __ jmp(&done);
2749 __ Bind(&smi_to_double); 2749 __ Bind(&smi_to_double);
2750 __ Bind(&call_method); 2750 __ Bind(&call_method);
2751 __ LoadObject(ECX, node->function()); 2751 __ LoadObject(ECX, node->function());
2752 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), 2752 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(),
2753 node->arguments()->names())); 2753 node->arguments()->names()));
2754 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel(), 2754 GenerateCall(node->token_pos(), &StubCode::CallStaticFunctionLabel(),
2755 PcDescriptors::kFuncCall); 2755 PcDescriptors::kFuncCall);
2756 __ Bind(&done); 2756 __ Bind(&done);
2757 return true; 2757 return true;
2758 } 2758 }
2759 return false; 2759 return false;
2760 } 2760 }
2761 2761
2762 2762
2763 void OptimizingCodeGenerator::VisitStaticCallNode(StaticCallNode* node) { 2763 void OptimizingCodeGenerator::VisitStaticCallNode(StaticCallNode* node) {
2764 node->arguments()->Visit(this); 2764 node->arguments()->Visit(this);
2765 if (TryInlineStaticCall(node)) { 2765 if (TryInlineStaticCall(node)) {
2766 // Static method is inlined, result is in EAX. 2766 // Static method is inlined, result is in EAX.
2767 } else { 2767 } else {
2768 __ LoadObject(ECX, node->function()); 2768 __ LoadObject(ECX, node->function());
2769 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(), 2769 __ LoadObject(EDX, ArgumentsDescriptor(node->arguments()->length(),
2770 node->arguments()->names())); 2770 node->arguments()->names()));
2771 GenerateCall(node->token_index(), &StubCode::CallStaticFunctionLabel(), 2771 GenerateCall(node->token_pos(), &StubCode::CallStaticFunctionLabel(),
2772 PcDescriptors::kFuncCall); 2772 PcDescriptors::kFuncCall);
2773 } 2773 }
2774 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize)); 2774 __ addl(ESP, Immediate(node->arguments()->length() * kWordSize));
2775 // Result is in EAX. 2775 // Result is in EAX.
2776 HandleResult(node, EAX); 2776 HandleResult(node, EAX);
2777 } 2777 }
2778 2778
2779 2779
2780 void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) { 2780 void OptimizingCodeGenerator::VisitReturnNode(ReturnNode* node) {
2781 if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) { 2781 if ((node->inlined_finally_list_length() > 0) || FLAG_enable_type_checks) {
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2880 } 2880 }
2881 } 2881 }
2882 // TODO(srdjan): Implement unary kSUB (negate) Mint. 2882 // TODO(srdjan): Implement unary kSUB (negate) Mint.
2883 CodeGenerator::VisitUnaryOpNode(node); 2883 CodeGenerator::VisitUnaryOpNode(node);
2884 } 2884 }
2885 2885
2886 2886
2887 } // namespace dart 2887 } // namespace dart
2888 2888
2889 #endif // defined TARGET_ARCH_IA32 2889 #endif // defined TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « vm/opt_code_generator_ia32.h ('k') | vm/parser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698