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:
parent
1ef2b9a385
commit
4718466e48
@ -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.
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user