Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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->debug(), |
| 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 Loading... | |
| 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 bool DebugEvaluate::HasNoSideEffect(Handle<BytecodeArray> bytecode_array) { | |
| 259 if (FLAG_trace_side_effect_free_debug_evaluate) { | |
| 260 PrintF("[debug-evaluate] Checking bytecode array\n"); | |
| 261 bytecode_array->Print(); | |
| 262 } | |
| 263 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); | |
| 264 it.Advance()) { | |
| 265 typedef interpreter::Bytecode Bytecode; | |
| 266 typedef interpreter::Bytecodes Bytecodes; | |
| 267 Bytecode bytecode = it.current_bytecode(); | |
| 268 | |
| 269 // TODO(yangguo): whitelist more bytecodes. | |
| 270 if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) continue; | |
| 271 // if (Bytecodes::IsCallRuntime(bytecode)) continue; | |
| 272 if (Bytecodes::IsCallOrNew(bytecode)) continue; | |
| 273 if (Bytecodes::IsCallRuntime(bytecode)) { | |
| 274 Runtime::FunctionId runtime_function; | |
| 275 if (bytecode == Bytecode::kInvokeIntrinsic) { | |
| 276 runtime_function = it.GetIntrinsicIdOperand(0); | |
| 277 } else { | |
| 278 runtime_function = it.GetRuntimeIdOperand(0); | |
| 279 } | |
| 280 switch (runtime_function) { | |
| 281 case Runtime::kToObject: | |
| 282 case Runtime::kInlineToObject: | |
| 283 case Runtime::kLoadLookupSlotForCall: | |
| 284 case Runtime::kThrowReferenceError: | |
| 285 continue; | |
| 286 default: | |
| 287 if (FLAG_trace_side_effect_free_debug_evaluate) { | |
| 288 PrintF("[debug-evaluate] %s is not a read-only runtime function.\n", | |
| 289 Runtime::FunctionForId(runtime_function)->name); | |
| 290 } | |
| 291 return false; | |
| 292 } | |
| 293 } | |
| 294 switch (bytecode) { | |
| 295 case Bytecode::kStackCheck: | |
| 296 case Bytecode::kLdaLookupSlot: | |
| 297 case Bytecode::kLdaGlobal: | |
| 298 case Bytecode::kLdaNamedProperty: | |
| 299 case Bytecode::kLdaKeyedProperty: | |
| 300 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
| |
| 301 case Bytecode::kReturn: | |
| 302 case Bytecode::kCreateCatchContext: | |
| 303 case Bytecode::kSetPendingMessage: | |
| 304 case Bytecode::kPushContext: | |
| 305 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.
| |
| 306 continue; | |
| 307 default: | |
| 308 if (FLAG_trace_side_effect_free_debug_evaluate) { | |
| 309 PrintF("[debug-evaluate] %s is not a read-only bytecode.\n", | |
| 310 interpreter::Bytecodes::ToString(bytecode)); | |
| 311 } | |
| 312 return false; | |
| 313 } | |
| 314 } | |
| 315 return true; | |
| 316 } | |
| 317 | |
| 252 } // namespace internal | 318 } // namespace internal |
| 253 } // namespace v8 | 319 } // namespace v8 |
| OLD | NEW |