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 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
385 | 385 |
386 // Setup argc and argv in callee-saved registers. | 386 // Setup argc and argv in callee-saved registers. |
387 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | 387 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; |
388 mov(edi, Operand(eax)); | 388 mov(edi, Operand(eax)); |
389 lea(esi, Operand(ebp, eax, times_4, offset)); | 389 lea(esi, Operand(ebp, eax, times_4, offset)); |
390 | 390 |
391 EnterExitFrameEpilogue(2); | 391 EnterExitFrameEpilogue(2); |
392 } | 392 } |
393 | 393 |
394 | 394 |
395 void MacroAssembler::EnterApiExitFrame(int stack_space, | 395 void MacroAssembler::EnterApiExitFrame(int argc) { |
396 int argc) { | |
397 EnterExitFramePrologue(); | 396 EnterExitFramePrologue(); |
398 | |
399 int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize; | |
400 lea(esi, Operand(ebp, (stack_space * kPointerSize) + offset)); | |
401 | |
402 EnterExitFrameEpilogue(argc); | 397 EnterExitFrameEpilogue(argc); |
403 } | 398 } |
404 | 399 |
405 | 400 |
406 void MacroAssembler::LeaveExitFrame() { | 401 void MacroAssembler::LeaveExitFrame() { |
407 // Get the return address from the stack and restore the frame pointer. | 402 // Get the return address from the stack and restore the frame pointer. |
408 mov(ecx, Operand(ebp, 1 * kPointerSize)); | 403 mov(ecx, Operand(ebp, 1 * kPointerSize)); |
409 mov(ebp, Operand(ebp, 0 * kPointerSize)); | 404 mov(ebp, Operand(ebp, 0 * kPointerSize)); |
410 | 405 |
411 // Pop the arguments and the receiver from the caller stack. | 406 // Pop the arguments and the receiver from the caller stack. |
412 lea(esp, Operand(esi, 1 * kPointerSize)); | 407 lea(esp, Operand(esi, 1 * kPointerSize)); |
413 | 408 |
| 409 // Push the return address to get ready to return. |
| 410 push(ecx); |
| 411 |
| 412 LeaveExitFrameEpilogue(); |
| 413 } |
| 414 |
| 415 void MacroAssembler::LeaveExitFrameEpilogue() { |
414 // Restore current context from top and clear it in debug mode. | 416 // Restore current context from top and clear it in debug mode. |
415 ExternalReference context_address(Top::k_context_address); | 417 ExternalReference context_address(Top::k_context_address); |
416 mov(esi, Operand::StaticVariable(context_address)); | 418 mov(esi, Operand::StaticVariable(context_address)); |
417 #ifdef DEBUG | 419 #ifdef DEBUG |
418 mov(Operand::StaticVariable(context_address), Immediate(0)); | 420 mov(Operand::StaticVariable(context_address), Immediate(0)); |
419 #endif | 421 #endif |
420 | 422 |
421 // Push the return address to get ready to return. | |
422 push(ecx); | |
423 | |
424 // Clear the top frame. | 423 // Clear the top frame. |
425 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); | 424 ExternalReference c_entry_fp_address(Top::k_c_entry_fp_address); |
426 mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); | 425 mov(Operand::StaticVariable(c_entry_fp_address), Immediate(0)); |
427 } | 426 } |
428 | 427 |
429 | 428 |
| 429 void MacroAssembler::LeaveApiExitFrame() { |
| 430 mov(esp, Operand(ebp)); |
| 431 pop(ebp); |
| 432 |
| 433 LeaveExitFrameEpilogue(); |
| 434 } |
| 435 |
| 436 |
430 void MacroAssembler::PushTryHandler(CodeLocation try_location, | 437 void MacroAssembler::PushTryHandler(CodeLocation try_location, |
431 HandlerType type) { | 438 HandlerType type) { |
432 // Adjust this code if not the case. | 439 // Adjust this code if not the case. |
433 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); | 440 ASSERT(StackHandlerConstants::kSize == 4 * kPointerSize); |
434 // The pc (return address) is already on TOS. | 441 // The pc (return address) is already on TOS. |
435 if (try_location == IN_JAVASCRIPT) { | 442 if (try_location == IN_JAVASCRIPT) { |
436 if (type == TRY_CATCH_HANDLER) { | 443 if (type == TRY_CATCH_HANDLER) { |
437 push(Immediate(StackHandler::TRY_CATCH)); | 444 push(Immediate(StackHandler::TRY_CATCH)); |
438 } else { | 445 } else { |
439 push(Immediate(StackHandler::TRY_FINALLY)); | 446 push(Immediate(StackHandler::TRY_FINALLY)); |
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1103 int result_size) { | 1110 int result_size) { |
1104 // TODO(1236192): Most runtime routines don't need the number of | 1111 // TODO(1236192): Most runtime routines don't need the number of |
1105 // arguments passed in because it is constant. At some point we | 1112 // arguments passed in because it is constant. At some point we |
1106 // should remove this need and make the runtime routine entry code | 1113 // should remove this need and make the runtime routine entry code |
1107 // smarter. | 1114 // smarter. |
1108 Set(eax, Immediate(num_arguments)); | 1115 Set(eax, Immediate(num_arguments)); |
1109 JumpToExternalReference(ext); | 1116 JumpToExternalReference(ext); |
1110 } | 1117 } |
1111 | 1118 |
1112 | 1119 |
| 1120 MaybeObject* MacroAssembler::TryTailCallExternalReference( |
| 1121 const ExternalReference& ext, int num_arguments, int result_size) { |
| 1122 // TODO(1236192): Most runtime routines don't need the number of |
| 1123 // arguments passed in because it is constant. At some point we |
| 1124 // should remove this need and make the runtime routine entry code |
| 1125 // smarter. |
| 1126 Set(eax, Immediate(num_arguments)); |
| 1127 return TryJumpToExternalReference(ext); |
| 1128 } |
| 1129 |
| 1130 |
1113 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 1131 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
1114 int num_arguments, | 1132 int num_arguments, |
1115 int result_size) { | 1133 int result_size) { |
1116 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); | 1134 TailCallExternalReference(ExternalReference(fid), num_arguments, result_size); |
1117 } | 1135 } |
1118 | 1136 |
1119 | 1137 |
| 1138 MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid, |
| 1139 int num_arguments, |
| 1140 int result_size) { |
| 1141 return TryTailCallExternalReference( |
| 1142 ExternalReference(fid), num_arguments, result_size); |
| 1143 } |
| 1144 |
| 1145 |
1120 // If true, a Handle<T> passed by value is passed and returned by | 1146 // If true, a Handle<T> passed by value is passed and returned by |
1121 // using the location_ field directly. If false, it is passed and | 1147 // using the location_ field directly. If false, it is passed and |
1122 // returned as a pointer to a handle. | 1148 // returned as a pointer to a handle. |
1123 #ifdef USING_BSD_ABI | 1149 #ifdef USING_BSD_ABI |
1124 static const bool kPassHandlesDirectly = true; | 1150 static const bool kPassHandlesDirectly = true; |
1125 #else | 1151 #else |
1126 static const bool kPassHandlesDirectly = false; | 1152 static const bool kPassHandlesDirectly = false; |
1127 #endif | 1153 #endif |
1128 | 1154 |
1129 | 1155 |
1130 Operand ApiParameterOperand(int index) { | 1156 Operand ApiParameterOperand(int index) { |
1131 return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize); | 1157 return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize); |
1132 } | 1158 } |
1133 | 1159 |
1134 | 1160 |
1135 void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) { | 1161 void MacroAssembler::PrepareCallApiFunction(int argc, Register scratch) { |
1136 if (kPassHandlesDirectly) { | 1162 if (kPassHandlesDirectly) { |
1137 EnterApiExitFrame(stack_space, argc); | 1163 EnterApiExitFrame(argc); |
1138 // When handles as passed directly we don't have to allocate extra | 1164 // When handles as passed directly we don't have to allocate extra |
1139 // space for and pass an out parameter. | 1165 // space for and pass an out parameter. |
1140 } else { | 1166 } else { |
1141 // We allocate two additional slots: return value and pointer to it. | 1167 // We allocate two additional slots: return value and pointer to it. |
1142 EnterApiExitFrame(stack_space, argc + 2); | 1168 EnterApiExitFrame(argc + 2); |
1143 } | |
1144 } | |
1145 | 1169 |
1146 | |
1147 void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) { | |
1148 if (!kPassHandlesDirectly) { | |
1149 // The argument slots are filled as follows: | 1170 // The argument slots are filled as follows: |
1150 // | 1171 // |
1151 // n + 1: output cell | 1172 // n + 1: output cell |
1152 // n: arg n | 1173 // n: arg n |
1153 // ... | 1174 // ... |
1154 // 1: arg1 | 1175 // 1: arg1 |
1155 // 0: pointer to the output cell | 1176 // 0: pointer to the output cell |
1156 // | 1177 // |
1157 // Note that this is one more "argument" than the function expects | 1178 // Note that this is one more "argument" than the function expects |
1158 // so the out cell will have to be popped explicitly after returning | 1179 // so the out cell will have to be popped explicitly after returning |
1159 // from the function. The out cell contains Handle. | 1180 // from the function. The out cell contains Handle. |
1160 lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell. | 1181 |
1161 mov(Operand(esp, 0 * kPointerSize), eax); // output. | 1182 // pointer to out cell. |
1162 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. | 1183 lea(scratch, Operand(esp, (argc + 1) * kPointerSize)); |
| 1184 mov(Operand(esp, 0 * kPointerSize), scratch); // output. |
| 1185 if (FLAG_debug_code) { |
| 1186 mov(Operand(esp, (argc + 1) * kPointerSize), Immediate(0)); // out cell. |
| 1187 } |
1163 } | 1188 } |
| 1189 } |
1164 | 1190 |
| 1191 |
| 1192 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, |
| 1193 int stack_space) { |
1165 ExternalReference next_address = | 1194 ExternalReference next_address = |
1166 ExternalReference::handle_scope_next_address(); | 1195 ExternalReference::handle_scope_next_address(); |
1167 ExternalReference limit_address = | 1196 ExternalReference limit_address = |
1168 ExternalReference::handle_scope_limit_address(); | 1197 ExternalReference::handle_scope_limit_address(); |
1169 ExternalReference level_address = | 1198 ExternalReference level_address = |
1170 ExternalReference::handle_scope_level_address(); | 1199 ExternalReference::handle_scope_level_address(); |
1171 | 1200 |
1172 // Allocate HandleScope in callee-save registers. | 1201 // Allocate HandleScope in callee-save registers. |
1173 mov(ebx, Operand::StaticVariable(next_address)); | 1202 mov(ebx, Operand::StaticVariable(next_address)); |
1174 mov(edi, Operand::StaticVariable(limit_address)); | 1203 mov(edi, Operand::StaticVariable(limit_address)); |
(...skipping 28 matching lines...) Expand all Loading... |
1203 cmp(edi, Operand::StaticVariable(limit_address)); | 1232 cmp(edi, Operand::StaticVariable(limit_address)); |
1204 j(not_equal, &delete_allocated_handles, not_taken); | 1233 j(not_equal, &delete_allocated_handles, not_taken); |
1205 bind(&leave_exit_frame); | 1234 bind(&leave_exit_frame); |
1206 | 1235 |
1207 // Check if the function scheduled an exception. | 1236 // Check if the function scheduled an exception. |
1208 ExternalReference scheduled_exception_address = | 1237 ExternalReference scheduled_exception_address = |
1209 ExternalReference::scheduled_exception_address(); | 1238 ExternalReference::scheduled_exception_address(); |
1210 cmp(Operand::StaticVariable(scheduled_exception_address), | 1239 cmp(Operand::StaticVariable(scheduled_exception_address), |
1211 Immediate(Factory::the_hole_value())); | 1240 Immediate(Factory::the_hole_value())); |
1212 j(not_equal, &promote_scheduled_exception, not_taken); | 1241 j(not_equal, &promote_scheduled_exception, not_taken); |
1213 LeaveExitFrame(); | 1242 LeaveApiExitFrame(); |
1214 ret(0); | 1243 ret(stack_space * kPointerSize); |
1215 bind(&promote_scheduled_exception); | 1244 bind(&promote_scheduled_exception); |
1216 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); | 1245 MaybeObject* result = |
| 1246 TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
| 1247 if (result->IsFailure()) { |
| 1248 return result; |
| 1249 } |
1217 bind(&empty_handle); | 1250 bind(&empty_handle); |
1218 // It was zero; the result is undefined. | 1251 // It was zero; the result is undefined. |
1219 mov(eax, Factory::undefined_value()); | 1252 mov(eax, Factory::undefined_value()); |
1220 jmp(&prologue); | 1253 jmp(&prologue); |
1221 | 1254 |
1222 // HandleScope limit has changed. Delete allocated extensions. | 1255 // HandleScope limit has changed. Delete allocated extensions. |
1223 bind(&delete_allocated_handles); | 1256 bind(&delete_allocated_handles); |
1224 mov(Operand::StaticVariable(limit_address), edi); | 1257 mov(Operand::StaticVariable(limit_address), edi); |
1225 mov(edi, eax); | 1258 mov(edi, eax); |
1226 mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions())); | 1259 mov(eax, Immediate(ExternalReference::delete_handle_scope_extensions())); |
1227 call(Operand(eax)); | 1260 call(Operand(eax)); |
1228 mov(eax, edi); | 1261 mov(eax, edi); |
1229 jmp(&leave_exit_frame); | 1262 jmp(&leave_exit_frame); |
| 1263 |
| 1264 return result; |
1230 } | 1265 } |
1231 | 1266 |
1232 | 1267 |
1233 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { | 1268 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { |
1234 // Set the entry point and jump to the C entry runtime stub. | 1269 // Set the entry point and jump to the C entry runtime stub. |
1235 mov(ebx, Immediate(ext)); | 1270 mov(ebx, Immediate(ext)); |
1236 CEntryStub ces(1); | 1271 CEntryStub ces(1); |
1237 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 1272 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
1238 } | 1273 } |
1239 | 1274 |
1240 | 1275 |
| 1276 MaybeObject* MacroAssembler::TryJumpToExternalReference( |
| 1277 const ExternalReference& ext) { |
| 1278 // Set the entry point and jump to the C entry runtime stub. |
| 1279 mov(ebx, Immediate(ext)); |
| 1280 CEntryStub ces(1); |
| 1281 return TryTailCallStub(&ces); |
| 1282 } |
| 1283 |
| 1284 |
1241 void MacroAssembler::InvokePrologue(const ParameterCount& expected, | 1285 void MacroAssembler::InvokePrologue(const ParameterCount& expected, |
1242 const ParameterCount& actual, | 1286 const ParameterCount& actual, |
1243 Handle<Code> code_constant, | 1287 Handle<Code> code_constant, |
1244 const Operand& code_operand, | 1288 const Operand& code_operand, |
1245 Label* done, | 1289 Label* done, |
1246 InvokeFlag flag) { | 1290 InvokeFlag flag) { |
1247 bool definitely_matches = false; | 1291 bool definitely_matches = false; |
1248 Label invoke; | 1292 Label invoke; |
1249 if (expected.is_immediate()) { | 1293 if (expected.is_immediate()) { |
1250 ASSERT(actual.is_immediate()); | 1294 ASSERT(actual.is_immediate()); |
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1764 | 1808 |
1765 // Check that the code was patched as expected. | 1809 // Check that the code was patched as expected. |
1766 ASSERT(masm_.pc_ == address_ + size_); | 1810 ASSERT(masm_.pc_ == address_ + size_); |
1767 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1811 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
1768 } | 1812 } |
1769 | 1813 |
1770 | 1814 |
1771 } } // namespace v8::internal | 1815 } } // namespace v8::internal |
1772 | 1816 |
1773 #endif // V8_TARGET_ARCH_IA32 | 1817 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |