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" |
| (...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 |