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

Side by Side Diff: src/ia32/macro-assembler-ia32.cc

Issue 4100005: Version 2.5.2 (Closed)
Patch Set: Created 10 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
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/ia32/regexp-macro-assembler-ia32.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 } 577 }
578 } 578 }
579 579
580 580
581 void MacroAssembler::AllocateInNewSpace(int object_size, 581 void MacroAssembler::AllocateInNewSpace(int object_size,
582 Register result, 582 Register result,
583 Register result_end, 583 Register result_end,
584 Register scratch, 584 Register scratch,
585 Label* gc_required, 585 Label* gc_required,
586 AllocationFlags flags) { 586 AllocationFlags flags) {
587 if (!FLAG_inline_new) {
588 if (FLAG_debug_code) {
589 // Trash the registers to simulate an allocation failure.
590 mov(result, Immediate(0x7091));
591 if (result_end.is_valid()) {
592 mov(result_end, Immediate(0x7191));
593 }
594 if (scratch.is_valid()) {
595 mov(scratch, Immediate(0x7291));
596 }
597 }
598 jmp(gc_required);
599 return;
600 }
587 ASSERT(!result.is(result_end)); 601 ASSERT(!result.is(result_end));
588 602
589 // Load address of new object into result. 603 // Load address of new object into result.
590 LoadAllocationTopHelper(result, result_end, scratch, flags); 604 LoadAllocationTopHelper(result, result_end, scratch, flags);
591 605
592 Register top_reg = result_end.is_valid() ? result_end : result; 606 Register top_reg = result_end.is_valid() ? result_end : result;
593 607
594 // Calculate new top and bail out if new space is exhausted. 608 // Calculate new top and bail out if new space is exhausted.
595 ExternalReference new_space_allocation_limit = 609 ExternalReference new_space_allocation_limit =
596 ExternalReference::new_space_allocation_limit_address(); 610 ExternalReference::new_space_allocation_limit_address();
(...skipping 23 matching lines...) Expand all
620 634
621 635
622 void MacroAssembler::AllocateInNewSpace(int header_size, 636 void MacroAssembler::AllocateInNewSpace(int header_size,
623 ScaleFactor element_size, 637 ScaleFactor element_size,
624 Register element_count, 638 Register element_count,
625 Register result, 639 Register result,
626 Register result_end, 640 Register result_end,
627 Register scratch, 641 Register scratch,
628 Label* gc_required, 642 Label* gc_required,
629 AllocationFlags flags) { 643 AllocationFlags flags) {
644 if (!FLAG_inline_new) {
645 if (FLAG_debug_code) {
646 // Trash the registers to simulate an allocation failure.
647 mov(result, Immediate(0x7091));
648 mov(result_end, Immediate(0x7191));
649 if (scratch.is_valid()) {
650 mov(scratch, Immediate(0x7291));
651 }
652 // Register element_count is not modified by the function.
653 }
654 jmp(gc_required);
655 return;
656 }
630 ASSERT(!result.is(result_end)); 657 ASSERT(!result.is(result_end));
631 658
632 // Load address of new object into result. 659 // Load address of new object into result.
633 LoadAllocationTopHelper(result, result_end, scratch, flags); 660 LoadAllocationTopHelper(result, result_end, scratch, flags);
634 661
635 // Calculate new top and bail out if new space is exhausted. 662 // Calculate new top and bail out if new space is exhausted.
636 ExternalReference new_space_allocation_limit = 663 ExternalReference new_space_allocation_limit =
637 ExternalReference::new_space_allocation_limit_address(); 664 ExternalReference::new_space_allocation_limit_address();
638 lea(result_end, Operand(result, element_count, element_size, header_size)); 665 lea(result_end, Operand(result, element_count, element_size, header_size));
639 cmp(result_end, Operand::StaticVariable(new_space_allocation_limit)); 666 cmp(result_end, Operand::StaticVariable(new_space_allocation_limit));
640 j(above, gc_required); 667 j(above, gc_required);
641 668
642 // Tag result if requested. 669 // Tag result if requested.
643 if ((flags & TAG_OBJECT) != 0) { 670 if ((flags & TAG_OBJECT) != 0) {
644 lea(result, Operand(result, kHeapObjectTag)); 671 lea(result, Operand(result, kHeapObjectTag));
645 } 672 }
646 673
647 // Update allocation top. 674 // Update allocation top.
648 UpdateAllocationTopHelper(result_end, scratch); 675 UpdateAllocationTopHelper(result_end, scratch);
649 } 676 }
650 677
651 678
652 void MacroAssembler::AllocateInNewSpace(Register object_size, 679 void MacroAssembler::AllocateInNewSpace(Register object_size,
653 Register result, 680 Register result,
654 Register result_end, 681 Register result_end,
655 Register scratch, 682 Register scratch,
656 Label* gc_required, 683 Label* gc_required,
657 AllocationFlags flags) { 684 AllocationFlags flags) {
685 if (!FLAG_inline_new) {
686 if (FLAG_debug_code) {
687 // Trash the registers to simulate an allocation failure.
688 mov(result, Immediate(0x7091));
689 mov(result_end, Immediate(0x7191));
690 if (scratch.is_valid()) {
691 mov(scratch, Immediate(0x7291));
692 }
693 // object_size is left unchanged by this function.
694 }
695 jmp(gc_required);
696 return;
697 }
658 ASSERT(!result.is(result_end)); 698 ASSERT(!result.is(result_end));
659 699
660 // Load address of new object into result. 700 // Load address of new object into result.
661 LoadAllocationTopHelper(result, result_end, scratch, flags); 701 LoadAllocationTopHelper(result, result_end, scratch, flags);
662 702
663 // Calculate new top and bail out if new space is exhausted. 703 // Calculate new top and bail out if new space is exhausted.
664 ExternalReference new_space_allocation_limit = 704 ExternalReference new_space_allocation_limit =
665 ExternalReference::new_space_allocation_limit_address(); 705 ExternalReference::new_space_allocation_limit_address();
666 if (!object_size.is(result_end)) { 706 if (!object_size.is(result_end)) {
667 mov(result_end, object_size); 707 mov(result_end, object_size);
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
929 bind(&done); 969 bind(&done);
930 } 970 }
931 971
932 972
933 void MacroAssembler::CallStub(CodeStub* stub) { 973 void MacroAssembler::CallStub(CodeStub* stub) {
934 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 974 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
935 call(stub->GetCode(), RelocInfo::CODE_TARGET); 975 call(stub->GetCode(), RelocInfo::CODE_TARGET);
936 } 976 }
937 977
938 978
939 Object* MacroAssembler::TryCallStub(CodeStub* stub) { 979 MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
940 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 980 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
941 Object* result = stub->TryGetCode(); 981 Object* result;
942 if (!result->IsFailure()) { 982 { MaybeObject* maybe_result = stub->TryGetCode();
943 call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 983 if (!maybe_result->ToObject(&result)) return maybe_result;
944 } 984 }
985 call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
945 return result; 986 return result;
946 } 987 }
947 988
948 989
949 void MacroAssembler::TailCallStub(CodeStub* stub) { 990 void MacroAssembler::TailCallStub(CodeStub* stub) {
950 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 991 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
951 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); 992 jmp(stub->GetCode(), RelocInfo::CODE_TARGET);
952 } 993 }
953 994
954 995
955 Object* MacroAssembler::TryTailCallStub(CodeStub* stub) { 996 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) {
956 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs. 997 ASSERT(allow_stub_calls()); // Calls are not allowed in some stubs.
957 Object* result = stub->TryGetCode(); 998 Object* result;
958 if (!result->IsFailure()) { 999 { MaybeObject* maybe_result = stub->TryGetCode();
959 jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); 1000 if (!maybe_result->ToObject(&result)) return maybe_result;
960 } 1001 }
1002 jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET);
961 return result; 1003 return result;
962 } 1004 }
963 1005
964 1006
965 void MacroAssembler::StubReturn(int argc) { 1007 void MacroAssembler::StubReturn(int argc) {
966 ASSERT(argc >= 1 && generating_stub()); 1008 ASSERT(argc >= 1 && generating_stub());
967 ret((argc - 1) * kPointerSize); 1009 ret((argc - 1) * kPointerSize);
968 } 1010 }
969 1011
970 1012
(...skipping 22 matching lines...) Expand all
993 mov(index, hash); 1035 mov(index, hash);
994 } 1036 }
995 } 1037 }
996 1038
997 1039
998 void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) { 1040 void MacroAssembler::CallRuntime(Runtime::FunctionId id, int num_arguments) {
999 CallRuntime(Runtime::FunctionForId(id), num_arguments); 1041 CallRuntime(Runtime::FunctionForId(id), num_arguments);
1000 } 1042 }
1001 1043
1002 1044
1003 Object* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, 1045 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id,
1004 int num_arguments) { 1046 int num_arguments) {
1005 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); 1047 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments);
1006 } 1048 }
1007 1049
1008 1050
1009 void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) { 1051 void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
1010 // If the expected number of arguments of the runtime function is 1052 // If the expected number of arguments of the runtime function is
1011 // constant, we check that the actual number of arguments match the 1053 // constant, we check that the actual number of arguments match the
1012 // expectation. 1054 // expectation.
1013 if (f->nargs >= 0 && f->nargs != num_arguments) { 1055 if (f->nargs >= 0 && f->nargs != num_arguments) {
1014 IllegalOperation(num_arguments); 1056 IllegalOperation(num_arguments);
1015 return; 1057 return;
1016 } 1058 }
1017 1059
1018 // TODO(1236192): Most runtime routines don't need the number of 1060 // TODO(1236192): Most runtime routines don't need the number of
1019 // arguments passed in because it is constant. At some point we 1061 // arguments passed in because it is constant. At some point we
1020 // should remove this need and make the runtime routine entry code 1062 // should remove this need and make the runtime routine entry code
1021 // smarter. 1063 // smarter.
1022 Set(eax, Immediate(num_arguments)); 1064 Set(eax, Immediate(num_arguments));
1023 mov(ebx, Immediate(ExternalReference(f))); 1065 mov(ebx, Immediate(ExternalReference(f)));
1024 CEntryStub ces(1); 1066 CEntryStub ces(1);
1025 CallStub(&ces); 1067 CallStub(&ces);
1026 } 1068 }
1027 1069
1028 1070
1029 Object* MacroAssembler::TryCallRuntime(Runtime::Function* f, 1071 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::Function* f,
1030 int num_arguments) { 1072 int num_arguments) {
1031 if (f->nargs >= 0 && f->nargs != num_arguments) { 1073 if (f->nargs >= 0 && f->nargs != num_arguments) {
1032 IllegalOperation(num_arguments); 1074 IllegalOperation(num_arguments);
1033 // Since we did not call the stub, there was no allocation failure. 1075 // Since we did not call the stub, there was no allocation failure.
1034 // Return some non-failure object. 1076 // Return some non-failure object.
1035 return Heap::undefined_value(); 1077 return Heap::undefined_value();
1036 } 1078 }
1037 1079
1038 // TODO(1236192): Most runtime routines don't need the number of 1080 // TODO(1236192): Most runtime routines don't need the number of
1039 // arguments passed in because it is constant. At some point we 1081 // arguments passed in because it is constant. At some point we
1040 // should remove this need and make the runtime routine entry code 1082 // should remove this need and make the runtime routine entry code
(...skipping 27 matching lines...) Expand all
1068 } 1110 }
1069 1111
1070 1112
1071 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, 1113 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
1072 int num_arguments, 1114 int num_arguments,
1073 int result_size) { 1115 int result_size) {
1074 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); 1116 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
1075 } 1117 }
1076 1118
1077 1119
1078 void MacroAssembler::PushHandleScope(Register scratch) { 1120 // If true, a Handle<T> passed by value is passed and returned by
1079 // Push the number of extensions, smi-tagged so the gc will ignore it. 1121 // using the location_ field directly. If false, it is passed and
1080 ExternalReference extensions_address = 1122 // returned as a pointer to a handle.
1081 ExternalReference::handle_scope_extensions_address(); 1123 #ifdef USING_BSD_ABI
1082 mov(scratch, Operand::StaticVariable(extensions_address)); 1124 static const bool kPassHandlesDirectly = true;
1083 SmiTag(scratch); 1125 #else
1084 push(scratch); 1126 static const bool kPassHandlesDirectly = false;
1085 mov(Operand::StaticVariable(extensions_address), Immediate(0)); 1127 #endif
1086 // Push next and limit pointers which will be wordsize aligned and 1128
1087 // hence automatically smi tagged. 1129
1088 ExternalReference next_address = 1130 Operand ApiParameterOperand(int index) {
1089 ExternalReference::handle_scope_next_address(); 1131 return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize);
1090 push(Operand::StaticVariable(next_address));
1091 ExternalReference limit_address =
1092 ExternalReference::handle_scope_limit_address();
1093 push(Operand::StaticVariable(limit_address));
1094 } 1132 }
1095 1133
1096 1134
1097 Object* MacroAssembler::PopHandleScopeHelper(Register saved, 1135 void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) {
1098 Register scratch, 1136 if (kPassHandlesDirectly) {
1099 bool gc_allowed) { 1137 EnterApiExitFrame(stack_space, argc);
1100 Object* result = NULL; 1138 // When handles as passed directly we don't have to allocate extra
1101 ExternalReference extensions_address = 1139 // space for and pass an out parameter.
1102 ExternalReference::handle_scope_extensions_address();
1103 Label write_back;
1104 mov(scratch, Operand::StaticVariable(extensions_address));
1105 cmp(Operand(scratch), Immediate(0));
1106 j(equal, &write_back);
1107 push(saved);
1108 if (gc_allowed) {
1109 CallRuntime(Runtime::kDeleteHandleScopeExtensions, 0);
1110 } else { 1140 } else {
1111 result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); 1141 // We allocate two additional slots: return value and pointer to it.
1112 if (result->IsFailure()) return result; 1142 EnterApiExitFrame(stack_space, argc + 2);
1113 } 1143 }
1114 pop(saved);
1115
1116 bind(&write_back);
1117 ExternalReference limit_address =
1118 ExternalReference::handle_scope_limit_address();
1119 pop(Operand::StaticVariable(limit_address));
1120 ExternalReference next_address =
1121 ExternalReference::handle_scope_next_address();
1122 pop(Operand::StaticVariable(next_address));
1123 pop(scratch);
1124 SmiUntag(scratch);
1125 mov(Operand::StaticVariable(extensions_address), scratch);
1126
1127 return result;
1128 } 1144 }
1129 1145
1130 1146
1131 void MacroAssembler::PopHandleScope(Register saved, Register scratch) { 1147 void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) {
1132 PopHandleScopeHelper(saved, scratch, true); 1148 if (!kPassHandlesDirectly) {
1149 // The argument slots are filled as follows:
1150 //
1151 // n + 1: output cell
1152 // n: arg n
1153 // ...
1154 // 1: arg1
1155 // 0: pointer to the output cell
1156 //
1157 // Note that this is one more "argument" than the function expects
1158 // so the out cell will have to be popped explicitly after returning
1159 // from the function. The out cell contains Handle.
1160 lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell.
1161 mov(Operand(esp, 0 * kPointerSize), eax); // output.
1162 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell.
1163 }
1164
1165 ExternalReference next_address =
1166 ExternalReference::handle_scope_next_address();
1167 ExternalReference limit_address =
1168 ExternalReference::handle_scope_limit_address();
1169 ExternalReference level_address =
1170 ExternalReference::handle_scope_level_address();
1171
1172 // Allocate HandleScope in callee-save registers.
1173 mov(ebx, Operand::StaticVariable(next_address));
1174 mov(edi, Operand::StaticVariable(limit_address));
1175 add(Operand::StaticVariable(level_address), Immediate(1));
1176
1177 // Call the api function!
1178 call(function->address(), RelocInfo::RUNTIME_ENTRY);
1179
1180 if (!kPassHandlesDirectly) {
1181 // The returned value is a pointer to the handle holding the result.
1182 // Dereference this to get to the location.
1183 mov(eax, Operand(eax, 0));
1184 }
1185
1186 Label empty_handle;
1187 Label prologue;
1188 Label promote_scheduled_exception;
1189 Label delete_allocated_handles;
1190 Label leave_exit_frame;
1191
1192 // Check if the result handle holds 0.
1193 test(eax, Operand(eax));
1194 j(zero, &empty_handle, not_taken);
1195 // It was non-zero. Dereference to get the result value.
1196 mov(eax, Operand(eax, 0));
1197 bind(&prologue);
1198 // No more valid handles (the result handle was the last one). Restore
1199 // previous handle scope.
1200 mov(Operand::StaticVariable(next_address), ebx);
1201 sub(Operand::StaticVariable(level_address), Immediate(1));
1202 Assert(above_equal, "Invalid HandleScope level");
1203 cmp(edi, Operand::StaticVariable(limit_address));
1204 j(not_equal, &delete_allocated_handles, not_taken);
1205 bind(&leave_exit_frame);
1206
1207 // Check if the function scheduled an exception.
1208 ExternalReference scheduled_exception_address =
1209 ExternalReference::scheduled_exception_address();
1210 cmp(Operand::StaticVariable(scheduled_exception_address),
1211 Immediate(Factory::the_hole_value()));
1212 j(not_equal, &promote_scheduled_exception, not_taken);
1213 LeaveExitFrame();
1214 ret(0);
1215 bind(&promote_scheduled_exception);
1216 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
1217 bind(&empty_handle);
1218 // It was zero; the result is undefined.
1219 mov(eax, Factory::undefined_value());
1220 jmp(&prologue);
1221
1222 // HandleScope limit has changed. Delete allocated extensions.
1223 bind(&delete_allocated_handles);
1224 mov(Operand::StaticVariable(limit_address), edi);
1225 mov(edi, eax);
1226 mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions()));
1227 call(Operand(eax));
1228 mov(eax, edi);
1229 jmp(&leave_exit_frame);
1133 } 1230 }
1134 1231
1135 1232
1136 Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) {
1137 return PopHandleScopeHelper(saved, scratch, false);
1138 }
1139
1140
1141 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { 1233 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
1142 // Set the entry point and jump to the C entry runtime stub. 1234 // Set the entry point and jump to the C entry runtime stub.
1143 mov(ebx, Immediate(ext)); 1235 mov(ebx, Immediate(ext));
1144 CEntryStub ces(1); 1236 CEntryStub ces(1);
1145 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); 1237 jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
1146 } 1238 }
1147 1239
1148 1240
1149 void MacroAssembler::InvokePrologue(const ParameterCount& expected, 1241 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
1150 const ParameterCount& actual, 1242 const ParameterCount& actual,
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after
1672 1764
1673 // Check that the code was patched as expected. 1765 // Check that the code was patched as expected.
1674 ASSERT(masm_.pc_ == address_ + size_); 1766 ASSERT(masm_.pc_ == address_ + size_);
1675 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); 1767 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap);
1676 } 1768 }
1677 1769
1678 1770
1679 } } // namespace v8::internal 1771 } } // namespace v8::internal
1680 1772
1681 #endif // V8_TARGET_ARCH_IA32 1773 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/ia32/regexp-macro-assembler-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698