OLD | NEW |
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 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1068 } | 1068 } |
1069 | 1069 |
1070 | 1070 |
1071 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 1071 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
1072 int num_arguments, | 1072 int num_arguments, |
1073 int result_size) { | 1073 int result_size) { |
1074 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); | 1074 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); |
1075 } | 1075 } |
1076 | 1076 |
1077 | 1077 |
1078 void MacroAssembler::PushHandleScope(Register scratch) { | 1078 // 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. | 1079 // using the location_ field directly. If false, it is passed and |
1080 ExternalReference extensions_address = | 1080 // returned as a pointer to a handle. |
1081 ExternalReference::handle_scope_extensions_address(); | 1081 #ifdef USING_BSD_ABI |
1082 mov(scratch, Operand::StaticVariable(extensions_address)); | 1082 static const bool kPassHandlesDirectly = true; |
1083 SmiTag(scratch); | 1083 #else |
1084 push(scratch); | 1084 static const bool kPassHandlesDirectly = false; |
1085 mov(Operand::StaticVariable(extensions_address), Immediate(0)); | 1085 #endif |
1086 // Push next and limit pointers which will be wordsize aligned and | 1086 |
1087 // hence automatically smi tagged. | 1087 |
1088 ExternalReference next_address = | 1088 Operand ApiParameterOperand(int index) { |
1089 ExternalReference::handle_scope_next_address(); | 1089 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 } | 1090 } |
1095 | 1091 |
1096 | 1092 |
1097 Object* MacroAssembler::PopHandleScopeHelper(Register saved, | 1093 void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) { |
1098 Register scratch, | 1094 if (kPassHandlesDirectly) { |
1099 bool gc_allowed) { | 1095 EnterApiExitFrame(stack_space, argc); |
1100 Object* result = NULL; | 1096 // When handles as passed directly we don't have to allocate extra |
1101 ExternalReference extensions_address = | 1097 // 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 { | 1098 } else { |
1111 result = TryCallRuntime(Runtime::kDeleteHandleScopeExtensions, 0); | 1099 // We allocate two additional slots: return value and pointer to it. |
1112 if (result->IsFailure()) return result; | 1100 EnterApiExitFrame(stack_space, argc + 2); |
1113 } | 1101 } |
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 } | 1102 } |
1129 | 1103 |
1130 | 1104 |
1131 void MacroAssembler::PopHandleScope(Register saved, Register scratch) { | 1105 void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) { |
1132 PopHandleScopeHelper(saved, scratch, true); | 1106 if (!kPassHandlesDirectly) { |
| 1107 // The argument slots are filled as follows: |
| 1108 // |
| 1109 // n + 1: output cell |
| 1110 // n: arg n |
| 1111 // ... |
| 1112 // 1: arg1 |
| 1113 // 0: pointer to the output cell |
| 1114 // |
| 1115 // Note that this is one more "argument" than the function expects |
| 1116 // so the out cell will have to be popped explicitly after returning |
| 1117 // from the function. The out cell contains Handle. |
| 1118 lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell. |
| 1119 mov(Operand(esp, 0 * kPointerSize), eax); // output. |
| 1120 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. |
| 1121 } |
| 1122 |
| 1123 ExternalReference next_address = |
| 1124 ExternalReference::handle_scope_next_address(); |
| 1125 ExternalReference limit_address = |
| 1126 ExternalReference::handle_scope_limit_address(); |
| 1127 ExternalReference level_address = |
| 1128 ExternalReference::handle_scope_level_address(); |
| 1129 |
| 1130 // Allocate HandleScope in callee-save registers. |
| 1131 mov(ebx, Operand::StaticVariable(next_address)); |
| 1132 mov(edi, Operand::StaticVariable(limit_address)); |
| 1133 add(Operand::StaticVariable(level_address), Immediate(1)); |
| 1134 |
| 1135 // Call the api function! |
| 1136 call(function->address(), RelocInfo::RUNTIME_ENTRY); |
| 1137 |
| 1138 if (!kPassHandlesDirectly) { |
| 1139 // The returned value is a pointer to the handle holding the result. |
| 1140 // Dereference this to get to the location. |
| 1141 mov(eax, Operand(eax, 0)); |
| 1142 } |
| 1143 |
| 1144 Label empty_handle; |
| 1145 Label prologue; |
| 1146 Label promote_scheduled_exception; |
| 1147 Label delete_allocated_handles; |
| 1148 Label leave_exit_frame; |
| 1149 |
| 1150 // Check if the result handle holds 0. |
| 1151 test(eax, Operand(eax)); |
| 1152 j(zero, &empty_handle, not_taken); |
| 1153 // It was non-zero. Dereference to get the result value. |
| 1154 mov(eax, Operand(eax, 0)); |
| 1155 bind(&prologue); |
| 1156 // No more valid handles (the result handle was the last one). Restore |
| 1157 // previous handle scope. |
| 1158 mov(Operand::StaticVariable(next_address), ebx); |
| 1159 sub(Operand::StaticVariable(level_address), Immediate(1)); |
| 1160 Assert(above_equal, "Invalid HandleScope level"); |
| 1161 cmp(edi, Operand::StaticVariable(limit_address)); |
| 1162 j(not_equal, &delete_allocated_handles, not_taken); |
| 1163 bind(&leave_exit_frame); |
| 1164 |
| 1165 // Check if the function scheduled an exception. |
| 1166 ExternalReference scheduled_exception_address = |
| 1167 ExternalReference::scheduled_exception_address(); |
| 1168 cmp(Operand::StaticVariable(scheduled_exception_address), |
| 1169 Immediate(Factory::the_hole_value())); |
| 1170 j(not_equal, &promote_scheduled_exception, not_taken); |
| 1171 LeaveExitFrame(); |
| 1172 ret(0); |
| 1173 bind(&promote_scheduled_exception); |
| 1174 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
| 1175 bind(&empty_handle); |
| 1176 // It was zero; the result is undefined. |
| 1177 mov(eax, Factory::undefined_value()); |
| 1178 jmp(&prologue); |
| 1179 |
| 1180 // HandleScope limit has changed. Delete allocated extensions. |
| 1181 bind(&delete_allocated_handles); |
| 1182 mov(Operand::StaticVariable(limit_address), edi); |
| 1183 mov(edi, eax); |
| 1184 mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions())); |
| 1185 call(Operand(eax)); |
| 1186 mov(eax, edi); |
| 1187 jmp(&leave_exit_frame); |
1133 } | 1188 } |
1134 | 1189 |
1135 | 1190 |
1136 Object* MacroAssembler::TryPopHandleScope(Register saved, Register scratch) { | |
1137 return PopHandleScopeHelper(saved, scratch, false); | |
1138 } | |
1139 | |
1140 | |
1141 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { | 1191 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { |
1142 // Set the entry point and jump to the C entry runtime stub. | 1192 // Set the entry point and jump to the C entry runtime stub. |
1143 mov(ebx, Immediate(ext)); | 1193 mov(ebx, Immediate(ext)); |
1144 CEntryStub ces(1); | 1194 CEntryStub ces(1); |
1145 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 1195 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
1146 } | 1196 } |
1147 | 1197 |
1148 | 1198 |
1149 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1199 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
1150 const ParameterCount& actual, | 1200 const ParameterCount& actual, |
(...skipping 521 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1672 | 1722 |
1673 // Check that the code was patched as expected. | 1723 // Check that the code was patched as expected. |
1674 ASSERT(masm_.pc_ == address_ + size_); | 1724 ASSERT(masm_.pc_ == address_ + size_); |
1675 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1725 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
1676 } | 1726 } |
1677 | 1727 |
1678 | 1728 |
1679 } } // namespace v8::internal | 1729 } } // namespace v8::internal |
1680 | 1730 |
1681 #endif // V8_TARGET_ARCH_IA32 | 1731 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |