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