Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/debug/debug-evaluate.cc

Issue 1264993002: Debugger: refactor ScopeIterator, FrameInspector and DebugEvaluate. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: readd include Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include "src/debug/debug-evaluate.h"
6
7 #include "src/accessors.h"
8 #include "src/contexts.h"
9 #include "src/debug/debug.h"
10 #include "src/debug/debug-frames.h"
11 #include "src/debug/debug-scopes.h"
12 #include "src/isolate.h"
13
14 namespace v8 {
15 namespace internal {
16
17
18 static inline bool IsDebugContext(Isolate* isolate, Context* context) {
19 // Try to unwrap script context if it exist.
20 if (context->IsScriptContext()) context = context->previous();
21 DCHECK_NOT_NULL(context);
22 return context == *isolate->debug()->debug_context();
23 }
24
25
26 MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
27 Handle<String> source,
28 bool disable_break,
29 Handle<Object> context_extension) {
30 // Handle the processing of break.
31 DisableBreak disable_break_scope(isolate->debug(), disable_break);
32
33 // Enter the top context from before the debugger was invoked.
34 SaveContext save(isolate);
35 SaveContext* top = &save;
36 while (top != NULL && IsDebugContext(isolate, *top->context())) {
37 top = top->prev();
38 }
39 if (top != NULL) isolate->set_context(*top->context());
40
41 // Get the native context now set to the top context from before the
42 // debugger was invoked.
43 Handle<Context> context = isolate->native_context();
44 Handle<JSObject> receiver(context->global_proxy());
45 Handle<SharedFunctionInfo> outer_info(context->closure()->shared(), isolate);
46 return Evaluate(isolate, outer_info, context, context_extension, receiver,
47 source);
48 }
49
50
51 MaybeHandle<Object> DebugEvaluate::Local(Isolate* isolate,
52 StackFrame::Id frame_id,
53 int inlined_jsframe_index,
54 Handle<String> source,
55 bool disable_break,
56 Handle<Object> context_extension) {
57 // Handle the processing of break.
58 DisableBreak disable_break_scope(isolate->debug(), disable_break);
59
60 // Get the frame where the debugging is performed.
61 JavaScriptFrameIterator it(isolate, frame_id);
62 JavaScriptFrame* frame = it.frame();
63
64 // Traverse the saved contexts chain to find the active context for the
65 // selected frame.
66 SaveContext* save =
67 DebugFrameHelper::FindSavedContextForFrame(isolate, frame);
68 SaveContext savex(isolate);
69 isolate->set_context(*(save->context()));
70
71 // Materialize stack locals and the arguments object.
72 ContextBuilder context_builder(isolate, frame, inlined_jsframe_index);
73 if (isolate->has_pending_exception()) return MaybeHandle<Object>();
74
75 Handle<Object> receiver(frame->receiver(), isolate);
76 MaybeHandle<Object> maybe_result = Evaluate(
77 isolate, context_builder.outer_info(),
78 context_builder.innermost_context(), context_extension, receiver, source);
79 if (!maybe_result.is_null()) context_builder.UpdateValues();
80 return maybe_result;
81 }
82
83
84 // Compile and evaluate source for the given context.
85 MaybeHandle<Object> DebugEvaluate::Evaluate(
86 Isolate* isolate, Handle<SharedFunctionInfo> outer_info,
87 Handle<Context> context, Handle<Object> context_extension,
88 Handle<Object> receiver, Handle<String> source) {
89 if (context_extension->IsJSObject()) {
90 Handle<JSObject> extension = Handle<JSObject>::cast(context_extension);
91 Handle<JSFunction> closure(context->closure(), isolate);
92 context = isolate->factory()->NewWithContext(closure, context, extension);
93 }
94
95 Handle<JSFunction> eval_fun;
96 ASSIGN_RETURN_ON_EXCEPTION(isolate, eval_fun,
97 Compiler::GetFunctionFromEval(
98 source, outer_info, context, SLOPPY,
99 NO_PARSE_RESTRICTION, RelocInfo::kNoPosition),
100 Object);
101
102 Handle<Object> result;
103 ASSIGN_RETURN_ON_EXCEPTION(
104 isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL),
105 Object);
106
107 // Skip the global proxy as it has no properties and always delegates to the
108 // real global object.
109 if (result->IsJSGlobalProxy()) {
110 PrototypeIterator iter(isolate, result);
111 // TODO(verwaest): This will crash when the global proxy is detached.
112 result = Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
113 }
114
115 return result;
116 }
117
118
119 DebugEvaluate::ContextBuilder::ContextBuilder(Isolate* isolate,
120 JavaScriptFrame* frame,
121 int inlined_jsframe_index)
122 : isolate_(isolate),
123 frame_(frame),
124 inlined_jsframe_index_(inlined_jsframe_index) {
125 FrameInspector frame_inspector(frame, inlined_jsframe_index, isolate);
126 Handle<JSFunction> function =
127 handle(JSFunction::cast(frame_inspector.GetFunction()));
128 Handle<Context> outer_context = handle(function->context(), isolate);
129 outer_info_ = handle(function->shared());
130 Handle<Context> inner_context;
131
132 bool stop = false;
133 for (ScopeIterator it(isolate, &frame_inspector);
134 !it.Failed() && !it.Done() && !stop; it.Next()) {
135 ScopeIterator::ScopeType scope_type = it.Type();
136
137 if (scope_type == ScopeIterator::ScopeTypeLocal) {
138 Handle<Context> parent_context =
139 it.HasContext() ? it.CurrentContext() : outer_context;
140
141 // The "this" binding, if any, can't be bound via "with". If we need
142 // to, add another node onto the outer context to bind "this".
143 parent_context = MaterializeReceiver(parent_context, function);
144
145 Handle<JSObject> materialized_function = NewJSObjectWithNullProto();
146
147 frame_inspector.MaterializeStackLocals(materialized_function, function);
148
149 MaterializeArgumentsObject(materialized_function, function);
150
151 Handle<Context> with_context = isolate->factory()->NewWithContext(
152 function, parent_context, materialized_function);
153
154 ContextChainElement context_chain_element;
155 context_chain_element.original_context = it.CurrentContext();
156 context_chain_element.materialized_object = materialized_function;
157 context_chain_element.scope_info = it.CurrentScopeInfo();
158 context_chain_.Add(context_chain_element);
159
160 stop = true;
161 RecordContextsInChain(&inner_context, with_context, with_context);
162 } else if (scope_type == ScopeIterator::ScopeTypeCatch ||
163 scope_type == ScopeIterator::ScopeTypeWith) {
164 Handle<Context> cloned_context =
165 Handle<Context>::cast(FixedArray::CopySize(
166 it.CurrentContext(), it.CurrentContext()->length()));
167
168 ContextChainElement context_chain_element;
169 context_chain_element.original_context = it.CurrentContext();
170 context_chain_element.cloned_context = cloned_context;
171 context_chain_.Add(context_chain_element);
172
173 RecordContextsInChain(&inner_context, cloned_context, cloned_context);
174 } else if (scope_type == ScopeIterator::ScopeTypeBlock) {
175 Handle<JSObject> materialized_object = NewJSObjectWithNullProto();
176 frame_inspector.MaterializeStackLocals(materialized_object,
177 it.CurrentScopeInfo());
178 if (it.HasContext()) {
179 Handle<Context> cloned_context =
180 Handle<Context>::cast(FixedArray::CopySize(
181 it.CurrentContext(), it.CurrentContext()->length()));
182 Handle<Context> with_context = isolate->factory()->NewWithContext(
183 function, cloned_context, materialized_object);
184
185 ContextChainElement context_chain_element;
186 context_chain_element.original_context = it.CurrentContext();
187 context_chain_element.cloned_context = cloned_context;
188 context_chain_element.materialized_object = materialized_object;
189 context_chain_element.scope_info = it.CurrentScopeInfo();
190 context_chain_.Add(context_chain_element);
191
192 RecordContextsInChain(&inner_context, cloned_context, with_context);
193 } else {
194 Handle<Context> with_context = isolate->factory()->NewWithContext(
195 function, outer_context, materialized_object);
196
197 ContextChainElement context_chain_element;
198 context_chain_element.materialized_object = materialized_object;
199 context_chain_element.scope_info = it.CurrentScopeInfo();
200 context_chain_.Add(context_chain_element);
201
202 RecordContextsInChain(&inner_context, with_context, with_context);
203 }
204 } else {
205 stop = true;
206 }
207 }
208 if (innermost_context_.is_null()) {
209 innermost_context_ = outer_context;
210 }
211 DCHECK(!innermost_context_.is_null());
212 }
213
214
215 void DebugEvaluate::ContextBuilder::UpdateValues() {
216 for (int i = 0; i < context_chain_.length(); i++) {
217 ContextChainElement element = context_chain_[i];
218 if (!element.original_context.is_null() &&
219 !element.cloned_context.is_null()) {
220 Handle<Context> cloned_context = element.cloned_context;
221 cloned_context->CopyTo(
222 Context::MIN_CONTEXT_SLOTS, *element.original_context,
223 Context::MIN_CONTEXT_SLOTS,
224 cloned_context->length() - Context::MIN_CONTEXT_SLOTS);
225 }
226 if (!element.materialized_object.is_null()) {
227 // Write back potential changes to materialized stack locals to the
228 // stack.
229 FrameInspector(frame_, inlined_jsframe_index_, isolate_)
230 .UpdateStackLocalsFromMaterializedObject(element.materialized_object,
231 element.scope_info);
232 }
233 }
234 }
235
236
237 Handle<JSObject> DebugEvaluate::ContextBuilder::NewJSObjectWithNullProto() {
238 Handle<JSObject> result =
239 isolate_->factory()->NewJSObject(isolate_->object_function());
240 Handle<Map> new_map =
241 Map::Copy(Handle<Map>(result->map()), "ObjectWithNullProto");
242 Map::SetPrototype(new_map, isolate_->factory()->null_value());
243 JSObject::MigrateToMap(result, new_map);
244 return result;
245 }
246
247
248 void DebugEvaluate::ContextBuilder::RecordContextsInChain(
249 Handle<Context>* inner_context, Handle<Context> first,
250 Handle<Context> last) {
251 if (!inner_context->is_null()) {
252 (*inner_context)->set_previous(*last);
253 } else {
254 innermost_context_ = last;
255 }
256 *inner_context = first;
257 }
258
259
260 void DebugEvaluate::ContextBuilder::MaterializeArgumentsObject(
261 Handle<JSObject> target, Handle<JSFunction> function) {
262 // Do not materialize the arguments object for eval or top-level code.
263 // Skip if "arguments" is already taken.
264 if (!function->shared()->is_function()) return;
265 Maybe<bool> maybe = JSReceiver::HasOwnProperty(
266 target, isolate_->factory()->arguments_string());
267 DCHECK(maybe.IsJust());
268 if (maybe.FromJust()) return;
269
270 // FunctionGetArguments can't throw an exception.
271 Handle<JSObject> arguments =
272 Handle<JSObject>::cast(Accessors::FunctionGetArguments(function));
273 Handle<String> arguments_str = isolate_->factory()->arguments_string();
274 JSObject::SetOwnPropertyIgnoreAttributes(target, arguments_str, arguments,
275 NONE)
276 .Check();
277 }
278
279
280 Handle<Context> DebugEvaluate::ContextBuilder::MaterializeReceiver(
281 Handle<Context> target, Handle<JSFunction> function) {
282 Handle<SharedFunctionInfo> shared(function->shared());
283 Handle<ScopeInfo> scope_info(shared->scope_info());
284 Handle<Object> receiver;
285 switch (scope_info->scope_type()) {
286 case FUNCTION_SCOPE: {
287 VariableMode mode;
288 VariableLocation location;
289 InitializationFlag init_flag;
290 MaybeAssignedFlag maybe_assigned_flag;
291
292 // Don't bother creating a fake context node if "this" is in the context
293 // already.
294 if (ScopeInfo::ContextSlotIndex(
295 scope_info, isolate_->factory()->this_string(), &mode, &location,
296 &init_flag, &maybe_assigned_flag) >= 0) {
297 return target;
298 }
299 receiver = handle(frame_->receiver(), isolate_);
300 break;
301 }
302 case MODULE_SCOPE:
303 receiver = isolate_->factory()->undefined_value();
304 break;
305 case SCRIPT_SCOPE:
306 receiver = handle(function->global_proxy(), isolate_);
307 break;
308 default:
309 // For eval code, arrow functions, and the like, there's no "this" binding
310 // to materialize.
311 return target;
312 }
313
314 return isolate_->factory()->NewCatchContext(
315 function, target, isolate_->factory()->this_string(), receiver);
316 }
317
318 } // namespace internal
319 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug-evaluate.h ('k') | src/debug/debug-frames.h » ('j') | src/debug/debug-scopes.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698