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

Reply via email to