@@ -680,6 +680,51 @@ static MaybeObject* CheckNonStrictCallerOrThrow(
680
680
}
681
681
682
682
683
+ class FrameFunctionIterator {
684
+ public:
685
+ FrameFunctionIterator (Isolate* isolate, const AssertNoAllocation& promise)
686
+ : frame_iterator_(isolate),
687
+ functions_ (2 ),
688
+ index_(0 ) {
689
+ GetFunctions ();
690
+ }
691
+ JSFunction* next () {
692
+ if (functions_.length () == 0 ) return NULL ;
693
+ JSFunction* next_function = functions_[index_];
694
+ index_--;
695
+ if (index_ < 0 ) {
696
+ GetFunctions ();
697
+ }
698
+ return next_function;
699
+ }
700
+
701
+ // Iterate through functions until the first occurence of 'function'.
702
+ // Returns true if 'function' is found, and false if the iterator ends
703
+ // without finding it.
704
+ bool Find (JSFunction* function) {
705
+ JSFunction* next_function;
706
+ do {
707
+ next_function = next ();
708
+ if (next_function == function) return true ;
709
+ } while (next_function != NULL );
710
+ return false ;
711
+ }
712
+ private:
713
+ void GetFunctions () {
714
+ functions_.Rewind (0 );
715
+ if (frame_iterator_.done ()) return ;
716
+ JavaScriptFrame* frame = frame_iterator_.frame ();
717
+ frame->GetFunctions (&functions_);
718
+ ASSERT (functions_.length () > 0 );
719
+ frame_iterator_.Advance ();
720
+ index_ = functions_.length () - 1 ;
721
+ }
722
+ JavaScriptFrameIterator frame_iterator_;
723
+ List<JSFunction*> functions_;
724
+ int index_;
725
+ };
726
+
727
+
683
728
MaybeObject* Accessors::FunctionGetCaller (Object* object, void *) {
684
729
Isolate* isolate = Isolate::Current ();
685
730
HandleScope scope (isolate);
@@ -689,38 +734,30 @@ MaybeObject* Accessors::FunctionGetCaller(Object* object, void*) {
689
734
if (!found_it) return isolate->heap ()->undefined_value ();
690
735
Handle <JSFunction> function (holder, isolate);
691
736
692
- List<JSFunction*> functions (2 );
693
- for (JavaScriptFrameIterator it (isolate); !it.done (); it.Advance ()) {
694
- JavaScriptFrame* frame = it.frame ();
695
- frame->GetFunctions (&functions);
696
- for (int i = functions.length () - 1 ; i >= 0 ; i--) {
697
- if (functions[i] == *function) {
698
- // Once we have found the frame, we need to go to the caller
699
- // frame. This may require skipping through a number of top-level
700
- // frames, e.g. frames for scripts not functions.
701
- if (i > 0 ) {
702
- ASSERT (!functions[i - 1 ]->shared ()->is_toplevel ());
703
- return CheckNonStrictCallerOrThrow (isolate, functions[i - 1 ]);
704
- } else {
705
- for (it.Advance (); !it.done (); it.Advance ()) {
706
- frame = it.frame ();
707
- functions.Rewind (0 );
708
- frame->GetFunctions (&functions);
709
- if (!functions.last ()->shared ()->is_toplevel ()) {
710
- return CheckNonStrictCallerOrThrow (isolate, functions.last ());
711
- }
712
- ASSERT (functions.length () == 1 );
713
- }
714
- if (it.done ()) return isolate->heap ()->null_value ();
715
- break ;
716
- }
717
- }
718
- }
719
- functions.Rewind (0 );
737
+ FrameFunctionIterator it (isolate, no_alloc);
738
+
739
+ // Find the function from the frames.
740
+ if (!it.Find (*function)) {
741
+ // No frame corresponding to the given function found. Return null.
742
+ return isolate->heap ()->null_value ();
720
743
}
721
744
722
- // No frame corresponding to the given function found. Return null.
723
- return isolate->heap ()->null_value ();
745
+ // Find previously called non-toplevel function.
746
+ JSFunction* caller;
747
+ do {
748
+ caller = it.next ();
749
+ if (caller == NULL ) return isolate->heap ()->null_value ();
750
+ } while (caller->shared ()->is_toplevel ());
751
+
752
+ // If caller is a built-in function and caller's caller is also built-in,
753
+ // use that instead.
754
+ JSFunction* potential_caller = caller;
755
+ while (potential_caller != NULL && potential_caller->IsBuiltin ()) {
756
+ caller = potential_caller;
757
+ potential_caller = it.next ();
758
+ }
759
+
760
+ return CheckNonStrictCallerOrThrow (isolate, caller);
724
761
}
725
762
726
763
0 commit comments