Win64 - Allow returning two values from a runtime function.

(Not yet fully functional)

Review URL: http://codereview.chromium.org/201042


git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@2845 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2009-09-08 11:52:05 +00:00
parent ae062d5df1
commit 8f60f1a46f
23 changed files with 398 additions and 317 deletions

View File

@ -5623,7 +5623,7 @@ void StackCheckStub::Generate(MacroAssembler* masm) {
// argument, so give it a Smi. // argument, so give it a Smi.
__ mov(r0, Operand(Smi::FromInt(0))); __ mov(r0, Operand(Smi::FromInt(0)));
__ push(r0); __ push(r0);
__ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1); __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1);
__ StubReturn(1); __ StubReturn(1);
} }
@ -5678,6 +5678,13 @@ void UnarySubStub::Generate(MacroAssembler* masm) {
} }
int CEntryStub::MinorKey() {
ASSERT(result_size_ <= 2);
// Result returned in r0 or r0+r1 by default.
return 0;
}
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// r0 holds the exception. // r0 holds the exception.
@ -6195,7 +6202,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// by calling the runtime system. // by calling the runtime system.
__ bind(&slow); __ bind(&slow);
__ push(r1); __ push(r1);
__ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1, 1);
} }
@ -6216,7 +6223,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
// Do the runtime call to allocate the arguments object. // Do the runtime call to allocate the arguments object.
__ bind(&runtime); __ bind(&runtime);
__ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1);
} }

View File

@ -391,7 +391,7 @@ void CallIC::Generate(MacroAssembler* masm,
__ mov(r0, Operand(2)); __ mov(r0, Operand(2));
__ mov(r1, Operand(f)); __ mov(r1, Operand(f));
CEntryStub stub; CEntryStub stub(1);
__ CallStub(&stub); __ CallStub(&stub);
// Move result to r1 and leave the internal frame. // Move result to r1 and leave the internal frame.
@ -503,7 +503,7 @@ void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ stm(db_w, sp, r2.bit() | r3.bit()); __ stm(db_w, sp, r2.bit() | r3.bit());
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 2); __ TailCallRuntime(f, 2, 1);
} }
@ -543,7 +543,7 @@ void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ ldm(ia, sp, r2.bit() | r3.bit()); __ ldm(ia, sp, r2.bit() | r3.bit());
__ stm(db_w, sp, r2.bit() | r3.bit()); __ stm(db_w, sp, r2.bit() | r3.bit());
__ TailCallRuntime(f, 2); __ TailCallRuntime(f, 2, 1);
} }
@ -599,7 +599,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
__ ldm(ia, sp, r0.bit() | r1.bit()); __ ldm(ia, sp, r0.bit() | r1.bit());
__ stm(db_w, sp, r0.bit() | r1.bit()); __ stm(db_w, sp, r0.bit() | r1.bit());
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2); __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2, 1);
// Fast case: Do the load. // Fast case: Do the load.
__ bind(&fast); __ bind(&fast);
@ -626,7 +626,7 @@ void KeyedStoreIC::Generate(MacroAssembler* masm,
__ ldm(ia, sp, r2.bit() | r3.bit()); __ ldm(ia, sp, r2.bit() | r3.bit());
__ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
__ TailCallRuntime(f, 3); __ TailCallRuntime(f, 3, 1);
} }
@ -684,7 +684,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
__ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object
__ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit()); __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1);
// Extra capacity case: Check if there is extra capacity to // Extra capacity case: Check if there is extra capacity to
// perform the store and update the length. Used for adding one // perform the store and update the length. Used for adding one
@ -761,7 +761,7 @@ void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime( __ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
} }
@ -798,7 +798,7 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime( __ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
} }
@ -814,7 +814,7 @@ void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit()); __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 3); __ TailCallRuntime(f, 3, 1);
} }

View File

@ -999,7 +999,8 @@ void MacroAssembler::CallRuntime(Runtime::FunctionId fid, int num_arguments) {
void MacroAssembler::TailCallRuntime(const ExternalReference& ext, void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
int num_arguments) { int num_arguments,
int result_size) {
// TODO(1236192): Most runtime routines don't need the number of // TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we // arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code // should remove this need and make the runtime routine entry code
@ -1015,7 +1016,7 @@ void MacroAssembler::JumpToBuiltin(const ExternalReference& builtin) {
ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1); ASSERT((reinterpret_cast<intptr_t>(builtin.address()) & 1) == 1);
#endif #endif
mov(r1, Operand(builtin)); mov(r1, Operand(builtin));
CEntryStub stub; CEntryStub stub(1);
Jump(stub.GetCode(), RelocInfo::CODE_TARGET); Jump(stub.GetCode(), RelocInfo::CODE_TARGET);
} }

View File

@ -259,7 +259,9 @@ class MacroAssembler: public Assembler {
// Tail call of a runtime routine (jump). // Tail call of a runtime routine (jump).
// Like JumpToBuiltin, but also takes care of passing the number // Like JumpToBuiltin, but also takes care of passing the number
// of parameters. // of parameters.
void TailCallRuntime(const ExternalReference& ext, int num_arguments); void TailCallRuntime(const ExternalReference& ext,
int num_arguments,
int result_size);
// Jump to the builtin routine. // Jump to the builtin routine.
void JumpToBuiltin(const ExternalReference& builtin); void JumpToBuiltin(const ExternalReference& builtin);

View File

@ -478,7 +478,7 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference load_callback_property = ExternalReference load_callback_property =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallRuntime(load_callback_property, 5); __ TailCallRuntime(load_callback_property, 5, 1);
} }
@ -514,7 +514,7 @@ void StubCompiler::GenerateLoadInterceptor(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference load_ic_property = ExternalReference load_ic_property =
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
__ TailCallRuntime(load_ic_property, 5); __ TailCallRuntime(load_ic_property, 5, 1);
} }
@ -884,7 +884,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_callback_property = ExternalReference store_callback_property =
ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
__ TailCallRuntime(store_callback_property, 4); __ TailCallRuntime(store_callback_property, 4, 1);
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
@ -936,7 +936,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_ic_property = ExternalReference store_ic_property =
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
__ TailCallRuntime(store_ic_property, 3); __ TailCallRuntime(store_ic_property, 3, 1);
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);

View File

@ -517,7 +517,10 @@ const char* RuntimeStub::GetName() {
void RuntimeStub::Generate(MacroAssembler* masm) { void RuntimeStub::Generate(MacroAssembler* masm) {
masm->TailCallRuntime(ExternalReference(id_), num_arguments_); Runtime::Function* f = Runtime::FunctionForId(id_);
masm->TailCallRuntime(ExternalReference(f),
num_arguments_,
f->result_size);
} }

View File

@ -286,7 +286,7 @@ class CompareStub: public CodeStub {
class CEntryStub : public CodeStub { class CEntryStub : public CodeStub {
public: public:
CEntryStub() { } explicit CEntryStub(int result_size) : result_size_(result_size) { }
void Generate(MacroAssembler* masm) { GenerateBody(masm, false); } void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
@ -302,10 +302,14 @@ class CEntryStub : public CodeStub {
void GenerateThrowTOS(MacroAssembler* masm); void GenerateThrowTOS(MacroAssembler* masm);
void GenerateThrowUncatchable(MacroAssembler* masm, void GenerateThrowUncatchable(MacroAssembler* masm,
UncatchableExceptionType type); UncatchableExceptionType type);
private: private:
// Number of pointers/values returned.
int result_size_;
Major MajorKey() { return CEntry; } Major MajorKey() { return CEntry; }
int MinorKey() { return 0; } // Minor key must differ if different result_size_ values means different
// code is generated.
int MinorKey();
const char* GetName() { return "CEntryStub"; } const char* GetName() { return "CEntryStub"; }
}; };
@ -313,7 +317,7 @@ class CEntryStub : public CodeStub {
class CEntryDebugBreakStub : public CEntryStub { class CEntryDebugBreakStub : public CEntryStub {
public: public:
CEntryDebugBreakStub() { } CEntryDebugBreakStub() : CEntryStub(1) { }
void Generate(MacroAssembler* masm) { GenerateBody(masm, true); } void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }

View File

@ -1319,7 +1319,7 @@ bool Heap::CreateApiObjects() {
void Heap::CreateCEntryStub() { void Heap::CreateCEntryStub() {
CEntryStub stub; CEntryStub stub(1);
set_c_entry_code(*stub.GetCode()); set_c_entry_code(*stub.GetCode());
} }

View File

@ -6886,7 +6886,7 @@ void GenericBinaryOpStub::Generate(MacroAssembler* masm) {
__ j(above_equal, &string1); __ j(above_equal, &string1);
// First and second argument are strings. // First and second argument are strings.
__ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2); __ TailCallRuntime(ExternalReference(Runtime::kStringAdd), 2, 1);
// Only first argument is a string. // Only first argument is a string.
__ bind(&string1); __ bind(&string1);
@ -7175,7 +7175,7 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ pop(ebx); // Return address. __ pop(ebx); // Return address.
__ push(edx); __ push(edx);
__ push(ebx); __ push(ebx);
__ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); __ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1, 1);
} }
@ -7200,7 +7200,7 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
// Do the runtime call to allocate the arguments object. // Do the runtime call to allocate the arguments object.
__ bind(&runtime); __ bind(&runtime);
__ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); __ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3, 1);
} }
@ -7436,7 +7436,7 @@ void StackCheckStub::Generate(MacroAssembler* masm) {
__ push(eax); __ push(eax);
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1); __ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1, 1);
} }
@ -7468,6 +7468,13 @@ void CallFunctionStub::Generate(MacroAssembler* masm) {
} }
int CEntryStub::MinorKey() {
ASSERT(result_size_ <= 2);
// Result returned in eax, or eax+edx if result_size_ is 2.
return 0;
}
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// eax holds the exception. // eax holds the exception.

View File

@ -404,7 +404,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
__ push(eax); __ push(eax);
__ push(ecx); __ push(ecx);
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1);
// Check whether the elements is a pixel array. // Check whether the elements is a pixel array.
// eax: value // eax: value
@ -667,7 +667,7 @@ void CallIC::Generate(MacroAssembler* masm,
__ push(ebx); __ push(ebx);
// Call the entry. // Call the entry.
CEntryStub stub; CEntryStub stub(1);
__ mov(eax, Immediate(2)); __ mov(eax, Immediate(2));
__ mov(ebx, Immediate(f)); __ mov(ebx, Immediate(f));
__ CallStub(&stub); __ CallStub(&stub);
@ -799,7 +799,7 @@ void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ push(ebx); // return address __ push(ebx); // return address
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 2); __ TailCallRuntime(f, 2, 1);
} }
@ -927,7 +927,7 @@ void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ push(ebx); // return address __ push(ebx); // return address
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 2); __ TailCallRuntime(f, 2, 1);
} }
@ -967,7 +967,7 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime( __ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
} }
@ -987,7 +987,7 @@ void StoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ push(ebx); __ push(ebx);
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 3); __ TailCallRuntime(f, 3, 1);
} }
@ -1010,7 +1010,7 @@ void KeyedStoreIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
__ push(ecx); __ push(ecx);
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(f, 3); __ TailCallRuntime(f, 3, 1);
} }
@ -1032,7 +1032,7 @@ void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime( __ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
} }
#undef __ #undef __

View File

@ -896,7 +896,8 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
void MacroAssembler::TailCallRuntime(const ExternalReference& ext, void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
int num_arguments) { int num_arguments,
int result_size) {
// TODO(1236192): Most runtime routines don't need the number of // TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we // arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code // should remove this need and make the runtime routine entry code
@ -909,7 +910,7 @@ void MacroAssembler::TailCallRuntime(const ExternalReference& ext,
void MacroAssembler::JumpToBuiltin(const ExternalReference& ext) { void MacroAssembler::JumpToBuiltin(const ExternalReference& ext) {
// Set the entry point and jump to the C entry runtime stub. // Set the entry point and jump to the C entry runtime stub.
mov(ebx, Immediate(ext)); mov(ebx, Immediate(ext));
CEntryStub ces; CEntryStub ces(1);
jmp(ces.GetCode(), RelocInfo::CODE_TARGET); jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
} }

View File

@ -256,7 +256,9 @@ class MacroAssembler: public Assembler {
// Tail call of a runtime routine (jump). // Tail call of a runtime routine (jump).
// Like JumpToBuiltin, but also takes care of passing the number // Like JumpToBuiltin, but also takes care of passing the number
// of arguments. // of arguments.
void TailCallRuntime(const ExternalReference& ext, int num_arguments); void TailCallRuntime(const ExternalReference& ext,
int num_arguments,
int result_size);
// Jump to the builtin routine. // Jump to the builtin routine.
void JumpToBuiltin(const ExternalReference& ext); void JumpToBuiltin(const ExternalReference& ext);

View File

@ -302,7 +302,7 @@ static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
__ mov(eax, Immediate(5)); __ mov(eax, Immediate(5));
__ mov(ebx, Immediate(ref)); __ mov(ebx, Immediate(ref));
CEntryStub stub; CEntryStub stub(1);
__ CallStub(&stub); __ CallStub(&stub);
} }
@ -467,7 +467,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
ExternalReference ref = ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallRuntime(ref, 5); __ TailCallRuntime(ref, 5, 1);
__ bind(&cleanup); __ bind(&cleanup);
__ pop(scratch1); __ pop(scratch1);
@ -489,7 +489,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
ExternalReference ref = ExternalReference( ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
__ TailCallRuntime(ref, 5); __ TailCallRuntime(ref, 5, 1);
} }
private: private:
@ -593,7 +593,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
__ mov(eax, Immediate(5)); __ mov(eax, Immediate(5));
__ mov(ebx, Immediate(ref)); __ mov(ebx, Immediate(ref));
CEntryStub stub; CEntryStub stub(1);
__ CallStub(&stub); __ CallStub(&stub);
__ LeaveInternalFrame(); __ LeaveInternalFrame();
@ -789,7 +789,7 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference load_callback_property = ExternalReference load_callback_property =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallRuntime(load_callback_property, 5); __ TailCallRuntime(load_callback_property, 5, 1);
} }
@ -1237,7 +1237,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_callback_property = ExternalReference store_callback_property =
ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
__ TailCallRuntime(store_callback_property, 4); __ TailCallRuntime(store_callback_property, 4, 1);
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
@ -1290,7 +1290,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_ic_property = ExternalReference store_ic_property =
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
__ TailCallRuntime(store_ic_property, 3); __ TailCallRuntime(store_ic_property, 3, 1);
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);

View File

@ -4556,22 +4556,25 @@ static Object* Runtime_LookupContext(Arguments args) {
} }
// A mechanism to return pairs of Object*'s. This is somewhat // A mechanism to return a pair of Object pointers in registers (if possible).
// compiler-dependent as it assumes that a 64-bit value (a long long) // How this is achieved is calling convention-dependent.
// is returned via two registers (edx:eax on ia32). Both the ia32 and // All currently supported x86 compiles uses calling conventions that are cdecl
// arm platform support this; it is mostly an issue of "coaxing" the // variants where a 64-bit value is returned in two 32-bit registers
// compiler to do the right thing. // (edx:eax on ia32, r1:r0 on ARM).
// // In AMD-64 calling convention a struct of two pointers is returned in rdx:rax.
// TODO(1236026): This is a non-portable hack that should be removed. // In Win64 calling convention, a struct of two pointers is returned in space passed
// as a hidden first parameter.
#ifdef V8_HOST_ARCH_64_BIT #ifdef V8_HOST_ARCH_64_BIT
// Tested with GCC, not with MSVC.
struct ObjectPair { struct ObjectPair {
Object* x; Object* x;
Object* y; Object* y;
}; };
static inline ObjectPair MakePair(Object* x, Object* y) { static inline ObjectPair MakePair(Object* x, Object* y) {
ObjectPair result = {x, y}; ObjectPair result = {x, y};
return result; // Pointers x and y returned in rax and rdx, in AMD-x64-abi. // Pointers x and y returned in rax and rdx, in AMD-x64-abi.
// In Win64 they are assigned to a hidden first argument.
return result;
} }
#else #else
typedef uint64_t ObjectPair; typedef uint64_t ObjectPair;
@ -4582,8 +4585,6 @@ static inline ObjectPair MakePair(Object* x, Object* y) {
#endif #endif
static inline Object* Unhole(Object* x, PropertyAttributes attributes) { static inline Object* Unhole(Object* x, PropertyAttributes attributes) {
ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0); ASSERT(!x->IsTheHole() || (attributes & READ_ONLY) != 0);
USE(attributes); USE(attributes);
@ -7619,7 +7620,7 @@ static Object* Runtime_ListNatives(Arguments args) {
HandleScope scope; HandleScope scope;
Handle<JSArray> result = Factory::NewJSArray(0); Handle<JSArray> result = Factory::NewJSArray(0);
int index = 0; int index = 0;
#define ADD_ENTRY(Name, argc) \ #define ADD_ENTRY(Name, argc, ressize) \
{ \ { \
HandleScope inner; \ HandleScope inner; \
Handle<String> name = \ Handle<String> name = \
@ -7655,13 +7656,13 @@ static Object* Runtime_IS_VAR(Arguments args) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Implementation of Runtime // Implementation of Runtime
#define F(name, nargs) \ #define F(name, nargs, ressize) \
{ #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \ { #name, "RuntimeStub_" #name, FUNCTION_ADDR(Runtime_##name), nargs, \
static_cast<int>(Runtime::k##name) }, static_cast<int>(Runtime::k##name), ressize },
static Runtime::Function Runtime_functions[] = { static Runtime::Function Runtime_functions[] = {
RUNTIME_FUNCTION_LIST(F) RUNTIME_FUNCTION_LIST(F)
{ NULL, NULL, NULL, 0, -1 } { NULL, NULL, NULL, 0, -1, 0 }
}; };
#undef F #undef F

View File

@ -43,269 +43,269 @@ namespace internal {
// this problem. Please avoid large recursive macros whenever possible. // this problem. Please avoid large recursive macros whenever possible.
#define RUNTIME_FUNCTION_LIST_ALWAYS_1(F) \ #define RUNTIME_FUNCTION_LIST_ALWAYS_1(F) \
/* Property access */ \ /* Property access */ \
F(GetProperty, 2) \ F(GetProperty, 2, 1) \
F(KeyedGetProperty, 2) \ F(KeyedGetProperty, 2, 1) \
F(DeleteProperty, 2) \ F(DeleteProperty, 2, 1) \
F(HasLocalProperty, 2) \ F(HasLocalProperty, 2, 1) \
F(HasProperty, 2) \ F(HasProperty, 2, 1) \
F(HasElement, 2) \ F(HasElement, 2, 1) \
F(IsPropertyEnumerable, 2) \ F(IsPropertyEnumerable, 2, 1) \
F(GetPropertyNames, 1) \ F(GetPropertyNames, 1, 1) \
F(GetPropertyNamesFast, 1) \ F(GetPropertyNamesFast, 1, 1) \
F(GetArgumentsProperty, 1) \ F(GetArgumentsProperty, 1, 1) \
F(ToFastProperties, 1) \ F(ToFastProperties, 1, 1) \
F(ToSlowProperties, 1) \ F(ToSlowProperties, 1, 1) \
\ \
F(IsInPrototypeChain, 2) \ F(IsInPrototypeChain, 2, 1) \
F(SetHiddenPrototype, 2) \ F(SetHiddenPrototype, 2, 1) \
\ \
F(IsConstructCall, 0) \ F(IsConstructCall, 0, 1) \
\ \
/* Utilities */ \ /* Utilities */ \
F(GetCalledFunction, 0) \ F(GetCalledFunction, 0, 1) \
F(GetFunctionDelegate, 1) \ F(GetFunctionDelegate, 1, 1) \
F(GetConstructorDelegate, 1) \ F(GetConstructorDelegate, 1, 1) \
F(NewArguments, 1) \ F(NewArguments, 1, 1) \
F(NewArgumentsFast, 3) \ F(NewArgumentsFast, 3, 1) \
F(LazyCompile, 1) \ F(LazyCompile, 1, 1) \
F(SetNewFunctionAttributes, 1) \ F(SetNewFunctionAttributes, 1, 1) \
\ \
/* Array join support */ \ /* Array join support */ \
F(PushIfAbsent, 2) \ F(PushIfAbsent, 2, 1) \
F(ArrayConcat, 1) \ F(ArrayConcat, 1, 1) \
\ \
/* Conversions */ \ /* Conversions */ \
F(ToBool, 1) \ F(ToBool, 1, 1) \
F(Typeof, 1) \ F(Typeof, 1, 1) \
\ \
F(StringToNumber, 1) \ F(StringToNumber, 1, 1) \
F(StringFromCharCodeArray, 1) \ F(StringFromCharCodeArray, 1, 1) \
F(StringParseInt, 2) \ F(StringParseInt, 2, 1) \
F(StringParseFloat, 1) \ F(StringParseFloat, 1, 1) \
F(StringToLowerCase, 1) \ F(StringToLowerCase, 1, 1) \
F(StringToUpperCase, 1) \ F(StringToUpperCase, 1, 1) \
F(CharFromCode, 1) \ F(CharFromCode, 1, 1) \
F(URIEscape, 1) \ F(URIEscape, 1, 1) \
F(URIUnescape, 1) \ F(URIUnescape, 1, 1) \
\ \
F(NumberToString, 1) \ F(NumberToString, 1, 1) \
F(NumberToInteger, 1) \ F(NumberToInteger, 1, 1) \
F(NumberToJSUint32, 1) \ F(NumberToJSUint32, 1, 1) \
F(NumberToJSInt32, 1) \ F(NumberToJSInt32, 1, 1) \
F(NumberToSmi, 1) \ F(NumberToSmi, 1, 1) \
\ \
/* Arithmetic operations */ \ /* Arithmetic operations */ \
F(NumberAdd, 2) \ F(NumberAdd, 2, 1) \
F(NumberSub, 2) \ F(NumberSub, 2, 1) \
F(NumberMul, 2) \ F(NumberMul, 2, 1) \
F(NumberDiv, 2) \ F(NumberDiv, 2, 1) \
F(NumberMod, 2) \ F(NumberMod, 2, 1) \
F(NumberUnaryMinus, 1) \ F(NumberUnaryMinus, 1, 1) \
\ \
F(StringAdd, 2) \ F(StringAdd, 2, 1) \
F(StringBuilderConcat, 2) \ F(StringBuilderConcat, 2, 1) \
\ \
/* Bit operations */ \ /* Bit operations */ \
F(NumberOr, 2) \ F(NumberOr, 2, 1) \
F(NumberAnd, 2) \ F(NumberAnd, 2, 1) \
F(NumberXor, 2) \ F(NumberXor, 2, 1) \
F(NumberNot, 1) \ F(NumberNot, 1, 1) \
\ \
F(NumberShl, 2) \ F(NumberShl, 2, 1) \
F(NumberShr, 2) \ F(NumberShr, 2, 1) \
F(NumberSar, 2) \ F(NumberSar, 2, 1) \
\ \
/* Comparisons */ \ /* Comparisons */ \
F(NumberEquals, 2) \ F(NumberEquals, 2, 1) \
F(StringEquals, 2) \ F(StringEquals, 2, 1) \
\ \
F(NumberCompare, 3) \ F(NumberCompare, 3, 1) \
F(SmiLexicographicCompare, 2) \ F(SmiLexicographicCompare, 2, 1) \
F(StringCompare, 2) \ F(StringCompare, 2, 1) \
\ \
/* Math */ \ /* Math */ \
F(Math_abs, 1) \ F(Math_abs, 1, 1) \
F(Math_acos, 1) \ F(Math_acos, 1, 1) \
F(Math_asin, 1) \ F(Math_asin, 1, 1) \
F(Math_atan, 1) \ F(Math_atan, 1, 1) \
F(Math_atan2, 2) \ F(Math_atan2, 2, 1) \
F(Math_ceil, 1) \ F(Math_ceil, 1, 1) \
F(Math_cos, 1) \ F(Math_cos, 1, 1) \
F(Math_exp, 1) \ F(Math_exp, 1, 1) \
F(Math_floor, 1) \ F(Math_floor, 1, 1) \
F(Math_log, 1) \ F(Math_log, 1, 1) \
F(Math_pow, 2) \ F(Math_pow, 2, 1) \
F(Math_round, 1) \ F(Math_round, 1, 1) \
F(Math_sin, 1) \ F(Math_sin, 1, 1) \
F(Math_sqrt, 1) \ F(Math_sqrt, 1, 1) \
F(Math_tan, 1) \ F(Math_tan, 1, 1) \
\ \
/* Regular expressions */ \ /* Regular expressions */ \
F(RegExpCompile, 3) \ F(RegExpCompile, 3, 1) \
F(RegExpExec, 4) \ F(RegExpExec, 4, 1) \
\ \
/* Strings */ \ /* Strings */ \
F(StringCharCodeAt, 2) \ F(StringCharCodeAt, 2, 1) \
F(StringIndexOf, 3) \ F(StringIndexOf, 3, 1) \
F(StringLastIndexOf, 3) \ F(StringLastIndexOf, 3, 1) \
F(StringLocaleCompare, 2) \ F(StringLocaleCompare, 2, 1) \
F(StringSlice, 3) \ F(StringSlice, 3, 1) \
F(StringReplaceRegExpWithString, 4) \ F(StringReplaceRegExpWithString, 4, 1) \
F(StringMatch, 3) \ F(StringMatch, 3, 1) \
\ \
/* Numbers */ \ /* Numbers */ \
F(NumberToRadixString, 2) \ F(NumberToRadixString, 2, 1) \
F(NumberToFixed, 2) \ F(NumberToFixed, 2, 1) \
F(NumberToExponential, 2) \ F(NumberToExponential, 2, 1) \
F(NumberToPrecision, 2) F(NumberToPrecision, 2, 1)
#define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \ #define RUNTIME_FUNCTION_LIST_ALWAYS_2(F) \
/* Reflection */ \ /* Reflection */ \
F(FunctionSetInstanceClassName, 2) \ F(FunctionSetInstanceClassName, 2, 1) \
F(FunctionSetLength, 2) \ F(FunctionSetLength, 2, 1) \
F(FunctionSetPrototype, 2) \ F(FunctionSetPrototype, 2, 1) \
F(FunctionGetName, 1) \ F(FunctionGetName, 1, 1) \
F(FunctionSetName, 2) \ F(FunctionSetName, 2, 1) \
F(FunctionGetSourceCode, 1) \ F(FunctionGetSourceCode, 1, 1) \
F(FunctionGetScript, 1) \ F(FunctionGetScript, 1, 1) \
F(FunctionGetScriptSourcePosition, 1) \ F(FunctionGetScriptSourcePosition, 1, 1) \
F(FunctionGetPositionForOffset, 2) \ F(FunctionGetPositionForOffset, 2, 1) \
F(FunctionIsAPIFunction, 1) \ F(FunctionIsAPIFunction, 1, 1) \
F(GetScript, 1) \ F(GetScript, 1, 1) \
F(CollectStackTrace, 2) \ F(CollectStackTrace, 2, 1) \
\ \
F(ClassOf, 1) \ F(ClassOf, 1, 1) \
F(SetCode, 2) \ F(SetCode, 2, 1) \
\ \
F(CreateApiFunction, 1) \ F(CreateApiFunction, 1, 1) \
F(IsTemplate, 1) \ F(IsTemplate, 1, 1) \
F(GetTemplateField, 2) \ F(GetTemplateField, 2, 1) \
F(DisableAccessChecks, 1) \ F(DisableAccessChecks, 1, 1) \
F(EnableAccessChecks, 1) \ F(EnableAccessChecks, 1, 1) \
\ \
/* Dates */ \ /* Dates */ \
F(DateCurrentTime, 0) \ F(DateCurrentTime, 0, 1) \
F(DateParseString, 2) \ F(DateParseString, 2, 1) \
F(DateLocalTimezone, 1) \ F(DateLocalTimezone, 1, 1) \
F(DateLocalTimeOffset, 0) \ F(DateLocalTimeOffset, 0, 1) \
F(DateDaylightSavingsOffset, 1) \ F(DateDaylightSavingsOffset, 1, 1) \
\ \
/* Numbers */ \ /* Numbers */ \
F(NumberIsFinite, 1) \ F(NumberIsFinite, 1, 1) \
\ \
/* Globals */ \ /* Globals */ \
F(CompileString, 2) \ F(CompileString, 2, 1) \
F(GlobalPrint, 1) \ F(GlobalPrint, 1, 1) \
\ \
/* Eval */ \ /* Eval */ \
F(GlobalReceiver, 1) \ F(GlobalReceiver, 1, 1) \
F(ResolvePossiblyDirectEval, 2) \ F(ResolvePossiblyDirectEval, 2, 1) \
\ \
F(SetProperty, -1 /* 3 or 4 */) \ F(SetProperty, -1 /* 3 or 4 */, 1) \
F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */) \ F(IgnoreAttributesAndSetProperty, -1 /* 3 or 4 */, 1) \
\ \
/* Arrays */ \ /* Arrays */ \
F(RemoveArrayHoles, 2) \ F(RemoveArrayHoles, 2, 1) \
F(GetArrayKeys, 2) \ F(GetArrayKeys, 2, 1) \
F(MoveArrayContents, 2) \ F(MoveArrayContents, 2, 1) \
F(EstimateNumberOfElements, 1) \ F(EstimateNumberOfElements, 1, 1) \
\ \
/* Getters and Setters */ \ /* Getters and Setters */ \
F(DefineAccessor, -1 /* 4 or 5 */) \ F(DefineAccessor, -1 /* 4 or 5 */, 1) \
F(LookupAccessor, 3) \ F(LookupAccessor, 3, 1) \
\ \
/* Literals */ \ /* Literals */ \
F(MaterializeRegExpLiteral, 4)\ F(MaterializeRegExpLiteral, 4, 1)\
F(CreateArrayLiteralBoilerplate, 3) \ F(CreateArrayLiteralBoilerplate, 3, 1) \
F(CreateObjectLiteralBoilerplate, 3) \ F(CreateObjectLiteralBoilerplate, 3, 1) \
F(CloneLiteralBoilerplate, 1) \ F(CloneLiteralBoilerplate, 1, 1) \
F(CloneShallowLiteralBoilerplate, 1) \ F(CloneShallowLiteralBoilerplate, 1, 1) \
\ \
/* Catch context extension objects */ \ /* Catch context extension objects */ \
F(CreateCatchExtensionObject, 2) \ F(CreateCatchExtensionObject, 2, 1) \
\ \
/* Statements */ \ /* Statements */ \
F(NewClosure, 2) \ F(NewClosure, 2, 1) \
F(NewObject, 1) \ F(NewObject, 1, 1) \
F(Throw, 1) \ F(Throw, 1, 1) \
F(ReThrow, 1) \ F(ReThrow, 1, 1) \
F(ThrowReferenceError, 1) \ F(ThrowReferenceError, 1, 1) \
F(StackGuard, 1) \ F(StackGuard, 1, 1) \
\ \
/* Contexts */ \ /* Contexts */ \
F(NewContext, 1) \ F(NewContext, 1, 1) \
F(PushContext, 1) \ F(PushContext, 1, 1) \
F(PushCatchContext, 1) \ F(PushCatchContext, 1, 1) \
F(LookupContext, 2) \ F(LookupContext, 2, 1) \
F(LoadContextSlot, 2) \ F(LoadContextSlot, 2, 2) \
F(LoadContextSlotNoReferenceError, 2) \ F(LoadContextSlotNoReferenceError, 2, 2) \
F(StoreContextSlot, 3) \ F(StoreContextSlot, 3, 1) \
\ \
/* Declarations and initialization */ \ /* Declarations and initialization */ \
F(DeclareGlobals, 3) \ F(DeclareGlobals, 3, 1) \
F(DeclareContextSlot, 4) \ F(DeclareContextSlot, 4, 1) \
F(InitializeVarGlobal, -1 /* 1 or 2 */) \ F(InitializeVarGlobal, -1 /* 1 or 2 */, 1) \
F(InitializeConstGlobal, 2) \ F(InitializeConstGlobal, 2, 1) \
F(InitializeConstContextSlot, 3) \ F(InitializeConstContextSlot, 3, 1) \
F(OptimizeObjectForAddingMultipleProperties, 2) \ F(OptimizeObjectForAddingMultipleProperties, 2, 1) \
F(TransformToFastProperties, 1) \ F(TransformToFastProperties, 1, 1) \
\ \
/* Debugging */ \ /* Debugging */ \
F(DebugPrint, 1) \ F(DebugPrint, 1, 1) \
F(DebugTrace, 0) \ F(DebugTrace, 0, 1) \
F(TraceEnter, 0) \ F(TraceEnter, 0, 1) \
F(TraceExit, 1) \ F(TraceExit, 1, 1) \
F(Abort, 2) \ F(Abort, 2, 1) \
/* Logging */ \ /* Logging */ \
F(Log, 2) \ F(Log, 2, 1) \
\ \
/* Pseudo functions - handled as macros by parser */ \ /* Pseudo functions - handled as macros by parser */ \
F(IS_VAR, 1) F(IS_VAR, 1, 1)
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F) \ #define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F) \
/* Debugger support*/ \ /* Debugger support*/ \
F(DebugBreak, 0) \ F(DebugBreak, 0, 1) \
F(SetDebugEventListener, 2) \ F(SetDebugEventListener, 2, 1) \
F(Break, 0) \ F(Break, 0, 1) \
F(DebugGetPropertyDetails, 2) \ F(DebugGetPropertyDetails, 2, 1) \
F(DebugGetProperty, 2) \ F(DebugGetProperty, 2, 1) \
F(DebugLocalPropertyNames, 1) \ F(DebugLocalPropertyNames, 1, 1) \
F(DebugLocalElementNames, 1) \ F(DebugLocalElementNames, 1, 1) \
F(DebugPropertyTypeFromDetails, 1) \ F(DebugPropertyTypeFromDetails, 1, 1) \
F(DebugPropertyAttributesFromDetails, 1) \ F(DebugPropertyAttributesFromDetails, 1, 1) \
F(DebugPropertyIndexFromDetails, 1) \ F(DebugPropertyIndexFromDetails, 1, 1) \
F(DebugInterceptorInfo, 1) \ F(DebugInterceptorInfo, 1, 1) \
F(DebugNamedInterceptorPropertyNames, 1) \ F(DebugNamedInterceptorPropertyNames, 1, 1) \
F(DebugIndexedInterceptorElementNames, 1) \ F(DebugIndexedInterceptorElementNames, 1, 1) \
F(DebugNamedInterceptorPropertyValue, 2) \ F(DebugNamedInterceptorPropertyValue, 2, 1) \
F(DebugIndexedInterceptorElementValue, 2) \ F(DebugIndexedInterceptorElementValue, 2, 1) \
F(CheckExecutionState, 1) \ F(CheckExecutionState, 1, 1) \
F(GetFrameCount, 1) \ F(GetFrameCount, 1, 1) \
F(GetFrameDetails, 2) \ F(GetFrameDetails, 2, 1) \
F(GetScopeCount, 2) \ F(GetScopeCount, 2, 1) \
F(GetScopeDetails, 3) \ F(GetScopeDetails, 3, 1) \
F(DebugPrintScopes, 0) \ F(DebugPrintScopes, 0, 1) \
F(GetCFrames, 1) \ F(GetCFrames, 1, 1) \
F(GetThreadCount, 1) \ F(GetThreadCount, 1, 1) \
F(GetThreadDetails, 2) \ F(GetThreadDetails, 2, 1) \
F(GetBreakLocations, 1) \ F(GetBreakLocations, 1, 1) \
F(SetFunctionBreakPoint, 3) \ F(SetFunctionBreakPoint, 3, 1) \
F(SetScriptBreakPoint, 3) \ F(SetScriptBreakPoint, 3, 1) \
F(ClearBreakPoint, 1) \ F(ClearBreakPoint, 1, 1) \
F(ChangeBreakOnException, 2) \ F(ChangeBreakOnException, 2, 1) \
F(PrepareStep, 3) \ F(PrepareStep, 3, 1) \
F(ClearStepping, 0) \ F(ClearStepping, 0, 1) \
F(DebugEvaluate, 4) \ F(DebugEvaluate, 4, 1) \
F(DebugEvaluateGlobal, 3) \ F(DebugEvaluateGlobal, 3, 1) \
F(DebugGetLoadedScripts, 0) \ F(DebugGetLoadedScripts, 0, 1) \
F(DebugReferencedBy, 3) \ F(DebugReferencedBy, 3, 1) \
F(DebugConstructedBy, 2) \ F(DebugConstructedBy, 2, 1) \
F(DebugGetPrototype, 1) \ F(DebugGetPrototype, 1, 1) \
F(SystemBreak, 0) \ F(SystemBreak, 0, 1) \
F(DebugDisassembleFunction, 1) \ F(DebugDisassembleFunction, 1, 1) \
F(DebugDisassembleConstructor, 1) \ F(DebugDisassembleConstructor, 1, 1) \
F(FunctionGetInferredName, 1) F(FunctionGetInferredName, 1, 1)
#else #else
#define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F) #define RUNTIME_FUNCTION_LIST_DEBUGGER_SUPPORT(F)
#endif #endif
@ -313,7 +313,7 @@ namespace internal {
#ifdef DEBUG #ifdef DEBUG
#define RUNTIME_FUNCTION_LIST_DEBUG(F) \ #define RUNTIME_FUNCTION_LIST_DEBUG(F) \
/* Testing */ \ /* Testing */ \
F(ListNatives, 0) F(ListNatives, 0, 1)
#else #else
#define RUNTIME_FUNCTION_LIST_DEBUG(F) #define RUNTIME_FUNCTION_LIST_DEBUG(F)
#endif #endif
@ -336,7 +336,7 @@ namespace internal {
class Runtime : public AllStatic { class Runtime : public AllStatic {
public: public:
enum FunctionId { enum FunctionId {
#define F(name, nargs) k##name, #define F(name, nargs, ressize) k##name,
RUNTIME_FUNCTION_LIST(F) RUNTIME_FUNCTION_LIST(F)
kNofFunctions kNofFunctions
#undef F #undef F
@ -357,6 +357,9 @@ class Runtime : public AllStatic {
// arguments. // arguments.
int nargs; int nargs;
int stub_id; int stub_id;
// Size of result, if complex (larger than a single pointer),
// otherwise zero.
int result_size;
}; };
// Get the runtime function with the given function id. // Get the runtime function with the given function id.

View File

@ -541,7 +541,7 @@ void ExternalReferenceTable::PopulateTable() {
#undef DEF_ENTRY_A #undef DEF_ENTRY_A
// Runtime functions // Runtime functions
#define RUNTIME_ENTRY(name, nargs) \ #define RUNTIME_ENTRY(name, nargs, ressize) \
{ RUNTIME_FUNCTION, \ { RUNTIME_FUNCTION, \
Runtime::k##name, \ Runtime::k##name, \
"Runtime::" #name }, "Runtime::" #name },

View File

@ -44,7 +44,7 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm, CFunctionId id) {
// rax, but JumpToBuiltin expects rax to contain the number of // rax, but JumpToBuiltin expects rax to contain the number of
// arguments including the receiver. // arguments including the receiver.
__ incq(rax); __ incq(rax);
__ JumpToBuiltin(ExternalReference(id)); __ JumpToBuiltin(ExternalReference(id), 1);
} }

View File

@ -6829,7 +6829,8 @@ void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) {
// Do the runtime call to allocate the arguments object. // Do the runtime call to allocate the arguments object.
__ bind(&runtime); __ bind(&runtime);
__ TailCallRuntime(ExternalReference(Runtime::kNewArgumentsFast), 3); Runtime::Function* f = Runtime::FunctionForId(Runtime::kNewArgumentsFast);
__ TailCallRuntime(ExternalReference(f), 3, f->result_size);
} }
@ -6891,7 +6892,9 @@ void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
__ pop(rbx); // Return address. __ pop(rbx); // Return address.
__ push(rdx); __ push(rdx);
__ push(rbx); __ push(rbx);
__ TailCallRuntime(ExternalReference(Runtime::kGetArgumentsProperty), 1); Runtime::Function* f =
Runtime::FunctionForId(Runtime::kGetArgumentsProperty);
__ TailCallRuntime(ExternalReference(f), 1, f->result_size);
} }
@ -6915,6 +6918,23 @@ void ArgumentsAccessStub::GenerateReadLength(MacroAssembler* masm) {
} }
int CEntryStub::MinorKey() {
ASSERT(result_size_ <= 2);
#ifdef _WIN64
// Simple results returned in rax (using default code).
// Complex results must be written to address passed as first argument.
// Use even numbers for minor keys, reserving the odd numbers for
// CEntryDebugBreakStub.
return (result_size_ < 2) ? 0 : result_size_ * 2;
#else
// Single results returned in rax (both AMD64 and Win64 calling conventions)
// and a struct of two pointers in rax+rdx (AMD64 calling convention only)
// by default.
return 0;
#endif
}
void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) { void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
// Check that stack should contain next handler, frame pointer, state and // Check that stack should contain next handler, frame pointer, state and
// return address in that order. // return address in that order.
@ -6986,8 +7006,18 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
// Store Arguments object on stack, below the 4 WIN64 ABI parameter slots. // Store Arguments object on stack, below the 4 WIN64 ABI parameter slots.
__ movq(Operand(rsp, 4 * kPointerSize), r14); // argc. __ movq(Operand(rsp, 4 * kPointerSize), r14); // argc.
__ movq(Operand(rsp, 5 * kPointerSize), r15); // argv. __ movq(Operand(rsp, 5 * kPointerSize), r15); // argv.
// Pass a pointer to the Arguments object as the first argument. if (result_size_ < 2) {
__ lea(rcx, Operand(rsp, 4 * kPointerSize)); // Pass a pointer to the Arguments object as the first argument.
// Return result in single register (rax).
__ lea(rcx, Operand(rsp, 4 * kPointerSize));
} else {
ASSERT_EQ(2, result_size_);
// Pass a pointer to the result location as the first argument.
__ lea(rcx, Operand(rsp, 6 * kPointerSize));
// Pass a pointer to the Arguments object as the second argument.
__ lea(rdx, Operand(rsp, 4 * kPointerSize));
}
#else // ! defined(_WIN64) #else // ! defined(_WIN64)
// GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9. // GCC passes arguments in rdi, rsi, rdx, rcx, r8, r9.
__ movq(rdi, r14); // argc. __ movq(rdi, r14); // argc.
@ -7010,7 +7040,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
__ j(zero, &failure_returned); __ j(zero, &failure_returned);
// Exit the JavaScript to C++ exit frame. // Exit the JavaScript to C++ exit frame.
__ LeaveExitFrame(frame_type); __ LeaveExitFrame(frame_type, result_size_);
__ ret(0); __ ret(0);
// Handling of failure. // Handling of failure.
@ -7146,7 +7176,7 @@ void CEntryStub::GenerateBody(MacroAssembler* masm, bool is_debug_break) {
StackFrame::EXIT; StackFrame::EXIT;
// Enter the exit frame that transitions from JavaScript to C++. // Enter the exit frame that transitions from JavaScript to C++.
__ EnterExitFrame(frame_type); __ EnterExitFrame(frame_type, result_size_);
// rax: Holds the context at this point, but should not be used. // rax: Holds the context at this point, but should not be used.
// On entry to code generated by GenerateCore, it must hold // On entry to code generated by GenerateCore, it must hold
@ -7333,7 +7363,8 @@ void StackCheckStub::Generate(MacroAssembler* masm) {
__ push(rax); __ push(rax);
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kStackGuard), 1); Runtime::Function* f = Runtime::FunctionForId(Runtime::kStackGuard);
__ TailCallRuntime(ExternalReference(f), 1, f->result_size);
} }

View File

@ -236,7 +236,7 @@ void KeyedLoadIC::Generate(MacroAssembler* masm,
__ push(rbx); // return address __ push(rbx); // return address
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 2); __ TailCallRuntime(f, 2, 1);
} }
@ -373,7 +373,7 @@ void KeyedStoreIC::Generate(MacroAssembler* masm, ExternalReference const& f) {
__ push(rcx); // return address __ push(rcx); // return address
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(f, 3); __ TailCallRuntime(f, 3, 1);
} }
@ -394,7 +394,7 @@ void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime( __ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
} }
@ -460,7 +460,7 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
__ push(rax); __ push(rax);
__ push(rcx); __ push(rcx);
// Do tail-call to runtime routine. // Do tail-call to runtime routine.
__ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3); __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1);
// Extra capacity case: Check if there is extra capacity to // Extra capacity case: Check if there is extra capacity to
@ -532,7 +532,7 @@ void CallIC::Generate(MacroAssembler* masm,
__ push(rbx); __ push(rbx);
// Call the entry. // Call the entry.
CEntryStub stub; CEntryStub stub(1);
__ movq(rax, Immediate(2)); __ movq(rax, Immediate(2));
__ movq(rbx, f); __ movq(rbx, f);
__ CallStub(&stub); __ CallStub(&stub);
@ -763,7 +763,7 @@ void LoadIC::Generate(MacroAssembler* masm, ExternalReference const& f) {
__ push(rbx); // return address __ push(rbx); // return address
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 2); __ TailCallRuntime(f, 2, 1);
} }
@ -940,7 +940,7 @@ void StoreIC::Generate(MacroAssembler* masm, ExternalReference const& f) {
__ push(rbx); // return address __ push(rbx); // return address
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime(f, 3); __ TailCallRuntime(f, 3, 1);
} }
void StoreIC::GenerateExtendStorage(MacroAssembler* masm) { void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
@ -959,7 +959,7 @@ void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
// Perform tail call to the entry. // Perform tail call to the entry.
__ TailCallRuntime( __ TailCallRuntime(
ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3); ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
} }
void StoreIC::GenerateMegamorphic(MacroAssembler* masm) { void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {

View File

@ -318,7 +318,8 @@ void MacroAssembler::CallRuntime(Runtime::Function* f, int num_arguments) {
void MacroAssembler::TailCallRuntime(ExternalReference const& ext, void MacroAssembler::TailCallRuntime(ExternalReference const& ext,
int num_arguments) { int num_arguments,
int result_size) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rsp[0] : return address // -- rsp[0] : return address
// -- rsp[8] : argument num_arguments - 1 // -- rsp[8] : argument num_arguments - 1
@ -331,14 +332,15 @@ void MacroAssembler::TailCallRuntime(ExternalReference const& ext,
// should remove this need and make the runtime routine entry code // should remove this need and make the runtime routine entry code
// smarter. // smarter.
movq(rax, Immediate(num_arguments)); movq(rax, Immediate(num_arguments));
JumpToBuiltin(ext); JumpToBuiltin(ext, result_size);
} }
void MacroAssembler::JumpToBuiltin(const ExternalReference& ext) { void MacroAssembler::JumpToBuiltin(const ExternalReference& ext,
int result_size) {
// Set the entry point and jump to the C entry runtime stub. // Set the entry point and jump to the C entry runtime stub.
movq(rbx, ext); movq(rbx, ext);
CEntryStub ces; CEntryStub ces(result_size);
movq(kScratchRegister, ces.GetCode(), RelocInfo::CODE_TARGET); movq(kScratchRegister, ces.GetCode(), RelocInfo::CODE_TARGET);
jmp(kScratchRegister); jmp(kScratchRegister);
} }
@ -971,7 +973,7 @@ void MacroAssembler::LeaveFrame(StackFrame::Type type) {
void MacroAssembler::EnterExitFrame(StackFrame::Type type) { void MacroAssembler::EnterExitFrame(StackFrame::Type type, int result_size) {
ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG); ASSERT(type == StackFrame::EXIT || type == StackFrame::EXIT_DEBUG);
// Setup the frame structure on the stack. // Setup the frame structure on the stack.
@ -1016,6 +1018,21 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
} }
#endif #endif
#ifdef _WIN64
// Reserve space on stack for result and argument structures, if necessary.
int result_stack_space = (result_size < 2) ? 0 : result_size * kPointerSize;
// Reserve space for the Arguments object. The Windows 64-bit ABI
// requires us to pass this structure as a pointer to its location on
// the stack. The structure contains 2 values.
int argument_stack_space = 2 * kPointerSize;
// We also need backing space for 4 parameters, even though
// we only pass one or two parameter, and it is in a register.
int argument_mirror_space = 4 * kPointerSize;
int total_stack_space =
argument_mirror_space + argument_stack_space + result_stack_space;
subq(rsp, Immediate(total_stack_space));
#endif
// Get the required frame alignment for the OS. // Get the required frame alignment for the OS.
static const int kFrameAlignment = OS::ActivationFrameAlignment(); static const int kFrameAlignment = OS::ActivationFrameAlignment();
if (kFrameAlignment > 0) { if (kFrameAlignment > 0) {
@ -1024,30 +1041,19 @@ void MacroAssembler::EnterExitFrame(StackFrame::Type type) {
and_(rsp, kScratchRegister); and_(rsp, kScratchRegister);
} }
#ifdef _WIN64
// Reserve space for the Arguments object. The Windows 64-bit ABI
// requires us to pass this structure as a pointer to its location on
// the stack. The structure contains 2 pointers.
// The structure on the stack must be 16-byte aligned.
// We also need backing space for 4 parameters, even though
// we only pass one parameter, and it is in a register.
subq(rsp, Immediate(6 * kPointerSize));
ASSERT(kFrameAlignment == 2 * kPointerSize); // Change the padding if needed.
#endif
// Patch the saved entry sp. // Patch the saved entry sp.
movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp); movq(Operand(rbp, ExitFrameConstants::kSPOffset), rsp);
} }
void MacroAssembler::LeaveExitFrame(StackFrame::Type type) { void MacroAssembler::LeaveExitFrame(StackFrame::Type type, int result_size) {
// Registers: // Registers:
// r15 : argv // r15 : argv
#ifdef ENABLE_DEBUGGER_SUPPORT #ifdef ENABLE_DEBUGGER_SUPPORT
// Restore the memory copy of the registers by digging them out from // Restore the memory copy of the registers by digging them out from
// the stack. This is needed to allow nested break points. // the stack. This is needed to allow nested break points.
if (type == StackFrame::EXIT_DEBUG) { if (type == StackFrame::EXIT_DEBUG) {
// It's okay to clobber register ebx below because we don't need // It's okay to clobber register rbx below because we don't need
// the function pointer after this. // the function pointer after this.
const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize; const int kCallerSavedSize = kNumJSCallerSaved * kPointerSize;
int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize; int kOffset = ExitFrameConstants::kDebugMarkOffset - kCallerSavedSize;
@ -1060,7 +1066,18 @@ void MacroAssembler::LeaveExitFrame(StackFrame::Type type) {
movq(rcx, Operand(rbp, 1 * kPointerSize)); movq(rcx, Operand(rbp, 1 * kPointerSize));
movq(rbp, Operand(rbp, 0 * kPointerSize)); movq(rbp, Operand(rbp, 0 * kPointerSize));
// Pop the arguments and the receiver from the caller stack. #ifdef _WIN64
// If return value is on the stack, pop it to registers.
if (result_size > 1) {
ASSERT_EQ(2, result_size);
// Position above 4 argument mirrors and arguments object.
movq(rax, Operand(rsp, 6 * kPointerSize));
movq(rdx, Operand(rsp, 7 * kPointerSize));
}
#endif
// Pop everything up to and including the arguments and the receiver
// from the caller stack.
lea(rsp, Operand(r15, 1 * kPointerSize)); lea(rsp, Operand(r15, 1 * kPointerSize));
// Restore current context from top and clear it in debug mode. // Restore current context from top and clear it in debug mode.

View File

@ -87,15 +87,15 @@ class MacroAssembler: public Assembler {
void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); } void LeaveConstructFrame() { LeaveFrame(StackFrame::CONSTRUCT); }
// Enter specific kind of exit frame; either EXIT or // Enter specific kind of exit frame; either EXIT or
// EXIT_DEBUG. Expects the number of arguments in register eax and // EXIT_DEBUG. Expects the number of arguments in register rax and
// sets up the number of arguments in register edi and the pointer // sets up the number of arguments in register rdi and the pointer
// to the first argument in register esi. // to the first argument in register rsi.
void EnterExitFrame(StackFrame::Type type); void EnterExitFrame(StackFrame::Type type, int result_size = 1);
// Leave the current exit frame. Expects the return value in // Leave the current exit frame. Expects/provides the return value in
// register eax:edx (untouched) and the pointer to the first // register rax:rdx (untouched) and the pointer to the first
// argument in register esi. // argument in register rsi.
void LeaveExitFrame(StackFrame::Type type); void LeaveExitFrame(StackFrame::Type type, int result_size = 1);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -298,10 +298,12 @@ class MacroAssembler: public Assembler {
// Tail call of a runtime routine (jump). // Tail call of a runtime routine (jump).
// Like JumpToBuiltin, but also takes care of passing the number // Like JumpToBuiltin, but also takes care of passing the number
// of arguments. // of arguments.
void TailCallRuntime(const ExternalReference& ext, int num_arguments); void TailCallRuntime(const ExternalReference& ext,
int num_arguments,
int result_size);
// Jump to the builtin routine. // Jump to the builtin routine.
void JumpToBuiltin(const ExternalReference& ext); void JumpToBuiltin(const ExternalReference& ext, int result_size);
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -612,7 +612,7 @@ Handle<Object> RegExpMacroAssemblerX64::GetCode(Handle<String> source) {
// MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots. // MSVC passes arguments in rcx, rdx, r8, r9, with backing stack slots.
// Store register parameters in pre-allocated stack slots, // Store register parameters in pre-allocated stack slots,
__ movq(Operand(rbp, kInputString), rcx); __ movq(Operand(rbp, kInputString), rcx);
__ movzxlq(Operand(rbp, kStartIndex), rdx); // Passed as int in eax. __ movq(Operand(rbp, kStartIndex), rdx); // Passed as int32 in edx.
__ movq(Operand(rbp, kInputStart), r8); __ movq(Operand(rbp, kInputStart), r8);
__ movq(Operand(rbp, kInputEnd), r9); __ movq(Operand(rbp, kInputEnd), r9);
// Callee-save on Win64. // Callee-save on Win64.

View File

@ -354,7 +354,7 @@ static void CompileCallLoadPropertyWithInterceptor(MacroAssembler* masm,
__ movq(rax, Immediate(5)); __ movq(rax, Immediate(5));
__ movq(rbx, ref); __ movq(rbx, ref);
CEntryStub stub; CEntryStub stub(1);
__ CallStub(&stub); __ CallStub(&stub);
} }
@ -489,7 +489,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
ExternalReference ref = ExternalReference ref =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallRuntime(ref, 5); __ TailCallRuntime(ref, 5, 1);
__ bind(&cleanup); __ bind(&cleanup);
__ pop(scratch1); __ pop(scratch1);
@ -511,7 +511,7 @@ class LoadInterceptorCompiler BASE_EMBEDDED {
ExternalReference ref = ExternalReference( ExternalReference ref = ExternalReference(
IC_Utility(IC::kLoadPropertyWithInterceptorForLoad)); IC_Utility(IC::kLoadPropertyWithInterceptorForLoad));
__ TailCallRuntime(ref, 5); __ TailCallRuntime(ref, 5, 1);
} }
private: private:
@ -661,7 +661,7 @@ class CallInterceptorCompiler BASE_EMBEDDED {
__ movq(rax, Immediate(5)); __ movq(rax, Immediate(5));
__ movq(rbx, ref); __ movq(rbx, ref);
CEntryStub stub; CEntryStub stub(1);
__ CallStub(&stub); __ CallStub(&stub);
__ LeaveInternalFrame(); __ LeaveInternalFrame();
@ -1362,7 +1362,7 @@ Object* StoreStubCompiler::CompileStoreCallback(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_callback_property = ExternalReference store_callback_property =
ExternalReference(IC_Utility(IC::kStoreCallbackProperty)); ExternalReference(IC_Utility(IC::kStoreCallbackProperty));
__ TailCallRuntime(store_callback_property, 4); __ TailCallRuntime(store_callback_property, 4, 1);
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
@ -1450,7 +1450,7 @@ Object* StoreStubCompiler::CompileStoreInterceptor(JSObject* receiver,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference store_ic_property = ExternalReference store_ic_property =
ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
__ TailCallRuntime(store_ic_property, 3); __ TailCallRuntime(store_ic_property, 3, 1);
// Handle store cache miss. // Handle store cache miss.
__ bind(&miss); __ bind(&miss);
@ -1652,7 +1652,7 @@ void StubCompiler::GenerateLoadCallback(JSObject* object,
// Do tail-call to the runtime system. // Do tail-call to the runtime system.
ExternalReference load_callback_property = ExternalReference load_callback_property =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty)); ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallRuntime(load_callback_property, 5); __ TailCallRuntime(load_callback_property, 5, 1);
} }