1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_DEBUG_DEBUG_EVALUATE_H_
6 #define V8_DEBUG_DEBUG_EVALUATE_H_
7 
8 #include "src/frames.h"
9 #include "src/objects.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 class DebugEvaluate : public AllStatic {
15  public:
16   static MaybeHandle<Object> Global(Isolate* isolate, Handle<String> source,
17                                     bool disable_break,
18                                     Handle<HeapObject> context_extension);
19 
20   // Evaluate a piece of JavaScript in the context of a stack frame for
21   // debugging.  Things that need special attention are:
22   // - Parameters and stack-allocated locals need to be materialized.  Altered
23   //   values need to be written back to the stack afterwards.
24   // - The arguments object needs to materialized.
25   static MaybeHandle<Object> Local(Isolate* isolate, StackFrame::Id frame_id,
26                                    int inlined_jsframe_index,
27                                    Handle<String> source, bool disable_break,
28                                    Handle<HeapObject> context_extension);
29 
30  private:
31   // This class builds a context chain for evaluation of expressions
32   // in debugger.
33   // The scope chain leading up to a breakpoint where evaluation occurs
34   // looks like:
35   // - [a mix of with, catch and block scopes]
36   //    - [function stack + context]
37   //      - [outer context]
38   // The builder materializes all stack variables into properties of objects;
39   // the expression is then evaluated as if it is inside a series of 'with'
40   // statements using those objects. To this end, the builder builds a new
41   // context chain, based on a scope chain:
42   //   - every With and Catch scope begets a cloned context
43   //   - Block scope begets one or two contexts:
44   //       - if a block has context-allocated varaibles, its context is cloned
45   //       - stack locals are materizalized as a With context
46   //   - Local scope begets a With context for materizalized locals, chained to
47   //     original function context. Original function context is the end of
48   //     the chain.
49   class ContextBuilder {
50    public:
51     ContextBuilder(Isolate* isolate, JavaScriptFrame* frame,
52                    int inlined_jsframe_index);
53 
54     void UpdateValues();
55 
innermost_context()56     Handle<Context> innermost_context() const { return innermost_context_; }
native_context()57     Handle<Context> native_context() const { return native_context_; }
outer_info()58     Handle<SharedFunctionInfo> outer_info() const { return outer_info_; }
59 
60    private:
61     struct ContextChainElement {
62       Handle<Context> original_context;
63       Handle<Context> cloned_context;
64       Handle<JSObject> materialized_object;
65       Handle<ScopeInfo> scope_info;
66     };
67 
68     void RecordContextsInChain(Handle<Context>* inner_context,
69                                Handle<Context> first, Handle<Context> last);
70 
71     Handle<JSObject> NewJSObjectWithNullProto();
72 
73     // Helper function to find or create the arguments object for
74     // Runtime_DebugEvaluate.
75     void MaterializeArgumentsObject(Handle<JSObject> target,
76                                     Handle<JSFunction> function);
77 
78     void MaterializeContextChain(Handle<JSObject> target,
79                                  Handle<Context> context);
80 
81     void UpdateContextChainFromMaterializedObject(Handle<JSObject> source,
82                                                   Handle<Context> context);
83 
84     Handle<Context> MaterializeReceiver(Handle<Context> parent_context,
85                                         Handle<Context> lookup_context,
86                                         Handle<JSFunction> local_function,
87                                         Handle<JSFunction> global_function,
88                                         bool this_is_non_local);
89 
90     MaybeHandle<Object> LoadFromContext(Handle<Context> context,
91                                         Handle<String> name, bool* global);
92 
93     void StoreToContext(Handle<Context> context, Handle<String> name,
94                         Handle<Object> value);
95 
96     Handle<SharedFunctionInfo> outer_info_;
97     Handle<Context> innermost_context_;
98     Handle<Context> native_context_;
99     List<ContextChainElement> context_chain_;
100     List<Handle<String> > non_locals_;
101     Isolate* isolate_;
102     JavaScriptFrame* frame_;
103     int inlined_jsframe_index_;
104   };
105 
106   static MaybeHandle<Object> Evaluate(Isolate* isolate,
107                                       Handle<SharedFunctionInfo> outer_info,
108                                       Handle<Context> context,
109                                       Handle<HeapObject> context_extension,
110                                       Handle<Object> receiver,
111                                       Handle<String> source);
112 };
113 
114 
115 }  // namespace internal
116 }  // namespace v8
117 
118 #endif  // V8_DEBUG_DEBUG_EVALUATE_H_
119