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 <vector> 9 10 #include "src/debug/debug-frames.h" 11 #include "src/debug/debug-scopes.h" 12 #include "src/objects.h" 13 #include "src/objects/shared-function-info.h" 14 #include "src/objects/string-table.h" 15 16 namespace v8 { 17 namespace internal { 18 19 class FrameInspector; 20 21 class DebugEvaluate : public AllStatic { 22 public: 23 static MaybeHandle<Object> Global(Isolate* isolate, Handle<String> source, 24 bool throw_on_side_effect); 25 26 // Evaluate a piece of JavaScript in the context of a stack frame for 27 // debugging. Things that need special attention are: 28 // - Parameters and stack-allocated locals need to be materialized. Altered 29 // values need to be written back to the stack afterwards. 30 // - The arguments object needs to materialized. 31 static MaybeHandle<Object> Local(Isolate* isolate, StackFrame::Id frame_id, 32 int inlined_jsframe_index, 33 Handle<String> source, 34 bool throw_on_side_effect); 35 36 // This is used for break-at-entry for builtins and API functions. 37 // Evaluate a piece of JavaScript in the native context, but with the 38 // materialized arguments object and receiver of the current call. 39 static MaybeHandle<Object> WithTopmostArguments(Isolate* isolate, 40 Handle<String> source); 41 42 static DebugInfo::SideEffectState FunctionGetSideEffectState( 43 Isolate* isolate, Handle<SharedFunctionInfo> info); 44 static bool CallbackHasNoSideEffect(Object* callback_info); 45 static void ApplySideEffectChecks(Handle<BytecodeArray> bytecode_array); 46 47 private: 48 // This class builds a context chain for evaluation of expressions 49 // in debugger. 50 // The scope chain leading up to a breakpoint where evaluation occurs 51 // looks like: 52 // - [a mix of with, catch and block scopes] 53 // - [function stack + context] 54 // - [outer context] 55 // The builder materializes all stack variables into properties of objects; 56 // the expression is then evaluated as if it is inside a series of 'with' 57 // statements using those objects. To this end, the builder builds a new 58 // context chain, based on a scope chain: 59 // - every With and Catch scope begets a cloned context 60 // - Block scope begets one or two contexts: 61 // - if a block has context-allocated varaibles, its context is cloned 62 // - stack locals are materizalized as a With context 63 // - Local scope begets a With context for materizalized locals, chained to 64 // original function context. Original function context is the end of 65 // the chain. 66 class ContextBuilder { 67 public: 68 ContextBuilder(Isolate* isolate, JavaScriptFrame* frame, 69 int inlined_jsframe_index); 70 71 void UpdateValues(); 72 evaluation_context()73 Handle<Context> evaluation_context() const { return evaluation_context_; } 74 Handle<SharedFunctionInfo> outer_info() const; 75 76 private: 77 struct ContextChainElement { 78 Handle<Context> wrapped_context; 79 Handle<JSObject> materialized_object; 80 Handle<StringSet> whitelist; 81 }; 82 83 Handle<Context> evaluation_context_; 84 std::vector<ContextChainElement> context_chain_; 85 Isolate* isolate_; 86 FrameInspector frame_inspector_; 87 ScopeIterator scope_iterator_; 88 }; 89 90 static MaybeHandle<Object> Evaluate(Isolate* isolate, 91 Handle<SharedFunctionInfo> outer_info, 92 Handle<Context> context, 93 Handle<Object> receiver, 94 Handle<String> source, 95 bool throw_on_side_effect); 96 }; 97 98 99 } // namespace internal 100 } // namespace v8 101 102 #endif // V8_DEBUG_DEBUG_EVALUATE_H_ 103