Index: src/debug/debug-evaluate.cc |
diff --git a/src/debug/debug-evaluate.cc b/src/debug/debug-evaluate.cc |
index e93b5952c876ad2ffc7ae80579cf7ed08520efbb..35003604bc014fa1a8beaa180104602262909176 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->debug(), |
+ 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,65 @@ void DebugEvaluate::ContextBuilder::MaterializeReceiver( |
JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check(); |
} |
+bool DebugEvaluate::HasNoSideEffect(Handle<BytecodeArray> bytecode_array) { |
+ if (FLAG_trace_side_effect_free_debug_evaluate) { |
+ PrintF("[debug-evaluate] Checking bytecode array\n"); |
+ bytecode_array->Print(); |
+ } |
+ for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); |
+ it.Advance()) { |
+ typedef interpreter::Bytecode Bytecode; |
+ typedef interpreter::Bytecodes Bytecodes; |
+ Bytecode bytecode = it.current_bytecode(); |
+ |
+ // TODO(yangguo): whitelist more bytecodes. |
+ if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) continue; |
+ // if (Bytecodes::IsCallRuntime(bytecode)) continue; |
+ if (Bytecodes::IsCallOrNew(bytecode)) continue; |
+ if (Bytecodes::IsCallRuntime(bytecode)) { |
+ Runtime::FunctionId runtime_function; |
+ if (bytecode == Bytecode::kInvokeIntrinsic) { |
+ runtime_function = it.GetIntrinsicIdOperand(0); |
+ } else { |
+ runtime_function = it.GetRuntimeIdOperand(0); |
+ } |
+ switch (runtime_function) { |
+ case Runtime::kToObject: |
+ case Runtime::kInlineToObject: |
+ case Runtime::kLoadLookupSlotForCall: |
+ case Runtime::kThrowReferenceError: |
+ continue; |
+ default: |
+ if (FLAG_trace_side_effect_free_debug_evaluate) { |
+ PrintF("[debug-evaluate] %s is not a read-only runtime function.\n", |
+ Runtime::FunctionForId(runtime_function)->name); |
+ } |
+ return false; |
+ } |
+ } |
+ switch (bytecode) { |
+ case Bytecode::kStackCheck: |
+ case Bytecode::kLdaLookupSlot: |
+ case Bytecode::kLdaGlobal: |
+ case Bytecode::kLdaNamedProperty: |
+ case Bytecode::kLdaKeyedProperty: |
+ case Bytecode::kAdd: |
rmcilroy
2017/01/10 21:10:25
You probably want to add kAddSmi as since kLdaSmi
Yang
2017/01/11 10:32:10
Yes. This whitelist is by far not complete. I'll p
|
+ case Bytecode::kReturn: |
+ case Bytecode::kCreateCatchContext: |
+ case Bytecode::kSetPendingMessage: |
+ case Bytecode::kPushContext: |
+ case Bytecode::kPopContext: |
rmcilroy
2017/01/10 18:17:38
It seems like this might bitrot as we add new byte
rmcilroy
2017/01/10 21:10:25
Ahh sorry, I missed the call to IsWithoutExternalS
Yang
2017/01/11 10:32:10
Done.
|
+ continue; |
+ default: |
+ if (FLAG_trace_side_effect_free_debug_evaluate) { |
+ PrintF("[debug-evaluate] %s is not a read-only bytecode.\n", |
+ interpreter::Bytecodes::ToString(bytecode)); |
+ } |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
} // namespace internal |
} // namespace v8 |