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

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

Issue 8475013: Emit node id at every call to runtime. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/isolate.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/code_generator_ia32.h ('k') | runtime/vm/isolate.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698