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

Side by Side Diff: src/x64/codegen-x64.cc

Issue 201042: Win64 - Allow returning two values from a runtime function. (Closed)
Patch Set: Fixed typo. Created 11 years, 3 months 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
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 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 6811 matching lines...) Expand 10 before | Expand all | Expand 10 after
6822 // Value in rcx is Smi encoded. 6822 // Value in rcx is Smi encoded.
6823 6823
6824 // Patch the arguments.length and the parameters pointer. 6824 // Patch the arguments.length and the parameters pointer.
6825 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 6825 __ movq(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
6826 __ movq(Operand(rsp, 1 * kPointerSize), rcx); 6826 __ movq(Operand(rsp, 1 * kPointerSize), rcx);
6827 __ lea(rdx, Operand(rdx, rcx, times_4, kDisplacement)); 6827 __ lea(rdx, Operand(rdx, rcx, times_4, kDisplacement));
6828 __ movq(Operand(rsp, 2 * kPointerSize), rdx); 6828 __ movq(Operand(rsp, 2 * kPointerSize), rdx);
6829 6829
6830 // Do the runtime call to allocate the arguments object. 6830 // Do the runtime call to allocate the arguments object.
6831 __ bind(&runtime); 6831 __ bind(&runtime);
6832 __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); 6832 Runtime::Function* f = Runtime::FunctionForId(Runtime::kNewArgumentsFast);
6833 __ TailCallRuntime(ExternalReference(f), 3, f->result_size);
6833 } 6834 }
6834 6835
6835 6836
6836 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) { 6837 void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
6837 // The key is in rdx and the parameter count is in rax. 6838 // The key is in rdx and the parameter count is in rax.
6838 6839
6839 // The displacement is used for skipping the frame pointer on the 6840 // The displacement is used for skipping the frame pointer on the
6840 // stack. It is the offset of the last parameter (if any) relative 6841 // stack. It is the offset of the last parameter (if any) relative
6841 // to the frame pointer. 6842 // to the frame pointer.
6842 static const int kDisplacement = 1 * kPointerSize; 6843 static const int kDisplacement = 1 * kPointerSize;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
6884 __ neg(rdx); 6885 __ neg(rdx);
6885 __ movq(rax, Operand(rbx, rdx, times_4, kDisplacement)); 6886 __ movq(rax, Operand(rbx, rdx, times_4, kDisplacement));
6886 __ Ret(); 6887 __ Ret();
6887 6888
6888 // Slow-case: Handle non-smi or out-of-bounds access to arguments 6889 // Slow-case: Handle non-smi or out-of-bounds access to arguments
6889 // by calling the runtime system. 6890 // by calling the runtime system.
6890 __ bind(&slow); 6891 __ bind(&slow);
6891 __ pop(rbx); // Return address. 6892 __ pop(rbx); // Return address.
6892 __ push(rdx); 6893 __ push(rdx);
6893 __ push(rbx); 6894 __ push(rbx);
6894 __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); 6895 Runtime::Function* f =
6896 Runtime::FunctionForId(Runtime::kGetArgumentsProperty);
6897 __ TailCallRuntime(ExternalReference(f), 1, f->result_size);
6895 } 6898 }
6896 6899
6897 6900
6898 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) { 6901 void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
6899 // Check if the calling frame is an arguments adaptor frame. 6902 // Check if the calling frame is an arguments adaptor frame.
6900 Label adaptor; 6903 Label adaptor;
6901 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); 6904 __ movq(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
6902 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); 6905 __ movq(rcx, Operand(rdx, StandardFrameConstants::kContextOffset));
6903 __ cmpq(rcx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); 6906 __ cmpq(rcx, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)));
6904 __ j(equal, &adaptor); 6907 __ j(equal, &adaptor);
6905 6908
6906 // Nothing to do: The formal number of parameters has already been 6909 // Nothing to do: The formal number of parameters has already been
6907 // passed in register rax by calling function. Just return it. 6910 // passed in register rax by calling function. Just return it.
6908 __ ret(0); 6911 __ ret(0);
6909 6912
6910 // Arguments adaptor case: Read the arguments length from the 6913 // Arguments adaptor case: Read the arguments length from the
6911 // adaptor frame and return it. 6914 // adaptor frame and return it.
6912 __ bind(&adaptor); 6915 __ bind(&adaptor);
6913 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); 6916 __ movq(rax, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset));
6914 __ ret(0); 6917 __ ret(0);
6915 } 6918 }
6916 6919
6917 6920
6921 int CEntryStub::MinorKey() {
6922 ASSERT(result_size_ <= 2);
6923 #ifdef _WIN64
6924 // Simple results returned in rax.
6925 // Complex results must be written to address passed as first argument.
6926 return (result_size_ < 2) ? 0 : result_size_ * 2;
William Hesse 2009/09/07 14:34:18 Why is the key 4 if the size is 2, and 0 if it is
Lasse Reichstein 2009/09/08 11:51:35 Previously, minor key 0 was used for CEntryStub an
6927 #else
6928 // Results returned in rax or in rax+rdx by default.
Søren Thygesen Gjesse 2009/09/07 12:22:33 Maybe add something about this being compiler spec
Lasse Reichstein 2009/09/08 11:51:35 I'll say something. It's calling convention specif
6929 return 0;
6930 #endif
6931 }
6932
6933
6918 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { 6934 void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
6919 // Check that stack should contain next handler, frame pointer, state and 6935 // Check that stack should contain next handler, frame pointer, state and
6920 // return address in that order. 6936 // return address in that order.
6921 ASSERT_EQ(StackHandlerConstants::kFPOffset + kPointerSize, 6937 ASSERT_EQ(StackHandlerConstants::kFPOffset + kPointerSize,
6922 StackHandlerConstants::kStateOffset); 6938 StackHandlerConstants::kStateOffset);
6923 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize, 6939 ASSERT_EQ(StackHandlerConstants::kStateOffset + kPointerSize,
6924 StackHandlerConstants::kPCOffset); 6940 StackHandlerConstants::kPCOffset);
6925 6941
6926 ExternalReference handler_address(Top::k_handler_address); 6942 ExternalReference handler_address(Top::k_handler_address);
6927 __ movq(kScratchRegister, handler_address); 6943 __ movq(kScratchRegister, handler_address);
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
6979 __ movq(kScratchRegister, scope_depth); 6995 __ movq(kScratchRegister, scope_depth);
6980 __ incl(Operand(kScratchRegister, 0)); 6996 __ incl(Operand(kScratchRegister, 0));
6981 } 6997 }
6982 6998
6983 // Call C function. 6999 // Call C function.
6984 #ifdef _WIN64 7000 #ifdef _WIN64
6985 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9 7001 // Windows 64-bit ABI passes arguments in rcx, rdx, r8, r9
6986 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. 7002 // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
6987 __ movq(Operand(rsp, 4 * kPointerSize), r14); // argc. 7003 __ movq(Operand(rsp, 4 * kPointerSize), r14); // argc.
6988 __ movq(Operand(rsp, 5 * kPointerSize), r15); // argv. 7004 __ movq(Operand(rsp, 5 * kPointerSize), r15); // argv.
6989 // Pass a pointer to the Arguments object as the first argument. 7005 if (result_size_ < 2) {
Søren Thygesen Gjesse 2009/09/07 12:22:33 Why not == 1? We only have 1 and 2 right?
Lasse Reichstein 2009/09/08 11:51:35 I was expecting 0 to be allowed too (for a functio
6990 __ lea(rcx, Operand(rsp, 4 * kPointerSize)); 7006 // Pass a pointer to the Arguments object as the first argument.
7007 // Return result in single register (rax).
7008 __ lea(rcx, Operand(rsp, 4 * kPointerSize));
7009 } else {
7010 ASSERT_EQ(2, result_size_);
7011 // Pass a pointer to the result location as the first argument.
7012 __ lea(rcx, Operand(rsp, 6 * kPointerSize));
7013 // Pass a pointer to the Arguments object as the second argument.
7014 __ lea(rdx, Operand(rsp, 4 * kPointerSize));
7015 }
7016
6991 #else // ! defined(_WIN64) 7017 #else // ! defined(_WIN64)
6992 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. 7018 // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
6993 __ movq(rdi, r14); // argc. 7019 __ movq(rdi, r14); // argc.
6994 __ movq(rsi, r15); // argv. 7020 __ movq(rsi, r15); // argv.
6995 #endif 7021 #endif
6996 __ call(rbx); 7022 __ call(rbx);
6997 // Result is in rax - do not destroy this register! 7023 // Result is in rax - do not destroy this register!
6998 7024
6999 if (always_allocate_scope) { 7025 if (always_allocate_scope) {
7000 __ movq(kScratchRegister, scope_depth); 7026 __ movq(kScratchRegister, scope_depth);
7001 __ decl(Operand(kScratchRegister, 0)); 7027 __ decl(Operand(kScratchRegister, 0));
7002 } 7028 }
7003 7029
7004 // Check for failure result. 7030 // Check for failure result.
7005 Label failure_returned; 7031 Label failure_returned;
7006 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); 7032 ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0);
7007 __ lea(rcx, Operand(rax, 1)); 7033 __ lea(rcx, Operand(rax, 1));
7008 // Lower 2 bits of rcx are 0 iff rax has failure tag. 7034 // Lower 2 bits of rcx are 0 iff rax has failure tag.
7009 __ testl(rcx, Immediate(kFailureTagMask)); 7035 __ testl(rcx, Immediate(kFailureTagMask));
7010 __ j(zero, &failure_returned); 7036 __ j(zero, &failure_returned);
7011 7037
7012 // Exit the JavaScript to C++ exit frame. 7038 // Exit the JavaScript to C++ exit frame.
7013 __ LeaveExitFrame(frame_type); 7039 __ LeaveExitFrame(frame_type, result_size_);
7014 __ ret(0); 7040 __ ret(0);
7015 7041
7016 // Handling of failure. 7042 // Handling of failure.
7017 __ bind(&failure_returned); 7043 __ bind(&failure_returned);
7018 7044
7019 Label retry; 7045 Label retry;
7020 // If the returned exception is RETRY_AFTER_GC continue at retry label 7046 // If the returned exception is RETRY_AFTER_GC continue at retry label
7021 ASSERT(Failure::RETRY_AFTER_GC == 0); 7047 ASSERT(Failure::RETRY_AFTER_GC == 0);
7022 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize)); 7048 __ testl(rax, Immediate(((1 << kFailureTypeTagSize) - 1) << kFailureTagSize));
7023 __ j(zero, &retry); 7049 __ j(zero, &retry);
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
7139 // NOTE: Invocations of builtins may return failure objects 7165 // NOTE: Invocations of builtins may return failure objects
7140 // instead of a proper result. The builtin entry handles 7166 // instead of a proper result. The builtin entry handles
7141 // this by performing a garbage collection and retrying the 7167 // this by performing a garbage collection and retrying the
7142 // builtin once. 7168 // builtin once.
7143 7169
7144 StackFrame::Type frame_type = is_debug_break ? 7170 StackFrame::Type frame_type = is_debug_break ?
7145 StackFrame::EXIT_DEBUG : 7171 StackFrame::EXIT_DEBUG :
7146 StackFrame::EXIT; 7172 StackFrame::EXIT;
7147 7173
7148 // Enter the exit frame that transitions from JavaScript to C++. 7174 // Enter the exit frame that transitions from JavaScript to C++.
7149 __ EnterExitFrame(frame_type); 7175 __ EnterExitFrame(frame_type, result_size_);
7150 7176
7151 // rax: Holds the context at this point, but should not be used. 7177 // rax: Holds the context at this point, but should not be used.
7152 // On entry to code generated by GenerateCore, it must hold 7178 // On entry to code generated by GenerateCore, it must hold
7153 // a failure result if the collect_garbage argument to GenerateCore 7179 // a failure result if the collect_garbage argument to GenerateCore
7154 // is true. This failure result can be the result of code 7180 // is true. This failure result can be the result of code
7155 // generated by a previous call to GenerateCore. The value 7181 // generated by a previous call to GenerateCore. The value
7156 // of rax is then passed to Runtime::PerformGC. 7182 // of rax is then passed to Runtime::PerformGC.
7157 // rbx: pointer to builtin function (C callee-saved). 7183 // rbx: pointer to builtin function (C callee-saved).
7158 // rbp: frame pointer of exit frame (restored after C call). 7184 // rbp: frame pointer of exit frame (restored after C call).
7159 // rsp: stack pointer (restored after C call). 7185 // rsp: stack pointer (restored after C call).
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
7326 void StackCheckStub::Generate(MacroAssembler* masm) { 7352 void StackCheckStub::Generate(MacroAssembler* masm) {
7327 // Because builtins always remove the receiver from the stack, we 7353 // Because builtins always remove the receiver from the stack, we
7328 // have to fake one to avoid underflowing the stack. The receiver 7354 // have to fake one to avoid underflowing the stack. The receiver
7329 // must be inserted below the return address on the stack so we 7355 // must be inserted below the return address on the stack so we
7330 // temporarily store that in a register. 7356 // temporarily store that in a register.
7331 __ pop(rax); 7357 __ pop(rax);
7332 __ push(Immediate(Smi::FromInt(0))); 7358 __ push(Immediate(Smi::FromInt(0)));
7333 __ push(rax); 7359 __ push(rax);
7334 7360
7335 // Do tail-call to runtime routine. 7361 // Do tail-call to runtime routine.
7336 __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1); 7362 Runtime::Function* f = Runtime::FunctionForId(Runtime::kStackGuard);
7363 __ TailCallRuntime(ExternalReference(f), 1, f->result_size);
7337 } 7364 }
7338 7365
7339 7366
7340 void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm, 7367 void FloatingPointHelper::AllocateHeapNumber(MacroAssembler* masm,
7341 Label* need_gc, 7368 Label* need_gc,
7342 Register scratch, 7369 Register scratch,
7343 Register result) { 7370 Register result) {
7344 // Allocate heap number in new space. 7371 // Allocate heap number in new space.
7345 __ AllocateObjectInNewSpace(HeapNumber::kSize, 7372 __ AllocateObjectInNewSpace(HeapNumber::kSize,
7346 result, 7373 result,
(...skipping 558 matching lines...) Expand 10 before | Expand all | Expand 10 after
7905 int CompareStub::MinorKey() { 7932 int CompareStub::MinorKey() {
7906 // Encode the two parameters in a unique 16 bit value. 7933 // Encode the two parameters in a unique 16 bit value.
7907 ASSERT(static_cast<unsigned>(cc_) < (1 << 15)); 7934 ASSERT(static_cast<unsigned>(cc_) < (1 << 15));
7908 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0); 7935 return (static_cast<unsigned>(cc_) << 1) | (strict_ ? 1 : 0);
7909 } 7936 }
7910 7937
7911 7938
7912 #undef __ 7939 #undef __
7913 7940
7914 } } // namespace v8::internal 7941 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698