Landing for Zaheer.

Direct call accessor getter callbacks (arm implementation).

Original review: http://codereview.chromium.org/6462029/

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6938 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
antonm@chromium.org 2011-02-24 15:39:09 +00:00
parent 1ef2b9a385
commit 4718466e48
8 changed files with 129 additions and 43 deletions

View File

@ -5957,11 +5957,10 @@ void DirectCEntryStub::Generate(MacroAssembler* masm) {
void DirectCEntryStub::GenerateCall(MacroAssembler* masm,
ApiFunction *function) {
ExternalReference function) {
__ mov(lr, Operand(reinterpret_cast<intptr_t>(GetCode().location()),
RelocInfo::CODE_TARGET));
__ mov(r2,
Operand(ExternalReference(function, ExternalReference::DIRECT_CALL)));
__ mov(r2, Operand(function));
// Push return address (accessible to GC through exit frame pc).
__ str(pc, MemOperand(sp, 0));
__ Jump(r2); // Call the api function.

View File

@ -592,7 +592,7 @@ class DirectCEntryStub: public CodeStub {
public:
DirectCEntryStub() {}
void Generate(MacroAssembler* masm);
void GenerateCall(MacroAssembler* masm, ApiFunction *function);
void GenerateCall(MacroAssembler* masm, ExternalReference function);
void GenerateCall(MacroAssembler* masm, Register target);
private:

View File

@ -1618,7 +1618,7 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
ApiFunction* function, int stack_space) {
ExternalReference function, int stack_space) {
ExternalReference next_address =
ExternalReference::handle_scope_next_address();
const int kNextOffset = 0;

View File

@ -690,7 +690,7 @@ class MacroAssembler: public Assembler {
// from handle and propagates exceptions. Restores context.
// stack_space - space to be unwound on exit (includes the call js
// arguments space and the additional space allocated for the fast call).
MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function,
MaybeObject* TryCallApiFunctionAndReturn(ExternalReference function,
int stack_space);
// Jump to a runtime routine.

View File

@ -1531,7 +1531,11 @@ typedef double (*SimulatorRuntimeFPCall)(int32_t arg0,
// This signature supports direct call in to API function native callback
// (refer to InvocationCallback in v8.h).
typedef v8::Handle<v8::Value> (*SimulatorRuntimeApiCall)(int32_t arg0);
typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
// This signature supports direct call to accessor getter callback.
typedef v8::Handle<v8::Value> (*SimulatorRuntimeDirectGetterCall)(int32_t arg0,
int32_t arg1);
// Software interrupt instructions are used by the simulator to call into the
// C-based V8 runtime.
@ -1572,14 +1576,12 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
CHECK(stack_aligned);
double result = target(arg0, arg1, arg2, arg3);
SetFpResult(result);
} else if (redirection->type() == ExternalReference::DIRECT_CALL) {
SimulatorRuntimeApiCall target =
reinterpret_cast<SimulatorRuntimeApiCall>(external);
} else if (redirection->type() == ExternalReference::DIRECT_API_CALL) {
SimulatorRuntimeDirectApiCall target =
reinterpret_cast<SimulatorRuntimeDirectApiCall>(external);
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
PrintF(
"Call to host function at %p args %08x",
FUNCTION_ADDR(target),
arg0);
PrintF("Call to host function at %p args %08x",
FUNCTION_ADDR(target), arg0);
if (!stack_aligned) {
PrintF(" with unaligned stack %08x\n", get_register(sp));
}
@ -1591,6 +1593,23 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
}
set_register(r0, (int32_t) *result);
} else if (redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
SimulatorRuntimeDirectGetterCall target =
reinterpret_cast<SimulatorRuntimeDirectGetterCall>(external);
if (::v8::internal::FLAG_trace_sim || !stack_aligned) {
PrintF("Call to host function at %p args %08x %08x",
FUNCTION_ADDR(target), arg0, arg1);
if (!stack_aligned) {
PrintF(" with unaligned stack %08x\n", get_register(sp));
}
PrintF("\n");
}
CHECK(stack_aligned);
v8::Handle<v8::Value> result = target(arg0, arg1);
if (::v8::internal::FLAG_trace_sim) {
PrintF("Returned %p\n", reinterpret_cast<void *>(*result));
}
set_register(r0, (int32_t) *result);
} else {
// builtin call.
ASSERT(redirection->type() == ExternalReference::BUILTIN_CALL);

View File

@ -655,12 +655,10 @@ static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm,
// already generated). Do not allow the assembler to perform a
// garbage collection but instead return the allocation failure
// object.
MaybeObject* result = masm->TryCallApiFunctionAndReturn(
&fun, argc + kFastApiCallArguments + 1);
if (result->IsFailure()) {
return result;
}
return Heap::undefined_value();
const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
ExternalReference ref =
ExternalReference(&fun, ExternalReference::DIRECT_API_CALL);
return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
}
class CallInterceptorCompiler BASE_EMBEDDED {
@ -1245,18 +1243,38 @@ MaybeObject* StubCompiler::GenerateLoadCallback(JSObject* object,
CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
name, miss);
// Push the arguments on the JS stack of the caller.
__ push(receiver); // Receiver.
__ mov(scratch3, Operand(Handle<AccessorInfo>(callback))); // callback data
__ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
__ Push(reg, ip, scratch3, name_reg);
// Build AccessorInfo::args_ list on the stack and push property name below
// the exit frame to make GC aware of them and store pointers to them.
__ push(receiver);
__ mov(scratch2, sp); // scratch2 = AccessorInfo::args_
Handle<AccessorInfo> callback_handle(callback);
if (Heap::InNewSpace(callback_handle->data())) {
__ Move(scratch3, callback_handle);
__ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
} else {
__ Move(scratch3, Handle<Object>(callback_handle->data()));
}
__ Push(reg, scratch3, name_reg);
__ mov(r0, sp); // r0 = Handle<String>
// Do tail-call to the runtime system.
ExternalReference load_callback_property =
ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
__ TailCallExternalReference(load_callback_property, 5, 1);
Address getter_address = v8::ToCData<Address>(callback->getter());
ApiFunction fun(getter_address);
return Heap::undefined_value(); // Success.
const int kApiStackSpace = 1;
__ EnterExitFrame(false, kApiStackSpace);
// Create AccessorInfo instance on the stack above the exit frame with
// scratch2 (internal::Object **args_) as the data.
__ str(scratch2, MemOperand(sp, 1 * kPointerSize));
__ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo&
// 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.
const int kStackUnwindSpace = 4;
ExternalReference ref =
ExternalReference(&fun, ExternalReference::DIRECT_GETTER_CALL);
return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
}

View File

@ -481,21 +481,22 @@ class Debug_Address;
class ExternalReference BASE_EMBEDDED {
public:
// Used in the simulator to support different native api calls.
//
// BUILTIN_CALL - builtin call.
// MaybeObject* f(v8::internal::Arguments).
//
// FP_RETURN_CALL - builtin call that returns floating point.
// double f(double, double).
//
// DIRECT_CALL - direct call to API function native callback
// from generated code.
// Handle<Value> f(v8::Arguments&)
//
enum Type {
// Builtin call.
// MaybeObject* f(v8::internal::Arguments).
BUILTIN_CALL, // default
// Builtin call that returns floating point.
// double f(double, double).
FP_RETURN_CALL,
DIRECT_CALL
// Direct call to API function callback.
// Handle<Value> f(v8::Arguments&)
DIRECT_API_CALL,
// Direct call to accessor getter callback.
// Handle<value> f(Local<String> property, AccessorInfo& info)
DIRECT_GETTER_CALL
};
typedef void* ExternalReferenceRedirector(void* original, Type type);

View File

@ -7627,10 +7627,11 @@ static void GenerateSomeGarbage() {
"garbage = undefined;");
}
v8::Handle<v8::Value> DirectApiCallback(const v8::Arguments& args) {
static int count = 0;
if (count++ % 3 == 0) {
v8::V8::LowMemoryNotification(); // This should move the stub
i::Heap::CollectAllGarbage(true); // This should move the stub
GenerateSomeGarbage(); // This should ensure the old stub memory is flushed
}
return v8::Handle<v8::Value>();
@ -7682,6 +7683,54 @@ THREADED_TEST(CallICFastApi_DirectCall_Throw) {
}
v8::Handle<v8::Value> DirectGetterCallback(Local<String> name,
const v8::AccessorInfo& info) {
if (++p_getter_count % 3 == 0) {
i::Heap::CollectAllGarbage(true);
GenerateSomeGarbage();
}
return v8::Handle<v8::Value>();
}
THREADED_TEST(LoadICFastApi_DirectCall_GCMoveStub) {
v8::HandleScope scope;
LocalContext context;
v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
obj->SetAccessor(v8_str("p1"), DirectGetterCallback);
context->Global()->Set(v8_str("o1"), obj->NewInstance());
p_getter_count = 0;
CompileRun(
"function f() {"
" for (var i = 0; i < 30; i++) o1.p1;"
"}"
"f();");
CHECK_EQ(30, p_getter_count);
}
v8::Handle<v8::Value> ThrowingDirectGetterCallback(
Local<String> name, const v8::AccessorInfo& info) {
return v8::ThrowException(v8_str("g"));
}
THREADED_TEST(LoadICFastApi_DirectCall_Throw) {
v8::HandleScope scope;
LocalContext context;
v8::Handle<v8::ObjectTemplate> obj = v8::ObjectTemplate::New();
obj->SetAccessor(v8_str("p1"), ThrowingDirectGetterCallback);
context->Global()->Set(v8_str("o1"), obj->NewInstance());
v8::Handle<Value> result = CompileRun(
"var result = '';"
"for (var i = 0; i < 5; i++) {"
" try { o1.p1; } catch (e) { result += e; }"
"}"
"result;");
CHECK_EQ(v8_str("ggggg"), result);
}
THREADED_TEST(InterceptorCallICFastApi_TrivialSignature) {
int interceptor_call_count = 0;
v8::HandleScope scope;