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