Revision: 9040
Author:   [email protected]
Date:     Mon Aug 29 03:40:31 2011
Log:      Port r9030 and part of r9016 to 3.3 branch.

Made FromPropertyDescriptor not hit inherited setters.

Changed computation of func.caller to skip some built-in functions.
Now skips built-in functions called from other built-in functions,
so only the initally called built-in function is exposed.

Review URL: http://codereview.chromium.org/7736011
http://code.google.com/p/v8/source/detail?r=9040

Modified:
 /branches/3.3/src/accessors.cc
 /branches/3.3/src/v8natives.js
 /branches/3.3/src/version.cc
 /branches/3.3/test/mjsunit/function-caller.js

=======================================
--- /branches/3.3/src/accessors.cc      Tue Jun 21 01:22:29 2011
+++ /branches/3.3/src/accessors.cc      Mon Aug 29 03:40:31 2011
@@ -680,6 +680,52 @@
 }


+class FrameFunctionIterator {
+ public:
+ FrameFunctionIterator(Isolate* isolate, const AssertNoAllocation& promise)
+      : frame_iterator_(isolate),
+        functions_(2),
+        index_(0) {
+    GetFunctions();
+  }
+
+  JSFunction* next() {
+    if (functions_.length() == 0) return NULL;
+    JSFunction* next_function = functions_[index_];
+    index_--;
+    if (index_ < 0) {
+      GetFunctions();
+    }
+    return next_function;
+  }
+
+  // Iterate through functions until the first occurence of 'function'.
+  // Returns true if 'function' is found, and false if the iterator ends
+  // without finding it.
+  bool Find(JSFunction* function) {
+    JSFunction* next_function;
+    do {
+      next_function = next();
+      if (next_function == function) return true;
+    } while (next_function != NULL);
+    return false;
+  }
+ private:
+  void GetFunctions() {
+    functions_.Rewind(0);
+    if (frame_iterator_.done()) return;
+    JavaScriptFrame* frame = frame_iterator_.frame();
+    frame->GetFunctions(&functions_);
+    ASSERT(functions_.length() > 0);
+    frame_iterator_.Advance();
+    index_ = functions_.length() - 1;
+  }
+  JavaScriptFrameIterator frame_iterator_;
+  List<JSFunction*> functions_;
+  int index_;
+};
+
+
 MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
   Isolate* isolate = Isolate::Current();
   HandleScope scope(isolate);
@@ -689,38 +735,30 @@
   if (!found_it) return isolate->heap()->undefined_value();
   Handle<JSFunction> function(holder, isolate);

-  List<JSFunction*> functions(2);
-  for (JavaScriptFrameIterator it(isolate); !it.done(); it.Advance()) {
-    JavaScriptFrame* frame = it.frame();
-    frame->GetFunctions(&functions);
-    for (int i = functions.length() - 1; i >= 0; i--) {
-      if (functions[i] == *function) {
-        // Once we have found the frame, we need to go to the caller
-        // frame. This may require skipping through a number of top-level
-        // frames, e.g. frames for scripts not functions.
-        if (i > 0) {
-          ASSERT(!functions[i - 1]->shared()->is_toplevel());
-          return CheckNonStrictCallerOrThrow(isolate, functions[i - 1]);
-        } else {
-          for (it.Advance(); !it.done(); it.Advance()) {
-            frame = it.frame();
-            functions.Rewind(0);
-            frame->GetFunctions(&functions);
-            if (!functions.last()->shared()->is_toplevel()) {
- return CheckNonStrictCallerOrThrow(isolate, functions.last());
-            }
-            ASSERT(functions.length() == 1);
-          }
-          if (it.done()) return isolate->heap()->null_value();
-          break;
-        }
-      }
-    }
-    functions.Rewind(0);
+  FrameFunctionIterator it(isolate, no_alloc);
+
+  // Find the function from the frames.
+  if (!it.Find(*function)) {
+    // No frame corresponding to the given function found. Return null.
+    return isolate->heap()->null_value();
   }

-  // No frame corresponding to the given function found. Return null.
-  return isolate->heap()->null_value();
+  // Find previously called non-toplevel function.
+  JSFunction* caller;
+  do {
+    caller = it.next();
+    if (caller == NULL) return isolate->heap()->null_value();
+  } while (caller->shared()->is_toplevel());
+
+  // If caller is a built-in function and caller's caller is also built-in,
+  // use that instead.
+  JSFunction* potential_caller = caller;
+  while (potential_caller != NULL && potential_caller->IsBuiltin()) {
+    caller = potential_caller;
+    potential_caller = it.next();
+  }
+
+  return CheckNonStrictCallerOrThrow(isolate, caller);
 }


=======================================
--- /branches/3.3/src/v8natives.js      Mon Aug 22 04:47:26 2011
+++ /branches/3.3/src/v8natives.js      Mon Aug 29 03:40:31 2011
@@ -326,18 +326,18 @@
 // ES5 8.10.4
 function FromPropertyDescriptor(desc) {
   if (IS_UNDEFINED(desc)) return desc;
-  var obj = new $Object();
+
   if (IsDataDescriptor(desc)) {
-    obj.value = desc.getValue();
-    obj.writable = desc.isWritable();
-  }
-  if (IsAccessorDescriptor(desc)) {
-    obj.get = desc.getGet();
-    obj.set = desc.getSet();
-  }
-  obj.enumerable = desc.isEnumerable();
-  obj.configurable = desc.isConfigurable();
-  return obj;
+    return { value: desc.getValue(),
+             writable: desc.isWritable(),
+             enumerable: desc.isEnumerable(),
+             configurable: desc.isConfigurable() };
+  }
+ // Must be an AccessorDescriptor then. We never return a generic descriptor.
+  return { get: desc.getGet(),
+           set: desc.getSet(),
+           enumerable: desc.isEnumerable(),
+           configurable: desc.isConfigurable() };
 }

 // ES5 8.10.5.
=======================================
--- /branches/3.3/src/version.cc        Mon Aug 22 06:54:47 2011
+++ /branches/3.3/src/version.cc        Mon Aug 29 03:40:31 2011
@@ -35,7 +35,7 @@
 #define MAJOR_VERSION     3
 #define MINOR_VERSION     3
 #define BUILD_NUMBER      10
-#define PATCH_LEVEL       32
+#define PATCH_LEVEL       33
 // Use 1 for candidates and 0 otherwise.
 // (Boolean macro values are not supported by all preprocessors.)
 #define IS_CANDIDATE_VERSION 0
=======================================
--- /branches/3.3/test/mjsunit/function-caller.js       Wed Dec  3 08:05:52 2008
+++ /branches/3.3/test/mjsunit/function-caller.js       Mon Aug 29 03:40:31 2011
@@ -46,3 +46,10 @@
 // Check called from eval.
 eval('f(null)');

+// Check called from builtin functions. Only show the initially called
+// (publicly exposed) builtin function, not it's internal helper functions.
+[Array.prototype.sort, Array.prototype.sort].sort(f);
+
+"abel".replace(/b/g, function h() {
+   assertEquals(String.prototype.replace, h.caller);
+});

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to