Revision: 6938
Author: [email protected]
Date: Thu Feb 24 07:39:09 2011
Log: Landing for Zaheer.
Direct call accessor getter callbacks (arm implementation).
Original review: http://codereview.chromium.org/6462029/
Review URL: http://codereview.chromium.org/6576035
http://code.google.com/p/v8/source/detail?r=6938
Modified:
/branches/bleeding_edge/src/arm/code-stubs-arm.cc
/branches/bleeding_edge/src/arm/code-stubs-arm.h
/branches/bleeding_edge/src/arm/macro-assembler-arm.cc
/branches/bleeding_edge/src/arm/macro-assembler-arm.h
/branches/bleeding_edge/src/arm/simulator-arm.cc
/branches/bleeding_edge/src/arm/stub-cache-arm.cc
/branches/bleeding_edge/src/assembler.h
/branches/bleeding_edge/test/cctest/test-api.cc
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Tue Feb 22 04:26:31
2011
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Thu Feb 24 07:39:09
2011
@@ -5957,11 +5957,10 @@
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.
=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.h Tue Feb 22 01:35:37
2011
+++ /branches/bleeding_edge/src/arm/code-stubs-arm.h Thu Feb 24 07:39:09
2011
@@ -592,7 +592,7 @@
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:
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Feb 24
00:23:08 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Feb 24
07:39:09 2011
@@ -1618,7 +1618,7 @@
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;
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Feb 23
02:41:13 2011
+++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Thu Feb 24
07:39:09 2011
@@ -690,7 +690,7 @@
// 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.
=======================================
--- /branches/bleeding_edge/src/arm/simulator-arm.cc Fri Feb 4 05:43:38
2011
+++ /branches/bleeding_edge/src/arm/simulator-arm.cc Thu Feb 24 07:39:09
2011
@@ -1531,7 +1531,11 @@
// 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 @@
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));
}
@@ -1590,6 +1592,23 @@
if (::v8::internal::FLAG_trace_sim) {
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.
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Feb 21 16:39:21
2011
+++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Thu Feb 24 07:39:09
2011
@@ -655,12 +655,10 @@
// 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 @@
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);
-
- // Do tail-call to the runtime system.
- ExternalReference load_callback_property =
- ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
- __ TailCallExternalReference(load_callback_property, 5, 1);
-
- return Heap::undefined_value(); // Success.
+ // 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>
+
+ Address getter_address = v8::ToCData<Address>(callback->getter());
+ ApiFunction fun(getter_address);
+
+ 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);
}
=======================================
--- /branches/bleeding_edge/src/assembler.h Thu Feb 24 02:29:01 2011
+++ /branches/bleeding_edge/src/assembler.h Thu Feb 24 07:39:09 2011
@@ -481,21 +481,22 @@
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);
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Mon Feb 21 07:59:23 2011
+++ /branches/bleeding_edge/test/cctest/test-api.cc Thu Feb 24 07:39:09 2011
@@ -7626,11 +7626,12 @@
"}"
"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>();
@@ -7680,6 +7681,54 @@
"f(); result;");
CHECK_EQ(v8_str("ggggg"), result);
}
+
+
+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) {
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev