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 amd runtime functions. |
| 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::kShiftLeft: |
| 334 case Bytecode::kShiftLeftSmi: |
| 335 case Bytecode::kShiftRight: |
| 336 case Bytecode::kShiftRightSmi: |
| 337 case Bytecode::kShiftRightLogical: |
| 338 case Bytecode::kInc: |
| 339 case Bytecode::kDec: |
| 340 case Bytecode::kLogicalNot: |
| 341 case Bytecode::kToBooleanLogicalNot: |
| 342 case Bytecode::kTypeOf: |
| 343 // Contexts. |
| 344 case Bytecode::kCreateBlockContext: |
| 345 case Bytecode::kCreateCatchContext: |
| 346 case Bytecode::kCreateFunctionContext: |
| 347 case Bytecode::kCreateEvalContext: |
| 348 case Bytecode::kCreateWithContext: |
| 349 // Literals. |
| 350 case Bytecode::kCreateArrayLiteral: |
| 351 case Bytecode::kCreateObjectLiteral: |
| 352 case Bytecode::kCreateRegExpLiteral: |
| 353 // Misc. |
| 354 case Bytecode::kCreateUnmappedArguments: |
| 355 case Bytecode::kThrow: |
| 356 case Bytecode::kIllegal: |
| 357 case Bytecode::kCallJSRuntime: |
| 358 case Bytecode::kStackCheck: |
305 case Bytecode::kReturn: | 359 case Bytecode::kReturn: |
306 case Bytecode::kCreateCatchContext: | |
307 case Bytecode::kSetPendingMessage: | 360 case Bytecode::kSetPendingMessage: |
308 return true; | 361 return true; |
309 default: | 362 default: |
310 if (FLAG_trace_side_effect_free_debug_evaluate) { | 363 if (FLAG_trace_side_effect_free_debug_evaluate) { |
311 PrintF("[debug-evaluate] bytecode %s may cause side effect.\n", | 364 PrintF("[debug-evaluate] bytecode %s may cause side effect.\n", |
312 Bytecodes::ToString(bytecode)); | 365 Bytecodes::ToString(bytecode)); |
313 } | 366 } |
314 return false; | 367 return false; |
315 } | 368 } |
316 } | 369 } |
317 | 370 |
318 bool BuiltinHasNoSideEffect(Builtins::Name id) { | 371 bool BuiltinHasNoSideEffect(Builtins::Name id) { |
319 switch (id) { | 372 switch (id) { |
320 // Whitelist for builtins. | 373 // Whitelist for builtins. |
| 374 // Math builtins. |
| 375 case Builtins::kMathAbs: |
| 376 case Builtins::kMathAcos: |
| 377 case Builtins::kMathAcosh: |
| 378 case Builtins::kMathAsin: |
| 379 case Builtins::kMathAsinh: |
| 380 case Builtins::kMathAtan: |
| 381 case Builtins::kMathAtanh: |
| 382 case Builtins::kMathAtan2: |
| 383 case Builtins::kMathCeil: |
| 384 case Builtins::kMathCbrt: |
| 385 case Builtins::kMathExpm1: |
| 386 case Builtins::kMathClz32: |
| 387 case Builtins::kMathCos: |
| 388 case Builtins::kMathCosh: |
| 389 case Builtins::kMathExp: |
| 390 case Builtins::kMathFloor: |
| 391 case Builtins::kMathFround: |
| 392 case Builtins::kMathHypot: |
| 393 case Builtins::kMathImul: |
| 394 case Builtins::kMathLog: |
| 395 case Builtins::kMathLog1p: |
| 396 case Builtins::kMathLog2: |
| 397 case Builtins::kMathLog10: |
| 398 case Builtins::kMathMax: |
| 399 case Builtins::kMathMin: |
| 400 case Builtins::kMathPow: |
| 401 case Builtins::kMathRandom: |
| 402 case Builtins::kMathRound: |
| 403 case Builtins::kMathSign: |
321 case Builtins::kMathSin: | 404 case Builtins::kMathSin: |
| 405 case Builtins::kMathSinh: |
| 406 case Builtins::kMathSqrt: |
| 407 case Builtins::kMathTan: |
| 408 case Builtins::kMathTanh: |
| 409 case Builtins::kMathTrunc: |
| 410 // Number builtins. |
| 411 case Builtins::kNumberConstructor: |
| 412 case Builtins::kNumberIsFinite: |
| 413 case Builtins::kNumberIsInteger: |
| 414 case Builtins::kNumberIsNaN: |
| 415 case Builtins::kNumberIsSafeInteger: |
| 416 case Builtins::kNumberParseFloat: |
| 417 case Builtins::kNumberParseInt: |
| 418 case Builtins::kNumberPrototypeToExponential: |
| 419 case Builtins::kNumberPrototypeToFixed: |
| 420 case Builtins::kNumberPrototypeToPrecision: |
| 421 case Builtins::kNumberPrototypeToString: |
| 422 case Builtins::kNumberPrototypeValueOf: |
| 423 // String builtins. Strings are immutable. |
| 424 case Builtins::kStringFromCharCode: |
| 425 case Builtins::kStringFromCodePoint: |
| 426 case Builtins::kStringConstructor: |
| 427 case Builtins::kStringPrototypeCharAt: |
| 428 case Builtins::kStringPrototypeCharCodeAt: |
| 429 case Builtins::kStringPrototypeEndsWith: |
| 430 case Builtins::kStringPrototypeIncludes: |
| 431 case Builtins::kStringPrototypeIndexOf: |
| 432 case Builtins::kStringPrototypeLastIndexOf: |
| 433 case Builtins::kStringPrototypeStartsWith: |
| 434 case Builtins::kStringPrototypeSubstr: |
| 435 case Builtins::kStringPrototypeSubstring: |
| 436 case Builtins::kStringPrototypeToString: |
| 437 case Builtins::kStringPrototypeTrim: |
| 438 case Builtins::kStringPrototypeTrimLeft: |
| 439 case Builtins::kStringPrototypeTrimRight: |
| 440 case Builtins::kStringPrototypeValueOf: |
| 441 // JSON builtins. |
| 442 case Builtins::kJsonParse: |
| 443 case Builtins::kJsonStringify: |
322 return true; | 444 return true; |
323 default: | 445 default: |
324 if (FLAG_trace_side_effect_free_debug_evaluate) { | 446 if (FLAG_trace_side_effect_free_debug_evaluate) { |
325 PrintF("[debug-evaluate] built-in %s may cause side effect.\n", | 447 PrintF("[debug-evaluate] built-in %s may cause side effect.\n", |
326 Builtins::name(id)); | 448 Builtins::name(id)); |
327 } | 449 } |
328 return false; | 450 return false; |
329 } | 451 } |
330 } | 452 } |
331 | 453 |
(...skipping 15 matching lines...) Expand all Loading... |
347 | 469 |
348 if (info->HasBytecodeArray()) { | 470 if (info->HasBytecodeArray()) { |
349 // Check bytecodes against whitelist. | 471 // Check bytecodes against whitelist. |
350 Handle<BytecodeArray> bytecode_array(info->bytecode_array()); | 472 Handle<BytecodeArray> bytecode_array(info->bytecode_array()); |
351 if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print(); | 473 if (FLAG_trace_side_effect_free_debug_evaluate) bytecode_array->Print(); |
352 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); | 474 for (interpreter::BytecodeArrayIterator it(bytecode_array); !it.done(); |
353 it.Advance()) { | 475 it.Advance()) { |
354 interpreter::Bytecode bytecode = it.current_bytecode(); | 476 interpreter::Bytecode bytecode = it.current_bytecode(); |
355 | 477 |
356 if (interpreter::Bytecodes::IsCallRuntime(bytecode)) { | 478 if (interpreter::Bytecodes::IsCallRuntime(bytecode)) { |
357 if (bytecode == interpreter::Bytecode::kInvokeIntrinsic) { | 479 Runtime::FunctionId id = |
358 Runtime::FunctionId id = it.GetIntrinsicIdOperand(0); | 480 (bytecode == interpreter::Bytecode::kInvokeIntrinsic) |
359 if (IntrinsicHasNoSideEffect(id)) continue; | 481 ? it.GetIntrinsicIdOperand(0) |
360 } else { | 482 : it.GetRuntimeIdOperand(0); |
361 Runtime::FunctionId id = it.GetRuntimeIdOperand(0); | 483 if (IntrinsicHasNoSideEffect(id)) continue; |
362 if (RuntimeFunctionHasNoSideEffect(id)) continue; | |
363 } | |
364 return false; | 484 return false; |
365 } | 485 } |
366 | 486 |
367 if (BytecodeHasNoSideEffect(bytecode)) continue; | 487 if (BytecodeHasNoSideEffect(bytecode)) continue; |
368 | 488 |
369 // Did not match whitelist. | 489 // Did not match whitelist. |
370 return false; | 490 return false; |
371 } | 491 } |
372 return true; | 492 return true; |
373 } else { | 493 } else { |
(...skipping 16 matching lines...) Expand all Loading... |
390 | 510 |
391 if (FLAG_trace_side_effect_free_debug_evaluate) { | 511 if (FLAG_trace_side_effect_free_debug_evaluate) { |
392 PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n", | 512 PrintF("[debug-evaluate] API Callback at %p may cause side effect.\n", |
393 reinterpret_cast<void*>(function_addr)); | 513 reinterpret_cast<void*>(function_addr)); |
394 } | 514 } |
395 return false; | 515 return false; |
396 } | 516 } |
397 | 517 |
398 } // namespace internal | 518 } // namespace internal |
399 } // namespace v8 | 519 } // namespace v8 |
OLD | NEW |