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

Unified 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 side-by-side diff with in-line comments
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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug/debug-evaluate.cc
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc
index e93b5952c876ad2ffc7ae80579cf7ed08520efbb..8f068284a71b863f55581ffe18b1903a8ea77411 100644
--- a/src/debug/debug-evaluate.cc
+++ b/src/debug/debug-evaluate.cc
@@ -12,6 +12,8 @@
#include "src/debug/debug.h"
#include "src/frames-inl.h"
#include "src/globals.h"
+#include "src/interpreter/bytecode-array-iterator.h"
+#include "src/interpreter/bytecodes.h"
#include "src/isolate-inl.h"
namespace v8 {
@@ -92,9 +94,13 @@ MaybeHandle<Object> DebugEvaluate::Evaluate(
Object);
Handle<Object> result;
- ASSIGN_RETURN_ON_EXCEPTION(
- isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL),
- Object);
+ {
+ NoSideEffectScope no_side_effect(isolate,
+ FLAG_side_effect_free_debug_evaluate);
+ ASSIGN_RETURN_ON_EXCEPTION(
+ isolate, result, Execution::Call(isolate, eval_fun, receiver, 0, NULL),
+ Object);
+ }
// Skip the global proxy as it has no properties and always delegates to the
// real global object.
@@ -249,5 +255,145 @@ void DebugEvaluate::ContextBuilder::MaterializeReceiver(
JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check();
}
+namespace {
+
+bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
+ DCHECK_EQ(Runtime::INLINE, Runtime::FunctionForId(id)->intrinsic_type);
+ switch (id) {
+ // Whitelist for intrinsics.
+ case Runtime::kInlineToObject:
+ return true;
+ default:
+ if (FLAG_trace_side_effect_free_debug_evaluate) {
+ PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n",
+ Runtime::FunctionForId(id)->name);
+ }
+ return false;
+ }
+}
+
+bool RuntimeFunctionHasNoSideEffect(Runtime::FunctionId id) {
+ DCHECK_EQ(Runtime::RUNTIME, Runtime::FunctionForId(id)->intrinsic_type);
+ switch (id) {
+ // Whitelist for runtime functions.
+ case Runtime::kToObject:
+ case Runtime::kLoadLookupSlotForCall:
+ case Runtime::kThrowReferenceError:
+ return true;
+ default:
+ if (FLAG_trace_side_effect_free_debug_evaluate) {
+ PrintF("[debug-evaluate] runtime %s may cause side effect.\n",
+ Runtime::FunctionForId(id)->name);
+ }
+ return false;
+ }
+}
+
+bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) {
+ typedef interpreter::Bytecode Bytecode;
+ typedef interpreter::Bytecodes Bytecodes;
+ if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true;
+ if (Bytecodes::IsCallOrNew(bytecode)) return true;
+ switch (bytecode) {
+ // Whitelist for bytecodes.
+ case Bytecode::kStackCheck:
+ case Bytecode::kLdaLookupSlot:
+ case Bytecode::kLdaGlobal:
+ case Bytecode::kLdaNamedProperty:
+ case Bytecode::kLdaKeyedProperty:
+ case Bytecode::kAdd:
+ case Bytecode::kReturn:
+ case Bytecode::kCreateCatchContext:
+ case Bytecode::kSetPendingMessage:
+ return true;
+ default:
+ if (FLAG_trace_side_effect_free_debug_evaluate) {
+ PrintF("[debug-evaluate] bytecode %s may cause side effect.\n",
+ Bytecodes::ToString(bytecode));
+ }
+ return false;
+ }
+}
+
+bool BuiltinHasNoSideEffect(Builtins::Name id) {
+ switch (id) {
+ // Whitelist for builtins.
+ case Builtins::kMathSin:
+ return true;
+ default:
+ if (FLAG_trace_side_effect_free_debug_evaluate) {
+ PrintF("[debug-evaluate] built-in %s may cause side effect.\n",
+ Builtins::name(id));
+ }
+ return false;
+ }
+}
+
+static const Address accessors_with_no_side_effect[] = {
+ // Whitelist for accessors.
+ FUNCTION_ADDR(Accessors::StringLengthGetter),
+ FUNCTION_ADDR(Accessors::ArrayLengthGetter)};
+
+} // anonymous namespace
+
+// static
+bool DebugEvaluate::FunctionHasNoSideEffect(Handle<SharedFunctionInfo> info) {
+ if (FLAG_trace_side_effect_free_debug_evaluate) {
+ PrintF("[debug-evaluate] Checking function %s for side effect.\n",
+ info->DebugName()->ToCString().get());
+ }
+
+ DCHECK(info->is_compiled());
+
+ if (info->HasBytecodeArray()) {
+ // Check bytecodes against whitelist.
+ Handle<BytecodeArray> bytecode_array(info->bytecode_array());
+ if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print();
+ for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done();
+ it.Advance()) {
+ interpreter::Bytecode bytecode = it.current_bytecode();
+
+ if (interpreter::Bytecodes::IsCallRuntime(bytecode)) {
+ if (bytecode == interpreter::Bytecode::kInvokeIntrinsic) {
+ Runtime::FunctionId id = it.GetIntrinsicIdOperand(0);
+ if (IntrinsicHasNoSideEffect(id)) continue;
+ } else {
+ Runtime::FunctionId id = it.GetRuntimeIdOperand(0);
+ if (RuntimeFunctionHasNoSideEffect(id)) continue;
+ }
+ return false;
+ }
+
+ if (BytecodeHasNoSideEffect(bytecode)) continue;
+
+ // Did not match whitelist.
+ return false;
+ }
+ return true;
+ } else {
+ // Check built-ins against whitelist.
+ int builtin_index = info->code()->builtin_index();
+ if (builtin_index >= 0 && builtin_index < Builtins::builtin_count &&
+ BuiltinHasNoSideEffect(static_cast<Builtins::Name>(builtin_index))) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// static
+bool DebugEvaluate::CallbackHasNoSideEffect(Address function_addr) {
+ for (size_t i = 0; i < arraysize(accessors_with_no_side_effect); i++) {
+ if (function_addr == accessors_with_no_side_effect[i]) return true;
+ }
+
+ if (FLAG_trace_side_effect_free_debug_evaluate) {
+ PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n",
+ reinterpret_cast<void*>(function_addr));
+ }
+ return false;
+}
+
} // namespace internal
} // namespace v8
« 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