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

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

Issue 2622863003: [debugger] infrastructure for side-effect-free debug-evaluate. (Closed)
Patch Set: fix mips one more time Created 3 years, 11 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
« no previous file with comments | « src/debug/debug-evaluate.h ('k') | src/debug/ia32/debug-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/debug/debug-evaluate.h" 5 #include "src/debug/debug-evaluate.h"
6 6
7 #include "src/accessors.h" 7 #include "src/accessors.h"
8 #include "src/compiler.h" 8 #include "src/compiler.h"
9 #include "src/contexts.h" 9 #include "src/contexts.h"
10 #include "src/debug/debug-frames.h" 10 #include "src/debug/debug-frames.h"
11 #include "src/debug/debug-scopes.h" 11 #include "src/debug/debug-scopes.h"
12 #include "src/debug/debug.h" 12 #include "src/debug/debug.h"
13 #include "src/frames-inl.h" 13 #include "src/frames-inl.h"
14 #include "src/globals.h" 14 #include "src/globals.h"
15 #include "src/interpreter/bytecode-array-iterator.h"
16 #include "src/interpreter/bytecodes.h"
15 #include "src/isolate-inl.h" 17 #include "src/isolate-inl.h"
16 18
17 namespace v8 { 19 namespace v8 {
18 namespace internal { 20 namespace internal {
19 21
20 static inline bool IsDebugContext(Isolate* isolate, Context* context) { 22 static inline bool IsDebugContext(Isolate* isolate, Context* context) {
21 return context->native_context() == *isolate->debug()->debug_context(); 23 return context->native_context() == *isolate->debug()->debug_context();
22 } 24 }
23 25
24 MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate, 26 MaybeHandle<Object> DebugEvaluate::Global(Isolate* isolate,
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
85 Handle<Context> context, Handle<Object> receiver, Handle<String> source) { 87 Handle<Context> context, Handle<Object> receiver, Handle<String> source) {
86 Handle<JSFunction> eval_fun; 88 Handle<JSFunction> eval_fun;
87 ASSIGN_RETURN_ON_EXCEPTION( 89 ASSIGN_RETURN_ON_EXCEPTION(
88 isolate, eval_fun, 90 isolate, eval_fun,
89 Compiler::GetFunctionFromEval(source, outer_info, context, SLOPPY, 91 Compiler::GetFunctionFromEval(source, outer_info, context, SLOPPY,
90 NO_PARSE_RESTRICTION, kNoSourcePosition, 92 NO_PARSE_RESTRICTION, kNoSourcePosition,
91 kNoSourcePosition), 93 kNoSourcePosition),
92 Object); 94 Object);
93 95
94 Handle<Object> result; 96 Handle<Object> result;
95 ASSIGN_RETURN_ON_EXCEPTION( 97 {
96 isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL), 98 NoSideEffectScope no_side_effect(isolate,
97 Object); 99 FLAG_side_effect_free_debug_evaluate);
100 ASSIGN_RETURN_ON_EXCEPTION(
101 isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL),
102 Object);
103 }
98 104
99 // Skip the global proxy as it has no properties and always delegates to the 105 // Skip the global proxy as it has no properties and always delegates to the
100 // real global object. 106 // real global object.
101 if (result->IsJSGlobalProxy()) { 107 if (result->IsJSGlobalProxy()) {
102 PrototypeIterator iter(isolate, Handle<JSGlobalProxy>::cast(result)); 108 PrototypeIterator iter(isolate, Handle<JSGlobalProxy>::cast(result));
103 // TODO(verwaest): This will crash when the global proxy is detached. 109 // TODO(verwaest): This will crash when the global proxy is detached.
104 result = PrototypeIterator::GetCurrent<JSObject>(iter); 110 result = PrototypeIterator::GetCurrent<JSObject>(iter);
105 } 111 }
106 112
107 return result; 113 return result;
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 // 'this' is allocated in an outer context and is is already being 248 // 'this' is allocated in an outer context and is is already being
243 // referenced by the current function, so it can be correctly resolved. 249 // referenced by the current function, so it can be correctly resolved.
244 return; 250 return;
245 } else if (local_function->shared()->scope_info()->HasReceiver() && 251 } else if (local_function->shared()->scope_info()->HasReceiver() &&
246 !frame_->receiver()->IsTheHole(isolate_)) { 252 !frame_->receiver()->IsTheHole(isolate_)) {
247 recv = handle(frame_->receiver(), isolate_); 253 recv = handle(frame_->receiver(), isolate_);
248 } 254 }
249 JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check(); 255 JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check();
250 } 256 }
251 257
258 namespace {
259
260 bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
261 DCHECK_EQ(Runtime::INLINE, Runtime::FunctionForId(id)->intrinsic_type);
262 switch (id) {
263 // Whitelist for intrinsics.
264 case Runtime::kInlineToObject:
265 return true;
266 default:
267 if (FLAG_trace_side_effect_free_debug_evaluate) {
268 PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
269 Runtime::FunctionForId(id)->name);
270 }
271 return false;
272 }
273 }
274
275 bool RuntimeFunctionHasNoSideEffect(Runtime::FunctionId id) {
276 DCHECK_EQ(Runtime::RUNTIME, Runtime::FunctionForId(id)->intrinsic_type);
277 switch (id) {
278 // Whitelist for runtime functions.
279 case Runtime::kToObject:
280 case Runtime::kLoadLookupSlotForCall:
281 case Runtime::kThrowReferenceError:
282 return true;
283 default:
284 if (FLAG_trace_side_effect_free_debug_evaluate) {
285 PrintF("[debug-evaluate] runtime %s may cause side effect.\n",
286 Runtime::FunctionForId(id)->name);
287 }
288 return false;
289 }
290 }
291
292 bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
293 typedef interpreter::Bytecode Bytecode;
294 typedef interpreter::Bytecodes Bytecodes;
295 if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
296 if (Bytecodes::IsCallOrNew(bytecode)) return true;
297 switch (bytecode) {
298 // Whitelist for bytecodes.
299 case Bytecode::kStackCheck:
300 case Bytecode::kLdaLookupSlot:
301 case Bytecode::kLdaGlobal:
302 case Bytecode::kLdaNamedProperty:
303 case Bytecode::kLdaKeyedProperty:
304 case Bytecode::kAdd:
305 case Bytecode::kReturn:
306 case Bytecode::kCreateCatchContext:
307 case Bytecode::kSetPendingMessage:
308 return true;
309 default:
310 if (FLAG_trace_side_effect_free_debug_evaluate) {
311 PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
312 Bytecodes::ToString(bytecode));
313 }
314 return false;
315 }
316 }
317
318 bool BuiltinHasNoSideEffect(Builtins::Name id) {
319 switch (id) {
320 // Whitelist for builtins.
321 case Builtins::kMathSin:
322 return true;
323 default:
324 if (FLAG_trace_side_effect_free_debug_evaluate) {
325 PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
326 Builtins::name(id));
327 }
328 return false;
329 }
330 }
331
332 static const Address accessors_with_no_side_effect[] = {
333 // Whitelist for accessors.
334 FUNCTION_ADDR(Accessors::StringLengthGetter),
335 FUNCTION_ADDR(Accessors::ArrayLengthGetter)};
336
337 } // anonymous namespace
338
339 // static
340 bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) {
341 if (FLAG_trace_side_effect_free_debug_evaluate) {
342 PrintF("[debug-evaluate] Checking function %s for side effect.\n",
343 info->DebugName()->ToCString().get());
344 }
345
346 DCHECK(info->is_compiled());
347
348 if (info->HasBytecodeArray()) {
349 // Check bytecodes against whitelist.
350 Handle<BytecodeArray> bytecode_array(info->bytecode_array());
351 if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print();
352 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
353 it.Advance()) {
354 interpreter::Bytecode bytecode = it.current_bytecode();
355
356 if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
357 if (bytecode == interpreter::Bytecode::kInvokeIntrinsic) {
358 Runtime::FunctionId id = it.GetIntrinsicIdOperand(0);
359 if (IntrinsicHasNoSideEffect(id)) continue;
360 } else {
361 Runtime::FunctionId id = it.GetRuntimeIdOperand(0);
362 if (RuntimeFunctionHasNoSideEffect(id)) continue;
363 }
364 return false;
365 }
366
367 if (BytecodeHasNoSideEffect(bytecode)) continue;
368
369 // Did not match whitelist.
370 return false;
371 }
372 return true;
373 } else {
374 // Check built-ins against whitelist.
375 int builtin_index = info->code()->builtin_index();
376 if (builtin_index >= 0 && builtin_index < Builtins::builtin_count &&
377 BuiltinHasNoSideEffect(static_cast<Builtins::Name>(builtin_index))) {
378 return true;
379 }
380 }
381
382 return false;
383 }
384
385 // static
386 bool DebugEvaluate::CallbackHasNoSideEffect(Address function_addr) {
387 for (size_t i = 0; i < arraysize(accessors_with_no_side_effect); i++) {
388 if (function_addr == accessors_with_no_side_effect[i]) return true;
389 }
390
391 if (FLAG_trace_side_effect_free_debug_evaluate) {
392 PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n",
393 reinterpret_cast<void*>(function_addr));
394 }
395 return false;
396 }
397
252 } // namespace internal 398 } // namespace internal
253 } // namespace v8 399 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug-evaluate.h ('k') | src/debug/ia32/debug-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698