| 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 |