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" |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 } else if (local_function->shared()->scope_info()->HasReceiver() && | 251 } else if (local_function->shared()->scope_info()->HasReceiver() && |
252 !frame_->receiver()->IsTheHole(isolate_)) { | 252 !frame_->receiver()->IsTheHole(isolate_)) { |
253 recv = handle(frame_->receiver(), isolate_); | 253 recv = handle(frame_->receiver(), isolate_); |
254 } | 254 } |
255 JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check(); | 255 JSObject::SetOwnPropertyIgnoreAttributes(target, name, recv, NONE).Check(); |
256 } | 256 } |
257 | 257 |
258 namespace { | 258 namespace { |
259 | 259 |
260 bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { | 260 bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) { |
261 DCHECK_EQ(Runtime::INLINE, Runtime::FunctionForId(id)->intrinsic_type); | |
262 switch (id) { | 261 switch (id) { |
263 // Whitelist for intrinsics. | 262 // Whitelist for intrinsics. |
jgruber
2017/01/13 10:08:02
Nit: the comment and function name could be update
Yang
2017/01/16 13:20:31
Done.
| |
263 // Conversions. | |
264 case Runtime::kToInteger: | |
265 case Runtime::kInlineToInteger: | |
266 case Runtime::kToObject: | |
264 case Runtime::kInlineToObject: | 267 case Runtime::kInlineToObject: |
268 case Runtime::kToString: | |
269 case Runtime::kInlineToString: | |
270 case Runtime::kToLength: | |
271 case Runtime::kInlineToLength: | |
272 // Loads. | |
273 case Runtime::kLoadLookupSlotForCall: | |
274 // Errors. | |
275 case Runtime::kThrowReferenceError: | |
276 // Strings. | |
277 case Runtime::kInlineStringCharCodeAt: | |
278 case Runtime::kStringCharCodeAt: | |
279 case Runtime::kStringIndexOf: | |
280 case Runtime::kStringReplaceOneCharWithString: | |
281 case Runtime::kSubString: | |
282 case Runtime::kInlineSubString: | |
283 case Runtime::kStringToLowerCase: | |
284 case Runtime::kStringToUpperCase: | |
285 case Runtime::kRegExpInternalReplace: | |
286 // Literals. | |
287 case Runtime::kCreateArrayLiteral: | |
288 case Runtime::kCreateObjectLiteral: | |
289 case Runtime::kCreateRegExpLiteral: | |
290 // Misc. | |
291 case Runtime::kInlineCall: | |
292 case Runtime::kCall: | |
293 case Runtime::kInlineMaxSmi: | |
294 case Runtime::kMaxSmi: | |
265 return true; | 295 return true; |
266 default: | 296 default: |
267 if (FLAG_trace_side_effect_free_debug_evaluate) { | 297 if (FLAG_trace_side_effect_free_debug_evaluate) { |
268 PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n", | 298 PrintF("[debug-evaluate] intrinsic %s may cause side effect.\n", |
269 Runtime::FunctionForId(id)->name); | 299 Runtime::FunctionForId(id)->name); |
270 } | 300 } |
271 return false; | 301 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 } | 302 } |
290 } | 303 } |
291 | 304 |
292 bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { | 305 bool BytecodeHasNoSideEffect(interpreter::Bytecode bytecode) { |
293 typedef interpreter::Bytecode Bytecode; | 306 typedef interpreter::Bytecode Bytecode; |
294 typedef interpreter::Bytecodes Bytecodes; | 307 typedef interpreter::Bytecodes Bytecodes; |
295 if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true; | 308 if (Bytecodes::IsWithoutExternalSideEffects(bytecode)) return true; |
296 if (Bytecodes::IsCallOrNew(bytecode)) return true; | 309 if (Bytecodes::IsCallOrNew(bytecode)) return true; |
310 if (Bytecodes::WritesBooleanToAccumulator(bytecode)) return true; | |
311 if (Bytecodes::IsJumpIfToBoolean(bytecode)) return true; | |
312 if (Bytecodes::IsPrefixScalingBytecode(bytecode)) return true; | |
297 switch (bytecode) { | 313 switch (bytecode) { |
298 // Whitelist for bytecodes. | 314 // Whitelist for bytecodes. |
299 case Bytecode::kStackCheck: | 315 // Loads. |
300 case Bytecode::kLdaLookupSlot: | 316 case Bytecode::kLdaLookupSlot: |
301 case Bytecode::kLdaGlobal: | 317 case Bytecode::kLdaGlobal: |
302 case Bytecode::kLdaNamedProperty: | 318 case Bytecode::kLdaNamedProperty: |
303 case Bytecode::kLdaKeyedProperty: | 319 case Bytecode::kLdaKeyedProperty: |
320 // Arithmetics. | |
304 case Bytecode::kAdd: | 321 case Bytecode::kAdd: |
322 case Bytecode::kAddSmi: | |
323 case Bytecode::kSub: | |
324 case Bytecode::kSubSmi: | |
325 case Bytecode::kMul: | |
326 case Bytecode::kDiv: | |
327 case Bytecode::kMod: | |
328 case Bytecode::kBitwiseAnd: | |
329 case Bytecode::kBitwiseAndSmi: | |
330 case Bytecode::kBitwiseOr: | |
331 case Bytecode::kBitwiseOrSmi: | |
332 case Bytecode::kBitwiseXor: | |
333 case Bytecode::kLogicalNot: | |
334 case Bytecode::kShiftLeft: | |
335 case Bytecode::kShiftLeftSmi: | |
336 case Bytecode::kShiftRight: | |
337 case Bytecode::kShiftRightSmi: | |
338 case Bytecode::kShiftRightLogical: | |
339 case Bytecode::kInc: | |
340 case Bytecode::kDec: | |
341 case Bytecode::kLogicalNot: | |
342 case Bytecode::kToBooleanLogicalNot: | |
343 case Bytecode::kTypeOf: | |
344 // Contexts. | |
345 case Bytecode::kCreateBlockContext: | |
346 case Bytecode::kCreateCatchContext: | |
347 case Bytecode::kCreateFunctionContext: | |
348 case Bytecode::kCreateEvalContext: | |
349 case Bytecode::kCreateWithContext: | |
350 // Literals. | |
351 case Bytecode::kCreateArrayLiteral: | |
352 case Bytecode::kCreateObjectLiteral: | |
353 case Bytecode::kCreateRegExpLiteral: | |
354 // Misc. | |
355 case Bytecode::kCreateUnmappedArguments: | |
356 case Bytecode::kThrow: | |
357 case Bytecode::kIllegal: | |
358 case Bytecode::kCallJSRuntime: | |
359 case Bytecode::kStackCheck: | |
305 case Bytecode::kReturn: | 360 case Bytecode::kReturn: |
306 case Bytecode::kCreateCatchContext: | |
307 case Bytecode::kSetPendingMessage: | 361 case Bytecode::kSetPendingMessage: |
308 return true; | 362 return true; |
309 default: | 363 default: |
310 if (FLAG_trace_side_effect_free_debug_evaluate) { | 364 if (FLAG_trace_side_effect_free_debug_evaluate) { |
311 PrintF("[debug-evaluate] bytecode %s may cause side effect.\n", | 365 PrintF("[debug-evaluate] bytecode %s may cause side effect.\n", |
312 Bytecodes::ToString(bytecode)); | 366 Bytecodes::ToString(bytecode)); |
313 } | 367 } |
314 return false; | 368 return false; |
315 } | 369 } |
316 } | 370 } |
317 | 371 |
318 bool BuiltinHasNoSideEffect(Builtins::Name id) { | 372 bool BuiltinHasNoSideEffect(Builtins::Name id) { |
319 switch (id) { | 373 switch (id) { |
320 // Whitelist for builtins. | 374 // Whitelist for builtins. |
375 // Math builtins. | |
376 case Builtins::kMathAbs: | |
377 case Builtins::kMathAcos: | |
378 case Builtins::kMathAcosh: | |
379 case Builtins::kMathAsin: | |
380 case Builtins::kMathAsinh: | |
381 case Builtins::kMathAtan: | |
382 case Builtins::kMathAtanh: | |
383 case Builtins::kMathAtan2: | |
384 case Builtins::kMathCeil: | |
385 case Builtins::kMathCbrt: | |
386 case Builtins::kMathExpm1: | |
387 case Builtins::kMathClz32: | |
388 case Builtins::kMathCos: | |
389 case Builtins::kMathCosh: | |
390 case Builtins::kMathExp: | |
391 case Builtins::kMathFloor: | |
392 case Builtins::kMathFround: | |
393 case Builtins::kMathHypot: | |
394 case Builtins::kMathImul: | |
395 case Builtins::kMathLog: | |
396 case Builtins::kMathLog1p: | |
397 case Builtins::kMathLog2: | |
398 case Builtins::kMathLog10: | |
399 case Builtins::kMathMax: | |
400 case Builtins::kMathMin: | |
401 case Builtins::kMathPow: | |
402 case Builtins::kMathRandom: | |
403 case Builtins::kMathRound: | |
404 case Builtins::kMathSign: | |
321 case Builtins::kMathSin: | 405 case Builtins::kMathSin: |
406 case Builtins::kMathSinh: | |
407 case Builtins::kMathSqrt: | |
408 case Builtins::kMathTan: | |
409 case Builtins::kMathTanh: | |
410 case Builtins::kMathTrunc: | |
411 // Number builtins. | |
412 case Builtins::kNumberConstructor: | |
413 case Builtins::kNumberIsFinite: | |
414 case Builtins::kNumberIsInteger: | |
415 case Builtins::kNumberIsNaN: | |
416 case Builtins::kNumberIsSafeInteger: | |
417 case Builtins::kNumberParseFloat: | |
418 case Builtins::kNumberParseInt: | |
419 case Builtins::kNumberPrototypeToExponential: | |
420 case Builtins::kNumberPrototypeToFixed: | |
421 case Builtins::kNumberPrototypeToPrecision: | |
422 case Builtins::kNumberPrototypeToString: | |
423 case Builtins::kNumberPrototypeValueOf: | |
424 // String builtins. Strings are immutable. | |
425 case Builtins::kStringFromCharCode: | |
426 case Builtins::kStringFromCodePoint: | |
427 case Builtins::kStringConstructor: | |
428 case Builtins::kStringPrototypeCharAt: | |
429 case Builtins::kStringPrototypeCharCodeAt: | |
430 case Builtins::kStringPrototypeEndsWith: | |
431 case Builtins::kStringPrototypeIncludes: | |
432 case Builtins::kStringPrototypeIndexOf: | |
433 case Builtins::kStringPrototypeLastIndexOf: | |
434 case Builtins::kStringPrototypeStartsWith: | |
435 case Builtins::kStringPrototypeSubstr: | |
436 case Builtins::kStringPrototypeSubstring: | |
437 case Builtins::kStringPrototypeToString: | |
438 case Builtins::kStringPrototypeTrim: | |
439 case Builtins::kStringPrototypeTrimLeft: | |
440 case Builtins::kStringPrototypeTrimRight: | |
441 case Builtins::kStringPrototypeValueOf: | |
442 // JSON builtins. | |
443 case Builtins::kJsonParse: | |
444 case Builtins::kJsonStringify: | |
322 return true; | 445 return true; |
323 default: | 446 default: |
324 if (FLAG_trace_side_effect_free_debug_evaluate) { | 447 if (FLAG_trace_side_effect_free_debug_evaluate) { |
325 PrintF("[debug-evaluate] built-in %s may cause side effect.\n", | 448 PrintF("[debug-evaluate] built-in %s may cause side effect.\n", |
326 Builtins::name(id)); | 449 Builtins::name(id)); |
327 } | 450 } |
328 return false; | 451 return false; |
329 } | 452 } |
330 } | 453 } |
331 | 454 |
(...skipping 15 matching lines...) Expand all Loading... | |
347 | 470 |
348 if (info->HasBytecodeArray()) { | 471 if (info->HasBytecodeArray()) { |
349 // Check bytecodes against whitelist. | 472 // Check bytecodes against whitelist. |
350 Handle<BytecodeArray> bytecode_array(info->bytecode_array()); | 473 Handle<BytecodeArray> bytecode_array(info->bytecode_array()); |
351 if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print(); | 474 if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print(); |
352 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); | 475 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); |
353 it.Advance()) { | 476 it.Advance()) { |
354 interpreter::Bytecode bytecode = it.current_bytecode(); | 477 interpreter::Bytecode bytecode = it.current_bytecode(); |
355 | 478 |
356 if (interpreter::Bytecodes::IsCallRuntime(bytecode)) { | 479 if (interpreter::Bytecodes::IsCallRuntime(bytecode)) { |
357 if (bytecode == interpreter::Bytecode::kInvokeIntrinsic) { | 480 Runtime::FunctionId id = |
358 Runtime::FunctionId id = it.GetIntrinsicIdOperand(0); | 481 (bytecode == interpreter::Bytecode::kInvokeIntrinsic) |
359 if (IntrinsicHasNoSideEffect(id)) continue; | 482 ? it.GetIntrinsicIdOperand(0) |
360 } else { | 483 : it.GetRuntimeIdOperand(0); |
361 Runtime::FunctionId id = it.GetRuntimeIdOperand(0); | 484 if (IntrinsicHasNoSideEffect(id)) continue; |
362 if (RuntimeFunctionHasNoSideEffect(id)) continue; | |
363 } | |
364 return false; | 485 return false; |
365 } | 486 } |
366 | 487 |
367 if (BytecodeHasNoSideEffect(bytecode)) continue; | 488 if (BytecodeHasNoSideEffect(bytecode)) continue; |
368 | 489 |
369 // Did not match whitelist. | 490 // Did not match whitelist. |
370 return false; | 491 return false; |
371 } | 492 } |
372 return true; | 493 return true; |
373 } else { | 494 } else { |
(...skipping 16 matching lines...) Expand all Loading... | |
390 | 511 |
391 if (FLAG_trace_side_effect_free_debug_evaluate) { | 512 if (FLAG_trace_side_effect_free_debug_evaluate) { |
392 PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n", | 513 PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n", |
393 reinterpret_cast<void*>(function_addr)); | 514 reinterpret_cast<void*>(function_addr)); |
394 } | 515 } |
395 return false; | 516 return false; |
396 } | 517 } |
397 | 518 |
398 } // namespace internal | 519 } // namespace internal |
399 } // namespace v8 | 520 } // namespace v8 |
OLD | NEW |