Revision: 5791
Author: [email protected]
Date: Tue Nov 9 06:01:23 2010
Log: Direct call API functions (ia32 implementation).
Review URL: http://codereview.chromium.org/4456002
http://code.google.com/p/v8/source/detail?r=5791
Modified:
/branches/bleeding_edge/src/code-stubs.h
/branches/bleeding_edge/src/codegen.cc
/branches/bleeding_edge/src/ia32/assembler-ia32.h
/branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
/branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/objects-debug.cc
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.h
=======================================
--- /branches/bleeding_edge/src/code-stubs.h Mon Oct 25 08:22:03 2010
+++ /branches/bleeding_edge/src/code-stubs.h Tue Nov 9 06:01:23 2010
@@ -542,7 +542,7 @@
ApiFunction* fun() { return fun_; }
Major MajorKey() { return NoCache; }
int MinorKey() { return 0; }
- const char* GetName() { return "ApiEntryStub"; }
+ const char* GetName() { return "ApiGetterEntryStub"; }
// The accessor info associated with the function.
Handle<AccessorInfo> info_;
// The function to be called.
@@ -550,6 +550,32 @@
};
+class ApiCallEntryStub : public CodeStub {
+ public:
+ ApiCallEntryStub(Handle<CallHandlerInfo> info,
+ ApiFunction* fun)
+ : info_(info),
+ fun_(fun) { }
+ void Generate(MacroAssembler* masm);
+ virtual bool has_custom_cache() { return true; }
+ virtual bool GetCustomCache(Code** code_out);
+ virtual void SetCustomCache(Code* value);
+
+ static const int kStackSpace = 0;
+ static const int kArgc = 5;
+ private:
+ Handle<CallHandlerInfo> info() { return info_; }
+ ApiFunction* fun() { return fun_; }
+ Major MajorKey() { return NoCache; }
+ int MinorKey() { return 0; }
+ const char* GetName() { return "ApiCallEntryStub"; }
+ // The call handler info associated with the function.
+ Handle<CallHandlerInfo> info_;
+ // The function to be called.
+ ApiFunction* fun_;
+};
+
+
class JSEntryStub : public CodeStub {
public:
JSEntryStub() { }
=======================================
--- /branches/bleeding_edge/src/codegen.cc Thu Nov 4 08:12:03 2010
+++ /branches/bleeding_edge/src/codegen.cc Tue Nov 9 06:01:23 2010
@@ -482,8 +482,8 @@
}
-bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
- Object* cache = info()->load_stub_cache();
+// Implementation of CodeStub::GetCustomCache.
+static bool GetCustomCacheHelper(Object* cache, Code** code_out) {
if (cache->IsUndefined()) {
return false;
} else {
@@ -491,11 +491,26 @@
return true;
}
}
+
+
+bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
+ return GetCustomCacheHelper(info()->load_stub_cache(), code_out);
+}
void ApiGetterEntryStub::SetCustomCache(Code* value) {
info()->set_load_stub_cache(value);
}
+
+
+bool ApiCallEntryStub::GetCustomCache(Code** code_out) {
+ return GetCustomCacheHelper(info()->call_stub_cache(), code_out);
+}
+
+
+void ApiCallEntryStub::SetCustomCache(Code* value) {
+ info()->set_call_stub_cache(value);
+}
} } // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Nov 4 08:12:03
2010
+++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Tue Nov 9 06:01:23
2010
@@ -521,7 +521,6 @@
void push(const Immediate& x);
void push(Register src);
void push(const Operand& src);
- void push(Label* label, RelocInfo::Mode relocation_mode);
void pop(Register dst);
void pop(const Operand& dst);
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 21 07:21:00
2010
+++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue Nov 9 06:01:23
2010
@@ -3065,6 +3065,26 @@
__ mov(ApiParameterOperand(1), eax); // arguments pointer.
__ CallApiFunctionAndReturn(fun(), kArgc);
}
+
+
+void ApiCallEntryStub::Generate(MacroAssembler* masm) {
+ __ PrepareCallApiFunction(kStackSpace, kArgc);
+ STATIC_ASSERT(kArgc == 5);
+
+ // Allocate the v8::Arguments structure in the arguments' space since
+ // it's not controlled by GC.
+ __ mov(ApiParameterOperand(1), eax); // v8::Arguments::implicit_args_.
+ __ mov(ApiParameterOperand(2), ebx); // v8::Arguments::values_.
+ __ mov(ApiParameterOperand(3), edx); // v8::Arguments::length_.
+ // v8::Arguments::is_construct_call_.
+ __ mov(ApiParameterOperand(4), Immediate(0));
+
+ // v8::InvocationCallback's argument.
+ __ lea(eax, ApiParameterOperand(1));
+ __ mov(ApiParameterOperand(0), eax);
+
+ __ CallApiFunctionAndReturn(fun(), kArgc);
+}
void CEntryStub::GenerateCore(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Oct 25
08:22:03 2010
+++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Tue Nov 9
06:01:23 2010
@@ -488,7 +488,7 @@
// stored in ApiParameterOperand(0), ApiParameterOperand(1) etc.
void PrepareCallApiFunction(int stack_space, int argc);
- // Tail call an API function (jump). Allocates HandleScope, extracts
+ // Calls an API function. Allocates HandleScope, extracts
// returned value from handle and propagates exceptions.
// Clobbers ebx, esi, edi and caller-save registers.
void CallApiFunctionAndReturn(ApiFunction* function, int argc);
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Nov 2 04:56:10
2010
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Nov 9 06:01:23
2010
@@ -411,6 +411,10 @@
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)),
5);
}
+
+
+// Number of pointers to be reserved on stack for fast API call.
+static const int kFastApiCallArguments = 3;
// Reserves space for the extra arguments to FastHandleApiCall in the
@@ -423,10 +427,9 @@
// -- esp[4] : last argument in the internal frame of the caller
// -----------------------------------
__ pop(scratch);
- __ push(Immediate(Smi::FromInt(0)));
- __ push(Immediate(Smi::FromInt(0)));
- __ push(Immediate(Smi::FromInt(0)));
- __ push(Immediate(Smi::FromInt(0)));
+ for (int i = 0; i < kFastApiCallArguments; i++) {
+ __ push(Immediate(Smi::FromInt(0)));
+ }
__ push(scratch);
}
@@ -434,75 +437,81 @@
// Undoes the effects of ReserveSpaceForFastApiCall.
static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register
scratch) {
// ----------- S t a t e -------------
- // -- esp[0] : return address
- // -- esp[4] : last fast api call extra argument
+ // -- esp[0] : return address.
+ // -- esp[4] : last fast api call extra argument.
// -- ...
- // -- esp[16] : first fast api call extra argument
- // -- esp[20] : last argument in the internal frame
+ // -- esp[kFastApiCallArguments * 4] : first fast api call extra
argument.
+ // -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
+ // frame.
// -----------------------------------
__ pop(scratch);
- __ add(Operand(esp), Immediate(kPointerSize * 4));
+ __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments));
__ push(scratch);
}
// Generates call to FastHandleApiCall builtin.
-static void GenerateFastApiCall(MacroAssembler* masm,
+static bool GenerateFastApiCall(MacroAssembler* masm,
const CallOptimization& optimization,
- int argc) {
+ int argc,
+ Failure** failure) {
// ----------- S t a t e -------------
// -- esp[0] : return address
// -- esp[4] : object passing the type check
// (last fast api call extra argument,
// set by CheckPrototypes)
- // -- esp[8] : api call data
- // -- esp[12] : api callback
- // -- esp[16] : api function
+ // -- esp[8] : api function
// (first fast api call extra argument)
- // -- esp[20] : last argument
+ // -- esp[12] : api call data
+ // -- esp[16] : last argument
// -- ...
- // -- esp[(argc + 5) * 4] : first argument
- // -- esp[(argc + 6) * 4] : receiver
+ // -- esp[(argc + 3) * 4] : first argument
+ // -- esp[(argc + 4) * 4] : receiver
// -----------------------------------
-
// Get the function and setup the context.
JSFunction* function = optimization.constant_function();
__ mov(edi, Immediate(Handle<JSFunction>(function)));
__ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
// Pass the additional arguments FastHandleApiCall expects.
- __ mov(Operand(esp, 4 * kPointerSize), edi);
- bool info_loaded = false;
- Object* callback = optimization.api_call_info()->callback();
- if (Heap::InNewSpace(callback)) {
- info_loaded = true;
- __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info()));
- __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset));
- __ mov(Operand(esp, 3 * kPointerSize), ebx);
- } else {
- __ mov(Operand(esp, 3 * kPointerSize),
Immediate(Handle<Object>(callback)));
- }
+ __ mov(Operand(esp, 2 * kPointerSize), edi);
Object* call_data = optimization.api_call_info()->data();
+ Handle<CallHandlerInfo>
api_call_info_handle(optimization.api_call_info());
if (Heap::InNewSpace(call_data)) {
- if (!info_loaded) {
- __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info()));
- }
+ __ mov(ecx, api_call_info_handle);
__ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
- __ mov(Operand(esp, 2 * kPointerSize), ebx);
+ __ mov(Operand(esp, 3 * kPointerSize), ebx);
} else {
- __ mov(Operand(esp, 2 * kPointerSize),
+ __ mov(Operand(esp, 3 * kPointerSize),
Immediate(Handle<Object>(call_data)));
}
- // Set the number of arguments.
- __ mov(eax, Immediate(argc + 4));
-
- // Jump to the fast api call builtin (tail call).
- Handle<Code> code = Handle<Code>(
- Builtins::builtin(Builtins::FastHandleApiCall));
- ParameterCount expected(0);
- __ InvokeCode(code, expected, expected,
- RelocInfo::CODE_TARGET, JUMP_FUNCTION);
+ // Prepare arguments for ApiCallEntryStub.
+ __ lea(eax, Operand(esp, 3 * kPointerSize));
+ __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize));
+ __ Set(edx, Immediate(argc));
+
+ Object* callback = optimization.api_call_info()->callback();
+ Address api_function_address = v8::ToCData<Address>(callback);
+ ApiFunction fun(api_function_address);
+
+ ApiCallEntryStub stub(api_call_info_handle, &fun);
+
+ __ EnterInternalFrame();
+
+ // Emitting a stub call may try to allocate (if the code is not
+ // already generated). Do not allow the assembler to perform a
+ // garbage collection but instead return the allocation failure
+ // object.
+ MaybeObject* result = masm->TryCallStub(&stub);
+ if (result->IsFailure()) {
+ *failure = Failure::cast(result);
+ return false;
+ }
+
+ __ LeaveInternalFrame();
+ __ ret((argc + 4) * kPointerSize);
+ return true;
}
@@ -515,7 +524,7 @@
arguments_(arguments),
name_(name) {}
- void Compile(MacroAssembler* masm,
+ bool Compile(MacroAssembler* masm,
JSObject* object,
JSObject* holder,
String* name,
@@ -524,7 +533,8 @@
Register scratch1,
Register scratch2,
Register scratch3,
- Label* miss) {
+ Label* miss,
+ Failure** failure) {
ASSERT(holder->HasNamedInterceptor());
ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());
@@ -535,17 +545,18 @@
CallOptimization optimization(lookup);
if (optimization.is_constant_call()) {
- CompileCacheable(masm,
- object,
- receiver,
- scratch1,
- scratch2,
- scratch3,
- holder,
- lookup,
- name,
- optimization,
- miss);
+ return CompileCacheable(masm,
+ object,
+ receiver,
+ scratch1,
+ scratch2,
+ scratch3,
+ holder,
+ lookup,
+ name,
+ optimization,
+ miss,
+ failure);
} else {
CompileRegular(masm,
object,
@@ -556,11 +567,12 @@
name,
holder,
miss);
+ return true;
}
}
private:
- void CompileCacheable(MacroAssembler* masm,
+ bool CompileCacheable(MacroAssembler* masm,
JSObject* object,
Register receiver,
Register scratch1,
@@ -570,7 +582,8 @@
LookupResult* lookup,
String* name,
const CallOptimization& optimization,
- Label* miss_label) {
+ Label* miss_label,
+ Failure** failure) {
ASSERT(optimization.is_constant_call());
ASSERT(!lookup->holder()->IsGlobalObject());
@@ -632,7 +645,11 @@
// Invoke function.
if (can_do_fast_api_call) {
- GenerateFastApiCall(masm, optimization, arguments_.immediate());
+ bool success = GenerateFastApiCall(masm, optimization,
+ arguments_.immediate(), failure);
+ if (!success) {
+ return false;
+ }
} else {
__ InvokeFunction(optimization.constant_function(), arguments_,
JUMP_FUNCTION);
@@ -650,6 +667,8 @@
if (can_do_fast_api_call) {
FreeSpaceForFastApiCall(masm, scratch1);
}
+
+ return true;
}
void CompileRegular(MacroAssembler* masm,
@@ -1046,8 +1065,7 @@
__ EnterInternalFrame();
// Push the stack address where the list of arguments ends.
- __ mov(scratch2, esp);
- __ sub(Operand(scratch2), Immediate(2 * kPointerSize));
+ __ lea(scratch2, Operand(esp, -2 * kPointerSize));
__ push(scratch2);
__ push(receiver); // receiver
__ push(reg); // holder
@@ -1061,12 +1079,11 @@
__ push(name_reg); // name
// Save a pointer to where we pushed the arguments pointer.
// This will be passed as the const AccessorInfo& to the C++ callback.
- __ mov(eax, esp);
- __ add(Operand(eax), Immediate(4 * kPointerSize));
+ STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5);
+ __ lea(eax, Operand(esp, 4 * kPointerSize));
__ mov(ebx, esp);
// Do call through the api.
- ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace);
Address getter_address = v8::ToCData<Address>(callback->getter());
ApiFunction fun(getter_address);
ApiGetterEntryStub stub(callback_handle, &fun);
@@ -2208,7 +2225,11 @@
}
if (depth != kInvalidProtoDepth) {
- GenerateFastApiCall(masm(), optimization, argc);
+ Failure* failure;
+ bool success = GenerateFastApiCall(masm(), optimization, argc,
&failure);
+ if (!success) {
+ return failure;
+ }
} else {
__ InvokeFunction(function, arguments(), JUMP_FUNCTION);
}
@@ -2253,16 +2274,21 @@
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
CallInterceptorCompiler compiler(this, arguments(), ecx);
- compiler.Compile(masm(),
- object,
- holder,
- name,
- &lookup,
- edx,
- ebx,
- edi,
- eax,
- &miss);
+ Failure* failure;
+ bool success = compiler.Compile(masm(),
+ object,
+ holder,
+ name,
+ &lookup,
+ edx,
+ ebx,
+ edi,
+ eax,
+ &miss,
+ &failure);
+ if (!success) {
+ return false;
+ }
// Restore receiver.
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Mon Oct 25 08:22:03 2010
+++ /branches/bleeding_edge/src/objects-debug.cc Tue Nov 9 06:01:23 2010
@@ -997,6 +997,8 @@
data()->ShortPrint();
PrintF("\n - flag: ");
flag()->ShortPrint();
+ PrintF("\n - load_stub_cache: ");
+ load_stub_cache()->ShortPrint();
}
void AccessCheckInfo::AccessCheckInfoVerify() {
@@ -1046,6 +1048,7 @@
CHECK(IsCallHandlerInfo());
VerifyPointer(callback());
VerifyPointer(data());
+ VerifyPointer(call_stub_cache());
}
void CallHandlerInfo::CallHandlerInfoPrint() {
@@ -1054,6 +1057,8 @@
callback()->ShortPrint();
PrintF("\n - data: ");
data()->ShortPrint();
+ PrintF("\n - call_stub_cache: ");
+ call_stub_cache()->ShortPrint();
}
void TemplateInfo::TemplateInfoVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Mon Nov 8 02:30:57 2010
+++ /branches/bleeding_edge/src/objects-inl.h Tue Nov 9 06:01:23 2010
@@ -2557,6 +2557,7 @@
ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
+ACCESSORS(CallHandlerInfo, call_stub_cache, Object, kCallStubCacheOffset)
ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
=======================================
--- /branches/bleeding_edge/src/objects.h Wed Oct 27 02:19:43 2010
+++ /branches/bleeding_edge/src/objects.h Tue Nov 9 06:01:23 2010
@@ -5423,6 +5423,7 @@
public:
DECL_ACCESSORS(callback, Object)
DECL_ACCESSORS(data, Object)
+ DECL_ACCESSORS(call_stub_cache, Object)
static inline CallHandlerInfo* cast(Object* obj);
@@ -5433,7 +5434,8 @@
static const int kCallbackOffset = HeapObject::kHeaderSize;
static const int kDataOffset = kCallbackOffset + kPointerSize;
- static const int kSize = kDataOffset + kPointerSize;
+ static const int kCallStubCacheOffset = kDataOffset + kPointerSize;
+ static const int kSize = kCallStubCacheOffset + kPointerSize;
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev