OLD | NEW |
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/code_generator.h" | 8 #include "vm/code_generator.h" |
9 | 9 |
10 #include "lib/error.h" | 10 #include "lib/error.h" |
(...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 AstPrinter::PrintFunctionNodes(parsed_function_); | 258 AstPrinter::PrintFunctionNodes(parsed_function_); |
259 } | 259 } |
260 if (FLAG_trace_functions) { | 260 if (FLAG_trace_functions) { |
261 // Preserve ECX (ic-data array or object) and EDX (arguments descriptor). | 261 // Preserve ECX (ic-data array or object) and EDX (arguments descriptor). |
262 __ pushl(ECX); | 262 __ pushl(ECX); |
263 __ pushl(EDX); | 263 __ pushl(EDX); |
264 const Function& function = | 264 const Function& function = |
265 Function::ZoneHandle(parsed_function_.function().raw()); | 265 Function::ZoneHandle(parsed_function_.function().raw()); |
266 __ LoadObject(EAX, function); | 266 __ LoadObject(EAX, function); |
267 __ pushl(EAX); | 267 __ pushl(EAX); |
268 GenerateCallRuntime(0, kTraceFunctionEntryRuntimeEntry); | 268 GenerateCallRuntime(AstNode::kNoId, |
| 269 0, |
| 270 kTraceFunctionEntryRuntimeEntry); |
269 __ popl(EAX); | 271 __ popl(EAX); |
270 __ popl(EDX); | 272 __ popl(EDX); |
271 __ popl(ECX); | 273 __ popl(ECX); |
272 } | 274 } |
273 | 275 |
274 const bool code_generation_finished = TryIntrinsify(); | 276 const bool code_generation_finished = TryIntrinsify(); |
275 // In some cases intrinsifier can generate all code and no AST based | 277 // In some cases intrinsifier can generate all code and no AST based |
276 // code generation is needed. In some cases slow-paths (e.g., overflows) are | 278 // code generation is needed. In some cases slow-paths (e.g., overflows) are |
277 // implemented by the AST based code generation and 'code_generation_finished' | 279 // implemented by the AST based code generation and 'code_generation_finished' |
278 // is false. | 280 // is false. |
(...skipping 12 matching lines...) Expand all Loading... |
291 parsed_function_.node_sequence()->Visit(this); | 293 parsed_function_.node_sequence()->Visit(this); |
292 } | 294 } |
293 // End of code. | 295 // End of code. |
294 __ int3(); | 296 __ int3(); |
295 GenerateDeferredCode(); | 297 GenerateDeferredCode(); |
296 | 298 |
297 // Emit function patching code. This will be swapped with the first 5 bytes | 299 // Emit function patching code. This will be swapped with the first 5 bytes |
298 // at entry point. | 300 // at entry point. |
299 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, | 301 pc_descriptors_list_->AddDescriptor(PcDescriptors::kPatchCode, |
300 assembler_->CodeSize(), | 302 assembler_->CodeSize(), |
301 AstNode::kInvalidId, | 303 AstNode::kNoId, |
302 0, | 304 0, |
303 -1); | 305 -1); |
304 __ jmp(&StubCode::FixCallersTargetLabel()); | 306 __ jmp(&StubCode::FixCallersTargetLabel()); |
305 } | 307 } |
306 | 308 |
307 | 309 |
308 void CodeGenerator::GenerateDeferredCode() { | 310 void CodeGenerator::GenerateDeferredCode() { |
309 } | 311 } |
310 | 312 |
311 | 313 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 if (FLAG_trace_compiler) { | 364 if (FLAG_trace_compiler) { |
363 OS::Print("Not checking pc decriptors, length %d\n", | 365 OS::Print("Not checking pc decriptors, length %d\n", |
364 descriptors.Length()); | 366 descriptors.Length()); |
365 } | 367 } |
366 return; | 368 return; |
367 } | 369 } |
368 for (intptr_t i = 0; i < descriptors.Length(); i++) { | 370 for (intptr_t i = 0; i < descriptors.Length(); i++) { |
369 intptr_t pc = descriptors.PC(i); | 371 intptr_t pc = descriptors.PC(i); |
370 PcDescriptors::Kind kind = descriptors.DescriptorKind(i); | 372 PcDescriptors::Kind kind = descriptors.DescriptorKind(i); |
371 // 'node_id' is set for kDeopt and kIcCall and must be unique for one kind. | 373 // 'node_id' is set for kDeopt and kIcCall and must be unique for one kind. |
372 intptr_t node_id = AstNode::kInvalidId; | 374 intptr_t node_id = AstNode::kNoId; |
373 if (check_ids) { | 375 if (check_ids) { |
374 if ((descriptors.DescriptorKind(i) == PcDescriptors::kDeopt) || | 376 if ((descriptors.DescriptorKind(i) == PcDescriptors::kDeopt) || |
375 (descriptors.DescriptorKind(i) == PcDescriptors::kIcCall)) { | 377 (descriptors.DescriptorKind(i) == PcDescriptors::kIcCall)) { |
376 node_id = descriptors.NodeId(i); | 378 node_id = descriptors.NodeId(i); |
377 } | 379 } |
378 } | 380 } |
379 for (intptr_t k = i + 1; k < descriptors.Length(); k++) { | 381 for (intptr_t k = i + 1; k < descriptors.Length(); k++) { |
380 if (kind == descriptors.DescriptorKind(k)) { | 382 if (kind == descriptors.DescriptorKind(k)) { |
381 if (node_id != AstNode::kInvalidId) { | 383 if (node_id != AstNode::kNoId) { |
382 ASSERT(descriptors.NodeId(k) != node_id); | 384 ASSERT(descriptors.NodeId(k) != node_id); |
383 } | 385 } |
384 ASSERT(pc != descriptors.PC(k)); | 386 ASSERT(pc != descriptors.PC(k)); |
385 } | 387 } |
386 } | 388 } |
387 } | 389 } |
388 #endif // DEBUG | 390 #endif // DEBUG |
389 } | 391 } |
390 | 392 |
391 | 393 |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 571 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
570 if (num_opt_params == 0) { | 572 if (num_opt_params == 0) { |
571 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); | 573 __ cmpl(EAX, Immediate(Smi::RawValue(num_fixed_params))); |
572 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); | 574 __ j(EQUAL, &argc_in_range, Assembler::kNearJump); |
573 } else { | 575 } else { |
574 __ subl(EAX, Immediate(Smi::RawValue(num_fixed_params))); | 576 __ subl(EAX, Immediate(Smi::RawValue(num_fixed_params))); |
575 __ cmpl(EAX, Immediate(Smi::RawValue(num_opt_params))); | 577 __ cmpl(EAX, Immediate(Smi::RawValue(num_opt_params))); |
576 __ j(BELOW_EQUAL, &argc_in_range, Assembler::kNearJump); | 578 __ j(BELOW_EQUAL, &argc_in_range, Assembler::kNearJump); |
577 } | 579 } |
578 if (function.IsClosureFunction()) { | 580 if (function.IsClosureFunction()) { |
579 GenerateCallRuntime(function.token_index(), | 581 GenerateCallRuntime(AstNode::kNoId, |
| 582 function.token_index(), |
580 kClosureArgumentMismatchRuntimeEntry); | 583 kClosureArgumentMismatchRuntimeEntry); |
581 } else { | 584 } else { |
582 __ Stop("Wrong number of arguments"); | 585 __ Stop("Wrong number of arguments"); |
583 } | 586 } |
584 __ Bind(&argc_in_range); | 587 __ Bind(&argc_in_range); |
585 } | 588 } |
586 } else { | 589 } else { |
587 ASSERT(first_param_index == -1); | 590 ASSERT(first_param_index == -1); |
588 // Copy positional arguments. | 591 // Copy positional arguments. |
589 // Check that no fewer than num_fixed_params positional arguments are passed | 592 // Check that no fewer than num_fixed_params positional arguments are passed |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
693 } | 696 } |
694 delete[] opt_param; | 697 delete[] opt_param; |
695 delete[] opt_param_position; | 698 delete[] opt_param_position; |
696 // Check that EDI now points to the null terminator in the array descriptor. | 699 // Check that EDI now points to the null terminator in the array descriptor. |
697 Label all_arguments_processed; | 700 Label all_arguments_processed; |
698 __ cmpl(Address(EDI, 0), raw_null); | 701 __ cmpl(Address(EDI, 0), raw_null); |
699 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); | 702 __ j(EQUAL, &all_arguments_processed, Assembler::kNearJump); |
700 | 703 |
701 __ Bind(&wrong_num_arguments); | 704 __ Bind(&wrong_num_arguments); |
702 if (function.IsClosureFunction()) { | 705 if (function.IsClosureFunction()) { |
703 GenerateCallRuntime(function.token_index(), | 706 GenerateCallRuntime(AstNode::kNoId, |
| 707 function.token_index(), |
704 kClosureArgumentMismatchRuntimeEntry); | 708 kClosureArgumentMismatchRuntimeEntry); |
705 } else { | 709 } else { |
706 // Invoke noSuchMethod function. | 710 // Invoke noSuchMethod function. |
707 ICData ic_data(String::Handle(function.name()), 1); | 711 ICData ic_data(String::Handle(function.name()), 1); |
708 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); | 712 __ LoadObject(ECX, Array::ZoneHandle(ic_data.data())); |
709 // EBP : points to previous frame pointer. | 713 // EBP : points to previous frame pointer. |
710 // EBP + 4 : points to return address. | 714 // EBP + 4 : points to return address. |
711 // EBP + 8 : address of last argument (arg n-1). | 715 // EBP + 8 : address of last argument (arg n-1). |
712 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). | 716 // ESP + 8 + 4*(n-1) : address of first argument (arg 0). |
713 // ECX : ic-data array. | 717 // ECX : ic-data array. |
714 // EDX : arguments descriptor array. | 718 // EDX : arguments descriptor array. |
715 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); | 719 __ call(&StubCode::CallNoSuchMethodFunctionLabel()); |
716 } | 720 } |
717 | 721 |
718 if (FLAG_trace_functions) { | 722 if (FLAG_trace_functions) { |
719 __ pushl(EAX); // Preserve result. | 723 __ pushl(EAX); // Preserve result. |
720 __ PushObject(function); | 724 __ PushObject(function); |
721 GenerateCallRuntime(0, kTraceFunctionExitRuntimeEntry); | 725 GenerateCallRuntime(AstNode::kNoId, |
| 726 0, |
| 727 kTraceFunctionExitRuntimeEntry); |
722 __ popl(EAX); // Remove argument. | 728 __ popl(EAX); // Remove argument. |
723 __ popl(EAX); // Restore result. | 729 __ popl(EAX); // Restore result. |
724 } | 730 } |
725 __ LeaveFrame(); | 731 __ LeaveFrame(); |
726 __ ret(); | 732 __ ret(); |
727 | 733 |
728 __ Bind(&all_arguments_processed); | 734 __ Bind(&all_arguments_processed); |
729 // Nullify originally passed arguments only after they have been copied and | 735 // Nullify originally passed arguments only after they have been copied and |
730 // checked, otherwise noSuchMethod would not see their original values. | 736 // checked, otherwise noSuchMethod would not see their original values. |
731 // This step can be skipped in case we decide that formal parameters are | 737 // This step can be skipped in case we decide that formal parameters are |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
783 __ LoadObject(EAX, literal); | 789 __ LoadObject(EAX, literal); |
784 } | 790 } |
785 } else { | 791 } else { |
786 // Pop the previously evaluated result value into EAX. | 792 // Pop the previously evaluated result value into EAX. |
787 __ popl(EAX); | 793 __ popl(EAX); |
788 } | 794 } |
789 | 795 |
790 // Generate type check. | 796 // Generate type check. |
791 if (FLAG_enable_type_checks) { | 797 if (FLAG_enable_type_checks) { |
792 GenerateAssertAssignable( | 798 GenerateAssertAssignable( |
| 799 node->id(), |
793 node->value()->token_index(), | 800 node->value()->token_index(), |
794 Type::ZoneHandle(parsed_function().function().result_type()), | 801 Type::ZoneHandle(parsed_function().function().result_type()), |
795 String::ZoneHandle(String::NewSymbol("function result"))); | 802 String::ZoneHandle(String::NewSymbol("function result"))); |
796 } | 803 } |
797 // Unchain the context(s) up to context level 0. | 804 // Unchain the context(s) up to context level 0. |
798 int context_level = state()->context_level(); | 805 int context_level = state()->context_level(); |
799 ASSERT(context_level >= 0); | 806 ASSERT(context_level >= 0); |
800 while (context_level-- > 0) { | 807 while (context_level-- > 0) { |
801 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); | 808 __ movl(CTX, FieldAddress(CTX, Context::parent_offset())); |
802 } | 809 } |
803 #ifdef DEBUG | 810 #ifdef DEBUG |
804 // Check that the entry stack size matches the exit stack size. | 811 // Check that the entry stack size matches the exit stack size. |
805 __ movl(EDX, EBP); | 812 __ movl(EDX, EBP); |
806 __ subl(EDX, ESP); | 813 __ subl(EDX, ESP); |
807 ASSERT(locals_space_size() >= 0); | 814 ASSERT(locals_space_size() >= 0); |
808 __ cmpl(EDX, Immediate(locals_space_size())); | 815 __ cmpl(EDX, Immediate(locals_space_size())); |
809 Label wrong_stack; | 816 Label wrong_stack; |
810 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); | 817 __ j(NOT_EQUAL, &wrong_stack, Assembler::kNearJump); |
811 #endif // DEBUG. | 818 #endif // DEBUG. |
812 | 819 |
813 if (FLAG_trace_functions) { | 820 if (FLAG_trace_functions) { |
814 __ pushl(EAX); // Preserve result. | 821 __ pushl(EAX); // Preserve result. |
815 const Function& function = | 822 const Function& function = |
816 Function::ZoneHandle(parsed_function_.function().raw()); | 823 Function::ZoneHandle(parsed_function_.function().raw()); |
817 __ LoadObject(EBX, function); | 824 __ LoadObject(EBX, function); |
818 __ pushl(EBX); | 825 __ pushl(EBX); |
819 GenerateCallRuntime(0, kTraceFunctionExitRuntimeEntry); | 826 GenerateCallRuntime(AstNode::kNoId, |
| 827 0, |
| 828 kTraceFunctionExitRuntimeEntry); |
820 __ popl(EAX); // Remove argument. | 829 __ popl(EAX); // Remove argument. |
821 __ popl(EAX); // Restore result. | 830 __ popl(EAX); // Restore result. |
822 } | 831 } |
823 __ LeaveFrame(); | 832 __ LeaveFrame(); |
824 __ ret(); | 833 __ ret(); |
825 | 834 |
826 #ifdef DEBUG | 835 #ifdef DEBUG |
827 __ Bind(&wrong_stack); | 836 __ Bind(&wrong_stack); |
828 __ Stop("Exit stack size does not match the entry stack size."); | 837 __ Stop("Exit stack size does not match the entry stack size."); |
829 #endif // DEBUG. | 838 #endif // DEBUG. |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 if (IsResultNeeded(node)) { | 1010 if (IsResultNeeded(node)) { |
1002 GeneratePushVariable(node->local(), EAX); | 1011 GeneratePushVariable(node->local(), EAX); |
1003 } | 1012 } |
1004 } | 1013 } |
1005 | 1014 |
1006 | 1015 |
1007 void CodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { | 1016 void CodeGenerator::VisitStoreLocalNode(StoreLocalNode* node) { |
1008 node->value()->Visit(this); | 1017 node->value()->Visit(this); |
1009 __ popl(EAX); | 1018 __ popl(EAX); |
1010 if (FLAG_enable_type_checks) { | 1019 if (FLAG_enable_type_checks) { |
1011 GenerateAssertAssignable(node->value()->token_index(), | 1020 GenerateAssertAssignable(node->id(), |
| 1021 node->value()->token_index(), |
1012 node->local().type(), | 1022 node->local().type(), |
1013 node->local().name()); | 1023 node->local().name()); |
1014 } | 1024 } |
1015 GenerateStoreVariable(node->local(), EAX, EDX); | 1025 GenerateStoreVariable(node->local(), EAX, EDX); |
1016 if (IsResultNeeded(node)) { | 1026 if (IsResultNeeded(node)) { |
1017 __ pushl(EAX); | 1027 __ pushl(EAX); |
1018 } | 1028 } |
1019 } | 1029 } |
1020 | 1030 |
1021 | 1031 |
1022 void CodeGenerator::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) { | 1032 void CodeGenerator::VisitLoadInstanceFieldNode(LoadInstanceFieldNode* node) { |
1023 node->instance()->Visit(this); | 1033 node->instance()->Visit(this); |
1024 MarkDeoptPoint(node->id(), node->token_index()); | 1034 MarkDeoptPoint(node->id(), node->token_index()); |
1025 __ popl(EAX); // Instance. | 1035 __ popl(EAX); // Instance. |
1026 __ movl(EAX, FieldAddress(EAX, node->field().Offset())); | 1036 __ movl(EAX, FieldAddress(EAX, node->field().Offset())); |
1027 if (IsResultNeeded(node)) { | 1037 if (IsResultNeeded(node)) { |
1028 __ pushl(EAX); | 1038 __ pushl(EAX); |
1029 } | 1039 } |
1030 } | 1040 } |
1031 | 1041 |
1032 | 1042 |
1033 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) { | 1043 void CodeGenerator::VisitStoreInstanceFieldNode(StoreInstanceFieldNode* node) { |
1034 node->instance()->Visit(this); | 1044 node->instance()->Visit(this); |
1035 node->value()->Visit(this); | 1045 node->value()->Visit(this); |
1036 MarkDeoptPoint(node->id(), node->token_index()); | 1046 MarkDeoptPoint(node->id(), node->token_index()); |
1037 __ popl(EAX); // Value. | 1047 __ popl(EAX); // Value. |
1038 if (FLAG_enable_type_checks) { | 1048 if (FLAG_enable_type_checks) { |
1039 GenerateAssertAssignable(node->value()->token_index(), | 1049 GenerateAssertAssignable(node->id(), |
| 1050 node->value()->token_index(), |
1040 Type::ZoneHandle(node->field().type()), | 1051 Type::ZoneHandle(node->field().type()), |
1041 String::ZoneHandle(node->field().name())); | 1052 String::ZoneHandle(node->field().name())); |
1042 } | 1053 } |
1043 __ popl(EDX); // Instance. | 1054 __ popl(EDX); // Instance. |
1044 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); | 1055 __ StoreIntoObject(EDX, FieldAddress(EDX, node->field().Offset()), EAX); |
1045 if (IsResultNeeded(node)) { | 1056 if (IsResultNeeded(node)) { |
1046 // The result is the input value. | 1057 // The result is the input value. |
1047 __ pushl(EAX); | 1058 __ pushl(EAX); |
1048 } | 1059 } |
1049 } | 1060 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 __ pushl(EAX); | 1141 __ pushl(EAX); |
1131 } | 1142 } |
1132 } | 1143 } |
1133 | 1144 |
1134 | 1145 |
1135 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { | 1146 void CodeGenerator::VisitStoreStaticFieldNode(StoreStaticFieldNode* node) { |
1136 node->value()->Visit(this); | 1147 node->value()->Visit(this); |
1137 MarkDeoptPoint(node->id(), node->token_index()); | 1148 MarkDeoptPoint(node->id(), node->token_index()); |
1138 __ popl(EAX); // Value. | 1149 __ popl(EAX); // Value. |
1139 if (FLAG_enable_type_checks) { | 1150 if (FLAG_enable_type_checks) { |
1140 GenerateAssertAssignable(node->value()->token_index(), | 1151 GenerateAssertAssignable(node->id(), |
| 1152 node->value()->token_index(), |
1141 Type::ZoneHandle(node->field().type()), | 1153 Type::ZoneHandle(node->field().type()), |
1142 String::ZoneHandle(node->field().name())); | 1154 String::ZoneHandle(node->field().name())); |
1143 } | 1155 } |
1144 __ LoadObject(EDX, node->field()); | 1156 __ LoadObject(EDX, node->field()); |
1145 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); | 1157 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); |
1146 if (IsResultNeeded(node)) { | 1158 if (IsResultNeeded(node)) { |
1147 // The result is the input value. | 1159 // The result is the input value. |
1148 __ pushl(EAX); | 1160 __ pushl(EAX); |
1149 } | 1161 } |
1150 } | 1162 } |
1151 | 1163 |
1152 | 1164 |
1153 void CodeGenerator::GenerateLogicalNotOp(UnaryOpNode* node) { | 1165 void CodeGenerator::GenerateLogicalNotOp(UnaryOpNode* node) { |
1154 // Generate false if operand is true, otherwise generate true. | 1166 // Generate false if operand is true, otherwise generate true. |
1155 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1167 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1156 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1168 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
1157 node->operand()->Visit(this); | 1169 node->operand()->Visit(this); |
1158 MarkDeoptPoint(node->id(), node->token_index()); | 1170 MarkDeoptPoint(node->id(), node->token_index()); |
1159 Label done; | 1171 Label done; |
1160 GenerateConditionTypeCheck(node->operand()->token_index()); | 1172 GenerateConditionTypeCheck(node->id(), node->operand()->token_index()); |
1161 __ popl(EDX); | 1173 __ popl(EDX); |
1162 __ LoadObject(EAX, bool_true); | 1174 __ LoadObject(EAX, bool_true); |
1163 __ cmpl(EAX, EDX); | 1175 __ cmpl(EAX, EDX); |
1164 __ j(NOT_EQUAL, &done, Assembler::kNearJump); | 1176 __ j(NOT_EQUAL, &done, Assembler::kNearJump); |
1165 __ LoadObject(EAX, bool_false); | 1177 __ LoadObject(EAX, bool_false); |
1166 __ Bind(&done); | 1178 __ Bind(&done); |
1167 if (IsResultNeeded(node)) { | 1179 if (IsResultNeeded(node)) { |
1168 __ pushl(EAX); | 1180 __ pushl(EAX); |
1169 } | 1181 } |
1170 } | 1182 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1212 // Preserve as result. | 1224 // Preserve as result. |
1213 __ pushl(EAX); | 1225 __ pushl(EAX); |
1214 } | 1226 } |
1215 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); | 1227 const Immediate value = Immediate(reinterpret_cast<int32_t>(Smi::New(1))); |
1216 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; | 1228 const char* operator_name = (node->kind() == Token::kINCR) ? "+" : "-"; |
1217 __ pushl(EAX); | 1229 __ pushl(EAX); |
1218 __ pushl(value); | 1230 __ pushl(value); |
1219 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); | 1231 GenerateBinaryOperatorCall(node->id(), node->token_index(), operator_name); |
1220 // result is in EAX. | 1232 // result is in EAX. |
1221 if (FLAG_enable_type_checks) { | 1233 if (FLAG_enable_type_checks) { |
1222 GenerateAssertAssignable( | 1234 GenerateAssertAssignable(node->id(), |
1223 node->token_index(), node->local().type(), node->local().name()); | 1235 node->token_index(), |
| 1236 node->local().type(), |
| 1237 node->local().name()); |
1224 } | 1238 } |
1225 GenerateStoreVariable(node->local(), EAX, EDX); | 1239 GenerateStoreVariable(node->local(), EAX, EDX); |
1226 if (node->prefix() && IsResultNeeded(node)) { | 1240 if (node->prefix() && IsResultNeeded(node)) { |
1227 __ pushl(EAX); | 1241 __ pushl(EAX); |
1228 } | 1242 } |
1229 } | 1243 } |
1230 | 1244 |
1231 | 1245 |
1232 void CodeGenerator::VisitIncrOpInstanceFieldNode( | 1246 void CodeGenerator::VisitIncrOpInstanceFieldNode( |
1233 IncrOpInstanceFieldNode* node) { | 1247 IncrOpInstanceFieldNode* node) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1296 } | 1310 } |
1297 if (node->field().IsNull()) { | 1311 if (node->field().IsNull()) { |
1298 __ pushl(EAX); | 1312 __ pushl(EAX); |
1299 // It is not necessary to generate a type test of the assigned value here, | 1313 // It is not necessary to generate a type test of the assigned value here, |
1300 // because the setter will check the type of its incoming arguments. | 1314 // because the setter will check the type of its incoming arguments. |
1301 GenerateStaticSetterCall(node->token_index(), | 1315 GenerateStaticSetterCall(node->token_index(), |
1302 node->field_class(), | 1316 node->field_class(), |
1303 node->field_name()); | 1317 node->field_name()); |
1304 } else { | 1318 } else { |
1305 if (FLAG_enable_type_checks) { | 1319 if (FLAG_enable_type_checks) { |
1306 GenerateAssertAssignable(node->token_index(), | 1320 GenerateAssertAssignable(node->id(), |
| 1321 node->token_index(), |
1307 Type::ZoneHandle(node->field().type()), | 1322 Type::ZoneHandle(node->field().type()), |
1308 String::ZoneHandle(node->field().name())); | 1323 String::ZoneHandle(node->field().name())); |
1309 } | 1324 } |
1310 __ LoadObject(EDX, node->field()); | 1325 __ LoadObject(EDX, node->field()); |
1311 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); | 1326 __ StoreIntoObject(EDX, FieldAddress(EDX, Field::value_offset()), EAX); |
1312 } | 1327 } |
1313 } | 1328 } |
1314 | 1329 |
1315 | 1330 |
1316 void CodeGenerator::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { | 1331 void CodeGenerator::VisitIncrOpIndexedNode(IncrOpIndexedNode* node) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1348 | 1363 |
1349 // Optimize instanceof type test by adding inlined tests for: | 1364 // Optimize instanceof type test by adding inlined tests for: |
1350 // - NULL -> return false. | 1365 // - NULL -> return false. |
1351 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1366 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
1352 // - Class equality (only if class is not parameterized). | 1367 // - Class equality (only if class is not parameterized). |
1353 // Inputs: | 1368 // Inputs: |
1354 // - EAX: object. | 1369 // - EAX: object. |
1355 // Destroys ECX. | 1370 // Destroys ECX. |
1356 // Returns: | 1371 // Returns: |
1357 // - true or false on stack. | 1372 // - true or false on stack. |
1358 void CodeGenerator::GenerateInstanceOf(intptr_t token_index, | 1373 void CodeGenerator::GenerateInstanceOf(intptr_t node_id, |
| 1374 intptr_t token_index, |
1359 const Type& type, | 1375 const Type& type, |
1360 bool negate_result) { | 1376 bool negate_result) { |
1361 ASSERT(type.IsFinalized()); | 1377 ASSERT(type.IsFinalized()); |
1362 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1378 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1363 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1379 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
1364 | 1380 |
1365 // All instances are of type Object. | 1381 // All instances are of type Object. |
1366 const Type& object_type = | 1382 const Type& object_type = |
1367 Type::Handle(Isolate::Current()->object_store()->object_type()); | 1383 Type::Handle(Isolate::Current()->object_store()->object_type()); |
1368 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { | 1384 if (type.IsInstantiated() && object_type.IsSubtypeOf(type)) { |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1425 } | 1441 } |
1426 const Object& result = Object::ZoneHandle(); | 1442 const Object& result = Object::ZoneHandle(); |
1427 __ PushObject(result); // Make room for the result of the runtime call. | 1443 __ PushObject(result); // Make room for the result of the runtime call. |
1428 __ pushl(EAX); // Push the instance. | 1444 __ pushl(EAX); // Push the instance. |
1429 __ PushObject(type); // Push the type. | 1445 __ PushObject(type); // Push the type. |
1430 if (!type.IsInstantiated()) { | 1446 if (!type.IsInstantiated()) { |
1431 GenerateInstantiatorTypeArguments(token_index); | 1447 GenerateInstantiatorTypeArguments(token_index); |
1432 } else { | 1448 } else { |
1433 __ pushl(raw_null); // Null instantiator. | 1449 __ pushl(raw_null); // Null instantiator. |
1434 } | 1450 } |
1435 GenerateCallRuntime(token_index, kInstanceofRuntimeEntry); | 1451 GenerateCallRuntime(node_id, token_index, kInstanceofRuntimeEntry); |
1436 // Pop the two parameters supplied to the runtime entry. The result of the | 1452 // Pop the two parameters supplied to the runtime entry. The result of the |
1437 // instanceof runtime call will be left as the result of the operation. | 1453 // instanceof runtime call will be left as the result of the operation. |
1438 __ addl(ESP, Immediate(3 * kWordSize)); | 1454 __ addl(ESP, Immediate(3 * kWordSize)); |
1439 if (negate_result) { | 1455 if (negate_result) { |
1440 Label negate_done; | 1456 Label negate_done; |
1441 __ popl(EDX); | 1457 __ popl(EDX); |
1442 __ LoadObject(EAX, bool_true); | 1458 __ LoadObject(EAX, bool_true); |
1443 __ cmpl(EDX, EAX); | 1459 __ cmpl(EDX, EAX); |
1444 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); | 1460 __ j(NOT_EQUAL, &negate_done, Assembler::kNearJump); |
1445 __ LoadObject(EAX, bool_false); | 1461 __ LoadObject(EAX, bool_false); |
(...skipping 19 matching lines...) Expand all Loading... |
1465 | 1481 |
1466 // Optimize assignable type check by adding inlined tests for: | 1482 // Optimize assignable type check by adding inlined tests for: |
1467 // - NULL -> return NULL. | 1483 // - NULL -> return NULL. |
1468 // - Smi -> compile time subtype check (only if dst class is not parameterized). | 1484 // - Smi -> compile time subtype check (only if dst class is not parameterized). |
1469 // - Class equality (only if class is not parameterized). | 1485 // - Class equality (only if class is not parameterized). |
1470 // Inputs: | 1486 // Inputs: |
1471 // - EAX: object. | 1487 // - EAX: object. |
1472 // Destroys ECX and EDX. | 1488 // Destroys ECX and EDX. |
1473 // Returns: | 1489 // Returns: |
1474 // - object in EAX for successful assignable check (or throws TypeError). | 1490 // - object in EAX for successful assignable check (or throws TypeError). |
1475 void CodeGenerator::GenerateAssertAssignable(intptr_t token_index, | 1491 void CodeGenerator::GenerateAssertAssignable(intptr_t node_id, |
| 1492 intptr_t token_index, |
1476 const Type& dst_type, | 1493 const Type& dst_type, |
1477 const String& dst_name) { | 1494 const String& dst_name) { |
1478 ASSERT(FLAG_enable_type_checks); | 1495 ASSERT(FLAG_enable_type_checks); |
1479 ASSERT(token_index >= 0); | 1496 ASSERT(token_index >= 0); |
1480 ASSERT(!dst_type.IsNull()); | 1497 ASSERT(!dst_type.IsNull()); |
1481 ASSERT(dst_type.IsFinalized()); | 1498 ASSERT(dst_type.IsFinalized()); |
1482 | 1499 |
1483 // Any expression is assignable to the DynamicType. Skip the test. | 1500 // Any expression is assignable to the DynamicType. Skip the test. |
1484 if (dst_type.IsDynamicType()) { | 1501 if (dst_type.IsDynamicType()) { |
1485 return; | 1502 return; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1583 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1600 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
1584 __ pushl(location); // Push the source location. | 1601 __ pushl(location); // Push the source location. |
1585 __ pushl(EAX); // Push the source object. | 1602 __ pushl(EAX); // Push the source object. |
1586 __ PushObject(dst_type); // Push the type of the destination. | 1603 __ PushObject(dst_type); // Push the type of the destination. |
1587 if (!dst_type.IsInstantiated()) { | 1604 if (!dst_type.IsInstantiated()) { |
1588 GenerateInstantiatorTypeArguments(token_index); | 1605 GenerateInstantiatorTypeArguments(token_index); |
1589 } else { | 1606 } else { |
1590 __ pushl(raw_null); // Null instantiator. | 1607 __ pushl(raw_null); // Null instantiator. |
1591 } | 1608 } |
1592 __ PushObject(dst_name); // Push the name of the destination. | 1609 __ PushObject(dst_name); // Push the name of the destination. |
1593 GenerateCallRuntime(token_index, kTypeCheckRuntimeEntry); | 1610 GenerateCallRuntime(node_id, token_index, kTypeCheckRuntimeEntry); |
1594 // Pop the parameters supplied to the runtime entry. The result of the | 1611 // Pop the parameters supplied to the runtime entry. The result of the |
1595 // type check runtime call is the checked value. | 1612 // type check runtime call is the checked value. |
1596 __ addl(ESP, Immediate(5 * kWordSize)); | 1613 __ addl(ESP, Immediate(5 * kWordSize)); |
1597 __ popl(EAX); | 1614 __ popl(EAX); |
1598 | 1615 |
1599 __ Bind(&done); | 1616 __ Bind(&done); |
1600 } | 1617 } |
1601 | 1618 |
1602 | 1619 |
1603 void CodeGenerator::GenerateArgumentTypeChecks() { | 1620 void CodeGenerator::GenerateArgumentTypeChecks() { |
1604 const Function& function = parsed_function_.function(); | 1621 const Function& function = parsed_function_.function(); |
1605 LocalScope* scope = parsed_function_.node_sequence()->scope(); | 1622 LocalScope* scope = parsed_function_.node_sequence()->scope(); |
1606 const int num_fixed_params = function.num_fixed_parameters(); | 1623 const int num_fixed_params = function.num_fixed_parameters(); |
1607 const int num_opt_params = function.num_optional_parameters(); | 1624 const int num_opt_params = function.num_optional_parameters(); |
1608 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables()); | 1625 ASSERT(num_fixed_params + num_opt_params <= scope->num_variables()); |
1609 for (int i = 0; i < num_fixed_params + num_opt_params; i++) { | 1626 for (int i = 0; i < num_fixed_params + num_opt_params; i++) { |
1610 LocalVariable* parameter = scope->VariableAt(i); | 1627 LocalVariable* parameter = scope->VariableAt(i); |
1611 GenerateLoadVariable(EAX, *parameter); | 1628 GenerateLoadVariable(EAX, *parameter); |
1612 GenerateAssertAssignable( | 1629 GenerateAssertAssignable(AstNode::kNoId, |
1613 parameter->token_index(), parameter->type(), parameter->name()); | 1630 parameter->token_index(), |
| 1631 parameter->type(), |
| 1632 parameter->name()); |
1614 } | 1633 } |
1615 } | 1634 } |
1616 | 1635 |
1617 | 1636 |
1618 void CodeGenerator::GenerateConditionTypeCheck(intptr_t token_index) { | 1637 void CodeGenerator::GenerateConditionTypeCheck(intptr_t node_id, |
| 1638 intptr_t token_index) { |
1619 if (!FLAG_enable_type_checks) { | 1639 if (!FLAG_enable_type_checks) { |
1620 return; | 1640 return; |
1621 } | 1641 } |
1622 | 1642 |
1623 // Check that the type of the object on the stack is allowed in conditional | 1643 // Check that the type of the object on the stack is allowed in conditional |
1624 // context. | 1644 // context. |
1625 // Call the runtime if the object is null or not of type bool. | 1645 // Call the runtime if the object is null or not of type bool. |
1626 const Immediate raw_null = | 1646 const Immediate raw_null = |
1627 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1647 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
1628 Label runtime_call, done; | 1648 Label runtime_call, done; |
(...skipping 11 matching lines...) Expand all Loading... |
1640 __ CompareObject(ECX, bool_class); | 1660 __ CompareObject(ECX, bool_class); |
1641 __ j(EQUAL, &done, Assembler::kNearJump); | 1661 __ j(EQUAL, &done, Assembler::kNearJump); |
1642 | 1662 |
1643 __ Bind(&runtime_call); | 1663 __ Bind(&runtime_call); |
1644 const Object& result = Object::ZoneHandle(); | 1664 const Object& result = Object::ZoneHandle(); |
1645 __ PushObject(result); // Make room for the result of the runtime call. | 1665 __ PushObject(result); // Make room for the result of the runtime call. |
1646 const Immediate location = | 1666 const Immediate location = |
1647 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); | 1667 Immediate(reinterpret_cast<int32_t>(Smi::New(token_index))); |
1648 __ pushl(location); // Push the source location. | 1668 __ pushl(location); // Push the source location. |
1649 __ pushl(EAX); // Push the source object. | 1669 __ pushl(EAX); // Push the source object. |
1650 GenerateCallRuntime(token_index, kConditionTypeErrorRuntimeEntry); | 1670 GenerateCallRuntime(node_id, token_index, kConditionTypeErrorRuntimeEntry); |
1651 // Pop the parameters supplied to the runtime entry. The result of the | 1671 // Pop the parameters supplied to the runtime entry. The result of the |
1652 // type check runtime call is the checked value. | 1672 // type check runtime call is the checked value. |
1653 __ addl(ESP, Immediate(3 * kWordSize)); | 1673 __ addl(ESP, Immediate(3 * kWordSize)); |
1654 | 1674 |
1655 __ Bind(&done); | 1675 __ Bind(&done); |
1656 } | 1676 } |
1657 | 1677 |
1658 | 1678 |
1659 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { | 1679 void CodeGenerator::VisitComparisonNode(ComparisonNode* node) { |
1660 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1680 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1661 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1681 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
1662 node->left()->Visit(this); | 1682 node->left()->Visit(this); |
1663 | 1683 |
1664 // The instanceof operator needs special handling. | 1684 // The instanceof operator needs special handling. |
1665 if (Token::IsInstanceofOperator(node->kind())) { | 1685 if (Token::IsInstanceofOperator(node->kind())) { |
1666 __ popl(EAX); // Left operand. | 1686 __ popl(EAX); // Left operand. |
1667 ASSERT(node->right()->IsTypeNode()); | 1687 ASSERT(node->right()->IsTypeNode()); |
1668 GenerateInstanceOf(node->token_index(), | 1688 GenerateInstanceOf(node->id(), |
| 1689 node->token_index(), |
1669 node->right()->AsTypeNode()->type(), | 1690 node->right()->AsTypeNode()->type(), |
1670 (node->kind() == Token::kISNOT)); | 1691 (node->kind() == Token::kISNOT)); |
1671 if (!IsResultNeeded(node)) { | 1692 if (!IsResultNeeded(node)) { |
1672 __ popl(EAX); // Pop the result of the instanceof operation. | 1693 __ popl(EAX); // Pop the result of the instanceof operation. |
1673 } | 1694 } |
1674 return; | 1695 return; |
1675 } | 1696 } |
1676 | 1697 |
1677 node->right()->Visit(this); | 1698 node->right()->Visit(this); |
1678 // Both left and right values on stack. | 1699 // Both left and right values on stack. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1790 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX); | 1811 __ movl(FieldAddress(EAX, Function::invocation_counter_offset()), EBX); |
1791 __ Bind(&done); | 1812 __ Bind(&done); |
1792 } | 1813 } |
1793 | 1814 |
1794 | 1815 |
1795 void CodeGenerator::VisitWhileNode(WhileNode* node) { | 1816 void CodeGenerator::VisitWhileNode(WhileNode* node) { |
1796 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1817 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1797 SourceLabel* label = node->label(); | 1818 SourceLabel* label = node->label(); |
1798 __ Bind(label->continue_label()); | 1819 __ Bind(label->continue_label()); |
1799 node->condition()->Visit(this); | 1820 node->condition()->Visit(this); |
1800 GenerateConditionTypeCheck(node->condition()->token_index()); | 1821 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1801 __ popl(EAX); | 1822 __ popl(EAX); |
1802 __ LoadObject(EDX, bool_true); | 1823 __ LoadObject(EDX, bool_true); |
1803 __ cmpl(EAX, EDX); | 1824 __ cmpl(EAX, EDX); |
1804 __ j(NOT_EQUAL, label->break_label()); | 1825 __ j(NOT_EQUAL, label->break_label()); |
1805 node->body()->Visit(this); | 1826 node->body()->Visit(this); |
1806 CountBackwardLoop(); | 1827 CountBackwardLoop(); |
1807 __ jmp(label->continue_label()); | 1828 __ jmp(label->continue_label()); |
1808 __ Bind(label->break_label()); | 1829 __ Bind(label->break_label()); |
1809 } | 1830 } |
1810 | 1831 |
1811 | 1832 |
1812 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) { | 1833 void CodeGenerator::VisitDoWhileNode(DoWhileNode* node) { |
1813 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1834 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1814 SourceLabel* label = node->label(); | 1835 SourceLabel* label = node->label(); |
1815 Label loop; | 1836 Label loop; |
1816 __ Bind(&loop); | 1837 __ Bind(&loop); |
1817 node->body()->Visit(this); | 1838 node->body()->Visit(this); |
1818 CountBackwardLoop(); | 1839 CountBackwardLoop(); |
1819 __ Bind(label->continue_label()); | 1840 __ Bind(label->continue_label()); |
1820 node->condition()->Visit(this); | 1841 node->condition()->Visit(this); |
1821 GenerateConditionTypeCheck(node->condition()->token_index()); | 1842 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1822 __ popl(EAX); | 1843 __ popl(EAX); |
1823 __ LoadObject(EDX, bool_true); | 1844 __ LoadObject(EDX, bool_true); |
1824 __ cmpl(EAX, EDX); | 1845 __ cmpl(EAX, EDX); |
1825 __ j(EQUAL, &loop); | 1846 __ j(EQUAL, &loop); |
1826 __ Bind(label->break_label()); | 1847 __ Bind(label->break_label()); |
1827 } | 1848 } |
1828 | 1849 |
1829 | 1850 |
1830 void CodeGenerator::VisitForNode(ForNode* node) { | 1851 void CodeGenerator::VisitForNode(ForNode* node) { |
1831 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1852 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1832 node->initializer()->Visit(this); | 1853 node->initializer()->Visit(this); |
1833 SourceLabel* label = node->label(); | 1854 SourceLabel* label = node->label(); |
1834 Label loop; | 1855 Label loop; |
1835 __ Bind(&loop); | 1856 __ Bind(&loop); |
1836 if (node->condition() != NULL) { | 1857 if (node->condition() != NULL) { |
1837 node->condition()->Visit(this); | 1858 node->condition()->Visit(this); |
1838 GenerateConditionTypeCheck(node->condition()->token_index()); | 1859 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1839 __ popl(EAX); | 1860 __ popl(EAX); |
1840 __ LoadObject(EDX, bool_true); | 1861 __ LoadObject(EDX, bool_true); |
1841 __ cmpl(EAX, EDX); | 1862 __ cmpl(EAX, EDX); |
1842 __ j(NOT_EQUAL, label->break_label()); | 1863 __ j(NOT_EQUAL, label->break_label()); |
1843 } | 1864 } |
1844 node->body()->Visit(this); | 1865 node->body()->Visit(this); |
1845 CountBackwardLoop(); | 1866 CountBackwardLoop(); |
1846 __ Bind(label->continue_label()); | 1867 __ Bind(label->continue_label()); |
1847 node->increment()->Visit(this); | 1868 node->increment()->Visit(this); |
1848 __ jmp(&loop); | 1869 __ jmp(&loop); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1880 } else { | 1901 } else { |
1881 __ jmp(label->continue_label()); | 1902 __ jmp(label->continue_label()); |
1882 } | 1903 } |
1883 } | 1904 } |
1884 | 1905 |
1885 | 1906 |
1886 void CodeGenerator::VisitConditionalExprNode(ConditionalExprNode* node) { | 1907 void CodeGenerator::VisitConditionalExprNode(ConditionalExprNode* node) { |
1887 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1908 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1888 Label false_label, done; | 1909 Label false_label, done; |
1889 node->condition()->Visit(this); | 1910 node->condition()->Visit(this); |
1890 GenerateConditionTypeCheck(node->condition()->token_index()); | 1911 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1891 __ popl(EAX); | 1912 __ popl(EAX); |
1892 __ LoadObject(EDX, bool_true); | 1913 __ LoadObject(EDX, bool_true); |
1893 __ cmpl(EAX, EDX); | 1914 __ cmpl(EAX, EDX); |
1894 __ j(NOT_EQUAL, &false_label); | 1915 __ j(NOT_EQUAL, &false_label); |
1895 node->true_expr()->Visit(this); | 1916 node->true_expr()->Visit(this); |
1896 __ jmp(&done); | 1917 __ jmp(&done); |
1897 __ Bind(&false_label); | 1918 __ Bind(&false_label); |
1898 node->false_expr()->Visit(this); | 1919 node->false_expr()->Visit(this); |
1899 __ Bind(&done); | 1920 __ Bind(&done); |
1900 if (!IsResultNeeded(node)) { | 1921 if (!IsResultNeeded(node)) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1940 __ Bind(&case_statements); | 1961 __ Bind(&case_statements); |
1941 node->statements()->Visit(this); | 1962 node->statements()->Visit(this); |
1942 __ Bind(&end_case); | 1963 __ Bind(&end_case); |
1943 } | 1964 } |
1944 | 1965 |
1945 | 1966 |
1946 void CodeGenerator::VisitIfNode(IfNode* node) { | 1967 void CodeGenerator::VisitIfNode(IfNode* node) { |
1947 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1968 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1948 Label false_label; | 1969 Label false_label; |
1949 node->condition()->Visit(this); | 1970 node->condition()->Visit(this); |
1950 GenerateConditionTypeCheck(node->condition()->token_index()); | 1971 GenerateConditionTypeCheck(node->id(), node->condition()->token_index()); |
1951 __ popl(EAX); | 1972 __ popl(EAX); |
1952 __ LoadObject(EDX, bool_true); | 1973 __ LoadObject(EDX, bool_true); |
1953 __ cmpl(EAX, EDX); | 1974 __ cmpl(EAX, EDX); |
1954 __ j(NOT_EQUAL, &false_label); | 1975 __ j(NOT_EQUAL, &false_label); |
1955 node->true_branch()->Visit(this); | 1976 node->true_branch()->Visit(this); |
1956 if (node->false_branch() != NULL) { | 1977 if (node->false_branch() != NULL) { |
1957 Label done; | 1978 Label done; |
1958 __ jmp(&done); | 1979 __ jmp(&done); |
1959 __ Bind(&false_label); | 1980 __ Bind(&false_label); |
1960 node->false_branch()->Visit(this); | 1981 node->false_branch()->Visit(this); |
1961 __ Bind(&done); | 1982 __ Bind(&done); |
1962 } else { | 1983 } else { |
1963 __ Bind(&false_label); | 1984 __ Bind(&false_label); |
1964 } | 1985 } |
1965 } | 1986 } |
1966 | 1987 |
1967 | 1988 |
1968 // Operators '&&' and '||' are not overloadabled, inline them. | 1989 // Operators '&&' and '||' are not overloadabled, inline them. |
1969 void CodeGenerator::GenerateLogicalAndOrOp(BinaryOpNode* node) { | 1990 void CodeGenerator::GenerateLogicalAndOrOp(BinaryOpNode* node) { |
1970 // Generate true if (left == true) op (right == true), otherwise generate | 1991 // Generate true if (left == true) op (right == true), otherwise generate |
1971 // false, with op being either || or &&. | 1992 // false, with op being either || or &&. |
1972 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); | 1993 const Bool& bool_true = Bool::ZoneHandle(Bool::True()); |
1973 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); | 1994 const Bool& bool_false = Bool::ZoneHandle(Bool::False()); |
1974 Label load_false, done; | 1995 Label load_false, done; |
1975 node->left()->Visit(this); | 1996 node->left()->Visit(this); |
1976 GenerateConditionTypeCheck(node->left()->token_index()); | 1997 GenerateConditionTypeCheck(node->id(), node->left()->token_index()); |
1977 __ popl(EAX); | 1998 __ popl(EAX); |
1978 __ LoadObject(EDX, bool_true); | 1999 __ LoadObject(EDX, bool_true); |
1979 __ cmpl(EAX, EDX); | 2000 __ cmpl(EAX, EDX); |
1980 if (node->kind() == Token::kAND) { | 2001 if (node->kind() == Token::kAND) { |
1981 __ j(NOT_EQUAL, &load_false); | 2002 __ j(NOT_EQUAL, &load_false); |
1982 } else { | 2003 } else { |
1983 ASSERT(node->kind() == Token::kOR); | 2004 ASSERT(node->kind() == Token::kOR); |
1984 __ j(EQUAL, &done); | 2005 __ j(EQUAL, &done); |
1985 } | 2006 } |
1986 node->right()->Visit(this); | 2007 node->right()->Visit(this); |
1987 GenerateConditionTypeCheck(node->right()->token_index()); | 2008 GenerateConditionTypeCheck(node->id(), node->right()->token_index()); |
1988 __ popl(EAX); | 2009 __ popl(EAX); |
1989 __ LoadObject(EDX, bool_true); | 2010 __ LoadObject(EDX, bool_true); |
1990 __ cmpl(EAX, EDX); | 2011 __ cmpl(EAX, EDX); |
1991 __ j(EQUAL, &done); | 2012 __ j(EQUAL, &done); |
1992 __ Bind(&load_false); | 2013 __ Bind(&load_false); |
1993 __ LoadObject(EAX, bool_false); | 2014 __ LoadObject(EAX, bool_false); |
1994 __ Bind(&done); | 2015 __ Bind(&done); |
1995 if (IsResultNeeded(node)) { | 2016 if (IsResultNeeded(node)) { |
1996 __ pushl(EAX); | 2017 __ pushl(EAX); |
1997 } | 2018 } |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2250 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); | 2271 __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); |
2251 } | 2272 } |
2252 __ Bind(&type_arguments_uninstantiated); | 2273 __ Bind(&type_arguments_uninstantiated); |
2253 if (node->constructor().IsFactory()) { | 2274 if (node->constructor().IsFactory()) { |
2254 // A runtime call to instantiate the type arguments is required before | 2275 // A runtime call to instantiate the type arguments is required before |
2255 // calling the factory. | 2276 // calling the factory. |
2256 const Object& result = Object::ZoneHandle(); | 2277 const Object& result = Object::ZoneHandle(); |
2257 __ PushObject(result); // Make room for the result of the runtime call. | 2278 __ PushObject(result); // Make room for the result of the runtime call. |
2258 __ PushObject(node->type_arguments()); | 2279 __ PushObject(node->type_arguments()); |
2259 __ pushl(EAX); // Push instantiator type arguments. | 2280 __ pushl(EAX); // Push instantiator type arguments. |
2260 GenerateCallRuntime(node->token_index(), | 2281 GenerateCallRuntime(node->id(), |
| 2282 node->token_index(), |
2261 kInstantiateTypeArgumentsRuntimeEntry); | 2283 kInstantiateTypeArgumentsRuntimeEntry); |
2262 __ popl(EAX); // Pop instantiator type arguments. | 2284 __ popl(EAX); // Pop instantiator type arguments. |
2263 __ popl(EAX); // Pop uninstantiated type arguments. | 2285 __ popl(EAX); // Pop uninstantiated type arguments. |
2264 __ popl(EAX); // Pop instantiated type arguments. | 2286 __ popl(EAX); // Pop instantiated type arguments. |
2265 __ Bind(&type_arguments_instantiated); | 2287 __ Bind(&type_arguments_instantiated); |
2266 __ pushl(EAX); // Instantiated type arguments. | 2288 __ pushl(EAX); // Instantiated type arguments. |
2267 } else { | 2289 } else { |
2268 // In the non-factory case, we rely on the allocation stub to | 2290 // In the non-factory case, we rely on the allocation stub to |
2269 // instantiate the type arguments. | 2291 // instantiate the type arguments. |
2270 __ PushObject(node->type_arguments()); | 2292 __ PushObject(node->type_arguments()); |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2567 | 2589 |
2568 | 2590 |
2569 void CodeGenerator::VisitThrowNode(ThrowNode* node) { | 2591 void CodeGenerator::VisitThrowNode(ThrowNode* node) { |
2570 const Object& result = Object::ZoneHandle(); | 2592 const Object& result = Object::ZoneHandle(); |
2571 node->exception()->Visit(this); | 2593 node->exception()->Visit(this); |
2572 __ popl(EAX); // Exception object is now in EAX. | 2594 __ popl(EAX); // Exception object is now in EAX. |
2573 if (node->stacktrace() != NULL) { | 2595 if (node->stacktrace() != NULL) { |
2574 __ PushObject(result); // Make room for the result of the runtime call. | 2596 __ PushObject(result); // Make room for the result of the runtime call. |
2575 __ pushl(EAX); // Push the exception object. | 2597 __ pushl(EAX); // Push the exception object. |
2576 node->stacktrace()->Visit(this); | 2598 node->stacktrace()->Visit(this); |
2577 GenerateCallRuntime(node->token_index(), kReThrowRuntimeEntry); | 2599 GenerateCallRuntime(node->id(), node->token_index(), kReThrowRuntimeEntry); |
2578 } else { | 2600 } else { |
2579 __ PushObject(result); // Make room for the result of the runtime call. | 2601 __ PushObject(result); // Make room for the result of the runtime call. |
2580 __ pushl(EAX); // Push the exception object. | 2602 __ pushl(EAX); // Push the exception object. |
2581 GenerateCallRuntime(node->token_index(), kThrowRuntimeEntry); | 2603 GenerateCallRuntime(node->id(), node->token_index(), kThrowRuntimeEntry); |
2582 } | 2604 } |
2583 // We should never return here. | 2605 // We should never return here. |
2584 __ int3(); | 2606 __ int3(); |
2585 } | 2607 } |
2586 | 2608 |
2587 | 2609 |
2588 void CodeGenerator::VisitInlinedFinallyNode(InlinedFinallyNode* node) { | 2610 void CodeGenerator::VisitInlinedFinallyNode(InlinedFinallyNode* node) { |
2589 int try_index = state()->try_index(); | 2611 int try_index = state()->try_index(); |
2590 if (try_index >= 0) { | 2612 if (try_index >= 0) { |
2591 // We are about to generate code for an inlined finally block. Exceptions | 2613 // We are about to generate code for an inlined finally block. Exceptions |
2592 // thrown in this block of code should be treated as though they are | 2614 // thrown in this block of code should be treated as though they are |
2593 // thrown not from the current try block but the outer try block if any. | 2615 // thrown not from the current try block but the outer try block if any. |
2594 // the code generator state. | 2616 // the code generator state. |
2595 state()->set_try_index((try_index - 1)); | 2617 state()->set_try_index((try_index - 1)); |
2596 } | 2618 } |
2597 | 2619 |
2598 // Restore CTX from local variable ':saved_context'. | 2620 // Restore CTX from local variable ':saved_context'. |
2599 GenerateLoadVariable(CTX, node->context_var()); | 2621 GenerateLoadVariable(CTX, node->context_var()); |
2600 node->finally_block()->Visit(this); | 2622 node->finally_block()->Visit(this); |
2601 | 2623 |
2602 if (try_index >= 0) { | 2624 if (try_index >= 0) { |
2603 state()->set_try_index(try_index); | 2625 state()->set_try_index(try_index); |
2604 } | 2626 } |
2605 } | 2627 } |
2606 | 2628 |
2607 | 2629 |
2608 void CodeGenerator::GenerateCall(intptr_t token_index, | 2630 void CodeGenerator::GenerateCall(intptr_t token_index, |
2609 const ExternalLabel* ext_label) { | 2631 const ExternalLabel* ext_label) { |
2610 __ call(ext_label); | 2632 __ call(ext_label); |
2611 AddCurrentDescriptor(PcDescriptors::kOther, AstNode::kInvalidId, token_index); | 2633 AddCurrentDescriptor(PcDescriptors::kOther, AstNode::kNoId, token_index); |
2612 } | 2634 } |
2613 | 2635 |
2614 | 2636 |
2615 void CodeGenerator::GenerateCallRuntime(intptr_t token_index, | 2637 void CodeGenerator::GenerateCallRuntime(intptr_t node_id, |
| 2638 intptr_t token_index, |
2616 const RuntimeEntry& entry) { | 2639 const RuntimeEntry& entry) { |
2617 __ CallRuntimeFromDart(entry); | 2640 __ CallRuntimeFromDart(entry); |
2618 AddCurrentDescriptor(PcDescriptors::kOther, AstNode::kInvalidId, token_index); | 2641 AddCurrentDescriptor(PcDescriptors::kOther, node_id, token_index); |
2619 } | 2642 } |
2620 | 2643 |
2621 | 2644 |
2622 void CodeGenerator::MarkDeoptPoint(intptr_t node_id, | 2645 void CodeGenerator::MarkDeoptPoint(intptr_t node_id, |
2623 intptr_t token_index) { | 2646 intptr_t token_index) { |
2624 ASSERT(node_id != AstNode::kInvalidId); | 2647 ASSERT(node_id != AstNode::kNoId); |
2625 AddCurrentDescriptor(PcDescriptors::kDeopt, node_id, token_index); | 2648 AddCurrentDescriptor(PcDescriptors::kDeopt, node_id, token_index); |
2626 } | 2649 } |
2627 | 2650 |
2628 | 2651 |
2629 // Uses current pc position and try-index. | 2652 // Uses current pc position and try-index. |
2630 void CodeGenerator::AddCurrentDescriptor(PcDescriptors::Kind kind, | 2653 void CodeGenerator::AddCurrentDescriptor(PcDescriptors::Kind kind, |
2631 intptr_t node_id, | 2654 intptr_t node_id, |
2632 intptr_t token_index) { | 2655 intptr_t token_index) { |
2633 pc_descriptors_list_->AddDescriptor(kind, | 2656 pc_descriptors_list_->AddDescriptor(kind, |
2634 assembler_->CodeSize(), | 2657 assembler_->CodeSize(), |
(...skipping 10 matching lines...) Expand all Loading... |
2645 const Class& cls = Class::Handle(parsed_function_.function().owner()); | 2668 const Class& cls = Class::Handle(parsed_function_.function().owner()); |
2646 const Script& script = Script::Handle(cls.script()); | 2669 const Script& script = Script::Handle(cls.script()); |
2647 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); | 2670 Parser::ReportMsg(script, token_index, "Error", error_msg, format, args); |
2648 Isolate::Current()->long_jump_base()->Jump(1, error_msg); | 2671 Isolate::Current()->long_jump_base()->Jump(1, error_msg); |
2649 UNREACHABLE(); | 2672 UNREACHABLE(); |
2650 } | 2673 } |
2651 | 2674 |
2652 } // namespace dart | 2675 } // namespace dart |
2653 | 2676 |
2654 #endif // defined TARGET_ARCH_IA32 | 2677 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |