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 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 #else | 1151 #else |
1145 static const bool kPassHandlesDirectly = false; | 1152 static const bool kPassHandlesDirectly = false; |
1146 #endif | 1153 #endif |
1147 | 1154 |
1148 | 1155 |
1149 Operand ApiParameterOperand(int index) { | 1156 Operand ApiParameterOperand(int index) { |
1150 return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize); | 1157 return Operand(esp, (index + (kPassHandlesDirectly ? 0 : 1)) * kPointerSize); |
1151 } | 1158 } |
1152 | 1159 |
1153 | 1160 |
1154 void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) { | 1161 void MacroAssembler::PrepareCallApiFunction(int argc, Register scratch) { |
1155 if (kPassHandlesDirectly) { | 1162 if (kPassHandlesDirectly) { |
1156 EnterApiExitFrame(stack_space, argc); | 1163 EnterApiExitFrame(argc); |
1157 // 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 |
1158 // space for and pass an out parameter. | 1165 // space for and pass an out parameter. |
1159 } else { | 1166 } else { |
1160 // We allocate two additional slots: return value and pointer to it. | 1167 // We allocate two additional slots: return value and pointer to it. |
1161 EnterApiExitFrame(stack_space, argc + 2); | 1168 EnterApiExitFrame(argc + 2); |
1162 } | |
1163 } | |
1164 | 1169 |
1165 | |
1166 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, | |
1167 int argc) { | |
1168 if (!kPassHandlesDirectly) { | |
1169 // The argument slots are filled as follows: | 1170 // The argument slots are filled as follows: |
1170 // | 1171 // |
1171 // n + 1: output cell | 1172 // n + 1: output cell |
1172 // n: arg n | 1173 // n: arg n |
1173 // ... | 1174 // ... |
1174 // 1: arg1 | 1175 // 1: arg1 |
1175 // 0: pointer to the output cell | 1176 // 0: pointer to the output cell |
1176 // | 1177 // |
1177 // Note that this is one more "argument" than the function expects | 1178 // Note that this is one more "argument" than the function expects |
1178 // 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 |
1179 // from the function. The out cell contains Handle. | 1180 // from the function. The out cell contains Handle. |
1180 lea(eax, Operand(esp, (argc + 1) * kPointerSize)); // pointer to out cell. | 1181 |
1181 mov(Operand(esp, 0 * kPointerSize), eax); // output. | 1182 // pointer to out cell. |
1182 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 } |
1183 } | 1188 } |
| 1189 } |
1184 | 1190 |
| 1191 |
| 1192 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, |
| 1193 int stack_space) { |
1185 ExternalReference next_address = | 1194 ExternalReference next_address = |
1186 ExternalReference::handle_scope_next_address(); | 1195 ExternalReference::handle_scope_next_address(); |
1187 ExternalReference limit_address = | 1196 ExternalReference limit_address = |
1188 ExternalReference::handle_scope_limit_address(); | 1197 ExternalReference::handle_scope_limit_address(); |
1189 ExternalReference level_address = | 1198 ExternalReference level_address = |
1190 ExternalReference::handle_scope_level_address(); | 1199 ExternalReference::handle_scope_level_address(); |
1191 | 1200 |
1192 // Allocate HandleScope in callee-save registers. | 1201 // Allocate HandleScope in callee-save registers. |
1193 mov(ebx, Operand::StaticVariable(next_address)); | 1202 mov(ebx, Operand::StaticVariable(next_address)); |
1194 mov(edi, Operand::StaticVariable(limit_address)); | 1203 mov(edi, Operand::StaticVariable(limit_address)); |
(...skipping 28 matching lines...) Expand all Loading... |
1223 cmp(edi, Operand::StaticVariable(limit_address)); | 1232 cmp(edi, Operand::StaticVariable(limit_address)); |
1224 j(not_equal, &delete_allocated_handles, not_taken); | 1233 j(not_equal, &delete_allocated_handles, not_taken); |
1225 bind(&leave_exit_frame); | 1234 bind(&leave_exit_frame); |
1226 | 1235 |
1227 // Check if the function scheduled an exception. | 1236 // Check if the function scheduled an exception. |
1228 ExternalReference scheduled_exception_address = | 1237 ExternalReference scheduled_exception_address = |
1229 ExternalReference::scheduled_exception_address(); | 1238 ExternalReference::scheduled_exception_address(); |
1230 cmp(Operand::StaticVariable(scheduled_exception_address), | 1239 cmp(Operand::StaticVariable(scheduled_exception_address), |
1231 Immediate(Factory::the_hole_value())); | 1240 Immediate(Factory::the_hole_value())); |
1232 j(not_equal, &promote_scheduled_exception, not_taken); | 1241 j(not_equal, &promote_scheduled_exception, not_taken); |
1233 LeaveExitFrame(); | 1242 LeaveApiExitFrame(); |
1234 ret(0); | 1243 ret(stack_space * kPointerSize); |
1235 bind(&promote_scheduled_exception); | 1244 bind(&promote_scheduled_exception); |
1236 MaybeObject* result = | 1245 MaybeObject* result = |
1237 TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); | 1246 TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
1238 if (result->IsFailure()) { | 1247 if (result->IsFailure()) { |
1239 return result; | 1248 return result; |
1240 } | 1249 } |
1241 bind(&empty_handle); | 1250 bind(&empty_handle); |
1242 // It was zero; the result is undefined. | 1251 // It was zero; the result is undefined. |
1243 mov(eax, Factory::undefined_value()); | 1252 mov(eax, Factory::undefined_value()); |
1244 jmp(&prologue); | 1253 jmp(&prologue); |
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1799 | 1808 |
1800 // Check that the code was patched as expected. | 1809 // Check that the code was patched as expected. |
1801 ASSERT(masm_.pc_ == address_ + size_); | 1810 ASSERT(masm_.pc_ == address_ + size_); |
1802 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); | 1811 ASSERT(masm_.reloc_info_writer.pos() == address_ + size_ + Assembler::kGap); |
1803 } | 1812 } |
1804 | 1813 |
1805 | 1814 |
1806 } } // namespace v8::internal | 1815 } } // namespace v8::internal |
1807 | 1816 |
1808 #endif // V8_TARGET_ARCH_IA32 | 1817 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |